文章目录基于尚硅谷 B 站视频 BV1Ry4y1574R 配套笔记改写
- 基本使用
- 配置方式
- 访问页面
- 过程总结
- @RequestMapping 注解
- 使用位置
- value 属性
- 模糊匹配路径
- 路径中的占位符(@PathVariable 注解)
- method 属性
- params 属性
- headers 属性
- 获取请求参数
- ServletAPI 获取
- 控制器方法的形参获取
- @RequestParam 注解
- @RequestHeader 注解 @CookieValue 注解
- JavaBean 对象获取请求参数
- 解决请求参数的乱码问题
- 用域对象共享数据
- ServletAPI 用法
- ModelAndView 用法
- Map、Model、ModelMap 等用法
- 向 session 域或 Application 域共享数据
- 视图
- ThymeleafView 视图
- InternalResourceView 转发视图
- RedirectView 重定向视图
- 视图控制器 view-controller
- 视图解析器 InternalResourceViewResolver(使用 jsp 页面)
- RESTFul 风格
- URL 地址
- HiddenHttpMethodFilter 发送 put 和 delete 请求
- SpringMVC Thymeleaf Vue RESTFul 风格案例
- 准备 JavaBean DAO
- 功能清单
- 访问首页
- 查询所有数据
- 删除数据
- 跳转到添加数据页面
- 保存数据
- 跳转到更新数据页面
- 更新数据
- HttpMessageConverter 报文信息转换
- @RequestBody 注解
- RequestEntity 类
- @ResponseBody 注解
- 响应 Java 对象转换为的 JSON 格式字符串
- SpringMVC 和 Axios 处理 Ajax
- @RestController 注解
- ResponseEntity 类
- 文件上传和下载
- 文件下载
- 文件上传
- 拦截器
- 拦截器的配置
- 拦截器的三个处理方法
- 多个拦截器的执行顺序
- 异常处理器
- 基于配置的异常处理
- 基于注解的异常处理
- 注解配置
- 创建初始化类,代替 web.xml
- 创建 SpringConfig 配置类,代替 spring 的配置文件
- 创建 WebConfig 配置类,代替 SpringMVC 的配置文件
- 常用组件和执行流程
- 常用组件
- 执行流程
创建 maven 项目,在 pom.xml 文件中引入相关依赖。
org.springframework
spring-webmvc
5.3.21
org.thymeleaf
thymeleaf-spring5
3.0.15.RELEASE
在 resources 目录下创建 Spring 配置文件。
在 web.xml 文件中配置前端控制器 DispatcherServlet 和 Spring 配置文件。
根据 Servlet 生命周期,第一次请求时会访问 Servlet 的 init 初始化方法。
类路径 classpath
指的是编译后路径:本项目[或模块目录]/target/[项目或模块名]/WEB-INF/classes
项目中 java 目录下的文件和 recources 目录下的文件都在类路径下。
SpringMVC 基于原生的 Servlet,通过功能强大的前端控制器 DispatcherServlet,对请求和响应进行统一处理。
标签中使用 / 和 path
匹配 0 或者任意数量的字符** ** /antpath 匹配 0 或者更多的目录 路径中的占位符(@PathVariable 注解)
- /ant 的形式是固定的,不能更改。
SpringMVC 支持使用路径中的占位符 {}。当浏览器把某些数据通过路径的方式发送给控制器方法时,在相应方法 @RequestMapping 注解的 value 属性中通过路径占位符表示传输的数据名称,再通过==@PathVariable 注解,将占位符所表示的数据赋值给控制器方法的形参。==
测试路径中的占位符@RequestMapping("/testPath/{id}/{username}") public String testPath // 注解将占位符 { } 所表示的数据赋值给控制器方法的形参 (@PathVariable("id") Integer id, @PathVariable("username") String username) { System.out.println("id = " + id + " username = " + username); return "success"; }method 属性@RequestMapping 注解的 value 属性用于设置支持的请求方式。这一属性是枚举的常量数组,表示一个注解可以支持多种请求方式。请求地址符合注解的 value 属性值,并且请求方式符合 method 属性值,请求才能成功。如果不设置 method 属性的值,则默认支持 get 和 post 请求方式。
@RequestMapping(value = "/method", // 一个注解可以支持多种请求方式(默认设置,可以不写) method = {RequestMethod.GET, RequestMethod.POST}) public String success() { return "success"; }对于处理指定请求方式的控制器方法,SpringMVC 中提供了 @RequestMapping 的派生注解,其作用相当于添加了一个 method 属性的值。
// @RequestMapping 的派生注解 @GetMapping("/testGetMapping") public String testGetMapping() { return "success"; }浏览器支持发送的请求方式有 get 和 post。若在 form 表单提交时,为表单的 method 属性设置了其他请求方式的属性值,则按默认请求方式 get 处理。
// 使用该控制器方法会报错,提示不支持 get 请求方式 @RequestMapping(value = "/testPut", method = RequestMethod.PUT) public String testPut() { return "success"; }params 属性@RequestMapping 注解的 params 属性用于限定请求的参数。这一属性是字符串数组,一个注解可以限定多个请求参数,参数符合所有 params 属性值的限定,请求才能成功。
限定请求参数的四种表达式及含义
表达式 含义 param 限定请求必须带有 param 参数 param 限定请求必须不带 param 参数 param=value 限定请求必须带有 param 参数且参数值为 value param!=value 限定请求必须带有 param 参数但参数值不为 value 测试 params 属性// 使用该控制器方法失败 @RequestMapping(value = "/testParamsAndHeaders", params = {"username", "password!=123"}) // 同时限定两个参数 public String testParamsAndHeaders() { return "success"; }headers 属性@RequestMapping 注解的 headers 属性用于限定请求头的信息,用法与 params 属性相似,也有限定信息的四种表达式。这一属性是字符串数组,一个注解可以限定多个请求头信息,请偷偷信息符合所有 headers 属性值的限定,请求才能成功。
@RequestMapping(value = "/testParamsAndHeaders", params = {"username", "password=123"}, headers = {"Host=localhost:9372"}) // 限定请求头信息 public String testParamsAndHeaders() { return "success"; }获取请求参数 ServletAPI 获取查看请求头信息
在浏览器按 F12 进入开发者界面,然后访问网页,再选择网络下的标头,找到请求标头。
将 HttpServletRequest 类对象作为控制器方法的形参,此时该形参表示封装了当前请求报文的对象。通过 ServletAPI 获取请求参数的方式是原生的,已经通过 SpringMVC 封装,不建议使用。
测试使用 Servlet API 获取请求参数
@RequestMapping("/testServletAPI") // 形参位置的 request 表示当前请求 public String testServletAPI(HttpServletRequest request) { String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println("username = " + username + " password = " + password); return "success"; }控制器方法的形参获取控制器方法中设置和请求参数同名的形参,当浏览器发送请求,使用该控制器方法时,请求参数会被赋值给相应的形参。
多个同名的请求参数
可以在控制器方法的形参中设置字符串数组或者字符串的形参接收此请求参数。
- 若使用字符串数组的形参,此参数的数组中包含每一个数据。
- 若使用字符串的形参,此参数的值为数据间使用逗号拼接的结果。
@RequestMapping("/testParam") public String testParam // 与请求参数同名的形参 (String username, String password, String[] hobby) // 可以用 String hobby,输出 java,c++,js { System.out.println("username = " + username + " password = " + password + " hobby = " + Arrays.toString(hobby)); return "success"; }@RequestParam 注解@RequestParam 注解用于在请求参数和控制器方法的形参件建立映射关系。
属性 作用 value 或 name 指定为形参赋值的请求参数的参数名。 defaultValue 当 value 属性值所指定的请求参数没有传输或传输的值为 “” 时,则使用该属性值作为默认值为形参赋值。 required 设置是否必须传输此请求参数,默认值为 true。
- required 属性值为 true 时,若没有传输该请求参数,且没有设置 defaultValue 属性值,则页面报错。
- required 属性值为 false 时,若没有传输 value 属性值所指定的请求参数,则注解所标识的形参的值为 null。
用户名:
@RequestMapping("/testParam") public String testParam // 形参与请求参数建立映射关系,且不一定传输请求参数值 (@RequestParam(value = "user_name", required = false, defaultValue = "default") // 形参默认值 String username, String password, String[] hobby)@RequestHeader 注解 @CookieValue 注解@RequestHeader 注解用于在请求参数和控制器方法的形参间建立映射关系。
@CookieValue 注解用于在 cookie 数据和控制器方法的形参间映射关系。
这两个注解的用法与 @RequestParam 注解相似。
@RequestMapping("/testParam") public String testParam (@RequestHeader(defaultValue = "localhost:8080") String host, @CookieValue(value = "Idea-ab16e683") String idea, // IDEA 的 cookie // session 的 cookie,不创建 session 是没有的 @CookieValue(value = "JSESSIONID", required = false) String session) { System.out.println("host = " + host + " idea = " + idea + " session = " + session); return "success"; }JavaBean 对象获取请求参数控制器方法的形参中设置 JavaBean 的形参,当浏览器传输请求参数的参数名和 JavaBean 中的属性名相同时,请求参数会为属性赋值。
@RequestMapping("/testBean") public String testBean(User user) // 请求参数会为 user 的属性赋值 { System.out.println(user); return "success"; }解决请求参数的乱码问题解决请求参数的乱码问题,可以使用 SpringMVC 提供的编码过滤器 CharacterEncodingFilter,但要在 web.xml 文件中进行配置,且一定要配置在其他过滤器之前,否则无效。
HiddenHttpMethodFilter 发送 put 和 delete 请求characterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 forceRequestEncoding true characterEncodingFilter @RequestMapping(value = "/user", method = RequestMethod.GET) public String getUsers() { System.out.println("查询所有用户信息"); return "success"; } @GetMapping("/user/{id}") public String getUserById() { System.out.println("根据 id 查询用户信息"); return "success"; } @PostMapping("/user") public String addUser(String username, String password) { System.out.println("添加用户信息:" + "username = " + username + " password = " + password); return "success"; } 浏览器只支持发送 get 和 post 请求,但通过 SpringMVC 提供的 HiddenHttpMethodFilter 可以把 post 请求转换为 delete 或 put 请求。 在 web.xml 文件中配置该过滤器就可以使用,注意其映射必须配置在 CharacterEncodingFilter 的映射之后,否则可能会有乱码。
HiddenHttpMethodFilter 转换到 put 和 delete 请求的条件:
- 请求方式必须设置为 post。
- 请求必须传输请求参数 _method,参数值为 put 或 delete。
常用组件和执行流程 常用组件hiddenHttpMethodFilter org.springframework.web.filter.HiddenHttpMethodFilter characterEncodingFilter @Configuration //扫描组件 @ComponentScan("com.insight.mvc.controller") //开启 MVC 注解驱动 @EnableWebMvc public class WebConfig implements WebMvcConfigurer { // 处理静态资源 @Override public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) { configurer.enable(); } // 配置拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { TestInterceptor testInterceptor = new TestInterceptor(); registry.addInterceptor(testInterceptor).addPathPatterns("/**"); } // 配置视图控制器 @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); } // 文件上传解析器 @Bean public MultipartResolver multipartResolver() { return new CommonsMultipartResolver(); } // 异常处理 @Override public void configureHandlerExceptionResolvers (List resolvers) { SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver(); Properties properties = new Properties(); //设置异常映射 properties.setProperty("java.lang.ArithmeticException", "error"); exceptionResolver.setExceptionMappings(properties); //设置共享异常信息的键 exceptionResolver.setExceptionAttribute("exception"); resolvers.add(exceptionResolver); } // 配置生成模板解析器 @Bean public ITemplateResolver templateResolver() { WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext(); // ServletContextTemplateResolver 需要 ServletContext 作为构造参数 // 可通过 WebApplicationContext 的方法获得 ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver (webApplicationContext.getServletContext()); templateResolver.setPrefix("/WEB-INF/templates/"); templateResolver.setSuffix(".html"); templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setTemplateMode(TemplateMode.HTML); return templateResolver; } // 生成模板引擎并为模板引擎注入模板解析器 @Bean public SpringTemplateEngine templateEngine (ITemplateResolver templateResolver) { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver); return templateEngine; } // 生成视图解析器并为解析器注入模板引擎 @Bean public ViewResolver viewResolver (SpringTemplateEngine templateEngine) { ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setCharacterEncoding("UTF-8"); viewResolver.setTemplateEngine(templateEngine); return viewResolver; } } 执行流程
- DispatcherServlet:前端控制器,由框架提供。作用:统一处理请求和响应,作为整个流程控制的中心,调用其它组件处理用户的请求。
- HandlerMapping:控制器的映射器,由框架提供。作用:根据请求的 url、method 等信息查找控制器方法。
- Handler:控制器,由工程师编写。作用:在 DispatcherServlet 的控制下的控制器对具体的用户请求进行处理。
- HandlerAdapter:处理器适配器,由框架提供。作用:执行控制器方法。
- ViewResolver:视图解析器,由框架提供。作用:进行视图解析,得到相应的视图。
- View:视图。作用:将模型数据通过页面展示给用户。
用户向服务器发送请求,请求被 SpringMVC 的前端控制器 DispatcherServlet 捕获。
DispatcherServlet 对请求 URL 进行解析,得到请求资源标识符(URI),判断 URI 对应的映射是否存在。
不存在。判断是否配置了 mvc:default-servlet-handler。
如果有配置,则访问目标资源(一般为静态资源,如:JS,CSS,HTML)。如果没配置,则会报错,请求失败。
如果存在,则执行以下流程:
根据该 URI,调用 HandlerMapping 获得该 Handler 配置的所有相关的对象(包括Handler 对象以及 Handler 对象对应的拦截器),最后以 HandlerExecutionChain 执行链对象的形式返回。
DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter。
如果成功获得 HandlerAdapter,此时将开始执行拦截器的 preHandler 方法。(正序)
提取 Request 中的模型数据,赋值 Handler 形参,开始执行 Handler(Controller) 方法,处理请求。 在赋值 Handler 的形参过程中,根据配置,Spring 将做一些额外的工作:
a)HttpMessageConveter:将请求消息(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的响应信息。
b)数据转换:对请求消息进行数据转换。如 String 转换成 Integer、Double 等。
c)数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。 d)数据验证:验证数据的有效性(长度、格式等),验证结果存储到 BindingResult 或Error 中。
Handler 执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象。
此时将开始执行拦截器的 postHandle 方法。(逆序)
根据返回的 ModelAndView(此时会判断是否存在异常,HandlerExceptionResolver 对存在的异常进行处理)选择一个适合的 ViewResolver 进行视图解析,根据 Model 和 View 来渲染视图。
渲染视图完毕后,执行拦截器的 afterCompletion 方法。(逆序)
将渲染结果返回给客户端。



