赞
踩
Version 5.3.30-SNAPSHOThttps://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html#mvc-servlet-config
Spring Web MVC是基于Servlet API的原始Web框架,从一开始就包含在Spring框架中。其正式名称“Spring Web MVC”来自其源模块(Spring -webmvc)的名称,但更常见的名称是“Spring MVC”。
与Spring Web MVC并行,Spring Framework 5.0引入了一个响应式堆栈Web框架,其名称“Spring WebFlux”也是基于其源模块(Spring - WebFlux)。
在挖掘Spring Web MVC之前,我们需要先搞清两个概念:MVC模式和前端控制器模式。
MVC是一种软件设计模式。MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。
我们创建Car模型对象,CarView是将Car信息打印在控制台的视图类,CarController负责存储模型数据到该控制器类并把相应的模型信息更新到CarView视图。
Car
package com.example.demo.mvc;
/**
* @Author yrz
* @create 2023/7/27 14:10
* @Description TODO
*/
public class Car {
public Car() {
}
public Car(String plateNo, String color) {
this.plateNo = plateNo;
this.color = color;
}
/**
* 车牌
*/
private String plateNo;
/**
* 车颜色
*/
private String color;
public String getPlateNo() {
return plateNo;
}
public void setPlateNo(String plateNo) {
this.plateNo = plateNo;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
CarView
package com.example.demo.mvc;
/**
* @Author yrz
* @create 2023/7/27 14:14
* @Description TODO
*/
public class CarView {
public void printCarInfo(Car car){
System.out.println(car.getPlateNo() + " " + car.getColor());
}
}
CarController
package com.example.demo.mvc;
/**
* @Author yrz
* @create 2023/7/27 14:16
* @Description TODO
*/
public class CarController {
private Car car;
private CarView carView;
public CarController(Car car, CarView carView) {
this.car = car;
this.carView = carView;
}
public void setCarPlateNo(String plateNo){
car.setPlateNo(plateNo);
}
public void setCarColor(String color){
car.setColor(color);
}
public void updateCarView(){
carView.printCarInfo(car);
}
}
MVCPatternDemo
package com.example.demo.mvc;
/**
* @Author yrz
* @create 2023/7/27 14:19
* @Description TODO
*/
public class MVCPatternDemo {
public static void main(String[] args) {
Car car = new Car("冀E6666", "红色");
CarView carView = new CarView();
CarController carController = new CarController(car, carView);
carController.updateCarView();
car.setColor("蓝色");
carController.updateCarView();
}
}
常见的基于MVC框架的B/S架构应用软件中,前端(Client Side)和后端(Server Side)负责不同的任务和职责。
用户交互:前端处理用户的输入和交互,例如接收用户的点击、输入和操作,并相应地更新视图。
前端控制器模式(Front Controller Pattern)是一种软件设计模式,用于构建 Web 应用程序的请求处理流程。它提供了一个中心化的组件,即前端控制器,用于集中处理所有的请求,并根据请求的类型和内容来调度相应的处理程序。
在前端控制器模式中,所有的请求都先经过前端控制器,然后根据请求的信息,分发给适当的处理程序来执行实际的处理逻辑。这种集中式的请求处理可以带来以下一些好处:
中心化的请求处理:前端控制器作为应用程序的入口点,负责接收和处理所有的请求。这种集中化的处理方式简化了请求分发和处理的逻辑,提高了代码的可维护性和重用性。
统一的请求处理:通过前端控制器,可以实现对请求的统一处理。例如,可以在前端控制器中进行身份验证、请求日志记录、异常处理等共同的处理步骤,避免在每个处理程序中重复编写相同的代码。
支持多样化的请求处理策略:前端控制器可以根据请求的类型、内容或其他标识来动态选择适当的处理程序。这种灵活性使得系统能够根据不同的请求需求进行定制化的处理,提升系统的可扩展性和适应性。
支持复杂的请求分发和路由:前端控制器可以根据请求的路由信息将请求分发给不同的处理程序。这种灵活的请求分发机制可以支持复杂的请求路由策略,如基于 URL、请求参数、请求头等进行路由和分发。
总的来说,前端控制器模式通过引入一个中心化的前端控制器组件,将请求的分发和处理集中在一个地方,提供了一种结构化和可扩展的方式来处理和管理 Web 应用程序的请求流程。它可以简化代码结构,提高代码复用性,并支持灵活的请求处理策略。
前端控制器设计模式(Front Controller Pattern)是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理。该处理程序可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。以下是这种设计模式的实体。
前端控制器+调度器=MVC中的Controller
我们将创建 FrontController、Dispatcher 分别当作前端控制器和调度器。HomeView 和 StudentView 表示各种为前端控制器接收到的请求而创建的视图。
FrontControllerPatternDemo,我们的演示类使用 FrontController 来演示前端控制器设计模式。
HomeView
public class HomeView {
public void show(){
System.out.println("Displaying Home Page");
}
}
StudentView
public class StudentView {
public void show(){
System.out.println("Displaying Student Page");
}
}
Dispatcher
public class Dispatcher {
private StudentView studentView;
private HomeView homeView;
public Dispatcher(){
studentView = new StudentView();
homeView = new HomeView();
}
public void dispatch(String request){
if(request.equalsIgnoreCase("STUDENT")){
studentView.show();
}else{
homeView.show();
}
}
}
FrontController
public class FrontController {
private Dispatcher dispatcher;
public FrontController(){
dispatcher = new Dispatcher();
}
private boolean isAuthenticUser(){
System.out.println("User is authenticated successfully.");
return true;
}
private void trackRequest(String request){
System.out.println("Page requested: " + request);
}
public void dispatchRequest(String request){
//记录每一个请求
trackRequest(request);
//对用户进行身份验证
if(isAuthenticUser()){
dispatcher.dispatch(request);
}
}
}
FrontControllerPatternDemo
public class FrontControllerPatternDemo {
public static void main(String[] args) {
FrontController frontController = new FrontController();
frontController.dispatchRequest("HOME");
frontController.dispatchRequest("STUDENT");
}
}
Servlet:(尤指 Java 语言中在服务器上运行的)小型应用程序;小服务程序
Servlet API 是用于开发基于 Java 的 Web 应用程序的标准 API(https://jakarta.ee/specifications/servlet/)。它提供了一组接口和类,用于处理 HTTP 请求和响应,并支持开发动态、可扩展的 Web 应用程序。下面是一些常用的 Servlet API 接口和类:
javax.servlet.Servlet
:所有 Servlet 类都必须实现的接口,定义了 servlet 的生命周期方法和服务方法。
javax.servlet.http.HttpServlet
:继承自 Servlet
接口的 HttpServlet 类,提供了用于处理 HTTP 请求的扩展方法,如 doGet()
、doPost()
等。
javax.servlet.ServletConfig
:表示 Servlet 的配置信息,包括初始化参数等。
javax.servlet.ServletContext
:表示 Servlet 的上下文,为 Servlet 提供共享的资源和信息。
javax.servlet.http.HttpServletRequest
:封装了客户端的 HTTP 请求信息,如请求 URI、请求参数、请求头等。
javax.servlet.http.HttpServletResponse
:封装了向客户端发送的 HTTP 响应信息,如响应状态码、响应头、输出流等。
javax.servlet.http.HttpSession
:用于在客户端和服务器之间跟踪会话状态,存储用户相关的数据。
javax.servlet.RequestDispatcher
:用于将请求转发给其他 Servlet 或 JSP 页面进行处理。
javax.servlet.Filter
:用于在请求到达 Servlet 之前或响应返回给客户端之前,对请求和响应进行预处理和后处理。
javax.servlet.annotation.WebServlet
:用于通过注解配置 Servlet。
以上仅是 Servlet API 中的一部分接口和类,Servlet API 还包含许多其他接口和类,用于处理会话管理、Cookie、文件上传下载、异步处理等。这些接口和类提供了构建 Web 应用程序所需的核心功能。
与许多其他web框架一样,Spring MVC是围绕前端控制器模式设计的,其中中心Servlet DispatcherServlet为请求处理提供共享算法,而实际工作由可配置的委托组件执行。这个模型是灵活的,并且支持不同的工作流。
DispatcherServlet和任何Servlet一样,需要通过使用Java配置或在web.xml中根据Servlet规范声明和映射。反过来,DispatcherServlet使用Spring配置来发现请求映射、视图解析、异常处理等所需的委托组件。
下面的Java配置示例注册并初始化DispatcherServlet,它由Servlet容器自动检测:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(context);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
这段代码是一个典型的实现了 WebApplicationInitializer
接口的类。它用于配置和初始化一个基于 Spring Web 的应用程序。
在 onStartup
方法中,主要完成以下几个任务:
创建并注册 Spring Web 应用程序的配置类:通过创建一个 AnnotationConfigWebApplicationContext
对象,并注册应用程序的配置类 AppConfig.class
,来告诉 Spring Web 如何配置和组装应用程序的相关组件。
创建并注册 DispatcherServlet:创建一个 DispatcherServlet
对象,将之前创建的 AnnotationConfigWebApplicationContext
对象作为参数传入。DispatcherServlet
是一个用于接收并处理所有请求的核心控制器。接着,利用 servletContext
对象的 addServlet
方法来注册 DispatcherServlet
,指定了 Servlet 名称为 “app”,并设置其加载顺序为 1。
配置 DispatcherServlet
的 URL 映射规则:通过调用 registration
对象的 addMapping
方法,将 “/app/*” 这个 URL 模式映射到刚刚创建的 DispatcherServlet
,这意味着所有以 “/app” 开头的请求都将由该 DispatcherServlet
来处理。
以上代码的作用是初始化和配置 Spring Web 应用程序。通过 WebApplicationInitializer
的实现类,我们可以自定义应用程序的启动行为,并按照需要进行各种配置操作,比如加载 Spring 配置、注册 Servlet、设置 URL 映射等。这种方式与传统的基于 web.xml 配置的方式相比,更加灵活且易于扩展。
在上面的代码中,AppConfig
是一个应用程序的配置类,用于配置和组装 Spring Web 应用程序的相关组件。具体来说,AppConfig
类通常会使用 @Configuration
注解进行标记,并且可能会使用其他注解来定义 Bean、拦截器、视图解析器等。
下面是一个示例的 AppConfig
类的实现,供参考:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example")
public class AppConfig implements WebMvcConfigurer {
// 配置视图解析器
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
// 配置静态资源
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
// 配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor());
}
// 配置请求处理器
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/about").setViewName("about");
}
// ...
}
在这个示例中,AppConfig
类使用了 @Configuration
注解来表明它是一个配置类。注解 @EnableWebMvc
启用了 Spring MVC 的自动配置,并同时允许我们进行一些自定义配置。
在 AppConfig
中,我们可以定义各种 Bean,比如视图解析器、拦截器等。示例中通过 viewResolver
方法定义了一个视图解析器,并设置了视图文件的前缀和后缀。configureDefaultServletHandling
方法用于配置处理静态资源的默认处理器。 addInterceptors
方法用于添加拦截器。addViewControllers
方法用于定义简单的请求处理器来处理特定的 URL 请求。
当然,实际开发中,根据项目需求,AppConfig
类的具体实现可能会有所不同。你可以根据项目的具体情况,定制 AppConfig
类的内容,包括定义其他的 Bean、配置数据源、事务等。
总之,AppConfig
类的作用是配置和组装 Spring Web 应用程序的相关组件,使得应用程序能够正确运行并提供所需的功能。
在 Spring Boot 项目中,通常不需要手动实现 WebApplicationInitializer
接口来配置 DispatcherServlet
。这是因为 Spring Boot 已经自动处理了这些配置,并提供了默认的配置方式。
Spring Boot 通过自动配置的方式,以约定大于配置的原则来简化和加速 Spring 应用程序的开发。它会自动检测项目中的依赖和文件结构,并根据约定为应用程序提供默认的配置和行为。
在 Spring Boot 中,通过添加依赖 spring-boot-starter-web
,框架会自动配置 DispatcherServlet
,并根据约定将它映射到根路径 “/”。Spring Boot 会自动加载并初始化 DispatcherServlet
,并自动配置一些默认的处理器、视图解析器、异常处理器等。
除了 DispatcherServlet
的自动配置,Spring Boot 还提供了其他许多自动配置的功能,如自动注册 Servlet、Filter、Listener,自动配置数据源、事务等。
如果需要自定义配置,Spring Boot 提供了各种方式来覆盖或扩展默认的配置。可以通过在应用程序的配置类中使用注解如 @EnableWebMvc
、@RequestMapping
来自定义 URL 映射规则和处理逻辑。也可以通过在 application.properties
或 application.yml
文件中配置自定义的属性来覆盖默认的配置。
Spring MVC 支持定义多个 DispatcherServlet
实例。每个 DispatcherServlet
实例都有自己独立的上下文和请求处理流程。
通常情况下,我们可以在一个 Spring MVC 应用程序中定义多个 DispatcherServlet
实例的场景包括:
处理不同 URL 模式的请求:如果我们希望将不同 URL 模式的请求分发给不同的处理器,可以为每个 URL 模式配置一个独立的 DispatcherServlet
实例。这样可以根据请求的 URL 来选择不同的处理逻辑。
多个 Web 应用程序的聚合:在某些情况下,我们可能需要将多个独立的 Web 应用程序聚合在一个父项目中。为了实现这种场景,我们可以为每个子应用程序配置一个独立的 DispatcherServlet
实例,以便独立处理每个子应用程序的请求。
使用不同的视图技术:如果我们需要在同一个应用程序中同时使用不同的视图技术(如 JSP、Thymeleaf、FreeMarker 等),可以为每种视图技术配置一个独立的 DispatcherServlet
实例。这样可以根据请求的视图技术选择相应的视图解析器和模板引擎。
需要注意的是,每个 DispatcherServlet
实例都需要在应用程序中具有唯一的名称,并配置独立的映射路径。可以通过在 web.xml
中进行配置,或者在 Spring Boot 中,通过在应用程序配置类中使用 @ServletComponentScan
注解来自定义 DispatcherServlet
实例。
总之,Spring MVC 提供了灵活的配置选项,允许我们在一个应用程序中定义多个独立的 DispatcherServlet
实例,以满足不同的需求和场景。
在 Spring Boot 的 Web 项目中,默认情况下会有两个 DispatcherServlet
实例。
主 DispatcherServlet
实例:默认映射路径为 “/*”,用于处理 Web 请求。这个实例是通过 @SpringBootApplication
注解自动创建的。它会加载应用程序的所有配置,并处理来自客户端的 Web 请求。
管理 DispatcherServlet
实例:默认映射路径为 “/actuator”,用于处理 Spring Boot 的管理端点请求。这个实例是由 Spring Boot 自动添加的,并提供了一系列的管理端点,用于监控和管理应用程序的运行状态。例如,可以通过 “/actuator/health” 端点来获取应用程序的健康状态。
这两个 DispatcherServlet
实例具有不同的映射路径,用于区分不同类型的请求。主 DispatcherServlet
处理一般的 Web 请求,而管理 DispatcherServlet
处理管理端点的请求。
需要注意的是,虽然默认情况下只有两个 DispatcherServlet
实例,但我们也可以自定义添加更多的 DispatcherServlet
实例,以适应特定的业务需求。
总结起来,在 Spring Boot 的 Web 项目中,默认情况下会有两个 DispatcherServlet
实例,一个用于处理一般的 Web 请求,另一个用于处理管理端点的请求。
DispatcherServlet需要一个WebApplicationContext(一个普通ApplicationContext的扩展)用于它自己的配置。WebApplicationContext有一个链接到ServletContext和它所关联的Servlet。它还绑定到ServletContext,这样应用程序就可以在需要访问WebApplicationContext时使用RequestContextUtils上的静态方法来查找它。
对于许多应用程序来说,只有一个单例WebApplicationContext就足够了。也可能有一种上下文层次结构,根WebApplicationContext在多个DispatcherServlet(或其他Servlet)实例之间共享,每个实例都有自己的子WebApplicationContext配置。
根WebApplicationContext通常包含基础设施bean,例如需要跨多个Servlet实例共享的数据存储库和业务服务。这些bean被有效地继承,并且可以在特定于Servlet的子WebApplicationContext中被重写(即重新声明),该子WebApplicationContext通常包含给定Servlet的本地bean。下图显示了这种关系:
结合2.1中的DispatcherServlet配置代码再看上面这张图,DispatcherServlet需要包含一个WebApplicationContext(AnnotationConfigWebApplicationContext),并定义Controllers、ViewResolver、HandlerMapping(AppConfig.class),这些实例组成DispatcherServlet上下文层次结构。
姑且这么理解吧|ू•ૅω•́)ᵎᵎᵎ
DispatcherServlet委托特殊的bean来处理请求并呈现适当的响应。所谓“特殊bean”,我们指的是实现框架契约的spring管理对象实例。它们通常带有内置契约,但您可以自定义它们的属性并扩展或替换它们。
下表列出了DispatcherServlet检测到的特殊bean:
Bean type | Explanation |
---|---|
HandlerMapping | 将一个请求映射到一个处理程序以及一个[拦截器]列表(https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html#mvc-handlermapping-interceptor),用于预处理和后处理。映射基于一些标准,其细节因’ HandlerMapping '实现而异。两个主要的“HandlerMapping”实现是“RequestMappingHandlerMapping”(它支持“@RequestMapping”注释方法)和“SimpleUrlHandlerMapping”(它维护对处理程序的URI路径模式的显式注册)。 |
HandlerAdapter | 帮助’ DispatcherServlet ‘调用映射到请求的处理程序,而不管处理程序实际上是如何调用的。例如,调用带注释的控制器需要解析注释。’ HandlerAdapter ‘的主要目的是保护’ DispatcherServlet '不受这些细节的影响。 |
HandlerExceptionResolver | 解决异常的策略,可能将它们映射到处理程序、HTML错误视图或其他目标。看到(异常)(https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html mvc-exceptionhandlers)。 |
ViewResolver | 解析从处理程序返回的逻辑的基于’ String ‘的视图名称到一个实际的’ view ',用它来呈现给响应。参见View Resolution和View Technologies。 |
LocaleResolver , LocaleContextResolver | 解析客户端正在使用的“区域设置”以及可能的时区,以便能够提供国际化视图。看到(地区)(https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html mvc-localeresolver)。 |
ThemeResolver | 解决您的web应用程序可以使用的主题-例如,提供个性化的布局。看到(主题)(https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html mvc-themeresolver)。 |
MultipartResolver | 抽象用于在一些多部分解析库的帮助下解析多部分请求(例如,浏览器表单文件上传)。参见多部分解析器。 |
FlashMapManager | 存储和检索“输入”和“输出”“FlashMap”,可以用来将属性从一个请求传递到另一个请求,通常是通过重定向。参见Flash属性 |
表格中的这些类或者接口都是DispatcherServlet的成员属性,了解成员属性作用其实也就知道了DispatcherServlet的作用。
两部分:
在 Spring MVC 5.3 之前的版本中,对于解码 requestURI
(请求的 URI)面临着以下问题:
URL 编码问题:当浏览器发送带有特殊字符或非 ASCII 字符的请求时,这些字符会被浏览器自动进行 URL 编码,即将特殊字符转换成 %
后面加上字符的 ASCII 表示形式。例如,空格会被编码为 %20
,中文字符会被编码为 %E4%BD%A0
等。而在旧版本的 Spring MVC 中,requestURI
默认是保持编码状态的,即不对 URL 进行解码处理。
中文乱码问题:由于 requestURI
是在浏览器编码之后传递给服务器的,服务器默认会将 %
后面的 ASCII 表示还原成原来的字符,但是对于中文字符,旧版本的 Spring MVC 会存在中文乱码的问题。比如 %E4%BD%A0
会被解码成乱码字符而不是正确的中文字符。
这些问题可能导致应用程序无法正确处理带有特殊字符或非 ASCII 字符的请求,导致出现乱码或参数解析错误等问题。
PathPattern和AntPathMatcher是两种用于匹配路径模式的工具。
?
表示匹配任意单个字符,*
表示匹配任意数量的字符(包括0个字符),**
表示匹配任意数量的路径(包括0个路径段)。AntPathMatcher可以用于匹配文件路径、URL路径等。例如,使用AntPathMatcher可以进行如下的路径匹配:
/user/?
可以匹配 /user/1
,但不能匹配 /user/1/friends
/user/*
可以匹配 /user/1
和 /user/1/friends
/user/**
可以匹配 /user/1
和 /user/1/friends
PathPattern
是 Spring Framework 5.3 引入的一个类,用于解决 URL 路径模式匹配的问题。在 Web 应用开发中,对于输入的 URL 路径进行匹配和解析是常见的需求。PathPattern
提供了一种更灵活和强大的方式来处理 URL 路径模式。
PathPattern
解决了以下问题:
URL 路径的灵活匹配:传统的 URL 路径匹配基于字符串匹配,无法处理复杂的路径模式匹配需求。PathPattern
支持使用路径变量、通配符、正则表达式等来构建灵活的 URL 路径匹配模式。例如,可以通过 /{category}/{id}
来匹配 /books/123
、/movies/456
等路径,并将 {category}
和 {id}
作为变量进行提取。
路径参数的提取和解析:PathPattern
可以从匹配的 URL 路径中提取出路径参数,并将其转换为对应的数据类型。路径参数可以用于动态地传递数据,例如 /books/123
中的 123
可以作为路径参数进行提取和解析。
RESTful 路由和资源映射:PathPattern
可以与 Spring Web MVC 或 Spring WebFlux 集成,用于进行 RESTful 路由和资源映射。通过定义和匹配路径模式,可以更方便地映射请求到相应的处理器方法,并且支持多种灵活的路径匹配模式。
安全路径匹配:PathPattern
通过对 URL 路径进行规范化和标准化处理,可以提供更安全的路径匹配。它可以处理 URL 编码、解码和规范化,避免在处理路径匹配时引入潜在的安全漏洞。
与AntPathMatcher相比,PathPattern提供了更丰富和灵活的路径匹配功能。PathPattern对路径进行了更严格的验证,并且支持更多的模式匹配规则,包括路径段的匹配、路径参数的匹配、查询参数的匹配等。
例如,使用PathPattern可以进行如下的路径匹配:
/user/{id}
可以匹配 /user/1
,但不能匹配 /user/1/friends
/user/{id}/**
可以匹配 /user/1
和 /user/1/friends
/user/{id:\\d+}
可以匹配 /user/1
,但不能匹配 /user/abc
如果你在项目用采用了Spring Boot 2.6.x,那么它的路径匹配格式为PathPattern,如果你又要集成Swagger,那么注意了启动会报错,需要修改Spring MVC的路径匹配规则为Ant风格:
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
Spring MVC定义了ViewResolver和View接口,使您可以在浏览器中呈现模型,而无需将您绑定到特定的视图技术。ViewResolver提供了视图名称和实际视图之间的映射。视图处理数据在移交给特定视图技术之前的准备工作。
下表提供了ViewResolver层次结构的更多细节:
ViewResolver | Description |
---|---|
AbstractCachingViewResolver | ’ AbstractCachingViewResolver ‘的子类缓存它们解析的视图实例。缓存提高了某些视图技术的性能。你可以通过设置’ cache ‘属性为’ false ‘来关闭缓存。此外,如果您必须在运行时刷新某个视图(例如,当修改FreeMarker模板时),您可以使用’ removeFromCache(String viewName, Locale loc) '方法。 |
UrlBasedViewResolver | ViewResolver接口的简单实现,可以直接将逻辑视图名称解析为url,而不需要显式的映射定义。如果您的逻辑名称以一种直接的方式匹配视图资源的名称,而不需要任意映射,那么这是合适的。 |
InternalResourceViewResolver | 方便的子类’ UrlBasedViewResolver ‘,支持’ InternalResourceView ‘(实际上,servlet和jsp)和子类,如’ JstlView ‘和’ TilesView ‘。你可以使用’ setViewClass(…) '为这个解析器生成的所有视图指定视图类。详细信息请参见’ UrlBasedViewResolver ’ javadoc。 |
FreeMarkerViewResolver | 方便的UrlBasedViewResolver子类,支持FreeMarkerView和自定义子类。 |
ContentNegotiatingViewResolver | ’ ViewResolver ‘接口的实现,该接口基于请求文件名或’ Accept '头解析视图。参见【内容协商】(https://docs.spring.io/spring-framework/docs/5.3.30-SNAPSHOT/reference/html/web.html#mvc-multiple-representations)。 |
`BeanNameViewResolver | ’ ViewResolver '接口的实现,该接口在当前应用程序上下文中将视图名称解释为bean名称。这是一个非常灵活的变体,允许基于不同的视图名称混合和匹配不同的视图类型。每个这样的“视图”都可以定义为一个bean,例如在XML或配置类中。 |
MultipartResolver是一种用于解析multipart 请求(包括文件上传)的策略。有一种实现基于Commons FileUpload,另一种实现基于Servlet 3.0多部分请求解析。
Commons FileUpload传统上只适用于POST请求,但接受任何multipart/内容类型。有关详细信息和配置选项,请参阅commonsmmultipartresolver javadoc。
Servlet 3.0多部分解析需要通过Servlet容器配置来启用。默认情况下,它将尝试用任何HTTP方法解析任何multipart/内容类型,但这可能不支持所有Servlet容器。有关详细信息和配置选项,请参阅StandardServletMultipartResolver javadoc。
Spring MVC提供了一个基于注解的编程模型,其中@Controller和@RestController组件使用注解来表达请求映射、请求输入、异常处理等等。带注释的控制器具有灵活的方法签名,不必扩展基类,也不必实现特定的接口。下面的例子展示了一个由注解定义的控制器:
@Controller
public class HelloController {
@GetMapping("/hello")
public String handle(Model model) {
model.addAttribute("message", "Hello World!");
return "index";
}
}
在前面的例子中,这个方法接受一个Model并返回一个字符串形式的视图名,但是还有很多其他的选项,我们将在本章后面解释。
@RestController是一个复合注释,它本身带有@Controller和@ResponseBody的元注释,以表明控制器的每个方法都继承了类型级的@ResponseBody注释,因此,直接写入响应体,而不是使用HTML模板进行视图解析和呈现。所以我们在Spring Boot项目中,在定义页面路由时,WebController应该采用@Controller注解而不是@RestController。
你可以使用@RequestMapping注释将请求映射到控制器方法。它有各种属性,可以根据URL、HTTP方法、请求参数、标头和媒体类型进行匹配。您可以在类级别使用它来表示共享映射,或者在方法级别使用它来缩小到特定的端点映射。
也有HTTP方法特定的快捷方式变体@RequestMapping:
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
快捷方式是提供自定义注释,因为大多数控制器方法应该映射到特定的HTTP方法,而不是使用@RequestMapping,默认情况下,它匹配所有HTTP方法。在类级别上仍然需要一个@RequestMapping来表达共享映射。
下面的例子有类型和方法级别的映射:
@RestController
@RequestMapping("/persons")
class PersonController {
@GetMapping("/{id}")
public Person getPerson(@PathVariable Long id) {
// ...
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public void add(@RequestBody Person person) {
// ...
}
}
Controller method argument | Description |
---|---|
WebRequest , NativeWebRequest | Generic access to request parameters and request and session attributes, without direct use of the Servlet API. |
javax.servlet.ServletRequest , javax.servlet.ServletResponse | Choose any specific request or response type — for example, ServletRequest , HttpServletRequest , or Spring’s MultipartRequest , MultipartHttpServletRequest . |
javax.servlet.http.HttpSession | Enforces the presence of a session. As a consequence, such an argument is never null . Note that session access is not thread-safe. Consider setting the RequestMappingHandlerAdapter instance’s synchronizeOnSession flag to true if multiple requests are allowed to concurrently access a session. |
javax.servlet.http.PushBuilder | Servlet 4.0 push builder API for programmatic HTTP/2 resource pushes. Note that, per the Servlet specification, the injected PushBuilder instance can be null if the client does not support that HTTP/2 feature. |
java.security.Principal | Currently authenticated user — possibly a specific Principal implementation class if known.Note that this argument is not resolved eagerly, if it is annotated in order to allow a custom resolver to resolve it before falling back on default resolution via HttpServletRequest#getUserPrincipal . For example, the Spring Security Authentication implements Principal and would be injected as such via HttpServletRequest#getUserPrincipal , unless it is also annotated with @AuthenticationPrincipal in which case it is resolved by a custom Spring Security resolver through Authentication#getPrincipal . |
HttpMethod | The HTTP method of the request. |
java.util.Locale | The current request locale, determined by the most specific LocaleResolver available (in effect, the configured LocaleResolver or LocaleContextResolver ). |
java.util.TimeZone + java.time.ZoneId | The time zone associated with the current request, as determined by a LocaleContextResolver . |
java.io.InputStream , java.io.Reader | For access to the raw request body as exposed by the Servlet API. |
java.io.OutputStream , java.io.Writer | For access to the raw response body as exposed by the Servlet API. |
@PathVariable | For access to URI template variables. See URI patterns. |
@MatrixVariable | For access to name-value pairs in URI path segments. See Matrix Variables. |
@RequestParam | For access to the Servlet request parameters, including multipart files. Parameter values are converted to the declared method argument type. See @RequestParam as well as Multipart.Note that use of @RequestParam is optional for simple parameter values. See “Any other argument”, at the end of this table. |
@RequestHeader | For access to request headers. Header values are converted to the declared method argument type. See @RequestHeader . |
@CookieValue | For access to cookies. Cookies values are converted to the declared method argument type. See @CookieValue . |
@RequestBody | For access to the HTTP request body. Body content is converted to the declared method argument type by using HttpMessageConverter implementations. See @RequestBody . |
HttpEntity<B> | For access to request headers and body. The body is converted with an HttpMessageConverter . See HttpEntity. |
@RequestPart | For access to a part in a multipart/form-data request, converting the part’s body with an HttpMessageConverter . See Multipart. |
java.util.Map , org.springframework.ui.Model , org.springframework.ui.ModelMap | For access to the model that is used in HTML controllers and exposed to templates as part of view rendering. |
RedirectAttributes | Specify attributes to use in case of a redirect (that is, to be appended to the query string) and flash attributes to be stored temporarily until the request after redirect. See Redirect Attributes and Flash Attributes. |
@ModelAttribute | For access to an existing attribute in the model (instantiated if not present) with data binding and validation applied. See @ModelAttribute as well as Model and DataBinder .Note that use of @ModelAttribute is optional (for example, to set its attributes). See “Any other argument” at the end of this table. |
Errors , BindingResult | For access to errors from validation and data binding for a command object (that is, a @ModelAttribute argument) or errors from the validation of a @RequestBody or @RequestPart arguments. You must declare an Errors , or BindingResult argument immediately after the validated method argument. |
SessionStatus + class-level @SessionAttributes | For marking form processing complete, which triggers cleanup of session attributes declared through a class-level @SessionAttributes annotation. See @SessionAttributes for more details. |
UriComponentsBuilder | For preparing a URL relative to the current request’s host, port, scheme, context path, and the literal part of the servlet mapping. See URI Links. |
@SessionAttribute | For access to any session attribute, in contrast to model attributes stored in the session as a result of a class-level @SessionAttributes declaration. See @SessionAttribute for more details. |
@RequestAttribute | For access to request attributes. See @RequestAttribute for more details. |
Any other argument | If a method argument is not matched to any of the earlier values in this table and it is a simple type (as determined by BeanUtils#isSimpleProperty), it is resolved as a @RequestParam . Otherwise, it is resolved as a @ModelAttribute . |
上述表格中为@Controller中方法的参数和参数注解,具体含义不翻译了可自行百度。有几个常见的、重要的还是有必要去了解的:javax.servlet.ServletRequest
, javax.servlet.ServletResponse
,javax.servlet.http.HttpSession
,@RequestBody
,@PathVariable
,@RequestParam
Controller method return value | Description |
---|---|
@ResponseBody | The return value is converted through HttpMessageConverter implementations and written to the response. See @ResponseBody . |
HttpEntity<B> , ResponseEntity<B> | The return value that specifies the full response (including HTTP headers and body) is to be converted through HttpMessageConverter implementations and written to the response. See ResponseEntity. |
HttpHeaders | For returning a response with headers and no body. |
String | A view name to be resolved with ViewResolver implementations and used together with the implicit model — determined through command objects and @ModelAttribute methods. The handler method can also programmatically enrich the model by declaring a Model argument (see Explicit Registrations). |
View | A View instance to use for rendering together with the implicit model — determined through command objects and @ModelAttribute methods. The handler method can also programmatically enrich the model by declaring a Model argument (see Explicit Registrations). |
java.util.Map , org.springframework.ui.Model | Attributes to be added to the implicit model, with the view name implicitly determined through a RequestToViewNameTranslator . |
@ModelAttribute | An attribute to be added to the model, with the view name implicitly determined through a RequestToViewNameTranslator .Note that @ModelAttribute is optional. See “Any other return value” at the end of this table. |
ModelAndView object | The view and model attributes to use and, optionally, a response status. |
void | A method with a void return type (or null return value) is considered to have fully handled the response if it also has a ServletResponse , an OutputStream argument, or an @ResponseStatus annotation. The same is also true if the controller has made a positive ETag or lastModified timestamp check (see Controllers for details).If none of the above is true, a void return type can also indicate “no response body” for REST controllers or a default view name selection for HTML controllers. |
DeferredResult<V> | Produce any of the preceding return values asynchronously from any thread — for example, as a result of some event or callback. See Asynchronous Requests and DeferredResult . |
Callable<V> | Produce any of the above return values asynchronously in a Spring MVC-managed thread. See Asynchronous Requests and Callable . |
ListenableFuture<V> , java.util.concurrent.CompletionStage<V> , java.util.concurrent.CompletableFuture<V> | Alternative to DeferredResult , as a convenience (for example, when an underlying service returns one of those). |
ResponseBodyEmitter , SseEmitter | Emit a stream of objects asynchronously to be written to the response with HttpMessageConverter implementations. Also supported as the body of a ResponseEntity . See Asynchronous Requests and HTTP Streaming. |
StreamingResponseBody | Write to the response OutputStream asynchronously. Also supported as the body of a ResponseEntity . See Asynchronous Requests and HTTP Streaming. |
Reactor and other reactive types registered via ReactiveAdapterRegistry | A single value type, e.g. Mono , is comparable to returning DeferredResult . A multi-value type, e.g. Flux , may be treated as a stream depending on the requested media type, e.g. “text/event-stream”, “application/json+stream”, or otherwise is collected to a List and rendered as a single value. See Asynchronous Requests and Reactive Types. |
Other return values | If a return value remains unresolved in any other way, it is treated as a model attribute, unless it is a simple type as determined by BeanUtils#isSimpleProperty, in which case it remains unresolved. |
Jackson是一个Java库,用于处理JSON格式的数据。它提供了一组强大的功能,可以在Java对象和JSON之间进行转换,包括序列化(将Java对象转换为JSON字符串)和反序列化(将JSON字符串转换为Java对象)。
以下是Jackson的主要作用:
对象序列化和反序列化:Jackson可以将Java对象转换为JSON字符串,以及将JSON字符串转换为Java对象。这对于在Java应用程序和前端或其他服务之间传递数据时非常有用。
数据绑定:Jackson可以将JSON数据绑定到Java对象上,并将JSON数据中的属性值映射到Java对象的相应属性上。这使得在处理JSON数据时可以轻松地将其转换为Java对象,并进行操作。
数据格式化和解析:Jackson提供了灵活的方式来格式化(美化)JSON数据并解析复杂的JSON结构。它支持各种JSON格式,如数组、嵌套对象、键值对等。
支持注解:Jackson支持在Java对象中使用注解,以控制JSON序列化和反序列化的行为。通过注解,可以自定义属性的命名、忽略某些属性、处理日期格式等。
支持流式API:Jackson提供了流式的API,可以逐行读取JSON数据,并进行处理,而不需要将整个JSON字符串加载到内存中。这对于处理大型JSON数据或实时流式数据非常有用。
Spring框架提供了对Jackson JSON库的全面支持,包括以下几个方面的应用:
JSON序列化和反序列化:Spring使用Jackson库作为默认的JSON序列化和反序列化工具。在处理HTTP请求和响应时,Spring MVC框架会自动将Java对象转换为JSON格式的响应数据,并将接收到的JSON数据转换为Java对象。这使得开发人员可以在控制器方法中直接使用Java对象,而不需要手动处理JSON数据的转换。
HTTP消息转换器:Spring提供了一组HTTP消息转换器,其中包括使用Jackson库进行JSON格式的消息转换器。这些转换器允许开发人员在处理HTTP请求和响应时轻松地将Java对象与JSON数据之间进行转换。
注解支持:Spring提供了对Jackson库注解的支持,包括@JsonSerialize
、@JsonDeserialize
、@JsonProperty
等。通过这些注解,开发人员可以自定义Java对象的JSON序列化和反序列化规则,包括属性的命名、类型转换、日期格式化等。
配置选项:Spring允许开发人员对Jackson库的配置进行细粒度的控制。例如,可以配置Jackson的特性,如是否缩进JSON输出、是否忽略空值属性等。通过配置选项,开发人员可以根据具体需求来调整JSON的序列化和反序列化行为。
支持其他JSON库:尽管Spring默认使用Jackson库进行JSON处理,但它也支持其他JSON库,如Gson、FastJson等。开发人员可以根据自己的喜好和项目需求选择合适的JSON库进行集成,并在Spring中进行配置。
总之,通过Spring对Jackson JSON库的支持,开发人员可以更加方便地处理JSON数据,实现Java对象和JSON数据之间的转换。这为开发RESTful API、处理前端与后端数据交互等场景提供了便利,并提升了开发效率和代码的可读性。
Spring MVC与Servlet 3.0异步请求处理有广泛的集成:
控制器方法中的DeferredResult和Callable返回值为单个异步返回值提供了基本支持。
控制器可以流式传输多个值,包括SSE和原始数据。
一旦在Servlet容器中启用了异步请求处理特性,控制器方法就可以用DeferredResult包装任何支持的控制器方法返回值,如下例所示:
@GetMapping("/quotes")
@ResponseBody
public DeferredResult<String> quotes() {
DeferredResult<String> deferredResult = new DeferredResult<String>();
// Save the deferredResult somewhere..
return deferredResult;
}
// From some other thread...
deferredResult.setResult(result);
控制器可以从不同的线程异步地生成返回值——例如,响应外部事件(JMS消息)、计划任务或其他事件。
控制器可以用java.util.concurrent包装任何支持的返回值。可调用,如下例所示:
@PostMapping
public Callable<String> processUpload(final MultipartFile file) {
return new Callable<String>() {
public String call() throws Exception {
// ...
return "someView";
}
};
}
然后可以通过配置的TaskExecutor运行给定的任务来获得返回值。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。