Spring MVC 常见问题
Spring MVC的主要组件有那些?
spring mvc 在使用 DispatcherServlet 处理 web 请求的时候,会用到 spring 中的九大组件,以下是几个关键的组件:
1、List<HandlerMapping> handlerMappings:映射处理器;
用来加载、解析容器中的 controller;
HandlerMapping 接口一共有 3 个实现类:
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
DispatcherServlet 的继承结构是这样的:
DispatcherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet -> Servlet;
DispatcherServlet、FrameworkServlet 、HttpServletBean 这三个 spring mvc 中的类;
HttpServlet、Servlet 是 javax.servlet 中的类;
也就是说,DispatcherServlet 实现了 servlet 标准接口,遵循 servlet 的生命周期;
Spring 的 MVC 框架是围绕 DispatcherServlet 来设计的,用来处理所有的 HTTP 请求和响应;
请描述Spring MVC的工作流程?描述一下 DispatcherServlet 的工作流程?
(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 进行渲染视图(即将模型数据填充至视图中);
(11)DispatcherServlet响应用户;
以下是 doDispatch 方法的源码解析:
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常用的注解有哪些?
@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用 于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
@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"
Spring MVC 常见问题的更多相关文章
- spring boot 1.x完整学习指南(含各种常见问题servlet、web.xml、maven打包,spring mvc差别及解决方法)
spring boot 入门 关于版本的选择,spring boot 2.0开始依赖于 Spring Framework 5.1.0,而spring 5.x和之前的版本差距比较大,而且应该来说还没有广 ...
- 框架应用:Spring framework (五) - Spring MVC技术
软件开发中的MVC设计模式 软件开发的目标是减小耦合,让模块之前关系清晰. MVC模式在软件开发中经常和ORM模式一起应用,主要作用是将(数据抽象,数据实体传输和前台数据展示)分层,这样前台,后台,数 ...
- UEditor1.4.3.3整合Spring MVC和七牛
[前言] 项目中涉及将UEditor上传服务器整合进已有的基于Spring MVC的服务中,并且将上传到本地改为上传到七牛,看似简单的一个需求,实际做起来还是遇到了一些困难.在这里分享一下经验-- 七 ...
- Spring MVC 多语言化的实践和学习
一.主要参考: SpringMVC简单实现国际化/多语言 - CSDN博客 https://blog.csdn.net/u013360850/article/details/70860144/ 二.总 ...
- 第一个使用Spring Tool Suite(STS)和Maven建立的Spring mvc 项目
一.目标 在这篇文章中.我将要向您展示怎样使用Spring Frameworks 和 Maven build创建您的第一个J2ee 应用程序. 二.信息 Maven是一个java项目的构建工具(或者自 ...
- Spring MVC -- MVC设计模式(演示4个基于MVC框架的案例)
对于简单的Java Web项目,我们的项目仅仅包含几个jsp页面,由于项目比较小,我们通常可以通过链接方式进行jsp页面间的跳转. 但是如果是一个中型或者大型的项目,上面那种方式就会带来许多维护困难, ...
- spring mvc json返回防止乱码
乱码问题 乱码一直是编程的常见问题,spring mvc 返回json数据时可能导致乱码,需要在controller中添加如下代码: @RequestMapping("/test" ...
- 如何用Java类配置Spring MVC(不通过web.xml和XML方式)
DispatcherServlet是Spring MVC的核心,按照传统方式, 需要把它配置到web.xml中. 我个人比较不喜欢XML配置方式, XML看起来太累, 冗长繁琐. 还好借助于Servl ...
- Spring MVC重定向和转发以及异常处理
SpringMVC核心技术---转发和重定向 当处理器对请求处理完毕后,向其他资源进行跳转时,有两种跳转方式:请求转发与重定向.而根据要跳转的资源类型,又可分为两类:跳转到页面与跳转到其他处理器.对于 ...
- Spring MVC入门
1.什么是SpringMvc Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面.Spring 框架提供了构建 Web 应用程序的全功能 M ...
随机推荐
- linux内核源码编译加制作rpm包
本章主要讲解实际操作步骤,具体理论知识可以自行百度 linux内核官网下载:https://cdn.kernel.org/pub/linux/kernel/ (如图) 根据官网发布的信息分析,目前 ...
- webstrom配置ES6 file watch没有生效
参考了文章https://www.cnblogs.com/kiimi/p/8663467.html设置后,依然没有看到编译后的文件,然后设置了输出文件夹为当前项目,再重启webstrom就看到了--
- CF79D 题解
题解 传送门 你有 \(n\) 个灯泡,一开始都未点亮. 同时你有 \(l\) 个长度,分别为 \(a_1 \sim a_l\). 每次你可以选择一段连续的子序列,且长度为某个 \(a_i\),并将这 ...
- Linux详解
什么是操作系统?1.操作系统:(Operating System,OS)是计算机系统中的一个系统软件,它们管理和控制计算机系统中的硬件及软件资源,为用户提供一个功能强大.使用方便的和可扩展的工作环境. ...
- vue仿QQ聊天室|vue聊天实例,直播聊天室
图片压缩 百亿站点 基于vue2.0+vue-cli+vuex+vue-router+webpack+es6+wcPop等技术开发的仿微信聊天界面|仿微信聊天室vue-chatRoom,实现了微信聊天 ...
- vue引入swiper的报错以及swiper在vue中的交互事件处理
安装遇到找不到 css的问题,百度查了一些帖子也不行,可能是swiper 升级6.0后的一些变化导致 安装成功的帖子:转载于:https://www.jianshu.com/p/0150d2ee109 ...
- Qframework UIKit
用QFramework的UIKit 功能很容易实现UI模块的MVC功能,但MVC模式构造起来还是会有些繁琐, 两个相互直接的UIElement 之间的一些数据传输和调用都要用Msg通过UIPanel ...
- heap 算法函数
这一系列函数是在做 这道题 时发现的 这道题空间卡的很死,是不能用数组存下所有数字进行快排的 后来又尝试用 \(multiset\) 优化空间,发现不行,可能是 \(multiset\) 还有结构性存 ...
- Linux 服务器配置。
关于防火墙 1.首先不管防火墙有没有关 都使用systemctl stop firewalld 关闭防火墙 2.然后使用 yum install iptables-services 安装或更新服务 3 ...
- APP性能测试——首次启动耗时测试
首次启动耗时: 即第一次安装(清除数据也可以),打开软件,直到进入到首页activity页面,并计算耗时. 示例代码: import os import time # 测试首次启动时间 # 创建App ...