🎨 MVC设计模式
MVC 是一种常见的软件设计模式,用于分离应用程序的不同部分以实现松散耦合和高内聚性。MVC 模式由三个核心组件组成:
- 模型(Model):表示应用程序的数据和业务逻辑。模型处理应用程序的数据,并根据控制器的指令执行相应的操作。
- 视图(View):提供模型数据的用户界面。视图通常是模板、HTML 页面、XML 文件或其他格式,可以呈现模型数据给用户。
- 控制器(Controller):处理用户交互并更新模型和视图。控制器负责接收来自视图的用户输入,对模型进行相应的操作,并更新视图以反映更改。
MVC 模式的优点是可以将代码分离成三个独立的组件,使得应用程序更易于维护和扩展。例如,如果要更改视图的外观,可以修改视图而不影响模型和控制器;如果要更改数据存储方式,可以修改模型而不影响视图和控制器。同时,MVC 模式还有助于降低应用程序中的耦合度,使得各组件更加独立和可重用。
🌐 SpringMVC模块
📖 概述
- Spring MVC 是非常著名的 Web 应用框架,现在的大多数 Web 项目都采用 Spring MVC。它与 Spring 有着紧密的关系。是 Spring 框架中的模块,专注 Web 应用,能够使用 Spring 提供的强大功能,IOC、AOP 等。
- Spring MVC 框架底层是基于 Servlet 技术。遵循 Servlet 规范,Web 组件 Servlet、Filter、Listener 在 Spring MVC 中都能使用。同时 Spring MVC 也是基于 MVC 架构模式的,职责分离,每个组件只负责自己的功能,组件解耦。
- Spring Boot 的自动配置、按约定编程极大简化,提高了 Web 应用的开发效率。
🔄 响应流程
<div align=“center”> <img src=“88a9f433929f4bce5f8cfc4a0b9d48b5.png” alt=“SpringMVC响应流程” width=“82%"> </div>
大体流程:请求到控制器(controller),经过业务模型(model)处理后返回响应给视图层。
具体流程:
- 客户端请求:用户通过浏览器发送 HTTP 请求,所有请求都被 DispatcherServlet 接收。
- 执行拦截器的
preHandle():如果配置了拦截器,Spring MVC 会首先执行preHandle()方法。如果返回false,请求处理终止;否则,继续处理。 - 请求映射:
DispatcherServlet根据配置的处理器映射器(HandlerMapping)查找与请求 URL 对应的控制器Controller。 - 调用控制器方法:找到控制器后,
DispatcherServlet将使用HandlerAdapter来调用Controller的处理方法。转发给对应的控制器方法进行处理。控制器方法处理业务逻辑后,通常返回一个ModelAndView对象,包含数据模型和视图名称。 - 执行拦截器的
postHandle():如果返回视图,拦截器的postHandle()方法会在视图渲染之前执行。对于 JSON 响应,该方法仍然会执行。 - 视图解析:
DispatcherServlet根据控制器返回的视图名称,使用视图解析器(ViewResolver)将逻辑视图名称解析为实际的视图。 - 视图渲染返回:视图渲染引擎根据数据模型渲染视图,并将生成的 HTML 响应返回给客户端。
🏗️ 结构组件
🎮 控制器controller
控制器是一种由 Spring 管理的 Bean 对象,赋予角色是"控制器”。
作用:处理请求,接收浏览器发送过来的参数,将数据或视图应答给浏览器或者客户端 App 等。
具体实现:一个 Java 类,使用 @Controller 或 @RestController。
{{<notice tip>}}
@Controller 和 @RestController 注解的区别:
@RestController包含了@Controller的功能,同时加入了@ResponseBody的注解。- 表示当前控制器类中的方法,都会默认加入
@ResponseBody的功能。方法的返回值是数据可以通过 HttpServletResponse 输出给浏览器。
{{</notice>}}
接收请求
-
@RequestMapping:用于将 Web 请求映射到控制器类的方法。此方法处理请求。可用作在类上或方法上。在类上和方法上同时使用。1 2 3@RequestMapping(value = "/updateProduct",method = RequestMethod.POST) public Result<String> updateProduct(@RequestParam MultipartFile file, @RequestParam String dname, @RequestParam String tname, @RequestParam String content,@RequestParam String olddname)- Value:别名 path 表示请求的 URI,在类和方法上同时使用 value,方法上的继承类上的 value。
- method:请求方式,支持 GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE。值为:RequestMethod[] method(),RequestMethod 是 enum 类型。
-
快捷注解:
@GetMapping:表示 get 请求方式的@RequestMapping@PostMapping:表示 post 请求方式的@RequestMapping@PutMapping:表示 put 请求方式的@RequestMapping@DeleteMapping:表示 delete 请求方式的@RequestMapping
接收请求参数
-
@RequestParam:把请求中的指定名称的参数传递给控制器中的形参赋值。- value 属性值指定请求中的参数。
- required 属性指定请求中的参数是否必须,默认为 true,如果加上 required=false,没对应上则不会报错,而是获取值为 null。
- 如果参数前不写
@RequestParam(xxx)的话,那么就前端可以有可以没有对应的参数名字都行,如果有参数名的话,那么就会自动匹配;没有的话,请求也能正确发送。
-
HttpServletRequest 对象
- 使用
HttpServletRequest对象接收参数,request.getParameter("XXX")获取对应的值,这是原始的JavaWeb中的方式。
- 使用
-
@RequestBody:主要用来接收前端传递给后端的 json 字符串中的数据的(通常 json 字符串放在请求体中)。GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。- 在后端的同一个接收方法里,
@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。 - 如果后端参数是一个对象,且该参数前是以
@RequestBody修饰的,那么前端传递 json 参数时,必须满足以下要求:后端@RequestBody注解对应的类在将 HTTP 的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,会根据 json 字符串中的 key 来匹配对应实体类的属性,如果匹配一致且 json 中的该 key 对应的值符合(或可转换为)实体类的对应属性的类型要求时,会调用实体类的 setter 方法将值赋给该属性。
-
@RequestHeader:从请求头中获取某些值。1 2 3 4 5 6 7 8 9 10 11 12import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { @GetMapping("/greet") public String greet(@RequestHeader("User-Agent") String userAgent) { return "Hello! You are using " + userAgent; } }
返回值
- 不使用
@ResponseBody的 String 返回值,返回的是一个页面视图。 - 使用
@ResponseBody的 String 返回值,返回的是一个 JSON 数据。 - 返回
ModelAndView,返回的是一个视图其中包含数据。(最后数据都是放到 Request 中的) - 返回自定义的对象,默认的返回格式是 json 字符串(有 jackson 工具)。
- 返回 Map,默认的返回格式是 json 字符串(有 jackson 工具)。
- 返回
ResponseEntity:包含数据和自定义的 HttpStatus Code。(默认转为 json 格式的字符串)
💾 模型 Model
- 在许多实际项目需求中,后台要从控制层直接返回前端所需要的数据,这时 Model 大家族就派上用场了。
- Model 是 Spring MVC 中的 “M”,是用来传输数据的。从控制层直接返回数据给前端。内置的 JSP,模板技术能够展现 Model 中存储的数据。
- Model 可以是承载数据的,也可以是处理具体业务的类,这些都是指 Spring MVC 中的 Model。
🖼️ 视图 View
- Spring MVC 中的 View(视图)用于展示数据的,视图技术的使用是可插拔的。无论选择使用 thymleaf、jsp 还是其他技术,classpath 有 jar 就能使用视图了。开发者主要就是更改配置。SpringBoot3 不推荐使用 FreeMarker、JSP 这些了。建议使用 Thymeleaf。
🎯 SpringMVC的核心组件
-
DispatcherServlet:核心的中央处理器,负责接收请求、分发,并给予客户端响应。- 当客户端发送请求时,
DispatcherServlet会先接收请求。 - 然后,它会根据请求 URL 通过
HandlerMapping找到合适的处理器(Controller)。 - 处理完请求后,它会根据
ViewResolver找到对应的视图,将处理结果发送回客户端。
- 当客户端发送请求时,
-
HandlerMapping:处理器映射器,根据 URL 去匹配查找能处理的Handler,并会将请求涉及到的拦截器和Handler一起封装。 -
HandlerAdapter:处理器适配器,根据HandlerMapping找到的Handler,适配执行对应的Handler; -
Handler:请求处理器,处理实际请求的处理器。- 接收来自
DispatcherServlet的请求,处理业务逻辑,并将处理结果返回给视图层。
- 接收来自
-
ViewResolver:视图解析器,根据Handler返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给DispatcherServlet响应客户端。- 根据控制器返回的视图名称找到对应的视图文件。
-
ModelAndView:控制器返回的对象,包含模型数据和视图名称。模型部分包含业务数据,视图部分指定渲染该数据的视图。 -
HandlerInterceptor:在请求处理的各个阶段(如控制器方法执行前后)进行拦截。它可以用于实现日志记录、权限验证等功能。
🔧 SpringBoot框架中对SpringMVC框架的集成
- 自动配置:SpringBoot 会自动配置一个嵌入式的 Servlet 容器(如 Tomcat),并为我们提供默认的 SpringMVC 配置。这样我们无需手动配置 Servlet 容器和 SpringMVC,只需添加相应的依赖即可快速搭建一个 Web 应用。
- 视图解析器:SpringBoot 默认使用 Thymeleaf 作为视图解析器,如果需要更换其他视图解析器,可以在 pom.xml 中修改对应的依赖。
- 静态资源处理:SpringBoot 默认会处理静态资源(如 HTML、CSS、JavaScript 等),并将其放在项目的 /static 或 /public 目录下。如果需要自定义静态资源的处理方式,可以通过编写一个类实现 WebMvcConfigurer 接口,并重写 addResourceHandlers 方法来实现。
- 拦截器:SpringBoot 支持自定义拦截器,可以通过实现 HandlerInterceptor 接口来创建拦截器,同时编写一个类实现 WebMvcConfigurer 接口,并重写 addInterceptors 方法来实现。
- 异常处理:SpringBoot 默认使用 WhitelabelErrorView 来处理异常,如果需要自定义异常处理方式,可以通过编写一个类实现 ErrorController 接口,并重写 errorHtml 方法来实现。
- 参数绑定:SpringBoot 支持多种参数绑定方式,如
@RequestParam、@PathVariable、@RequestBody等。如果需要自定义参数绑定方式,可以通过编写一个类实现 MethodArgumentResolver 接口,并重写 resolveArgument 方法来实现。 - 跨域支持:SpringBoot 默认支持 CORS 跨域请求,如果需要自定义跨域配置,可以通过编写一个类实现 WebMvcConfigurer 接口,并重写 addCorsMappings 方法来实现。
⚙️ Spring Boot中配置Spring MVC
📝 配置方法
因为 Spring Boot 自动装配机制的存在,一般来说我们不需要对 Spring MVC 进行配置,如果要进行特别定制化的配置,Spring Boot 也支持配置文件或者编写代码的两种方式来进行配置。
🔧 方法一:修改application.yml
可以通过修改 application.yml 的 spring.mvc 属性来修改 SpringBoot 对 SpringMVC 的默认配置。
|
|
💻 方法二:编写一个被注解@WebMvcConfiguration修饰的Java配置类
WebMvcConfigurer 接口是 Spring 提供的一个用于自定义 Spring MVC 配置的接口,主要提供了 WebMvcConfigurer 接口是 Spring 提供的一个用于自定义 Spring MVC 配置的接口,主要提供了多个回调方法,包括添加或修改 Spring MVC 的配置,如添加拦截器,自定义消息转换器等。具体来说,WebMvcConfigurer 接口的主要方法包括:
- configurePathMatch:此方法用于配置路由请求规则。
- configureContentNegotiation:该方法用于内容协商配置。
- configureAsyncSupport:该方法用于异步支持配置。
- configureDefaultServletHandling:该方法用于配置默认静态资源处理器。
- addFormatters:此方法用于注册自定义转化器。
- addInterceptors:此方法用于拦截器配置。
- addResourceHandlers:此方法用于资源处理。
- addCorsMappings:此方法用于 CORS 配置。
在使用时,只需要实现 WebMvcConfigurer 接口,重写上述的方法即可完成自定义配置。
|
|
{{<notice tip>}}
-
使用 Springboot 框架对 SpringMVC 的默认设置:直接编写控制器逻辑。
-
手动设置 SpringMVC 的部分功能,定义 MVC 的底层组件:@Configuration + 配置 WebMvcConfiguration,不要使用 @EnableWebMvc。
-
手动设置 SpringMVC 的所有功能:@Configuration + 配置 WebMvcConfiguration + @EnableMvc。
使用 @EnableWebMvc 会完全覆盖 SpringBoot 对 SpringMVC 的自动配置,因此如果使用了 @EnableWebMvc,就需要自己配置 Spring MVC 的全部内容,包括视图解析器、资源处理、异常处理等。通常情况下,只有在需要非常精细的控制 Spring MVC 配置时才会使用 @EnableWebMvc。
{{</notice>}}