• SpringMVC之DispacherServlet


    ds

    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 = config.getInitParameter(name);  
                params.put(name, value);  
            }  
        }  
     }  
  • 相关阅读:
    图片滚动懒加载用jquery-lazyload 与手动Jquery 写
    穿梭框(filter过滤方法,sort排序 v-model)
    选择添加好友(包含 去重,删除splice 等) v-show(解决显示隐藏闪动问题)
    求数组中最小的数值(结合apply() call())
    Vue
    js递归
    使用kdf 元素来接收键盘的输入指令
    编辑滚动条样式
    【IntelliJ IDEA】Debug调试的使用记录
    福利:IntelliJ IDEA 破解激活教程
  • 原文地址:https://www.cnblogs.com/zhihuayun/p/7217520.html
Copyright © 2020-2023  润新知