1、控制器实现方式&对应的处理器适配器
不一样的实现方式调用不一样的 HandlerAdapter
- 1.实现 Controller 接口 --> SimpleControllerHandlerAdapter
- 2.实现 HttpRequestHandler 接口 --> HttpRequestHandlerAdapter
- 3.经过 @Controller 注解 --> RequestMappingHandlerAdapter
2、执行流程
3、组件介绍
- DispatcherServlet
前端控制器,用于接收请求,处理响应结果前端
- HandlerMapping
处理器映射器,根据请求URL,找到对应的Handler。 其实就是HandlerExecutionChain ,HandlerExecutionChain 又包括了 - Handler 和 HandlerInterceptorweb
- HandlerAdapter
处理器适配器,用于调用处理器(Handler|Controller)的方法,这是个接口,会根据不一样的接口实现调用不一样的处理器适配器。数组
- HandlerInterceptor
处理器拦截器,自定义拦截器要实现该接口或者实现该接口的子类,根据业务实现 preHandle()、postHandle()、afterCompletion() 方法app
- Handler
处理器Handler又名Controller,用于接收用户请求数据,调用业务方法处理请求ide
4、源码解析
从DispatcherServlet 方法开始分析,在此以前 servlet 会调用 onRefresh()、doService(),上述流程图就是从doService() --> doDispatch() 方法开始的post
/** * 上述流程图的核心代码,去除了源码中的其余逻辑 */ protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; try { ModelAndView mv = null; Exception dispatchException = null; try { // 获取处理器执行调用链 HandlerExecutionChain,包括处理器 Controller 和拦截器 HandlerInterceptor // Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // 获取相应的处理器适配器,也被初始化过了 // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 调用拦截器的 preHandle()方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // 真正的调用Controller 中的方法,handle() 是个抽象方法,根据不一样的处理器调用 // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //调用拦截器的 hostHandle 方法,和调用 preHandle() 处理方式同样,就再也不分析了 mappedHandler.applyPostHandle(processedRequest, response, mv); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } }
获取处理器执行调用链对象
/** * this.handlerMappings 在此以前已经被初始化完成,这里直接根据 request 获取 */ protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
onRefresh 方法由 Servlet 调用,用来初始化处理请求用到的组件
@Override protected void onRefresh(ApplicationContext context) { initStrategies(context); } /** * 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); //初始化处理器适配器 initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
调用拦截器的 preHandle()方法
/** * 循环遍历拦截器数组中拦截器的 preHandle()方法,true-放行,false-请求被拦截 */ boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(request, response, this.handler)) { triggerAfterCompletion(request, response, null); return false; } this.interceptorIndex = i; } } return true; }
以RequestMappingHandlerAdapter处理器适配器的 handler()方法分析
@Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); //...省略其余处理逻辑 //真正执行 Controller 中的方法的代码,返回 ModelAndView 对象 mav = invokeHandlerMethod(request, response, handlerMethod); return mav; }
@Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { // 执行处理器的方法, //invocableMethod 就是映射过来的 Controller 类中对应的方法com.xxx.controller.XxxController#xxx() invocableMethod.invokeAndHandle(webRequest, mavContainer); return getModelAndView(mavContainer, modelFactory, webRequest); } }
@Nullable public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //获取请求参数 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } //终于要执行 Controller 的方法了 return doInvoke(args); }
5、自定义实现拦截器
- 第一步:实现一个拦截器HandlerInterceptor,根据业务实现 preHandle()、postHandle()、afterCompletion() 方法
//我这只实现了 preHandle()方法,true-放行,false-请求直接返回 public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("=============执行拦截器 preHandle()================"); return true; } }
- 第二步:把拦截器注入到 Spring 容器
/** * 注入的方式不少,你能够在MyInterceptor 上加@Component 注解,不用@Bean 的方式 */ @Configuration public class WebAppConfig implements WebMvcConfigurer { @Bean public MyInterceptor myInterceptor() { return new MyInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor()) //添加拦截的 url,/**表示匹配全部,/* 表示只匹配一层 .addPathPatterns("/**") //添加放行的 url .excludePathPatterns("/exclude/**"); } }