Spring Boot与Spring MVC中的上下文context

记载一下两种方式的web项目中的context对比与使用,这里的context均指spring的ApplicationContext,注意区别servlet容器的ServletContext。

1、spring mvc中的上下文

传统MVC拥有两个context:

根上下文root context,为全局上下文,无法访问子容器即mvc context中bean:

//root context 作为attrName名
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
//在ServletContext中以属性保存
WebApplicationContext root = servletContext.getAttribute(attrName);

和mvc context,其父容器为root context:

//mvc context作为HttpServletRequest的属性,名字为
DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE;

2、传统MVC中context创建时机

1)root context:

ContextLoaderListener在servlet容器启动完成后,执行initWebApplicationContext()方法

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
    ...
    if (this.context == null) {
        //创建root context
        this.context = createWebApplicationContext(servletContext);
    }
    ...
    //设置到servletContext属性
    servletContext.setAttribute(
        WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
        this.context
    );
    ...
}

2)mvc context

从初始化servlet的javax.servlet.GenericServlet.init开始到FrameworkServlet.initWebApplicationContext

protected WebApplicationContext initWebApplicationContext() {
    //首先拿到root context
    WebApplicationContext rootContext =...;  
    WebApplicationContext wac = null;
    ...
	
    if (wac == null) {
        //这里创建mvc context,rootContext作为父容器,子可以访问父
        wac = createWebApplicationContext(rootContext);
    }
    ...
    return wac;
}

3、boot 中的web上下文与创建时机

boot默认使用embed tomcat做servlet容器,只有一个root context,或者说mvc context也是同一个。

不同在于创建时机,servlet容器是被spring容器启动的;启动一个SpringBoot应用时:

public static void main(String[] args) {
    //run返回ConfigurableApplicationContext
    SpringApplication.run(App.class, args);
}

run的返回结果就是全局context,平常也可以通过ApplicationContextAware拿到,所以在DispatchServlet的父类中:

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
    ...

    public void setApplicationContext(ApplicationContext applicationContext) {
        if (this.webApplicationContext == null 
            && applicationContext instanceof WebApplicationContext) {
                //设置mvc上下文
                this.webApplicationContext = (WebApplicationContext) applicationContext;
	        this.webApplicationContextInjected = true;
            }
	}
    ...
}

boot在走创建mvc context流程时(上面2.2),可以看出root、mvc context是同一个。

protected WebApplicationContext initWebApplicationContext() {
    WebApplicationContext rootContext =...
    WebApplicationContext wac = null;
    //此时webApplicationContext == rootContext
    //类型AnnotationConfigServletWebServerApplicationContext
    if (this.webApplicationContext != null) {
        wac = this.webApplicationContext;
        ...
    }
    ...
}

4、一些工具方法

通过查看源码可以看到一些spring提供的工具类和一些静态属性名,就可以善加利用,下面在不同场景下获取。

1)获取请求和session

//获取请求
HttpServletRequest request = ((ServletRequestAttributes) 
        RequestContextHolder.getRequestAttributes())
        .getRequest();

//获取响应
HttpServletResponse response = ((ServletRequestAttributes)
        RequestContextHolder.getRequestAttributes())
        .getResponse();

//获取session
HttpSession session = request.getSession();

2)获取ServletContext

//1中获取了session
session.getServletContext();

//有了context后,如ContextLoader.getCurrentWebApplicationContext().
webApplicationContext.getServletContext();

3)获取root context:

//根据servletContext获取
WebApplicationContextUtils.getWebApplicationContext(servletContext);

//需要当前线程classloader和context相同
ContextLoader.getCurrentWebApplicationContext();

4)获取mvc context

RequestContextUtils.findWebApplicationContext(httpServletRequest);
//or
RequestContextUtils.findWebApplicationContext(httpServletRequest, servletContext);

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值