欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 8. Web应用程序(Web)

8. Web应用程序(Web)

2025/4/18 23:00:52 来源:https://blog.csdn.net/mxw_133/article/details/144846193  浏览:    关键词:8. Web应用程序(Web)

8. Web应用程序(Web)

Spring Boot 非常适用于Web应用程序开发。你可以使用嵌入式 Tomcat、Jetty、Undertow或Netty创建一个独立的HTTP服务器。大多是Web应用程序都会使用 spring-boot-starter-web 依赖模块来快速启动和运行项目。你也可以选择使用 spring-boot-starter-webflux 依赖模块来构建响应式Web英语程序。

如果你尚未开发过Spring Boot Web 应用程序,可以按照 入门 部分中的"Hello World!" 示例进行开发。

8.1 基于Servlet的Web应用程序(Servlet Web Applications)

如果你想构建基于servlet的Web应用程序,可以利用 Spring Boot 为 Spring MVC 或 Jersey 提供的自动配置功能。

8.1.1 Spring Web MVC框架(The “Spring Web MVC Framework”)

Spring Web MVC 框架 (通常称为 “Spring MVC”) 是一个功能完善的 “模块、视图、控制器” 的Web框架。Spring MVC 允许我们创建特殊的 @Controller 或者 @RestController bean 来处理传入的 HTTP 请求。控制器中的方法可以通过 @RequestMapping 注解映射到HTTP上。

下面代码展示了一个典型的返回 JSON 数据的 @RestController

@RestController
@RequestMapping("/users")
public class MyRestController {private final UserRepository userRepository;private final CustomerRepository customerRepository;public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) {this.userRepository = userRepository;this.customerRepository = customerRepository;}@GetMapping("/{userId}")public User getUser(@PathVariable Long userId) {return this.userRepository.findById(userId).get();}@GetMapping("/{userId}/customers")public List<Customer> getUserCustomers(@PathVariable Long userId) {return this.userRepository.findById(userId).map(this.customerRepository::findByUser).get();}@DeleteMapping("/{userId}")public void deleteUser(@PathVariable Long userId) {this.userRepository.deleteById(userId);}}

功能变量 “WebMvc.fn” 将路由配置和请求的实际处理分离开来,如下例所示:

@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);@Beanpublic RouterFunction<ServerResponse> routerFunction(MyUserHandler userHandler) {return route().GET("/{user}", ACCEPT_JSON, userHandler::getUser).GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers).DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser).build();}}
@Component
public class MyUserHandler {public ServerResponse getUser(ServerRequest request) {...return ServerResponse.ok().build();}public ServerResponse getUserCustomers(ServerRequest request) {...return ServerResponse.ok().build();}public ServerResponse deleteUser(ServerRequest request) {...return ServerResponse.ok().build();}}

Spring MVC 是 Spring 框架的核心部分,详细信息可以参考 reference documentation。还有一些指南覆盖 Spring MVC ,可以查看 spring.io/guides。

::: tip 提示

你可以定义任意多的 RouterFunction bean,以便于将路由器的定义模块化。如果需要排列优先级可以配置 bean 的顺序。

:::

Spring MVC 自动配置(Spring MVC Auto-configuration)

Spring Boot 为 Spring MVC 提供自动配置功能,可以适用于大多是应用程序。它取代了 @EnableWebMvc ,但两者不能同时使用。除了 Spring MVC 的默认设置外,自动配置还提供以下功能:

  • 包含 ContentNegotiatingViewResolverBeanNameViewResolver bean。
  • 支持静态资源服务,包括对 WebJars 的支持(本文档后面部分介绍)。
  • 自动注册 Converter, GenericConverter Formatter bean。
  • 支持 HttpMessageConverters (本文档后面部分介绍).
  • 自动注册 MessageCodesResolver (本文档后面部分介绍).
  • 支持静态 index.html
  • 自动使用 ConfigurableWebBindingInitializer bean (本文档后面部分介绍).

如果你想保留 Spring Boot MVC 自定义配置,并且想添加更多的 MVC 自定义配置 (拦截器,格式化器,视图控制器和其它功能),你可以添加自己的 @Configuration 类,它的类型为 WebMvcConfigurer ,但是不需要 @EnableWebMvc 注解。

如果你想提供自定义的 RequestMappingHandlerMappingRequestMappingHandlerAdapterExceptionHandlerExceptionResolver的实例,同时仍保留 the Spring Boot MVC 的自定义功能,您可以声明一个 WebMvcRegistrations 类型Bean,并使用它来提供这些组件的自定义实例。这些自定义实例将由 Spring MVC 进一步初始化和配置。若要参与后续处理,或根据需要重写后需处理,则应使用 WebMvcConfigurer

如果你不想使用自动配置,而是想完全控制 Spring MVC,可以添加自己的 @Configuration 注解 @EnableWebMvc。或者,按照 @EnableWebMvc 的 Javadoc 中所述,添加自己的 @Configuration 注解 DelegatingWebMvcConfiguration

Spring MVC 转换服务(Spring MVC Conversion Service)

Spring MVC 使用不同的 ConversionService 来转换 application.propertiesapplication.yaml 文件中的值。这意味着 PeriodDurationDataSize 转换器不可用,而且 @DurationUnit@DataSizeUnit 注解将会被忽略。

如果想自定义 Spring MVC ConversionService ,你可以提供带有 addFormatters 方法的 WebMvcConfigurer Bean。通过该方法,你可以注册任何你需要的转换器,或者你可以使用 ApplicationConversionService 上的静态方法。

还可以使用 spring.mvc.format.* 配置属性自定义转换。未配置时,将使用以下默认值:

PropertyDateTimeFormatter
spring.mvc.format.dateofLocalizedDate(FormatStyle.SHORT)
spring.mvc.format.timeofLocalizedTime(FormatStyle.SHORT)
spring.mvc.format.date-timeofLocalizedDateTime(FormatStyle.SHORT)
HttpMessageConverters

Spring MVC 使用 HttpMessageConverter 接口来转换HTTP请求和响应。开箱即包含合理的默认设置。例如,对象可以自动转换为JSON(通过使用 Jackson 库)或者 XML (通过使用 Jackson XML 扩展(如果可用)或者通过使用 JAXB (当 Jackson XML 扩展不可用时))。默认情况下,字符串使用 UTF-8 编码。

如果需要添加自定义转换器,可以使用 Spring Boot 的 HttpMessageConverters 类,如下所示:

@Configuration(proxyBeanMethods = false)
public class MyHttpMessageConvertersConfiguration {@Beanpublic HttpMessageConverters customConverters() {HttpMessageConverter<?> additional = new AdditionalHttpMessageConverter();HttpMessageConverter<?> another = new AnotherHttpMessageConverter();return new HttpMessageConverters(additional, another);}}

上下文中存在的任何 HttpMessageConverter Bean 都会被添加到转换器列表中。您也可以用同样的方法覆盖默认转换器。

MessageCodesResolver

Spring MVC 有一个生成错误代码的策略,用于从错误MessageCodesResolver中呈现错误消息。如果设置 spring.mvc.message-codes-resolver-format 属性为 PREFIX_ERROR_CODE 或者 POSTFIX_ERROR_CODE,则 Spring Boot 会为您创建一个(DefaultMessageCodesResolver.Format)。

静态内容(Static Content)

默认情况下,Spring Boot 会从类路径中的 /static/public/resources/META-INF/resources)目录或 ServletContext 的根目录中提供静态内容。它是使用Spring MVC的 ResourceHttpRequestHandler ,以便您可以通过添加自己的 WebMvcConfigurer 并覆盖 addResourceHandlers 方法来修改该操作。

在独立的Web应用程序中,容器中默认的 servlet 未启用。可以使用 server.servlet.register-default-servlet 属性来启用它。

默认 servlet 充当后备容器,如果 Spring 决定不处理它,它将从 ServletContext 根中提供内容。大多数情况下,这种情况不会发生(除非你修改了默认 MVC 配置),因为 Spring 总是可以通过 DispatcherServlet 处理请求。

默认情况下,资源映射到/**,但您可以使用spring.mvc.static-path-pattern属性对其进行调整。例如,将所有资源重新定位到/resources/**,实现如下:

spring:mvc:static-path-pattern: "/resources/**"

你还可以使用 spring.web.resources.static-locations 属性自定义静态资源位置(将默认值替换为自定义的目录位置列表)。root servlet 上下文路径 "/",也会自动添加为位置。

除了前面提到的 “标准 ”静态资源位置外,Webjars content 是一个特例。如果以 Webjars 格式打包,那么具有 /webjars/** 路径的资源,都将从 jar 文件中提供。

::: tip 提示

如果您的应用程序打包为jar,请不要使用 src/main/webapp 目录。虽然这个目录是一个通用标准,但它适用于 war 包,如果生成jar,大多数构建工具都会忽略它。

:::

Spring Boot 还支持 Spring MVC 提供的高级资源处理功能,允许使用缓存破坏静态资源或使用与 Webjar 无关 URL 等用例。

如果要使用与 Webjar 无关 URL,请添加webjars-locator-core依赖关系。然后声明你的 Webjar。以 jQuery 为例,添加“/webjars/jquery/jquery.min.js”后会出现“/webjars/jquery/x.y.z/jquery.min.js”,其中x.y.z是 Webjar 版本。

::: tip 备注

如果使用 JBoss,则需要声明 webjars-locator-jboss-vfs 依赖关系,而不是 webjars-locator-core。否则,所有 Webjars 都会解析为 404

:::

为了清除页面静态资源缓存,以下配置将为所有静态资源配置缓存清除解决方案,在URL中添加内容哈希值,如 <link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>

spring:web:resources:chain:strategy:content:enabled: truepaths: "/**"

::: tip 备注

由于 Thymeleaf 和 FreeMarker 自动配置了ResourceUrlEncodingFilter,因此在运行时可以在模板中重写资源链接。使用 JSP 时,应手动声明此过滤器。目前还不自动支持其他模板引擎,但可以通过自定义模板宏/助手和使用 ResourceUrlProvider来实现。

:::

在使用 JavaScript 模块加载器等动态加载资源时,无法重命名文件。因此,我们还需要支持其他策略,并可将其结合使用。“固定”策略会在 URL 中添加一个静态版本字符串,而不会更改文件名,如下例所示:

spring:web:resources:chain:strategy:content:enabled: truepaths: "/**"fixed:enabled: truepaths: "/js/lib/"version: "v12"

使用此配置后,位于"/js/lib/"下的 JavaScript 模块将使用固定的版本管理策略("/v12/js/lib/mymodule.js"),而其他资源仍将使用内容管理策略(<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>)。

有关更多支持内容,请参阅 WebProperties.Resources

::: tip 提示

此功能已在专门的 博客文章 和 Spring Framework 的 参考文档 中进行了详细描述。

:::

欢迎页面(Welcome Page)

Spring Boot 支持静态和模板化欢迎页面。它首先会在配置的静态内容位置中查找 index.html 文件。如果找不到,它就会寻找一个 index 模板。如果找到其中之一,就会自动将其用作应用程序的欢迎页面。

自定义 Favicon(Custom Favicon)

与其他静态资源一样,Spring Boot 会在配置的静态内容位置中检查是否存在 favicon.ico。如果存在此类文件,它将自动用作应用程序的 favicon。

路径匹配和内容协商(Path Matching and Content Negotiation)

Spring MVC 可以通过查看请求路径并将其与应用程序中定义的映射(例如 Controller 方法上的 @GetMapping 注解)进行匹配,从而将传入的 HTTP 请求映射到处理程序。

Spring Boot 默认情况下禁用后缀模式匹配,这意味着像 "GET /projects/spring-boot.json" 这样的请求经不会匹配到 @GetMapping("/projects/spring-boot") 接口。这被认为是 Spring MVC 应用程序的最佳实践。这一功能在过去主要适用与不发送正确的"Accept"的请求头的 HTTP 客户端;我们需要确保经正确的内容类型发给客户端。如今,内容协商功能更加可靠。

我们还有其它方法来处理哪些无法发送正确 “Accept” 请求头的HTTP 客户端。我们可以使用查询参数的形式来确保类似于 "GET /projects/spring-boot?format=json" 的请求映射到 @GetMapping("/projects/spring-boot"),来代替后缀模式匹配。

我们还有其他方法来处理那些不能持续发送正确 “接受 ”请求头的 HTTP 客户端。我们可以不使用后缀匹配,而是使用查询参数来确保类似“GET /projects/spring-boot?format=json” 这样的请求会被映射到@GetMapping(“/projects/spring-boot”)

spring:mvc:contentnegotiation:favor-parameter: true

或者,如果您希望使用不同的参数名称:

spring:mvc:contentnegotiation:favor-parameter: trueparameter-name: "myparam"

大多数标准媒体类型都支持开箱即用,但是你可以定义新的媒体类型:

spring:mvc:contentnegotiation:media-types:markdown: "text/markdown"

后缀模式匹配已被弃用,并将在未来的版本中删除。如果您了解其中的注意事项,但仍希望自己的应用程序使用后缀模式匹配,则需要进行以下配置:

spring:mvc:contentnegotiation:favor-path-extension: truepathmatch:use-suffix-pattern: true

另外,与其开放所有后缀模式,不如只支持已注册的后缀模式更安全:

spring:mvc:contentnegotiation:favor-path-extension: truepathmatch:use-registered-suffix-pattern: true

从 Spring Framework 5.3 开始,Spring MVC 支持两种将请求路径匹配到控制器的策略。默认情况下,Spring Boot 使用 PathPatternParser 策略。 PathPatternParser 是一种 优化实现 ,但是与 AntPathMatcher 相比有一些限制。 PathPatternParser 限制使用 某些路径模式变量。它还与后缀模式匹配(spring.mvc.pathmatch.use-suffix-patternspring.mvc.pathmatch.use-registered-suffix-pattern)和使用路径前缀配置的 DispatcherServletspring.mvc.servlet.path)不兼容。

可以使用 spring.mvc.pathmatch.matching-strategy 配置属性来配置策略,如下例所示:

spring:mvc:pathmatch:matching-strategy: "ant-path-matcher"

默认情况下,如果 Spring MVC 找不到请求对应的处理程序,将发送 404 Not Found 错误响应。若要抛出 NoHandlerFoundException ,请将配置 spring.mvc.throw-exception-if-no-handler-found 设置为 true。请注意,默认情况下,提供的静态内容 会被映射到 /** ,因此将为所有的请求提供处理程序。如果要抛出 NoHandlerFoundException ,还必须将 spring.mvc.static-path-pattern 设置为更加具体的值,如 /resources/** 或者将 spring.web.resources.add-mappings 设置为 false ,以便完全禁用静态内容服务。

ConfigurableWebBindingInitializer

Spring MVC 使用 WebBindingInitializer 为特定请求初始化 WebDataBinder 。如果你创建了自己的 ConfigurableWebBindingInitializer @Bean,Spring Boot 将会自动配置 Spring MVC 使用它。

模板引擎(Template Engines)

除 REST web 服务外,您还可以使用 Spring MVC 来提供动态 HTML 内容。Spring MVC 支持各种模板技术,包括 Thymeleaf,FreeMarker 和 JSP。此外,许多其他模板引擎包括他们自己的Spring MVC集成。

Spring Boot 包含对以下模板引擎的自动配置支持:

  • FreeMarker
  • Groovy
  • Thymeleaf
  • Mustache

::: tip 提示

如果可能,应避免使用 JSP。在将 JSP 与嵌入式 servlet 容器一起使用时,有几个已知限制。

:::

当您使用其中一个模板引擎和默认配置时,您的模板将从 src/main/resources/templates 自动获取。

::: tip 提示

根据运行应用程序的方式,集成开发环境可能会对 classpath 进行不同的排序。在 IDE 中通过主方法运行应用程序时,与使用 Maven 或 Gradle 或通过打包的 jar 运行应用程序时的排序不同。这可能导致 Spring Boot 无法找到预期的模板。如果遇到这个问题,可以在 IDE 中重新排列 classpath,将模块的类和资源放在前面。

:::

错误处理(Error Handling)

默认情况下,Spring Boot 提供 /error 映射,以合理的方式处理所有的错误,并在 servlet 容器中注册为 “全局” 错误页面。对于计算机客户端,它会返回一个JSON响应,其中包括错误、HTTP状态和异常信息的详细信息。对于浏览器客户端,有一个 “whitelabel” 错误视图,以HTML格式呈现相同的数据(如果要自定义它,需要添加一个解析 errorView)。

如果需要自定义默认的错误处理程序,可以设置一些 server.error 属性。请参阅附录中的 “服务器属性” 。

如果想要完全替换默认行为,你需要实现 ErrorController 并将其注册到Spring容器中,或者添加一个 ErrorAttributes 类型的 Bean 来使用现有机制替换内容。

::: tip 提示

BasicErrorController 可以作为定义 ErrorController 的基类。如果要为新 content type 添加处理程序,那么该功能特别有用(默认情况下,专门处理text/html的可以为其它内容提供支持)为此,请扩展 BasicErrorController,添加一个具有produces 属性的 @RequestMapping ,并创建新 content type 的Bean。

:::

你可以定义一个使用 @ControllerAdvice 注解的类,然后自定义针对特定控制器或者异常类型返回的JSON文档,如以下例所示:

@ControllerAdvice(basePackageClasses = SomeController.class)
public class MyControllerAdvice extends ResponseEntityExceptionHandler {@ResponseBody@ExceptionHandler(MyException.class)public ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {HttpStatus status = getStatus(request);return new ResponseEntity<>(new MyErrorBody(status.value(), ex.getMessage()), status);}private HttpStatus getStatus(HttpServletRequest request) {Integer code = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);HttpStatus status = HttpStatus.resolve(code);return (status != null) ? status : HttpStatus.INTERNAL_SERVER_ERROR;}}

在前面的示例中,如果 MyException 是由与 SomeController 定义在同一个包的控制器抛出的,则会使用 MyErrorBody POJO 的 JSON 标识而不是 ErrorAttributes 表示。

在某些情况下,metrics infrastructure 不会记录控制器级处理的错误。应用程序可以通过将处理过的异常设置为请求属性,确保请求指标记录此类异常:

@Controller
public class MyController {@ExceptionHandler(CustomException.class)String handleCustomException(HttpServletRequest request, CustomException ex) {request.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, ex);return "errorView";}}
自定义错误页面(Custom Error Pages)

如果要展示给定状态代码的自定义HTML错误页面,可以将文件添加到 /error 文件夹。错误页面可以是静态HTML(即,添加到任何静态资源文件夹下),也可以使用模板构建。文件名应是确定的状态代码或者系统掩码。

例如,要将 404 映射到静态HTML文件,你的文件夹结构将如下所示:

src/+- main/+- java/|   + <source code>+- resources/+- public/+- error/|   +- 404.html+- <other public assets>

要使用FreeMarker模板映射所有5xx错误,您的文件夹结构如下:

src/+- main/+- java/|   + <source code>+- resources/+- templates/+- error/|   +- 5xx.ftlh+- <other templates>

对于更复杂的映射,您还可以添加实现ErrorViewResolver接口的beans,如以下示例所示:

public class MyErrorViewResolver implements ErrorViewResolver {@Overridepublic ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {// Use the request or status to optionally return a ModelAndViewif (status == HttpStatus.INSUFFICIENT_STORAGE) {// We could add custom model values herenew ModelAndView("myview");}return null;}}

你还可以使用 Spring MVC 的功能,例如 @ExceptionHandler 方法 和 @ControllerAdvice. 然后ErrorController 会接收任何未处理的异常。

将错误页面映射到Spring MVC之外(Mapping Error Pages Outside of Spring MVC)

对于不使用 Spring MVC 的应用程序,可以使用 ErrorPageRegistrar 接口直接注册 ErrorPages。 该方式直接与底层嵌入式 servlet 容器配合使用,即使没有 Spring MVC DispatcherServlet 也能正常工作。

@Configuration(proxyBeanMethods = false)
public class MyErrorPagesConfiguration {@Beanpublic ErrorPageRegistrar errorPageRegistrar() {return this::registerErrorPages;}private void registerErrorPages(ErrorPageRegistry registry) {registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));}}

::: tip 备注

如果你注册ErrorPage的路径最终由Filter处理(如某些非Spring网页框架,如Jersey和Wicket),那么Filter必须显式注册为ERROR调度程序,如以下示例所示:

:::

@Configuration(proxyBeanMethods = false)
public class MyFilterConfiguration {@Beanpublic FilterRegistrationBean<MyFilter> myFilter() {FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>(new MyFilter());// ...registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));return registration;}}

请注意,默认FilterRegistrationBean不包括ERROR调度程序类型。

WAR 部署中的错误处理(Error Handling in a WAR Deployment)

当部署到 servlet 容器,Spring Boot 会使用错误页面过滤器将返回错误代码的请求转发到响应的错误页面。这是必要的,因为 servlet 规范没有提供注册错误页面的API。根据您部署 war 文件的容器和应用程序使用的技术,可能需要进行一些额外的配置。

只有在响应尚未提交的情况下,错误页面过滤器才能将请求转发到正确的错误页面。默认情况下,WebSphere Application Server 8.0 及更高版本会在 servlet 的服务方法成功完成后提交响应。您应将 com.ibm.ws.webcontainer.invokeFlushAfterService 设置为 false,从而禁用此行为。

如果使用 Spring Security 并希望访问错误页面中的 principal,则必须配置 Spring Security 的过滤器,以便在错误派发时调用。为此,请将 spring.security.filter.dispatcher-types 属性设置为 async, error, forward, request

CORS 支持(CORS Support)

跨域资源共享 (CORS) 是大多数浏览器 实现的 W3C 规范 ,允许您以灵活的方式指定授权何种跨域请求,而不是使用一些不太安全且功能较弱的方法,如IFRAME或JSONP。

从版本 4.2 开始,Spring MVC 支持 CORS。 在 Spring Boot 应用程序中使用不需要任何特定配置,带有@CrossOrigin 注解的 控制器方法 CORS 配置 。可以通过使用自定义的addCorsMappings(CorsRegistry)方法注册WebMvcConfigurer bean来定义全局 CORS 配置,如以下例所示:

@Configuration(proxyBeanMethods = false)
public class MyCorsConfiguration {@Beanpublic WebMvcConfigurer corsConfigurer() {return new WebMvcConfigurer() {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**");}};}}

8.1.2 JAX-RS 和 Jersey(JAX-RS and Jersey)

如果你更倾向于 REST 类型的 JAX-RS 编程模型,你可以使用其中一种可用的实现来代替 Spring MVC。 Jersey 和Apache CXF 开箱即用,效果相当不错。CXF 要求您将其 ServletFilter 注册为应用程序上下文中的 @Bean 。Jersey有一些原生的Spring支持,因此我们也在Spring Boot中提供了对它的自动配置支持,同时还提供了一个启动器。

要开始使用 Jersey,请将 spring-boot-starter-jersey 作为依赖项,然后你需要一个 ResourceConfig 类型的 @Bean,在其中注册所有端点,如下例所示:

@Component
public class MyJerseyConfig extends ResourceConfig {public MyJerseyConfig() {register(MyEndpoint.class);}}

::: warning 警告

Jersey 对扫描可执行文件的支持相当有限。例如,当运行可执行 war 文件时,Jersey 无法扫描完全可执行 jar 文件 或 WEB-INF/classes 中的包中的端点。为避免这一限制,不应使用 packages 方法,而应使用 register 方法单独注册端点,如上例所示。

:::

对于更多高级定制,您还可以注册任意数量的实现了 ResourceConfigCustomizer 的 Bean。

所有注册的端点都应是带有 HTTP 资源注解(@GET 及其他)的@Components,如下例所示:

@Component
@Path("/hello")
public class MyEndpoint {@GETpublic String message() {return "Hello";}}

由于 Endpoint 是 Spring @Component,因此其生命周期由 Spring 管理,你可以使用 @Autowired 注解将其注入到依赖关系中,并使用 @Value 注解注入外部配置。默认情况下,Jersey servlet 会注册并映射到 /*。您可以通过在 ResourceConfig 中添加 @ApplicationPath 来更改映射。

默认情况下,Jersey 在名为 jerseyServletRegistration@Bean 类型 ServletRegistrationBean 中设置为 servlet。 默认情况下,servlet 是懒加载的,但是你可以通过设置 spring.jersey.servlet.load-on-startup 来自定义该行为。你可以创建一个同名Bean,从而禁用或覆盖该Bean。你还可以通过设置 spring.jersey.type=filter 来使用过滤器而不是 servlet(在这种情况下,要替换或覆盖的@BeanjerseyFilterRegistration)。过滤器有一个 @Order,可以用 spring.jersey.filter.order 设置。 将 Jersey 用作过滤器时,必须有一个 servlet 来处理任何未被 Jersey 拦截的请求。如果您的应用程序不包含此类 servlet,您可能需要将 server.servlet.register-default-servlet 设置为 true,从而启用默认 servlet。通过使用spring.jersey.init.*来指定一个属性映射,可以为服务程序和过滤器注册提供初始参数。

8.1.3 支持嵌入式Servlet容器(Embedded Servlet Container Support)

对于 servlet 应用程序,Spring Boot 包含对嵌入式 Tomcat、Jetty 和 Undertow 服务器的支持、大多数开发人员都会使用相应的 “Starter” 来获取一个完全配置好的实例。默认情况下,嵌入式服务器通过 8080 端口侦听HTTP请求。

Servlets,过滤器和监听器(Servlets, Filters, and Listeners)

使用嵌入式 servlet 容器时,可以通过 Spring Bean 或扫描 servlet 组件,从 servlet spec 中注册 servlet、过滤器和所有的监听器(例如 HttpSessionListener)。

将 Servlet、过滤器和监听器注册为 Spring Bean(Registering Servlets, Filters, and Listeners as Spring Beans)

作为 Spring Bean 的任何 ServletFilter 或 servlet *Listener 实例都会在嵌入式容器中注册。如果您想在配置过程中引用application.properties中的值,这将特别方便。

默认情况下,如果上下文只包含一个 Servlet,它将被映射到 /。如果包含多个 Servlet Bean,Bean 名称将用作路径前缀。过滤器映射为 /*

如果基于约定的映射不够灵活,您可以使用 ServletRegistrationBeanFilterRegistrationBeanServletListenerRegistrationBean 类进行完全控制。

将 Filter bean 无序放置通常是安全的。如果需要特定的顺序,则应在 Filter 中添加 @Order 注解或使其实现 Ordered。你不能使用@Order注解来对 Filter 的 bean 方法进行配置顺序,你必须为Filter定义一个FilterRegistrationBean 并且使用 setOrder(int) 方法来设置注册 bean 的顺序。请不要配置Filter的顺序为Ordered.HIGHEST_PRECEDENCE ,因为它读取请求体时可能与应用程序的字符编码产生冲突。如果使用 servlet 过滤器封装请求,则应配置顺序小于等于 OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER

::: tip 提示

如果要查看应用程序中每个 Filter 的顺序,请启用 web logging group (logging.level.web=debug)。注册过滤器的详情信息,包括其顺序和URL patterns,将在启动时记录。

:::

::: warning 警告

注册 Filter Bean 时要注意,因为它们在应用程序生命周期的早期就会被初始化。如果您需要注册一个与其他 Bean 交互的 Filter,请考虑使用 DelegatingFilterProxyRegistrationBean 代替。

:::

Servlet 上下文初始化(Servlet Context Initialization)

嵌入式 servlet 容器不直接执行 servlet 3.0+ javax.servlet.ServletContainerInitializer 接口或 Spring 的 org.springframework.web.WebApplicationInitializer 接口。这是一个有意为之的设计决策,旨在降低为在 war 内运行而设计的第三方库破坏 Spring Boot 应用程序的风险。

如果需要在 Spring Boot 应用程序中执行 servlet 上下文初始化,则应注册一个实现 org.springframework.boot.web.servlet.ServletContextInitializer 接口的 Bean。单个 onStartup 方法提供了对 ServletContext 的访问,如有必要,还可轻松用作现有 WebApplicationInitializer 的适配器。

扫描 Servlet、Filter 和 listener(Scanning for Servlets, Filters, and listeners)

在使用嵌入式容器时,可使用 @ServletComponentScan 启用带有注解 @WebServlet@WebFilter@WebListener 的类进行自动注册。

::: tip 提示

在独立容器中,@ServletComponentScan不起作用,而是使用容器的内置发现机制。

:::

The ServletWebServerApplicationContext

Spring Boot 使用不同类型的 ApplicationContext 来支持嵌入式 servlet 容器。ServletWebServerApplicationContext 是一种特殊类型的 WebApplicationContext 。通过搜索单个 ServletWebServerFactory bean 来引导自己。 通常情况下已经自动配置了 TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactory

::: tip 备注

您通常不需要了解这些实现类。大多数应用程序都是自动配置的,相应的 ApplicationContextServletWebServerFactory 会以你的名义创建。

:::

在嵌入式容器设置中,ServletContext 是在应用程序上下文初始化期间作为服务器启动的一部分设置的。 因此,无法准确地使用 ServletContextApplicationContext 中的 Bean 进行初始化。解决这个问题的方法之一是将 ApplicationContext 作为 bean 的依赖注入,只有在需要时才访问 ServletContext。另一种方法是在服务器启动后使用回调。这可以使用一个 ApplicationListener 来实现,它可以监听 ApplicationStartedEvent 如下:

public class MyDemoBean implements ApplicationListener<ApplicationStartedEvent> {private ServletContext servletContext;@Overridepublic void onApplicationEvent(ApplicationStartedEvent event) {ApplicationContext applicationContext = event.getApplicationContext();this.servletContext = ((WebApplicationContext) applicationContext).getServletContext();}}
自定义嵌入式 Servlet 容器(Customizing Embedded Servlet Containers)

可以使用 Spring Environment 变量配置公共 Servlet 容器。通常,你将在 application.propertiesapplication.yaml 配置文件中定义属性。

常用的服务器配置包括:

  • 网络配置:侦听传入的 HTTP 请求的端口 (server.port),接口地址绑定到 server.address,依次类推。
  • 会话设置:会话是否持久配置 (server.servlet.session.persistent),会话超时配置(server.servlet.session.timeout), 会话数据位置配置(server.servlet.session.store-dir),和会话 cookie 配置 (server.servlet.session.cookie.*)。
  • 错误管理:错误页面位置配置 (server.error.path) ,依次类推。
  • SSL
  • HTTP 压缩

Spring Boot 尝试尽可能暴露更多的常见配置,但这并非总是可行。对于一些情况,专用命名空间提供特定于服务的自定义配置 (请参阅 server.tomcatserver.undertow)。例如,可以使用嵌入式 Servlet 容器的特定功能配置访问日志。

::: tip 备注

请参阅 ServerProperties 类获取完整配置列表。

:::

SameSite Cookies

浏览器可以使用 SameSite cookie 属性来控制是否以及如何在跨域请求中提交cookie。该属性对于现代浏览器尤为重要,因为它们已开始更改缺失该属性时使用的默认值。

如果要更改会话 cookie 的 SameSite 属性,可以使用 server.servlet.session.cookie.same-site 属性。自动配置的 Tomcat、Jetty 和 Undertow 服务器都支持该属性。它还用于配置基于 Spring Session servlet 的SessionRepositoryBean。

例如,如果希望会话 cookie 的SameSite属性为None,可以在application.propertiesapplication.yaml文件中添加以下内容:

server:servlet:session:cookie:same-site: "none"

如果想把更改添加到 HttpServletResponse 中的其他 cookie 上的 SameSite 属性,可以使用 CookieSameSiteSupplierCookieSameSiteSupplier会传递一个 Cookie,并可能返回一个 SameSite值或 null

您可以使用许多方便的工厂和过滤器方法来快速匹配特定的 cookie。例如,添加以下 bean 将自动为所有名称与正则表达式 myapp.* 匹配的 cookie 应用LaxSameSite

@Configuration(proxyBeanMethods = false)
public class MySameSiteConfiguration {@Beanpublic CookieSameSiteSupplier applicationCookieSameSiteSupplier() {return CookieSameSiteSupplier.ofLax().whenHasNameMatching("myapp.*");}}
字符编码(Character Encoding)

可使用 server.servlet.encoding.* 配置属性配置嵌入式 servlet 容器处理请求和响应的字符编码行为。

当请求的 Accept-Language 请求头指明了请求的地域时,它将被 servlet 容器自动映射为字符集。每个容器提供商都会提供默认的本地语言到字符集的映射,您应该验证它们是否满足您的应用程序的需求。如果它们不符合要求,请使用 server.servlet.encoding.mapping 配置属性自定义映射,如下例所示:

server:servlet:encoding:mapping:ko: "UTF-8"

在上例中,ko(韩语)locale 已被映射为UTF-8。这相当于传统 war 部署的 web.xml 文件中的 <locale-encoding-mapping-list> 条目。

程序定制(Programmatic Customization)

如果需要以编程方式配置嵌入式servlet容器,可以注册实现WebServerFactoryCustomizer接口并注册为 Spring bean。WebServerFactoryCustomizer 提供对 ConfigurableServletWebServerFactory 的访问,其中包括许多自定义 setter 方法。以下示例以编程方式设置端口:

@Component
public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {@Overridepublic void customize(ConfigurableServletWebServerFactory server) {server.setPort(9000);}}

TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactoryConfigurableServletWebServerFactory 的实现类,分别为 Tomcat,Jetty 和 Undertow 提供了额外的自定义 setter 方法。下面示例展示了如何自定义 TomcatServletWebServerFactory 来提供了访问 Tomcat 特定配置选项的权限:

@Component
public class MyTomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {@Overridepublic void customize(TomcatServletWebServerFactory server) {server.addConnectorCustomizers((connector) -> connector.setAsyncTimeout(Duration.ofSeconds(20).toMillis()));}}
直接定制 ConfigurableServletWebServerFactory(Customizing ConfigurableServletWebServerFactory Directly)

对于需要从 ServletWebServerFactory 扩展的更高级用例,您可以自己公开此类 Bean。

我们为许多配置选项提供了设置器。如果您需要做一些更特殊的事情,我们还提供了几个受保护的方法 “hooks”。详情请参见 源代码文档。

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();factory.setPort(9000);factory.setSessionTimeout(10, TimeUnit.MINUTES);factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));return factory;
}

::: tip 备注

自动配置的自定义程序仍会应用于自定义工厂,因此请谨慎使用该选项。

:::

JSP 限制(JSP Limitations)

在运行使用嵌入式 servlet 容器(并打包为可执行jar)的 Spring Boot 应用程序时,JSP 支持会受到一些限制。

  • 对于 Jetty 和 Tomcat,如果使用 war 打包,应该可以运行。使用 java -jar 启动时,war 将正常工作,而且还可以部署到任何标准容器中。使用可执行 jar 时不支持 JSP。
  • Undertow 不支持 JSP。
  • 创建自定义 error.jsp 页面不会覆盖 错误处理的默认视图。应改用自定义错误页面。

8.2 响应式 Web 应用程序(Reactive Web Applications)

Spring Boot 通过为 Spring Webflux 提供自动配置,简化了响应式 Web 应用程序的开发。

8.2.1 Spring WebFlux 框架(The “Spring WebFlux Framework”)

Spring WebFlux 是 Spring Framework 5.0 中引入的全新响应式 Web 框架。与 Spring MVC 不同,它不需要 servlet API,是完全异步和非阻塞的,并通过Reactor 项目 实现了Reactive Streams规范。

Spring WebFlux 有两种类型:功能型和基于注解型。基于注解的 Spring WebFlux 非常接近 Spring MVC 模型,如下例所示:

@RestController
@RequestMapping("/users")
public class MyRestController {private final UserRepository userRepository;private final CustomerRepository customerRepository;public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) {this.userRepository = userRepository;this.customerRepository = customerRepository;}@GetMapping("/{userId}")public Mono<User> getUser(@PathVariable Long userId) {return this.userRepository.findById(userId);}@GetMapping("/{userId}/customers")public Flux<Customer> getUserCustomers(@PathVariable Long userId) {return this.userRepository.findById(userId).flatMapMany(this.customerRepository::findByUser);}@DeleteMapping("/{userId}")public Mono<Void> deleteUser(@PathVariable Long userId) {return this.userRepository.deleteById(userId);}}

“WebFlux.fn "是功能变量,它将路由配置与请求的实际处理分离开来,如下例所示:

@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);@Beanpublic RouterFunction<ServerResponse> monoRouterFunction(MyUserHandler userHandler) {return route().GET("/{user}", ACCEPT_JSON, userHandler::getUser).GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers).DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser).build();}}
@Component
public class MyUserHandler {public Mono<ServerResponse> getUser(ServerRequest request) {...}public Mono<ServerResponse> getUserCustomers(ServerRequest request) {...}public Mono<ServerResponse> deleteUser(ServerRequest request) {...}}

WebFlux 是 Spring 框架的一部分,详细信息请参阅其 参考文档。

::: tip 提示

您可以定义任意多的 RouterFunction Bean,以便将路由器的定义模块化。如果需要应用优先级,可以对 Bean进行排序。

:::

要开始使用,请在应用程序中添加 spring-boot-starter-webflux 模块。

::: tip 备注

在应用程序中同时添加 spring-boot-starter-webspring-boot-starter-webflux 模块会导致 Spring Boot 自动配置 Spring MVC,而不是 WebFlux。之所以选择这种行为,是因为许多 Spring 开发人员将 spring-boot-starter-webflux 添加到他们的 Spring MVC 应用程序中,以使用响应式 WebClient。您仍然可以通过将所选应用程序类型设置为 SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)来执行您的选择。

:::

Spring WebFlux 自动配置(Spring WebFlux Auto-configuration)

Spring Boot 为 Spring WebFlux 提供了自动配置,可与大多数应用程序完美契合。

自动配置在 Spring 的默认配置基础上增加了以下功能:

  • HttpMessageReaderHttpMessageWriter实例配置编解码器(本文档稍后部分 将进行描述)。
  • 支持提供静态资源,包括对 WebJar 的支持(本文档稍后部分有描述)。

如果您想保留 Spring Boot WebFlux 的功能,又想添加额外的 WebFlux 配置,您可以添加自己的 @Configuration 类,其类型为 WebFluxConfigurer,但不包含 @EnableWebFlux

如果你想完全控制 Spring WebFlux,可以添加自己的 @Configuration 类,并添加注解 @EnableWebFlux

Spring WebFlux 转换服务(Spring WebFlux Conversion Service)

如果要自定义 Spring WebFlux 使用的ConversionService,可以提供带有addFormatters方法的 WebFluxConfigurer Bean。

还可以使用 spring.webflux.format.* 配置属性自定义转换。未配置时,将使用以下默认值:

PropertyDateTimeFormatter
spring.webflux.format.dateofLocalizedDate(FormatStyle.SHORT)
spring.webflux.format.timeofLocalizedTime(FormatStyle.SHORT)
spring.webflux.format.date-timeofLocalizedDateTime(FormatStyle.SHORT)
带有 HttpMessageReaders 和 HttpMessageWriters 的 HTTP 编/解码器(HTTP Codecs with HttpMessageReaders and HttpMessageWriters)

Spring WebFlux 使用 HttpMessageReaderHttpMessageWriter 接口来转换 HTTP 请求和响应。使用 CodecConfigurer 对它们进行配置,通过查看类路径中可用的库来获得合理的默认值。

Spring Boot 为编/解码器提供了专用的配置属性,即spring.codec.*。它还通过使用 CodecCustomizer 实例来进一步自定义。例如,spring.jackson.* 配置将应用于 Jackson 编/解码器。

如果需要添加或自定义编/解码器,可以创建一个自定义的 CodecCustomizer 组件,如下例所示:

@Configuration(proxyBeanMethods = false)
public class MyCodecsConfiguration {@Beanpublic CodecCustomizer myCodecCustomizer() {return (configurer) -> {configurer.registerDefaults(false);configurer.customCodecs().register(new ServerSentEventHttpMessageReader());// ...};}}

还可以利用 Boot 的自定义 JSON 序列化器和反序列化器。

静态内容(Static Content)

默认情况下,Spring Boot 会从类路径中名为 /static(或 /public/resources/META-INF/resources)的目录中提供静态内容。它使用 Spring WebFlux 中的 ResourceWebHandler 方法,因此你可以通过添加自己的 WebFluxConfigurer 和重载 addResourceHandlers 方法来修改该行为。

默认情况下,资源映射在 /**上,但你可以通过设置 spring.webflux.static-path-pattern 属性来调整。例如,将所有资源重新定位到 /resources/**,方法如下:

spring:webflux:static-path-pattern: "/resources/**"

您还可以使用 spring.web.resources.static-locations 来自定义静态资源位置。这样做可以用目录位置列表替换默认值。如果你这样做,默认的欢迎页面检测就会切换到自定义位置。因此,如果启动时在任何位置都有一个 index.html,它就是应用程序的主页。

除了前面列出的 “标准 ”静态资源位置外,Webjars content 也是一个特例。任何路径为 /webjars/**的资源,如果是以 Webjars 格式打包的,都是从 jar 文件中提供的。

::: tip 提示

Spring WebFlux 应用程序并不严格依赖于 servlet API,因此不能作为 war 文件部署,也不使用 src/main/webapp 目录。

:::

欢迎页(Welcome Page)

Spring Boot 支持静态和模板化欢迎页面。它首先会在配置的静态内容位置中查找 index.html 文件。如果找不到,它就会寻找一个 index 模板。如果找到其中之一,就会自动将其用作应用程序的欢迎页面。

模板引擎(Template Engines)

除了 REST web services,您还可以使用 Spring WebFlux 来提供动态 HTML 内容。Spring WebFlux 支持多种模板引擎,包括 Thymeleaf、FreeMarker 和 Mustache。

Spring Boot 包含对以下模板引擎的自动配置支持:

  • FreeMarker
  • Thymeleaf
  • Mustache

When you use one of these templating engines with the default configuration, your templates are picked up automatically from src/main/resources/templates.

当你使用这些这些模板引擎之一时(在默认配置下使用),模板会自动从 src/main/resources/templates 中提取。

异常处理(Error Handling)

Spring Boot 提供了一个 WebExceptionHandler类用来处理所有错误。它在处理顺序中的位置在 WebFlux 提供的处理程序之前,后者被认为是最后一个。对于机器客户端,它会生成一个 JSON 响应,其中包含错误的详细信息、HTTP 状态和异常消息。对于浏览器客户端,会有一个“whitelabel”错误处理程序,以 HTML 格式呈现相同的数据。您也可以提供自己的 HTML 模板来显示错误(请参阅 下一节)。

自定义此功能的第一步通常是使用现有机制,替换或扩充错误内容。为此,您可以添加一个 ErrorAttributes 类型的 Bean。

如果要更改错误处理行为,您可以实现 ErrorWebExceptionHandler 并注册 Bean 定义。由于 ErrorWebExceptionHandler 相对底层,因此 Spring Boot 还提供了方便的 AbstractErrorWebExceptionHandler 以让您以 WebFlux 功能方式处理错误,如下例所示:

@Component
public class MyErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, WebProperties webProperties,ApplicationContext applicationContext, ServerCodecConfigurer serverCodecConfigurer) {super(errorAttributes, webProperties.getResources(), applicationContext);setMessageReaders(serverCodecConfigurer.getReaders());setMessageWriters(serverCodecConfigurer.getWriters());}@Overrideprotected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {return RouterFunctions.route(this::acceptsXml, this::handleErrorAsXml);}private boolean acceptsXml(ServerRequest request) {return request.headers().accept().contains(MediaType.APPLICATION_XML);}public Mono<ServerResponse> handleErrorAsXml(ServerRequest request) {BodyBuilder builder = ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR);// ... additional builder callsreturn builder.build();}}

要了解更全面的情况,还可以直接子类化 DefaultErrorWebExceptionHandler 并覆盖特定方法。

在某些情况下,度量基础设施 不会记录在控制器或处理程序函数级别处理的错误。应用程序可通过将处理过的异常设置为请求属性,确保请求指标记录此类异常:

@Controller
public class MyExceptionHandlingController {@GetMapping("/profile")public Rendering userProfile() {// ...throw new IllegalStateException();}@ExceptionHandler(IllegalStateException.class)public Rendering handleIllegalState(ServerWebExchange exchange, IllegalStateException exc) {exchange.getAttributes().putIfAbsent(ErrorAttributes.ERROR_ATTRIBUTE, exc);return Rendering.view("errorView").modelAttribute("message", exc.getMessage()).build();}}
自定义异常页面(Custom Error Pages)

如果要为给定的状态代码显示自定义 HTML 错误页面,可以添加从 error/* 解析的视图,例如向 /error 目录中添加文件。错误页面既可以是静态 HTML(即添加到任何静态资源目录下),也可以使用模板构建。文件名应为准确的状态代码、状态代码系列掩码,如果没有其他匹配项,则应使用 error 作为默认值。请注意,默认错误视图的路径是 error/error,而 Spring MVC 的默认错误视图是 error

例如,要将 404 映射到静态 HTML 文件,目录结构如下:

src/+- main/+- java/|   + <source code>+- resources/+- public/+- error/|   +- 404.html+- <other public assets>

要使用 Mustache 模板映射所有 5xx 错误,您的目录结构如下:

src/+- main/+- java/|   + <source code>+- resources/+- templates/+- error/|   +- 5xx.mustache+- <other templates>
Web 过滤器(Web Filters)

Spring WebFlux provides a WebFilter interface that can be implemented to filter HTTP request-response exchanges. WebFilter beans found in the application context will be automatically used to filter each exchange.

Where the order of the filters is important they can implement Ordered or be annotated with @Order. Spring Boot auto-configuration may configure web filters for you. When it does so, the orders shown in the following table will be used:

Spring WebFlux 提供了一个 WebFilter接口,可用于过滤 HTTP request-response exchanges。应用程序上下文中的 WebFilter Bean 将自动用于过滤每个exchanges。

如果需要定义过滤器的顺序,可以实现 Ordered 或添加注解 @Order。Spring Boot 会为您自动配置 WebFilter。配置时,将使用下表所示的顺序:

Web FilterOrder
MetricsWebFilterOrdered.HIGHEST_PRECEDENCE + 1
WebFilterChainProxy (Spring Security)-100
HttpTraceWebFilterOrdered.LOWEST_PRECEDENCE - 10

8.2.2 支持嵌入式响应式服务器(Embedded Reactive Server Support)

Spring Boot includes support for the following embedded reactive web servers: Reactor Netty, Tomcat, Jetty, and Undertow. Most developers use the appropriate “Starter” to obtain a fully configured instance. By default, the embedded server listens for HTTP requests on port 8080.

自定义响应式服务器(Customizing Reactive Servers)

Common reactive web server settings can be configured by using Spring Environment properties. Usually, you would define the properties in your application.properties or application.yaml file.

Common server settings include:

常见的响应式 Web 服务器设置可通过使用 Spring Environment 属性来配置。通常,你会在application.propertiesapplication.yaml文件中定义这些属性。

常见的服务器设置包括

  • 网络配置:侦听传入的 HTTP 请求的端口 (server.port),接口地址绑定到 server.address,依次类推。
  • 错误管理:错误页面的位置 (server.error.path) 等。
  • SSL
  • HTTP 压缩

Spring Boot tries as much as possible to expose common settings, but this is not always possible. For those cases, dedicated namespaces such as server.netty.* offer server-specific customizations.

Spring Boot 尽可能暴露公开配置,但这并不是可能的。在这种情况下,专用命名空间(如 server.netty.*)可提供特定于服务器的自定义设置。

::: tip 提示

完整列表请参阅 ServerProperties 类。

:::

程序定制(Programmatic Customization)

如果需要以编程方式配置响应式 Web 服务器,可以注册一个实现了 WebServerFactoryCustomizer 接口的 Spring Bean。WebServerFactoryCustomizer提供了对 ConfigurableReactiveWebServerFactory的访问,其中包括大量自定义设置方法。下面的示例展示了如何通过编程设置端口:

@Component
public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableReactiveWebServerFactory> {@Overridepublic void customize(ConfigurableReactiveWebServerFactory server) {server.setPort(9000);}}

JettyReactiveWebServerFactoryNettyReactiveWebServerFactoryTomcatReactiveWebServerFactoryUndertowServletWebServerFactoryConfigurableReactiveWebServerFactory 的实现类,它们分别为 Jetty,Reactor Netty,Tomcat 和 Undertow 提供额外的自定义配置方法。下面的示例展示了如何定制可访问 Reactor Netty 特定配置选项的 NettyReactiveWebServerFactory

@Component
public class MyNettyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {@Overridepublic void customize(NettyReactiveWebServerFactory factory) {factory.addServerCustomizers((server) -> server.idleTimeout(Duration.ofSeconds(20)));}}
直接定制可配置的响应式 Web 服务器工厂(Customizing ConfigurableReactiveWebServerFactory Directly)

对于需要从ReactiveWebServerFactory扩展的更高级用法,您可以自行公开此类类型的 Bean。

我们为许多配置选项提供了设置器。如果您需要做一些更特殊的事情,我们还提供了几个受保护的方法 “hooks”。详情请参见 源代码文档。

::: tip 备注

自动配置的自定义程序仍会应用于自定义工厂,因此请谨慎使用该选项。

:::

8.2.3 响应式服务器资源配置(Reactive Server Resources Configuration)

在自动配置 Reactor Netty 或 Jetty 服务器时,Spring Boot 将创建特定的 Bean,为服务器实例提供 HTTP 资源:ReactorResourceFactoryJettyResourceFactory

默认情况下,这些资源也将与 Reactor Netty 和 Jetty 客户端共享,以获得最佳性能:

  • 服务器和客户端使用相同的技术
  • 客户端实例是使用 Spring Boot 自动配置的 WebClient.Builder Bean 构建的

开发人员可以通过提供自定义的 ReactorResourceFactoryJettyResourceFactoryBean 来覆盖 Jetty 和 Reactor Netty 的资源配置,这将同时应用于客户端和服务器。

有关客户端资源配置的更多信息,请参阅 WebClient Runtime 部分。

8.3 Graceful Shutdown

所有四种嵌入式 Web 服务器(Jetty、Reactor Netty、Tomcat 和 Undertow)以及基于 reactive 和 servlet 的 Web 应用程序都支持Graceful shutdown。它是关闭应用程序上下文的一部分,在停止 SmartLifecycleBean 的最早阶段执行。这种停止处理使用一个超时时间,提供一个宽限期,在此期间允许完成现有请求,但不允许有新请求。不允许新请求的具体方式因所使用的 Web 服务器而异。Jetty、Reactor Netty 和 Tomcat 将在网络层停止接受请求。Undertow 会接受请求,但会立即作出服务不可用 (503) 的回应。

::: tip 备注

Graceful shutdown 需要 Tomcat 9.0.33 或更高版本。

:::

要启用graceful shutdown,请配置 server.shutdown属性,如下例所示:

server:shutdown: "graceful"

要配置超时时间,请配置 spring.lifecycle.timeout-per-shutdown-phase 属性,如下例所示:

spring:lifecycle:timeout-per-shutdown-phase: "20s"

::: error 重要

如果集成开发环境没有发送正确的 SIGTERM信号,在集成开发环境中使用 “graceful shutdown ”可能无法正常工作。详情请查看集成开发环境的文档。

:::

8.4 Spring 安全(Spring Security)

如果 Spring Security 在 classpath 上,那么 web 应用程序默认是安全的。Spring Boot 依赖 Spring Security 的内容协商策略来决定是使用 httpBasic 还是 formLogin。要为 web 应用程序添加方法级安全,还可以添加 @EnableGlobalMethodSecurity 注解并进行所需配置。更多信息可参阅 Spring Security Reference Guide。

默认的 UserDetailsService 只有一个用户。用户名是 user,密码是随机的,并且在应用程序启动时打印到 WARN level 日志上,如下例所示:

Using generated security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35This generated password is for development use only. Your security configuration must be updated before running your application in production.

::: tip 备注

如果要微调日志配置,请确保将 org.springframework.boot.autoconfigure.security 类别设置为记录 WARN 级消息。否则,将不会打印默认密码。

:::

您可以通过提供spring.security.user.namespring.security.user.password来更改用户名和密码。

web 应用程序的默认基本功能包括:

  • UserDetailsService (如果是 WebFlux 应用程序,则为 ReactiveUserDetailsService ) bean,该 bean 具有内存存储和单个用户及生成的密码 (用户属性参阅 SecurityProperties.User )。
  • 整个应用程序基于Form login 或者 HTTP Basic 安全性(取决于请求中的 Accept 请求头,包括 actuator endpoints(如果actuator 位于类路径上))。
  • 用于发布身份验证事件的 DefaultAuthenticationEventPublisher

You can provide a different AuthenticationEventPublisher by adding a bean for it.

8.4.1 MVC 安全(MVC Security)

默认的安全配置在SecurityAutoConfigurationUserDetailsServiceAutoConfiguration 中实现。 SecurityAutoConfiguration 注入了用于 web 安全的 SpringBootWebSecurityConfiguration 和配置身份认证的 UserDetailsServiceAutoConfiguration,这在非 Web 应用程序中也非常重要。若要完全关闭默认的 Web 应用程序安全配置,或结合多个 Spring 安全组件(如 OAuth2 客户端和资源服务器),请添加一个 SecurityFilterChain 类型的 Bean(这样做不会禁用 UserDetailsService 配置或 Actuator 的安全性)。

要关闭 UserDetailsService 配置,您可以添加一个 UserDetailsServiceAuthenticationProviderAuthenticationManager 类型的 Bean。

可以通过添加自定义的 SecurityFilterChainWebSecurityConfigurerAdapter Bean 来重写访问规则。Spring Boot 提供了方便的方法,可用于重写 actuator endpoints 和静态资源的访问规则。EndpointRequest可用于创建基于management.endpoints.web.base-path属性的RequestMatcherPathRequest 可用于为常用位置的资源创建RequestMatcher

8.4.2 WebFlux 安全(WebFlux Security)

ReactiveSecurityAutoConfiguration imports WebFluxSecurityConfiguration for web security and UserDetailsServiceAutoConfiguration configures authentication, which is also relevant in non-web applications. To switch off the default web application security configuration completely, you can add a bean of type WebFilterChainProxy (doing so does not disable the UserDetailsService configuration or Actuator’s security).

与 Spring MVC 应用程序类似,您也可以通过添加 spring-boot-starter-security 依赖关系来确保 WebFlux 应用程序的安全。默认安全配置在 ReactiveSecurityAutoConfigurationUserDetailsServiceAutoConfiguration 中实现。ReactiveSecurityAutoConfiguration注入了用于网络安全的WebFluxSecurityConfiguration和配置身份认证的UserDetailsServiceAutoConfiguration,这在非网络应用中也很重要。要完全关闭默认的 Web 应用程序安全配置,可以添加一个 WebFilterChainProxy 类型的 Bean(这样做不会禁用 UserDetailsService 配置或 Actuator 的安全性)。

要关闭 UserDetailsService 配置,可以添加一个 ReactiveUserDetailsServiceReactiveAuthenticationManager 类型的 Bean。

访问规则和多个 Spring 安全组件(如 OAuth 2 客户端和资源服务器)的使用可以通过添加自定义的 SecurityWebFilterChain Bean 进行配置。Spring Boot 提供了方便的方法,可用于覆盖actuator endpoints和静态资源的访问规则。EndpointRequest 可用于创建基于management.endpoints.web.base-path属性的 ServerWebExchangeMatcher

PathRequest可用于为常用位置的资源创建ServerWebExchangeMatcher

例如,可以通过添加以下内容来定制安全配置:

@Configuration(proxyBeanMethods = false)
public class MyWebFluxSecurityConfiguration {@Beanpublic SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {http.authorizeExchange((exchange) -> {exchange.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();exchange.pathMatchers("/foo", "/bar").authenticated();});http.formLogin(withDefaults());return http.build();}}

8.4.3. OAuth2

OAuth2是一个广泛使用、基于Spring的授权框架。

客户端(Client)

如果你的类路径上有spring-security-oauth2-client,你就可以利用一些自动配置来设置 OAuth2/Open ID Connect 客户端。该配置使用了 OAuth2ClientProperties 中的属性。同样的属性适用于 servlet 和响应式应用程序。

您可以在 spring.security.oauth2.client 前缀下注册多个 OAuth2 客户端和提供程序,如下例所示:

spring:security:oauth2:client:registration:my-client-1:client-id: "abcd"client-secret: "password"client-name: "Client for user scope"provider: "my-oauth-provider"scope: "user"redirect-uri: "https://my-redirect-uri.com"client-authentication-method: "basic"authorization-grant-type: "authorization_code"my-client-2:client-id: "abcd"client-secret: "password"client-name: "Client for email scope"provider: "my-oauth-provider"scope: "email"redirect-uri: "https://my-redirect-uri.com"client-authentication-method: "basic"authorization-grant-type: "authorization_code"provider:my-oauth-provider:authorization-uri: "https://my-auth-server/oauth/authorize"token-uri: "https://my-auth-server/oauth/token"user-info-uri: "https://my-auth-server/userinfo"user-info-authentication-method: "header"jwk-set-uri: "https://my-auth-server/token_keys"user-name-attribute: "name"

对于支持 OpenID Connect discovery 的 OpenID Connect 提供程序,配置可以进一步简化。提供程序需要配置一个 issuer-uri(即作为其发行者的URL)。例如,如果提供的 issuer-uri 是 “https://example.com”, 那么将向"https://example.com/.well-known/openid-configuration" 发出 OpenID Provider Configuration Request ,返回结果将是一个 OpenID Provider Configuration Response。下面的示例展示了如何使用 issuer-uri配置OpenID Connect 提供程序:

spring:security:oauth2:client:provider:oidc-provider:issuer-uri: "https://dev-123456.oktapreview.com/oauth2/default/"

默认情况下,Spring Security 的 OAuth2LoginAuthenticationFilter 只处理与 /login/oauth2/code/* 匹配的 URL。如果要自定义 redirect-uri 去使用不同的模式,则需要提供处理该自定义模式的配置。例如,对于 servlet 应用程序,您可以添加类似于以下内容的自己的 SecurityFilterChain

@Configuration(proxyBeanMethods = false)
public class MyOAuthClientConfiguration {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeRequests((requests) -> requests.anyRequest().authenticated());http.oauth2Login((login) -> login.redirectionEndpoint().baseUri("custom-callback"));return http.build();}}

::: tip 提示

Spring Boot 会自动配置一个 InMemoryOAuth2AuthorizedClientService ,用于 Spring Security 管理客户端。InMemoryOAuth2AuthorizedClientService 功能有限,建议仅在开发环境中使用。对于生产环境,请考虑使用 JdbcOAuth2AuthorizedClientService 或创建自己的 OAuth2AuthorizedClientService 实现。

:::

通用提供商的 OAuth2 客户端注册(OAuth2 Client Registration for Common Providers)

对于通用的 OAuth2 和 OpenID 提供商,包括 Google, Github, Facebook 和 Okta,我们默认提供一组供应商的默认值 (分别为google, github, facebookokta)。

如果你不需要自定义这些应用程序,则可以将 provider 属性设置为你需要的默认值。此外,如果客户端注册的密钥和默认支持的提供者相匹配,则 Spring Boot 也会推断出来。

换句话说,以下示例中的两个配置使用Google提供程序:

spring:security:oauth2:client:registration:my-client:client-id: "abcd"client-secret: "password"provider: "google"google:client-id: "abcd"client-secret: "password"
资源服务器(Resource Server)

如果类路径上有 spring-security-oauth2-resource-server ,Spring Boot 可以设置 OAuth2 资源服务器。对于 JWT 配置。需要指定 JWK Set URI 或 OIDC Issuer URI,如以下示例所示:

spring:security:oauth2:resourceserver:jwt:jwk-set-uri: "https://example.com/oauth2/default/v1/keys"
spring:security:oauth2:resourceserver:jwt:issuer-uri: "https://dev-123456.oktapreview.com/oauth2/default/"

::: tip 备注

如果授权服务器不支持 JWK Set URI,则可使用用于验证 JWT 签名的公钥配置资源服务器。这可以使用 spring.security.oauth2.resourceserver.jwt.public-key-location 属性来完成,其中的值需要指向一个包含 PEM 编码 x509 格式公钥的文件。

:::

The spring.security.oauth2.resourceserver.jwt.audiences 属性可以用于指定 JWT 中 aud claim 的预期值。例如,要求 JWT 包含值为 my-audience 的 aud claim :

spring:security:oauth2:resourceserver:jwt:audiences:- "my-audience"

相同属性同时适用于 servlet 和 响应式应用程序。此外,您还可以为 servlet 应用程序定义自己的 JwtDecoder bean 或者为响应式应用程序定义 ReactiveJwtDecoder bean。

在使用私有 token 而不是 JWT 的情况下,你可以配置以下属性来通过token的验证:

spring:security:oauth2:resourceserver:opaquetoken:introspection-uri: "https://example.com/check-token"client-id: "my-client-id"client-secret: "my-client-secret"

同样,相同的属性适用于 servlet 和 响应式应用程序。另外,你也可以为 servlet 应用程序定义自己的 OpaqueTokenIntrospector bean,或为响应式应用程序定义 ReactiveOpaqueTokenIntrospector

授权服务器(Authorization Server)

目前,Spring Security 不支持实现 OAuth 2.0 授权服务器。不过 Spring Security OAuth 项目提供这一功能,该项目最终将被 Spring Security 取代。在此之前,你可以使用 spring-security-oauth2-autoconfigure 模块来设置 OAuth 2.0 授权服务器;有关说明,请参阅 文档 。

8.4.4 SAML 2.0

依赖方(Relying Party)

如果你的 classpath 上有spring-security-saml2-service-provider,你就可以利用一些自动配置来设置SAML 2.0依赖方。该配置使用了Saml2RelyingPartyProperties下的属性。

依赖方注册代表身份提供方(IDP)和服务提供商(SP)之间的配对配置。您可以在 spring.security.saml2.relyingparty前缀下注册多个依赖方,如下例所示:

spring:security:saml2:relyingparty:registration:my-relying-party1:signing:credentials:- private-key-location: "path-to-private-key"certificate-location: "path-to-certificate"decryption:credentials:- private-key-location: "path-to-private-key"certificate-location: "path-to-certificate"singlelogout:url: "https://myapp/logout/saml2/slo"response-url: "https://remoteidp2.slo.url"binding: "POST"assertingparty:verification:credentials:- certificate-location: "path-to-verification-cert"entity-id: "remote-idp-entity-id1"sso-url: "https://remoteidp1.sso.url"my-relying-party2:signing:credentials:- private-key-location: "path-to-private-key"certificate-location: "path-to-certificate"decryption:credentials:- private-key-location: "path-to-private-key"certificate-location: "path-to-certificate"assertingparty:verification:credentials:- certificate-location: "path-to-other-verification-cert"entity-id: "remote-idp-entity-id2"sso-url: "https://remoteidp2.sso.url"singlelogout:url: "https://remoteidp2.slo.url"reponse-url: "https://myapp/logout/saml2/slo"binding: "POST"

对于 SAML2 logout,Spring Security 的 Saml2LogoutRequestFilterSaml2LogoutResponseFilter 默认只处理与 /logout/saml2/slo 匹配的 URL。如果要自定义 AP 发起的 logout 请求发送到的 url 或 AP 发送 logout 响应到的 response-url 以使用不同的模式,则需要提供配置来处理该自定义模式。例如,对于 servlet 应用程序,您可以添加自己的 SecurityFilterChain ,如下所示:

@Configuration(proxyBeanMethods = false)
public class MySamlRelyingPartyConfiguration {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated();http.saml2Login();http.saml2Logout((saml2) -> saml2.logoutRequest((request) -> request.logoutUrl("/SLOService.saml2")).logoutResponse((response) -> response.logoutUrl("/SLOService.saml2")));return http.build();}}

8.5 Spring 会话(Spring Session)

Spring Boot 为各种数据存储提供了 Spring Session 模块。在构建 servlet web 应用程序时,可以自动配置以下存储功能:

  • JDBC
  • Redis
  • Hazelcast
  • MongoDB

此外,Spring Boot for Apache Geode 还提供了 将 Apache Geode 用作会话存储的自动配置.

servlet 自动配置取代了 @Enable*HttpSession 使用的需要。

在构建响应式 web 应用程序是,可以自动配置以下存储方式:

  • Redis
  • MongoDB

响应式 自动配置取代了 @Enable*WebSession 使用的需要。

如果类路径上只有一个 Spring Session 模块,Spring Boot 会自动使用该存储实现。如果有多个实现,则必须选择希望用于存储会话的 存储类型。例如,要使用 JDBC 作为后端存储,可以如下配置应用程序:

spring:session:store-type: "jdbc"

::: tip 提示

通过将 store-type 设置为 none,可以禁用 Spring Session。

:::

每个存储都有特定的附加配置。例如,可以自定义 JDBC 存储的表名,如下例所示:

spring:session:jdbc:table-name: "SESSIONS"

要设置会话超时,可以使用 spring.session.timeout 属性。如果未在 servlet web应用程序中设置该属性,配置就会自动使用 server.servlet.session.timeout 的值。

你可以使用 @Enable*HttpSession (servlet) 或 @Enable*WebSession (reactive) 来控制 Spring Session 的配置。这将导致自动配置关闭。然后,就可以使用注解的属性而不是之前描述的配置属性来配置 Spring Session 了。

8.6. Spring for GraphQL(Spring for GraphQL)

如果您想构建 GraphQL 应用程序,可以利用 Spring Boot 为 Spring for GraphQL提供的自动配置功能。Spring for GraphQL 项目基于 GraphQL Java。您至少需要 spring-boot-starter-graphql 启动器。由于 GraphQL 与传输无关,因此您还需要在应用程序中添加一个或多个启动器,以便通过网络公开 GraphQL API:

StarterTransportImplementation
spring-boot-starter-webHTTPSpring MVC
spring-boot-starter-websocketWebSocketWebSocket for Servlet apps
spring-boot-starter-webfluxHTTP, WebSocketSpring WebFlux
spring-boot-starter-rsocketTCP, WebSocketSpring WebFlux on Reactor Netty

8.6.1 GraphQL 模式(GraphQL Schema)

Spring GraphQL 应用程序需要在启动时定义 schema 。默认情况下,你可以在src/main/resources/graphql/**下编写 “.graphqls"或”.gqls"模式文件,Spring Boot 会自动获取它们。您可以使用 spring.graphql.schema.locations 自定义位置,使用 spring.graphql.schema.file-extensions 自定义文件扩展名。

::: tip 备注

If you want Spring Boot to detect schema files in all your application modules and dependencies for that location, you can set spring.graphql.schema.locations to "classpath*:graphql/**/" (note the classpath*: prefix).

如果希望 Spring Boot 检测所有应用模块中的 schema 文件以及该位置的依赖关系,可以将 spring.graphql.schema.locations 设置为 "classpath*:graphql/**/" (注意 classpath*: 前缀)。

:::

在下面的章节中,我们将对 GraphQL 模式进行举例,定义两种类型和两个查询:

type Query {greeting(name: String! = "Spring"): String!project(slug: ID!): Project
}""" A Project in the Spring portfolio """
type Project {""" Unique string id used in URLs """slug: ID!""" Project name """name: String!""" URL of the git repository """repositoryUrl: String!""" Current support status """status: ProjectStatus!
}enum ProjectStatus {""" Actively supported by the Spring team """ACTIVE""" Supported by the community """COMMUNITY""" Prototype, not officially supported yet  """INCUBATING""" Project being retired, in maintenance mode """ATTIC""" End-Of-Lifed """EOL
}

::: tip 备注

默认情况下,schema 将允许字段自省,因为这是 GraphiQL 等工具所必需的。如果不想公开 schema 信息,可以将 spring.graphql.schema.introspection.enabled 设为 false,从而禁用自省功能。

:::

8.6.2 GraphQL RuntimeWiring

GraphQL Java RuntimeWiring.Builder 可用于注册自定义标量类型、指令、类型解析器、DataFetcher等。您可以在 Spring 配置中声明 RuntimeWiringConfigurer Bean,以访问 RuntimeWiring.Builder 。Spring Boot 会检测到此类 Bean,并将它们添加到 GraphQlSource builder 中。

不过,通常情况下,应用程序不会直接实现 DataFetcher,而是会创建 annotated controllers。Spring Boot 会自动检测带有注解处理程序方法的 @Controller 类,并将其注册为 DataFetchers。下面是使用 @Controller 类实现问候语查询的示例:

@Controller
public class GreetingController {@QueryMappingpublic String greeting(@Argument String name) {return "Hello, " + name + "!";}}

8.6.3 支持 Querydsl 和 QueryByExample 存储库(Querydsl and QueryByExample Repositories Support)

Spring Data 支持 Querydsl 和 QueryByExample 存储库。Spring GraphQL 可以将 Querydsl 和 QueryByExample 存储库配置为 DataFetcher

Spring Data 存储库使用 @GraphQlRepository 进行注解,并扩展了以下功能之一:

  • QuerydslPredicateExecutor
  • ReactiveQuerydslPredicateExecutor
  • QueryByExampleExecutor
  • ReactiveQueryByExampleExecutor

被 Spring Boot 检测到,并被视为 DataFetcher的候选对象,用于匹配顶级查询。

8.6.4 传输(Transports)

HTTP 和 WebSocket

GraphQL HTTP 端点默认为 HTTP POST /graphql。路径可通过 spring.graphql.path 进行自定义。

::: tip 提示

Spring MVC 和 Spring WebFlux 的 HTTP 端点均由 @Order0RouterFunction Bean 提供。如果您定义了自己的 RouterFunction Bean,则可能需要添加适当的 @Order 注解,以确保正确排序。

:::

GraphQL WebSocket 端点默认关闭。要启用它

  • 对于 Servlet 应用程序,添加 WebSocket 启动器 spring-boot-starter-websocket
  • 对于 WebFlux 应用程序,不需要额外的依赖关系
  • 对于两者,都必须设置 spring.graphql.websocket.path 应用程序属性

Spring GraphQL 提供了Web 拦截 模型。这对于从 HTTP 请求头中获取信息并将其设置在 GraphQL 上下文中,或从同一上下文中获取信息并将其写入响应头非常有用。使用 Spring Boot,您可以声明一个 WebInterceptor Bean,让它在网络传输中注册。

Spring MVC 和 Spring WebFlux 支持 CORS(跨源资源共享)请求。对于从使用不同域的浏览器访问的 GraphQL 应用程序来说,CORS 是网络配置的关键部分。

Spring Boot 支持 spring.graphql.cors.* 命名空间下的许多配置属性;下面是一个简短的配置示例:

spring:graphql:cors:allowed-origins: "https://example.org"allowed-methods: GET,POSTmax-age: 1800s
RSocket

RSocket 也支持作为 WebSocket 或 TCP 的传输方式。一旦配置 RSocket 服务器,我们就可以使用 spring.graphql.rsocket.mapping 在特定路由上配置 GraphQL 处理程序。例如,映射配置“graphql”意味着我们可以在使用RSocketGraphQlClient发送请求时将其用作路由。

Spring Boot 会自动配置一个RSocketGraphQlClient.Builder<?>Bean,您可以将其注入到您的组件中:

@Component
public class RSocketGraphQlClientExample {private final RSocketGraphQlClient graphQlClient;public RSocketGraphQlClientExample(RSocketGraphQlClient.Builder<?> builder) {this.graphQlClient = builder.tcp("example.spring.io", 8181).route("graphql").build();}

然后发送请求:

Mono<Book> book = this.graphQlClient.document("{ bookById(id: \"book-1\"){ id name pageCount author } }").retrieve("bookById").toEntity(Book.class);

8.6.5 异常处理(Exception Handling)

Spring GraphQL 使应用程序能够注册一个或多个顺序调用的 Spring DataFetcherExceptionResolver 组件。可以解析的异常必须在graphql.GraphQLError对象列表中,参考Spring GraphQL 异常处理文档。Spring Boot 会自动检测 DataFetcherExceptionResolver Bean,并将其注册到 GraphQlSource.Builder 中。

8.6.6 GraphiQL 和 Schema printer(GraphiQL and Schema printer)

Spring GraphQL 提供了基础架构,可帮助开发人员使用或开发 GraphQL API。

Spring GraphQL 包括一个默认的 GraphiQL 页面,该页面默认在 "/graphiql" 目录中。该页面默认禁用,可通过 spring.graphql.graphiql.enabled 属性打启用。许多使用此页面的应用程序都倾向于自定义构建。默认实现在开发过程中非常有用,这就是为什么在开发过程中它会通过 spring-boot-devtools自动公开。

启用 spring.graphql.schema.printer.enabled 属性后,还可以选择在/graphql/schema中以文本格式公开 GraphQL schema。

8.7 Spring HATEOAS

如果您开发的 RESTful API 需要使用超媒体,Spring Boot 会为 Spring HATEOAS 提供自动配置,以便与大多数应用程序配合使用。自动配置取代了使用 @EnableHypermediaSupport 的需要,并注册了大量 Bean,以方便构建基于超媒体的应用程序,其中包括 LinkDiscoverers (用于客户端支持)和 ObjectMapper,配置这些 Bean 是为了将响应正确地编译成所需的表示形式。ObjectMapper 可通过设置各种 spring.jackson.* 属性或 Jackson2ObjectMapperBuilder Bean(如果存在)进行自定义。

通过使用 @EnableHypermediaSupport 可以控制 Spring HATEOAS 的配置。请注意,这样做会禁用前面描述的 ObjectMapper 自定义。

::: warning 警告

spring-boot-starter-hateoas 是 Spring MVC 专用的,不应与 Spring WebFlux 结合使用。要将 Spring HATEOAS 与 Spring WebFlux 结合使用,可以在 spring-boot-starter-webflux 中直接添加对 org.springframework.hateoas:spring-hateoas 的依赖。

:::

默认情况下,接受 application/json 的请求将收到 application/hal+json 的响应。要禁用此行为,请将 spring.hateoas.use-hal-as-default-json-media-type 设为 false,并定义 HypermediaMappingInformationHalConfiguration 以配置 Spring HATEOAS,从而满足应用程序及其客户端的需求。

8.8 下一步阅读(What to Read Next)

现在,您应该对如何使用 Spring Boot 开发 Web 应用程序有了很好的了解。接下来的几节将介绍 Spring Boot 如何与各种数据技术、消息系统和其他 IO 功能集成。您可以根据自己应用程序的需要选择其中任何一种。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词