一、springMvc概念
springMvc是基于servlet的web框架,其简化了web程序的开发
二、springMvc请求流程
在阅读时不妨可以带着几个问题阅读:
1.我们通常在浏览器输入的接口怎么由DispatcherServlet调到具体的Handler的(就是我们自己开发的Controller类)
2.编写Controller的形式有哪几种?
springMvc重要组件:
之所以先说这几个组件,是因为只要了解了这几个组件后你便可以对springMvc请求流程有个大致的清晰认识了。(Handler就是我们写的Controller)
HandlerMapping
HandlerAdapter
ViewResolver
View
HandlerExceptionResolver
HandlerInterceptor
DisPatcher作为一个主流程入口,看一下DispatcherServlet结构
DispatcherServlet为了简洁,省去了很多方法跟属性
public class DispatcherServlet extends FrameworkServlet { //定义了默认策略名字 private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties"; private static final Properties defaultStrategies; static { //从Properties文件中加载默认策略实现 ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class); defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); } private List<HandlerMapping> handlerMappings; private List<HandlerAdapter> handlerAdapters; private List<HandlerExceptionResolver> handlerExceptionResolvers; private List<ViewResolver> viewResolvers; //初始化策略 protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); } protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { try { ModelAndView mv = null; Exception dispatchException = null; try { //检查是否文件上传 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); //通过HandlerMapping 获取Handler(返回的是HandlerExecutionChain) /**public class HandlerExecutionChain { //HandlerExecutionChain封装了Handler(就是我们编写的Controller)跟interceptors private final Object handler; private HandlerInterceptor[] interceptors; **/ HandlerExecutionChain mappedHandler = getHandler(processedRequest); //获取的Handler是Object类型,需要通过HandlerAdapter获取Handler真实类型 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. //调用Handlerinterceptor PreHandle(前置拦截器),返回false则停止执行 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // 调用真实handler逻辑并返回ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //将ModelAndView返回值DispatcherServlet后 applyDefaultViewName(processedRequest, mv); //调用Handlerinterceptor PostHandle(后置拦截器) mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { //调用Handlerinterceptor afterCompletion mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }}
通过上面的DispatcherServlet大概分析可以得知几个组件的作用:
HandlerMapping:
根据请求url地址得到具体Handler(Controller)
HandlerAdapter
根据Handler得到Handler适配器
ViewResolver
试图仓库:根据ViewName得到View
View
具体解析视图
HandlerExceptionResolver
异常捕捕捉器
HandlerInterceptor
拦截器
三、springMvc处理流程图解:(引用他人流程图)
简略图:
四、各组件详解:
1.HandlerMapping
HandlerMapping方法:
HandlerMapping子类:
从上图看一看出常用的Mapping有三类:SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping、RequestMappingHandlerMapping。
RequestMappingHandlerMapping就是我们最长使用的方式基于注解@RequestMapping方式的url映射。
SimpleUrlHandlerMapping 基于手动配置 url 与control 映射
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/hello">helloController</prop> </props> </property> </bean> <bean id="helloController" class="com.ckd.controller.HelloController"/> ----------------------------------------------------------------------------------------------------------------------- import org.springframework.web.servlet.mvc.Controller; public class HelloController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mv = new ModelAndView("index"); mv.addObject("hello","world"); return mv; } }
BeanNameUrlHandlerMapping是配置IOC bean时id以"/"开头与Controller的映射
<bean id="/beanname" class="com.ckd.controller.BeanNameController"/> //需要继承HttpRequestHandler 此时可以把/beanname映射到handleRequest方法上 public class BeanNameControl implements HttpRequestHandler { @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { request.getRequestDispatcher("/WEB-INF/page/userView.jsp").forward(request, response); } }
通过DisPatcherServlet.getHandler()获得Handler的类型时Object,此时无法调用,因此需要HandlerAdapter根据Handler获取具体的适配器
2.HandlerAdapter
springmvc采用适配器的模式适配调用Handler,根据handler不同调用不同的适配器,Handler与HandlerAdapter对用关系如下:
Handler类别 | 对应适配器 | 描述 |
---|---|---|
Controller | SimpleControllerHandlerAdapter | 标准控制器,返回ModelAndView |
HttpRequestHandler | HttpRequestHandlerAdapter | 业务自行处理 请求,不需要通过modelAndView 转到视图 |
Servlet | SimpleServletHandlerAdapter | 基于标准的servlet 处理 |
HandlerMethod | RequestMappingHandlerAdapter | 基于@requestMapping对应方法处理 |
基于Servlet演示
<bean class="org.springframework.web.servlet.handler.SimpleServletHandlerAdapter"/> <bean id="/helloservlet" class="com.ckd.controller.HelloServlet"/> ---------------------------------------------------------------------------------------------------------------------------- public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().println("hello Servlet"); } }
HelloServlet注册IOC容器中时,会由BeanNameUrlHandlerMapping找到对应的Handler,由SimpleServletHandlerAdapter找到对应的适配器,调用业务逻辑Controller,并返回ModelAndView。
3.ViewResolver View
DispatcherServlet#getHandlerAdapter().handle()后返回ModelAndView,
调用resolveViewName() 去viewResolvers试图列表中查找对应的View并返回View.交由View解析生成html并返回
4.HandlerExceptionResolver
该组件用于指示 当出现异常时 mvc 该如何处理。 dispatcherServlet 会调用org.springframework.web.servlet.DispatcherServlet#processHandlerException() 方法,遍历 handlerExceptionResolvers 处理异常,处理完成之后返回errorView 跳转到异常视图。
- [ ] 演示自定义异常捕捉
<bean class="com.ckd.controller.ExceptionHandlerSample"/> public class ExceptionHandlerSample implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { return new ModelAndView("error"); } }
5.HandlerInterceptor
- [ ] 演示HandlerInterceptor
<mvc:interceptors> <mvc:interceptor> <!-- 拦截所有的请求,这个必须写在前面--> <mvc:mapping path="/**" /> <bean class="com.ckd.controller.SimpleHandlerInterceptor" /> </mvc:interceptor> </mvc:interceptors> ----------------------------------------------------------------------------------------------------------------------------------------- public class SimpleHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion"); } }
其实现机制是基于 HandlerExecutionChain 分别在 doDispatch 方法中执行以下方法:
- preHandle :业务处理前执行
- postHandle:业务处理后(异常则不执行)
- afterCompletion:视图处理后
具体逻辑源码参见:org.springframework.web.servlet.DispatcherServlet#doDispatch 方法。
转载:https://www.jianshu.com/p/c68cf985f877
来源:https://www.cnblogs.com/minikobe/p/12195831.html