1)BeanNameUrlHandlerMapping -> @Controller("/xxx") 类注解 + HttpRequestHandler 接口
2)RequestMappingHandlerMapping -> @Controller 类注解 + @RequestMapping("/xxx")方法注解
3)RouterFunctionMapping ->函数式映射方式;
2、List<HandlerAdapter> handlerAdapters:映射适配器;
handlerMappings 用来寻找请求对应的 controller,handlerAdapters 就是使用反射机制,执行 controller 中处理请求的方法;
常用的就是 RequestMappingHandlerAdapter,如果 controller 类的方法中带有 @RequestMapping 注解,就是会被 RequestMappingHandlerAdapter 所处理的目标方法;
RequestMappingHandlerAdapter 实现了 InitializingBean 接口;
在 getBean 创建该对象时执行了 InitializingBean 接口的方法进行了初始化;
给对象中添加了【参数解析器】和【返回值处理器】,使用 27 种参数解析器创建目标方法的参数,使用 15 种返回值处理器对目标方法的返回值进行处理,生成 ModelAndView 对象;
3、List<HandlerExceptionResolver> handlerExceptionResolvers:异常解析器;
默认异常解析器有以下 3 类:
(1)DefaultHandlerExceptionResolver:判断是不是 spring mvc 自己定义的异常,如果是就处理了;
其实底层代码就是使用 if else 挨个判断异常类型来实现的;
(2)ResponseStatusExceptionResolver:判断该异常有没有继承 ResponseStatusException 类,或者有没有标注 @ResponseStatus 注解;
(1)注解版: @ResponseStatus(value = HttpStatus.BAD_REQUEST) public class ExceptionAnnotation extends RuntimeException { private String errorMessage; public ExceptionAnnotation(String errorMessage) { super(errorMessage); } } (2)继承类: public class ExceptionClass extends ResponseStatusException { public ExceptionClass(HttpStatus status) { super(status); } public ExceptionClass(HttpStatus status, String reason) { super(status, reason); } public ExceptionClass(HttpStatus status, String reason, Throwable cause) { super(status, reason, cause); } }
(3)ExceptionHandlerExceptionResolver:找到一个{@code @ExceptionHandler}方法并调用它来处理引发的异常;
@ExceptionHandler public String error() { return "error"; }
4、List<ViewResolver> viewResolvers:视图解析器;
相当于这个请求怎么去其他页面,比如说转发还是重定向,还是返回一个图片或文档;
以下是 DispatcherServlet 属性源码:
DispatcherServlet 的属性中有【九大组件】,在处理请求时,就是用这些组件进行相应的处理: /** 文件上传解析器 */ @Nullable private MultipartResolver multipartResolver; /** 国际化解析器 */ @Nullable private LocaleResolver localeResolver; /** 主题解析器 */ @Nullable private ThemeResolver themeResolver; /** 请求映射处理器 List 集合,其实就是【请求地址 和 controller】的映射关系集合 */ @Nullable private List<HandlerMapping> handlerMappings; /** 处理器的适配器,可以理解为对应的【超级反射工具】 */ /** 这是一个 Adapter 适配器,适配的是 【handlerMappings 中的映射方法】,和【响应的处理】进行适配 @Nullable private List<HandlerAdapter> handlerAdapters; /** 处理器的异常解析器 */ @Nullable private List<HandlerExceptionResolver> handlerExceptionResolvers; /** (其实这个没啥用,不用管)请求到视图名的转换器,把请求转换为要跳转的页面地址的转换器 */ @Nullable private RequestToViewNameTranslator viewNameTranslator; /** 闪存管理器 */ @Nullable private FlashMapManager flashMapManager; /** 视图解析器,相当于这个请求怎么去其他页面,比如说转发还是重定向,还是返回一个图片或文档 */ @Nullable private List<ViewResolver> viewResolvers;
DispatcherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet -> Servlet;
DispatcherServlet、FrameworkServlet 、HttpServletBean 这三个 spring mvc 中的类;
HttpServlet、Servlet 是 javax.servlet 中的类;
也就是说,DispatcherServlet 实现了 servlet 标准接口,遵循 servlet 的生命周期;
Spring 的 MVC 框架是围绕 DispatcherServlet 来设计的,用来处理所有的 HTTP 请求和响应;
(1)用户发送请求至前端控制器 DispatcherServlet;
(2) DispatcherServlet 收到请求后,调用 HandlerMapping 处理器映射器, 请求获取 Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter 处理器适配器;
(5)HandlerAdapter 经过适配调用具体处理器(Handler,也叫后端控制器);
(6)Handler 执行完成返回 ModelAndView;
(7)HandlerAdapter 将 Handler 执行结果 ModelAndView 返回给 DispatcherServlet;
(8)DispatcherServlet 将 ModelAndView 传给 ViewResolver 视图解析器进行解析;
(9)ViewResolver 解析后返回具体 View;
(10)DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中);
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { // 创建异步请求处理管理器,这也是响应式 web 的基础 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); // 检查请求是不是文件上传请求,其实就是根据 http 规范,检查 request 的 header 的 Content-Type 是不是 "multipart/" 开头的 // 如果是文件上传请求,就创建一个 MultipartHttpServletRequest 类型的 request 替换之前的 HttpServletRequest 类型的 request processedRequest = checkMultipart(request); // 获取能够处理当前请求的 controller 的方法,mappedHandler 中封装了该方法(问题【2】和【3】) mappedHandler = getHandler(processedRequest); // 如果 mappedHandler 为 null,返回相应 404(404 就是这么来的!) if (mappedHandler == null) { // 该方法中会 throw 报错,或者 response.sendError(HttpServletResponse.SC_NOT_FOUND); 抛出 404 错误 noHandlerFound(processedRequest, response); return; } // 确定当前请求的处理程序适配器,一共 4 种适配器,对应处理不同的 controller,适配器的加载和 handlerMappings 基本一样 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 执行过滤器链 HandlerExecutionChain 中的拦截器的前置拦截过程 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // 适配器真正执行 controller 处理请求的方法 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // 如果没有指定的 view,设置默认的 view,注意:这里使用了九大组件之一的 viewNameTranslator,其实没啥用; applyDefaultViewName(processedRequest, mv); // 执行拦截器链的 postHandle 方法 mappedHandler.applyPostHandle(processedRequest, response, mv); /* 以上所有代码,均被 try catch 包裹 */ // 处理调度结果,处理处理程序选择和处理程序调用的结果,它是一个 ModelAndView 或一个要解析为 ModelAndView 的异常。 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); }
Spring MVC常用的注解有哪些?
@RequestBody:注解实现接收http请求的json数据,将json转换为java对 象。
@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给 客户。
@ResponseBody注解的作用
作用: 该注解用于将Controller的方法返回的对象,通过适当的 HttpMessageConverter 转换为指定格式后,写入到 Response 对象的 body 数据区。
使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
Spring MVC怎么样设定重定向和转发的?
(1) 转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4"
(2) 重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"