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); } } }