首页 > 代码库 > SpringMVC之DispacherServlet

SpringMVC之DispacherServlet

技术分享

1.DispacherServlet是前端控制器(Struts是Filter),负责接收前端请求,并根据请求找到具体的Handler(目前的Handler是方法级别的);SpringMVC中DispacherServlet初始化放在web.xml中,<load-on-start>1</load-on-start>,意思是Servlet容器启动时自动加载该Servlet。

2.HandlerMapping:负责将URL和controller匹配到一起,简单来说就是根据URL找到具体的类(根据注解@Controller和@RequestMapping找到);

3.HandlerAdapter:根据URL找到具体类的具体方法;

  jdk 具体执行过程如下:

  1.DispatcherServlet本质上还是一个Servlet,故需要在web容器里初始化

/**
     * Initialize the strategy objects that this servlet uses.
     * <p>May be overridden in subclasses in order to initialize further strategy objects.
     */
    protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context); 
        initHandlerMappings(context); // 从ApplicationContext容器中初始生成HandlerMappings
        initHandlerAdapters(context); // 初始化HandlerAdapter
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }

 

2.当有一个请求到达时,调用DispatcherServlet的doDispatch()方法,该方法找到真正的handler处理该请求;主要代码如下:

/**
     * Process the actual dispatching to the handler.
     * <p>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.
     * <p>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
   *
   
    通过查找HandlerMapping找到真正的Handler;先找到handler class,根据该class找到HandlerAdapter;   
    通过查询servlet已注册的HandlerAdapters,找到真正处理该请求的method
*/ protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; ModelAndView mv = null; // Determine handler for the current request.返回HandlerExecutionChain; mappedHandler = getHandler(processedRequest, false);       // Determine handler adapter for the current request.根据HandlerExecutionChain找到HandlerAdapter       HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());            // Actually invoke the handler.使用给定的handler处理请求;       mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); }
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name ‘" + getServletName() + "‘");
            }

    //查询所有已注册的HandlerMapping beans找到处理该请求的Handler;
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }

其中HandlerExecutionChain是有一个HandlerAdapter和若干个HandlerInteceptor组成,请求先经HandlerInteceptor处理后在传给Adapter。一般我们使用HandlerInteceptor做一些
登录验证,安全验证等

3.HandlerInterceptor和Servlet里的Filter作用很像,下面讲一下关于Filter的东西

  3.1  Filter作用?

    用于HttpServletRequest预处理和HttpServletResponse后处理;执行流程是 request---->listener----->filter------>struts拦截器(?)----->Servlet,这是链式处理过程,请求最后总会到达Servlet的;

  3.2 一般用来干啥?

    用户登录验证,用户发来请求,拦截请求后,验证用户是否登录过,如果没有登录调到登录页面;日志功能;编码格式

  3.3Filter有三个过程

    Filter一般在服务器端工作,故web容器调用它的init(),在web容器初始化的时候创建Filter的实例对象;

    chain.doFilter(),把要做的事情都放在doFilter()方法里面完成;

  3.4 filter使用配置文件注册,在web应用程序一启动,web服务器就会实例化filter对象;

    filter实例化

    web.xml配置:   

<!-- 编码过滤器 -->  
    <filter>  
        <filter-name>setCharacterEncoding</filter-name>  
        <filter-class>com.company.strutstudy.web.servletstudy.filter.EncodingFilter</filter-class>  //该过滤器(EncodingFilter)具体位置。
        <init-param>  
            <param-name>encoding</param-name>   // 设定encoding编码为utf-8.
            <param-value>utf-8</param-value>  
        </init-param>  
    </filter>  
    <filter-mapping>  
        <filter-name>setCharacterEncoding</filter-name>  
        <url-pattern>/*</url-pattern>    //处理所有页面的编码格式
    </filter-mapping>  
   
<!-- 请求url日志记录过滤器 -->  
    <filter>  
        <filter-name>logfilter</filter-name>  
        <filter-class>com.company.strutstudy.web.servletstudy.filter.LogFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>logfilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  

    编码拦截器:

public class EncodingFilter implements Filter {  
    private String encoding;  
    private Map<String, String> params = new HashMap<String, String>();  
    // 项目结束时就已经进行销毁  
    public void destroy() {  
        System.out.println("end do the encoding filter!");  
        params=null;  
        encoding=null;  
    }  
    public void doFilter(ServletRequest req, ServletResponse resp,  
            FilterChain chain) throws IOException, ServletException {  
        //UtilTimerStack.push("EncodingFilter_doFilter:");  
        System.out.println("before encoding " + encoding + " filter!");  
        req.setCharacterEncoding(encoding);  
        // resp.setCharacterEncoding(encoding);  
        // resp.setContentType("text/html;charset="+encoding);  
        chain.doFilter(req, resp);        
        System.out.println("after encoding " + encoding + " filter!");  
        System.err.println("----------------------------------------");  
        //UtilTimerStack.pop("EncodingFilter_doFilter:");  
    }  
   
    // 项目启动时就已经进行读取  
    public void init(FilterConfig config) throws ServletException {  
        System.out.println("begin do the encoding filter!");  
        encoding = config.getInitParameter("encoding");  
        for (Enumeration e = config.getInitParameterNames(); e  
                .hasMoreElements();) {  
            String name = (String) e.nextElement();  
            String value = http://www.mamicode.com/config.getInitParameter(name);  >

 

SpringMVC之DispacherServlet