现在的位置: 首页 > 综合 > 正文

Spring MVC 之servlet代理研究

2014年04月26日 ⁄ 综合 ⁄ 共 3506字 ⁄ 字号 评论关闭

Spring MVC 之servlet代理代码研究

  这里主要探讨spring web mvc在serlvet2.4中如何通过web.xml中的配置 ,将缺省的javax.sevelt.httpservlet 对request和response进行扩展的。
首先,在web.xml中,通过:
<servlet>
    <servlet-name>springapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
<servlet-mapping>
    <servlet-name>springapp</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>

将web对指定的url请求提交org.springframework.web.servlet.DispatcherServlet类 进行处理。
    事实上,处理交给DispatcherServlet时,需要通过以下几个类才能达到本体:

 spring mvc

Servelt 控制器走向

实际上,serlvlet的request与response到DispatcherServlet才得到封装处理,其他类都只是进行控制传递,不过对init方法,org.springframework.web.servlet.HttpServletBean已经重载并在config配置中加入了bean的属性。在org.springframework.web.servlet.FrameworkServlet又对init方法进行了扩展,加入了计时器,对初始化时间(initFrameworkServlet())进行统计,最后的初始化工作交给了DispatcherServlet的initFrameworkServlet()方法,该方法最终可以使得用户可以通过配置文件对bean进行配置.注意的是如何得到配置文件及如何从配置文件获取信息是通过FrameworkServletgetWebApplicationContext()方法.

DispatcherServlet,从doServices() ->doDispatch()方法中,request对象被设置了4 个属性:
其中跟配置文件相关的属性是:
/* Request attribute to hold the current web application context.*/
属性名:WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName()+".CONTEXT";
值:
getWebApplicationContext()

doDispatch()中,request对象首先通过:
LocaleContextHolder.setLocaleContext(new LocaleContext() {
   public Locale getLocale() {
    return localeResolver.resolveLocale(request);
   }
  });

方法处理,使得request中的私有静态字段与该对应的request请求者(一个thread线程)绑定.这样其他的request请求者就无法访问到别的requet中的私有字段了.
    附注:
 LocaleContextHolder.class:相关的方法
 ThreadLocal localeContextHolder = new InheritableThreadLocal()
 setLocaleContext(LocaleContext localeContext) {
  localeContextHolder.set(localeContext);
 }

InheritableThreadLocal.class的set方法:
   /**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.
     */
    public void set(Object value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

其后:
// Expose current RequestAttributes to current thread.
  RequestAttributes previousRequestAttributes  =  
                   RequestContextHolder.getRequestAttributes();
  ServletRequestAttributes requestAttributes =
                   new ServletRequestAttributes(request);
  RequestContextHolder.setRequestAttributes(requestAttributes);下面的操作都是为获取下个handler (其实就是servlet控制器),:

将当前的request属性绑定到当前的request请求者上.注意的是, getRequestAttributes与setRequestAttributes都是针对当前线程的.


下面的操作都是为获取下个handler (其实就是servlet控制器),

 

 

首先通过getHandler()查找
如果找到,则继续判断是否存在多个映射关系mapping(多个控制器),如果是,则根据先后
(通过List handlerMappings ,该list在初始化方法中被初始化. )返回单个hander.,并在request对象中设置了一个标记:
request.setAttribute(HANDLER_EXECUTION_CHAIN_ATTRIBUTE, handler);

对request对象的处理已经差不多了,该将控制权提交给被请求的那个hander了,在最后的的finally块中, doDispatch()做了3件事情:
清除request操作中的临时变量所占的资源
重置request请求者(curren thread)所绑定的资源,避免多余绑定
重置request请求者(curren thread)线程。

由于doDispatch()方法并没有显示的将dispather控制权交给下个hander(也就是request应该被那个hander处理),因此该把当前的request请求交给那个bean(在doDispatch会指定,实际上我们是在applicationcontext.xml中指定的)就由HandlerAdapters来做的,可以看doDispatch()方法的注释:
/**
 * Process the actual dispatching to the handler.
* The handler will be obtained by applying the servlet's
* HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed
* HandlerAdapters to find the first that supports the handler class.
* All HTTP methods are handled by this method. It's up to HandlerAdapters
* or handlers themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/

 

【上篇】
【下篇】

抱歉!评论已关闭.