Spring Boot非常适合Web应用程序开发。您可以使用Embedded Tomcat、Jetty、Undertow或Netty创建自包含的HTTP服务器。大多数Web应用程序使用SpringBoot-starter-web模块来快速启动和运行。您还可以选择使用Spring-boot-starter-webflow模块来构建反应式Web应用程序。

如果您还没有开发Spring Boot Web应用程序,您可以使用“Hello World!”入门部分中的示例。

1. Servlet Web Applications

如果你想构建基于Servlet的Web应用程序,你可以利用Spring Boot对Spring MVC或Jersey的自动配置。

1.1. The “Spring Web MVC Framework”

Spring Web MVC框架(通常称为“Spring MVC”)是一个丰富的“模型-视图-控制器”Web框架。Spring MVC允许您创建特殊的@Controller@RestControllerBean来处理传入的HTTP请求。控制器中的方法通过使用@Requestmap注释映射到HTTP。

下面的代码显示了一个典型的服务JSON数据的@RestController

Java
Kotlin
import java.util.List; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.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是一个功能变体,它将路由配置与请求的实际处理分开,如下例所示:

Java
Kotlin
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.servlet.function.RequestPredicate; import org.springframework.web.servlet.function.RouterFunction; import org.springframework.web.servlet.function.ServerResponse; import static org.springframework.web.servlet.function.RequestPredicates.accept; import static org.springframework.web.servlet.function.RouterFunctions.route; @Configuration(proxyBeanMethods = false) public class MyRoutingConfiguration { private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON); @Bean public 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(); } } 
            
            
Java
Kotlin
import org.springframework.stereotype.Component; import org.springframework.web.servlet.function.ServerRequest; import org.springframework.web.servlet.function.ServerResponse; @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框架的一部分,有关详细信息,请参阅参考文档。在spring.io/gueses上也有几个介绍Spring MVC的指南。

You can define as many RouterFunction beans as you like to modularize the definition of the router. Beans can be ordered if you need to apply a precedence.

1.1.1. Spring MVC Auto-configuration

Spring Boot为Spring MVC提供了自动配置,可以很好地与大多数应用程序配合使用。

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

  • 包含了ContentNeatheratingViewResolverBeanNameViewResolverBean。

  • 支持提供静态资源,包括对WebJars的支持(本文档后面将介绍)。

  • 自动注册ConverterGenericConverterFormatterBean。

  • 支持HttpMessageConverters(本文档后面部分)。

  • 自动注册MessageCodesResolver(本文档后面部分)。

  • 静态index.html支持。

  • 自动使用ConfigurableWebBindingInitializerBean(本文档后面部分介绍了)。

如果您想保留这些Spring Boot MVC定制,并进行更多的MVC定制(拦截器、格式化程序、视图控制器和其他功能),您可以添加您自己的@Configurant类,其类型为WebMvcConfigurer没有@EnableWebMvc

如果您想要提供RequestMappingHandlerAdapterRequestMappingHandlerAdapterExceptionHandlerExceptionResolver,的定制实例,并且仍然保留Spring Boot MVC定制,那么您可以声明一个WebMvcRegistrations类型的Bean,并使用它来提供这些组件的定制实例。

如果您想要完全控制Spring MVC,您可以添加您自己的@Configuration,或者添加您自己的@Configuration-注释的DelegatingWebMvcConfiguration,如@EnableWebMvc的Javadoc中所述。

Spring MVC使用的ConversionService与用于转换应用程序.Properties应用程序.yaml文件中的值的ConversionService不同。这意味着PeriodDurationDataSize转换器不可用,@DurationUnit@DataSizeUnit注释将被忽略。

如果您想要定制Spring MVC使用的ConversionService,您可以为WebMvcConfigurerBean提供一个addForMatters方法。您可以从此方法注册任何您喜欢的转换器,也可以委托给ApplicationConversionService上可用的静态方法。

1.1.2. HttpMessageConverters

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

如果您需要添加或定制转换器,可以使用Spring Boot的HttpMessageConverters类,如以下清单所示:

Java
Kotlin
import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; @Configuration(proxyBeanMethods = false) public class MyHttpMessageConvertersConfiguration { @Bean public HttpMessageConverters customConverters() { HttpMessageConverter<?> additional = new AdditionalHttpMessageConverter(); HttpMessageConverter<?> another = new AnotherHttpMessageConverter(); return new HttpMessageConverters(additional, another); } } 
             
             

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

1.1.3. MessageCodesResolver

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

1.1.4. Static Content

默认情况下,Spring Boot提供来自类路径中名为/静态(或/public/resource/META-INF/resource)目录或ServletContext根目录的静态内容。它使用来自Spring MVC的ResourceHttpRequestHandler,因此您可以通过添加您自己的WebMvcConfigurer并覆盖addResourceHandler方法来修改该行为。

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

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

默认情况下,资源被映射到/**上,但是您可以使用spring.mvc.static-Path-Pattern属性对其进行调优。例如,将所有资源重定位到/resource/**的方法如下:

Properties
Yaml
spring.mvc.static-path-pattern=/resources/**
             
             

您还可以使用spring.web.resources.static-locations属性(用目录位置列表替换默认值)来自定义静态资源位置。根Servlet上下文路径“/”也会自动添加为一个位置。

除了前面提到的“标准”静态资源位置之外,还为Webjars内容设置了一个特例。默认情况下,路径在/webjars/**中的任何资源都由JAR文件提供,如果它们以Webjars格式打包的话。路径可以使用spring.mvc.webjars-Path-Pattern属性进行定制。

Do not use the src/main/webapp directory if your application is packaged as a jar. Although this directory is a common standard, it works only with war packaging, and it is silently ignored by most build tools if you generate a jar.

Spring Boot还支持由Spring MVC提供的高级资源处理功能,允许使用缓存破坏静态资源或使用Webjars的版本无关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的版本。

If you use JBoss, you need to declare the webjars-locator-jboss-vfs dependency instead of the webjars-locator-core. Otherwise, all Webjars resolve as a 404.

要使用缓存破坏,以下配置为所有静态资源配置了缓存破坏方案,有效地添加了内容哈希,如URL中的 ,><;链接Hash:

Properties
Yaml
spring.web.resources.chain.strategy.content.enabled=true
spring.web.resources.chain.strategy.content.paths=/**
             
             
Links to resources are rewritten in templates at runtime, thanks to a ResourceUrlEncodingFilter that is auto-configured for Thymeleaf and FreeMarker. You should manually declare this filter when using JSPs. Other template engines are currently not automatically supported but can be with custom template macros/helpers and the use of the ResourceUrlProvider.

例如,当使用JavaScript模块加载器动态加载资源时,不能重命名文件。这就是为什么其他战略也得到支持并可以结合在一起的原因。FIXED策略在URL中添加静态版本字符串,而不更改文件名,如下例所示:

Properties
Yaml
spring.web.resources.chain.strategy.content.enabled=true
spring.web.resources.chain.strategy.content.paths=/**
spring.web.resources.chain.strategy.fixed.enabled=true
spring.web.resources.chain.strategy.fixed.paths=/js/lib/
spring.web.resources.chain.strategy.fixed.version=v12
             
             

在这种配置下,位于<代码>“/js/lib/” 下的JAVASCRIPT模块使用固定的版本控制策略(<代码>“/v12/js/lib/mymode.js” ),而其他资源仍然使用内容资源(<代码><;链接href=“/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css”/>;).

有关更多支持的选项,请参阅WebProperties.Resources

这个特性已经在专门的博客文章和Spring框架的参考文档中进行了详细描述。

1.1.5. Welcome Page

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

1.1.6. Custom Favicon

与其他静态资源一样,Spring Boot会在已配置的静态内容位置中检查avinic.ico。如果存在这样的文件,它将自动用作应用程序的收藏夹图标。

1.1.7. Path Matching and Content Negotiation

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

默认情况下,Spring Boot选择禁用后缀模式匹配,这意味着像“Get/Projects/Spring-boot.json” @GetMapping(“/projects/spring-boot”)>这样的请求将不会与Spring映射匹配。这被认为是Spring MVC应用程序的最佳实践。过去,该功能主要用于没有发送正确的“Accept”请求头的HTTP客户端;我们需要确保向客户端发送正确的Content Type。如今,内容协商要可靠得多。

还有其他方法可以处理不一致地发送正确的“Accept”请求标头的HTTP客户端。我们可以不使用后缀匹配,而是使用查询参数来确保像“Get/Projects/Spring-Boot?Format=json”这样的请求将被映射到@GetMapping(“/projects/spring-boot”)

Properties
Yaml
spring.mvc.contentnegotiation.favor-parameter=true
             
             

或者,如果您希望使用其他参数名称:

Properties
Yaml
spring.mvc.contentnegotiation.favor-parameter=true
spring.mvc.contentnegotiation.parameter-name=myparam
             
             

开箱即可支持大多数标准媒体类型,但您也可以定义新的媒体类型:

Properties
Yaml
spring.mvc.contentnegotiation.media-types.markdown=text/markdown
             
             

从Spring Framework5.3开始,Spring MVC支持几种将请求路径匹配到控制器处理程序的实现策略。它以前只支持AntPathMatcher策略,但现在它还提供PathPatternParser。Spring Boot现在提供了一个配置属性来选择和选择新策略:

Properties
Yaml
spring.mvc.pathmatch.matching-strategy=path-pattern-parser
             
             

有关为什么应该考虑这个新实现的更多详细信息,请参阅专门的博客文章

PathPatternParser is an optimized implementation but restricts usage of some path patterns variants. It is incompatible with suffix pattern matching or mapping the DispatcherServlet with a servlet prefix (spring.mvc.servlet.path).

1.1.8. ConfigurableWebBindingInitializer

Spring MVC使用WebBindingInitializer为特定请求初始化WebDataBinder。如果您创建自己的代码<ConfigurableWebBindingInitializer>@Bean,Spring Boot会自动配置Spring MVC以使用它。

1.1.9. Template Engines

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

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

If possible, JSPs should be avoided. There are several known limitations when using them with embedded servlet containers.

当您以默认配置使用这些模板引擎之一时,您的模板将自动从src/main/Resources/Templates中选取。

Depending on how you run your application, your IDE may order the classpath differently. Running your application in the IDE from its main method results in a different ordering than when you run your application by using Maven or Gradle or from its packaged jar. This can cause Spring Boot to fail to find the expected template. If you have this problem, you can reorder the classpath in the IDE to place the module’s classes and resources first.

1.1.10. Error Handling

默认情况下,Spring Boot提供一个/error映射,以合理的方式处理所有错误,并在Servlet容器中注册为“全局”错误页面。对于机器客户端,它生成一个JSON响应,其中包含错误、HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“白色标签”错误视图,它以HTML格式呈现相同的数据(要定制它,请添加一个视图,它可以解析为错误)。

如果要自定义默认错误处理行为,可以设置许多server.error属性。请参阅附录的“服务器属性”部分。

要完全替换默认行为,您可以实现ErrorController并注册该类型的Bean定义,或者添加类型为ErrorAttributes的Bean以使用现有机制但替换内容。

The BasicErrorController can be used as a base class for a custom ErrorController. This is particularly useful if you want to add a handler for a new content type (the default is to handle text/html specifically and provide a fallback for everything else). To do so, extend BasicErrorController, add a public method with a @RequestMapping that has a produces attribute, and create a bean of your new type.

从Spring Framework6.0开始,支持RFC 7807问题详情。Spring MVC可以生成应用程序/问题+json媒体类型的自定义错误消息,例如:

{
  "type": "https://example.org/problems/unknown-project",
  "title": "Unknown project",
  "status": 404,
  "detail": "No project found for id 'spring-unknown'",
  "instance": "/projects/spring-unknown"
}
             
             

可以通过将spring.mvc.problemdetails.enabled设置为TRUE来启用此支持。

您还可以定义一个用@ControllerAdance注释的类,以自定义为特定控制器和/或异常类型返回的JSON文档,如下例所示:

Java
Kotlin
import jakarta.servlet.RequestDispatcher; import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; @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相同的包中定义的控制器引发的,则使用MyErrorBodyPOJO的JSON表示而不是ErrorAttributes表示。

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

Java
Kotlin
import jakarta.servlet.http.HttpServletRequest; import org.springframework.boot.web.servlet.error.ErrorAttributes; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; @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接口的Bean,如下例所示:

Java
Kotlin
import java.util.Map; import jakarta.servlet.http.HttpServletRequest; import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver; import org.springframework.http.HttpStatus; import org.springframework.web.servlet.ModelAndView; public class MyErrorViewResolver implements ErrorViewResolver { @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { // Use the request or status to optionally return a ModelAndView if (status == HttpStatus.INSUFFICIENT_STORAGE) { // We could add custom model values here new ModelAndView("myview"); } return null; } } 
              
              

您还可以使用常规的Spring MVC特性,如@ExceptionHandler方法@ControllerAdacy。然后,Error控制器拾取任何未处理的异常。

Mapping Error Pages Outside of Spring MVC

对于不使用Spring MVC的应用程序,可以使用ErrorPageRegister接口直接注册ErrorPages。这种抽象直接与底层嵌入的Servlet容器一起工作,即使您没有Spring MVCDispatcherServlet也可以工作。

Java
Kotlin
import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.server.ErrorPageRegistrar; import org.springframework.boot.web.server.ErrorPageRegistry; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; @Configuration(proxyBeanMethods = false) public class MyErrorPagesConfiguration { @Bean public ErrorPageRegistrar errorPageRegistrar() { return this::registerErrorPages; } private void registerErrorPages(ErrorPageRegistry registry) { registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400")); } } 
              
              
If you register an ErrorPage with a path that ends up being handled by a Filter (as is common with some non-Spring web frameworks, like Jersey and Wicket), then the Filter has to be explicitly registered as an ERROR dispatcher, as shown in the following example:
Java
Kotlin
import java.util.EnumSet; import jakarta.servlet.DispatcherType; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class MyFilterConfiguration { @Bean public FilterRegistrationBean<MyFilter> myFilter() { FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>(new MyFilter()); // ... registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class)); return registration; } } 
              
              

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

Error Handling in a WAR Deployment

当部署到Servlet容器时,Spring Boot使用其错误页过滤器将具有错误状态的请求转发到适当的错误页。这是必要的,因为Servlet规范不提供用于注册错误页面的API。根据您要将WAR文件部署到的容器和应用程序使用的技术,可能需要一些额外的配置。

如果尚未提交响应,则错误页筛选器只能将请求转发到正确的错误页。默认情况下,WebSphereApplicationServer8.0及更高版本在成功完成Servlet的服务方法后提交响应。应该通过将com.ibm.ws.webcontainer.invokeFlushAfterService设置为FALSE来禁用此行为。

1.1.11. CORS Support

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

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

Java
Kotlin
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration(proxyBeanMethods = false) public class MyCorsConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**"); } }; } } 
             
             

1.2. JAX-RS and Jersey

如果您更喜欢REST端点的JAX-RS编程模型,您可以使用一种可用的实现来代替Spring MVC。JerseyApacheCXF开箱即用。CXF要求您在应用程序上下文中将其Servlet过滤器注册为@Bean。Jersey有一些原生的Spring支持,所以我们还在Spring Boot中提供了对它的自动配置支持,以及一个启动器。

要开始使用Jersey,请包括作为依赖项的Spring-Boot-starter-Jersey,然后您需要一个@Bean类型的资源配置,您可以在其中注册所有端点,如下例所示:

import org.glassfish.jersey.server.ResourceConfig; import org.springframework.stereotype.Component; @Component public class MyJerseyConfig extends ResourceConfig { public MyJerseyConfig() { register(MyEndpoint.class); } } 
            
            
Jersey’s support for scanning executable archives is rather limited. For example, it cannot scan for endpoints in a package found in a fully executable jar file or in WEB-INF/classes when running an executable war file. To avoid this limitation, the packages method should not be used, and endpoints should be registered individually by using the register method, as shown in the preceding example.

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

所有注册的端点都应该是带有HTTP资源注释的@Components(@get等),如下例所示:

import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import org.springframework.stereotype.Component; @Component @Path("/hello") public class MyEndpoint { @GET public String message() { return "Hello"; } } 
            
            

因为Endpoint是一个Spring@Component,所以它的生命周期由Spring管理,您可以使用@AuTower注释注入依赖项,使用@Value注释注入外部配置。默认情况下,Jersey Servlet被注册并映射到/*。您可以通过将@ApplicationPath添加到您的ResourceConfig来更改映射。

默认情况下,Jersey被设置为ServletRegistrationBean类型的@Bean中的一个Servlet,名为JerseyServletRegister。缺省情况下,Servlet是延迟初始化的,但您可以通过设置spring.jersey.servlet.load-on-startup.来自定义该行为您可以通过使用相同的名称创建自己的Bean来禁用或覆盖该Bean。您还可以通过设置spring.Jersey.type=Filter来使用过滤器而不是Servlet(在这种情况下,要替换或覆盖的@BeanJerseyFilterRegister)。过滤器有一个@order,您可以使用spring.Jersey.filter.order设置它。当使用Jersey作为过滤器时,必须存在一个Servlet,该Servlet将处理任何未被Jersey拦截的请求。如果您的应用程序不包含这样的Servlet,您可能希望通过将server.servlet.register-default-servlet设置为TRUE来启用默认的Servlet。通过使用spring.Jersey.init.*指定属性映射,可以为Servlet和过滤器注册提供init参数。

1.3. Embedded Servlet Container Support

对于Servlet应用程序,Spring Boot支持嵌入式TomcatJettyUndertow服务器。大多数开发人员使用适当的“启动器”来获得完全配置的实例。默认情况下,嵌入式服务器侦听端口8080上的HTTP请求。

1.3.1. Servlets, Filters, and Listeners

在使用嵌入式Servlet容器时,您可以通过使用SpringBeans或扫描Servlet组件来注册Servlet、过滤器和来自Servlet规范的所有侦听器(如HttpSessionListener)。

Registering Servlets, Filters, and Listeners as Spring Beans

任何作为Spring Bean的Servlet过滤器或Servlet*Listener实例都注册到嵌入的容器中。如果您想在配置期间引用应用程序的值,这会特别方便。

默认情况下,如果上下文仅包含单个Servlet,则将其映射到/。在多个Servlet Bean的情况下,Bean名称用作路径前缀。筛选器映射到/*

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

通常情况下,将滤豆放在没有订购的地方是安全的。如果需要特定的订单,您应该用@Order来注释筛选器,或者让它实现Order。您不能通过使用@Order注释其Bean方法来配置筛选器的顺序。如果无法将Filter类更改为Add@Order或实现Order,则必须为FilterRegistrationBean定义FilterRegistrationBean,并使用setOrder(Int)方法设置注册Bean的顺序。避免配置以Ordered.HIGHEST_PRORCESS读取请求正文的过滤器,因为这可能与应用程序的字符编码配置相冲突。如果Servlet筛选器包装请求,则应该使用小于或等于OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER.的顺序进行配置

To see the order of every Filter in your application, enable debug level logging for the web logging group (logging.level.web=debug). Details of the registered filters, including their order and URL patterns, will then be logged at startup.
Take care when registering Filter beans since they are initialized very early in the application lifecycle. If you need to register a Filter that interacts with other beans, consider using a DelegatingFilterProxyRegistrationBean instead.

1.3.2. Servlet Context Initialization

嵌入式Servlet容器不直接执行jakarta.servlet.ServletContainerInitializer接口或Spring的org.springframework.web.WebApplicationInitializer接口。这是一个有意的设计决定,旨在降低设计用于在WAR中运行的第三方库可能会破坏Spring Boot应用程序的风险。

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

Scanning for Servlets, Filters, and listeners

当使用嵌入式容器时,可以使用@WebServlet@WebFilter@WebListener来自动注册带有@WebServlet的类。

@ServletComponentScan has no effect in a standalone container, where the container’s built-in discovery mechanisms are used instead.

1.3.3. The ServletWebServerApplicationContext

在幕后,Spring Boot使用不同类型的ApplicationContext来支持嵌入式Servlet容器。ServletWebServerApplicationContext是一种特殊类型的WebApplicationContext,它通过搜索单个ServletWebServerFactoryBean来引导自身。通常已自动配置了TomcatServletWebServerFactoryJettyServletWebServerFactoryUnderowServletWebServerFactory

You usually do not need to be aware of these implementation classes. Most applications are auto-configured, and the appropriate ApplicationContext and ServletWebServerFactory are created on your behalf.

在嵌入式容器设置中,ServletContext设置为服务器启动的一部分,服务器启动是在应用程序上下文初始化期间发生的。因此,无法使用ServletContext可靠地初始化ApplicationContext中的Bean。解决此问题的一种方法是将ApplicationContext作为Bean的依赖项注入,并仅在需要时访问ServletContext。另一种方法是在服务器启动后使用回调。这可以使用侦听ApplicationStartedEventApplicationListener来完成,如下所示:

import jakarta.servlet.ServletContext; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.web.context.WebApplicationContext; public class MyDemoBean implements ApplicationListener<ApplicationStartedEvent> { private ServletContext servletContext; @Override public void onApplicationEvent(ApplicationStartedEvent event) { ApplicationContext applicationContext = event.getApplicationContext(); this.servletContext = ((WebApplicationContext) applicationContext).getServletContext(); } } 
             
             

1.3.4. Customizing Embedded Servlet Containers

可以使用SpringEnvironment属性配置常见的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容器的特定功能进行配置。

See the ServerProperties class for a complete list.
SameSite Cookies

Web浏览器可以使用SameSiteCookie属性来控制是否以及如何在跨站点请求中提交Cookie。该属性对于已开始更改在缺少该属性时使用的缺省值的现代Web浏览器特别相关。

如果希望更改会话Cookie的<代码>SameSite 属性,则可以使用server.servlet.session.cookie.same-site属性。自动配置的Tomcat、Jetty和Undertow服务器支持此属性。它还用于配置基于SessionRepositoryBean的Spring Session Servlet。

例如,如果希望会话Cookie的SameSite属性为None,则可以将以下内容添加到Application.PropertiesApplication.yaml文件中:

Properties
Yaml
server.servlet.session.cookie.same-site=none
              
              

如果要更改添加到HttpServletResponse的其他Cookie的SameSite属性,可以使用CookieSameSiteSupplier。向CookieSameSiteSupplier传递Cookie,并且可能返回SameSite值或

有许多方便的工厂和筛选器方法可用于快速匹配特定的Cookie。例如,添加以下Bean将自动为名称与正则表达式myapp.*匹配的所有cookie应用SameSitelax

Java
Kotlin
import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class MySameSiteConfiguration { @Bean public CookieSameSiteSupplier applicationCookieSameSiteSupplier() { return CookieSameSiteSupplier.ofLax().whenHasNameMatching("myapp.*"); } } 
              
              
Programmatic Customization

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

Java
Kotlin
import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.stereotype.Component; @Component public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> { @Override public void customize(ConfigurableServletWebServerFactory server) { server.setPort(9000); } } 
              
              

TomcatServletWebServerFactoryJettyServletWebServerFactoryUnderowServletWebServerFactoryConfigurableServletWebServerFactory的专用变体,它们分别为Tomcat、Jetty和Undertow提供了额外的定制设置方法。以下示例显示如何自定义TomcatServletWebServerFactory,以提供对Tomcat特定配置选项的访问:

Java
Kotlin
import java.time.Duration; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.stereotype.Component; @Component public class MyTomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Override public void customize(TomcatServletWebServerFactory server) { server.addConnectorCustomizers((connector) -> connector.setAsyncTimeout(Duration.ofSeconds(20).toMillis())); } } 
              
              
Customizing ConfigurableServletWebServerFactory Directly

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

为许多配置选项提供了设置器。如果您需要做一些更奇特的事情,还提供了几个受保护的方法“钩子”。有关详细信息,请参阅源代码文档。

Auto-configured customizers are still applied on your custom factory, so use that option carefully.

1.3.5. JSP Limitations

在运行使用嵌入式Servlet容器(并打包为可执行归档文件)的Spring Boot应用程序时,在JSP支持方面存在一些限制。

  • 对于Jetty和Tomcat,如果您使用WAR包装,它应该可以工作。当使用Java-JAR启动时,可执行的WAR将工作,并且还可以部署到任何标准容器。使用可执行JAR时不支持JSP。

  • Undertow不支持JSP。

  • 创建自定义error.jsp页面不会覆盖错误处理的默认视图。应改用自定义错误页

2. Reactive Web Applications

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

2.1. The “Spring WebFlux Framework”

Spring WebFlux是Spring Framework5.0中引入的新的反应式Web框架。与Spring MVC不同,它不需要Servlet API,是完全异步和非阻塞的,并通过反应器项目实现了反应流规范。

Spring WebFlux有两种风格:函数式和基于注释。基于注释的模型非常接近于Spring MVC模型,如下例所示:

Java
Kotlin
import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.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 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); } } 
            
            

函数变量“WebFlos.fn”将路由配置与请求的实际处理分开,如下例所示:

Java
Kotlin
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.server.RequestPredicate; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.ServerResponse; import static org.springframework.web.reactive.function.server.RequestPredicates.accept; import static org.springframework.web.reactive.function.server.RouterFunctions.route; @Configuration(proxyBeanMethods = false) public class MyRoutingConfiguration { private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON); @Bean public 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(); } } 
            
            
Java
Kotlin
import reactor.core.publisher.Mono; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; @Component public class MyUserHandler { public Mono<ServerResponse> getUser(ServerRequest request) { ... } public Mono<ServerResponse> getUserCustomers(ServerRequest request) { ... } public Mono<ServerResponse> deleteUser(ServerRequest request) { ... } } 
            
            

WebFlux是Spring框架的一部分,详细信息可在其参考文档中找到。

You can define as many RouterFunction beans as you like to modularize the definition of the router. Beans can be ordered if you need to apply a precedence.

要开始使用,请将Spring-ot-starter-webflow模块添加到应用程序中。

Adding both spring-boot-starter-web and spring-boot-starter-webflux modules in your application results in Spring Boot auto-configuring Spring MVC, not WebFlux. This behavior has been chosen because many Spring developers add spring-boot-starter-webflux to their Spring MVC application to use the reactive WebClient. You can still enforce your choice by setting the chosen application type to SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE).

2.1.1. Spring WebFlux Auto-configuration

Spring Boot为Spring WebFlux提供了自动配置,可以很好地与大多数应用程序配合使用。

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

  • HttpMessageReaderHttpMessageWriter实例配置编解码器(本文档后面部分介绍)。

  • 支持提供静态资源,包括对WebJars的支持(本文档后面将介绍)。

如果您想要保留Spring Boot WebFlux特性,并且想要添加额外的WebFlux配置,您可以添加您自己的@Configuration类,其类型为WebFlosConfigurer没有@EnableWebFlux

如果您想要完全控制Spring WebFlux,可以添加您自己的@configuration,并用@EnableWebFlux进行注释。

2.1.2. HTTP Codecs with HttpMessageReaders and HttpMessageWriters

Spring WebFlux使用HttpMessageReaderHttpMessageWriter接口来转换HTTP请求和响应。通过查看类路径中可用的库,使用CodecConfigurer将它们配置为具有合理的缺省值。

Spring Boot为编解码器提供专用的配置属性,spring.codec..*。它还通过使用CodecCustomizer实例应用进一步的定制。例如,spring.jackson.*配置密钥应用于Jackson编解码器。

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

Java
Kotlin
import org.springframework.boot.web.codec.CodecCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.codec.ServerSentEventHttpMessageReader; @Configuration(proxyBeanMethods = false) public class MyCodecsConfiguration { @Bean public CodecCustomizer myCodecCustomizer() { return (configurer) -> { configurer.registerDefaults(false); configurer.customCodecs().register(new ServerSentEventHttpMessageReader()); // ... }; } } 
             
             

2.1.3. Static Content

默认情况下,Spring Boot提供类路径中名为/静态(或/public/resource/META-INF/resource)目录中的静态内容。它使用来自Spring WebFlux的ResourceWebHandler,因此您可以通过添加您自己的WebFlosConfigurer并覆盖addResourceHandler方法来修改该行为。

默认情况下,资源映射到/**,但您可以通过设置spring.webflux.static-path-pattern属性对其进行优化。例如,将所有资源重定位到/resource/**的方法如下:

Properties
Yaml
spring.webflux.static-path-pattern=/resources/**
             
             

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

除了前面列出的“标准”静态资源位置之外,还为Webjars内容设置了一个特例。默认情况下,路径在/webjars/**中的任何资源都由JAR文件提供,如果它们以Webjars格式打包的话。可以使用spring.webflux.webjars-path-pattern属性自定义路径。

Spring WebFlux applications do not strictly depend on the servlet API, so they cannot be deployed as war files and do not use the src/main/webapp directory.

2.1.4. Welcome Page

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

2.1.5. Template Engines

除了REST Web服务,您还可以使用Spring WebFlux来提供动态的HTML内容。Spring WebFlux支持多种模板技术,包括Thymeleaf、FreeMarker和Mustache。

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

当您以默认配置使用这些模板引擎之一时,您的模板将自动从src/main/Resources/Templates中选取。

2.1.6. Error Handling

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

在直接定制Spring Boot中的错误处理之前,您可以利用Spring WebFlux中的RFC7807问题详细信息支持。Spring WebFlux可以生成应用程序/问题+json媒体类型的自定义错误消息,例如:

{
  "type": "https://example.org/problems/unknown-project",
  "title": "Unknown project",
  "status": 404,
  "detail": "No project found for id 'spring-unknown'",
  "instance": "/projects/spring-unknown"
}
             
             

可以通过将spring.webflux.problemdetails.enabled设置为TRUE来启用此支持。

定制此功能的第一步通常涉及使用现有机制,但替换或增加错误内容。为此,您可以添加ErrorAttributes类型的Bean。

要更改错误处理行为,您可以实现ErrorWebExceptionHandler并注册该类型的Bean定义。由于ErrorWebExceptionHandler是相当底层的,Spring Boot还提供了一个方便的AbstractErrorWebExceptionHandler,可以让您以WebFlux函数的方式处理错误,如下例所示:

Java
Kotlin
import reactor.core.publisher.Mono; import org.springframework.boot.autoconfigure.web.WebProperties.Resources; import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler; import org.springframework.boot.web.reactive.error.ErrorAttributes; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.function.server.ServerResponse.BodyBuilder; @Component public class MyErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler { public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, Resources resources, ApplicationContext applicationContext) { super(errorAttributes, resources, applicationContext); } @Override protected 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 calls return builder.build(); } } 
             
             

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

Java
Kotlin
import org.springframework.boot.web.reactive.error.ErrorAttributes; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.reactive.result.view.Rendering; import org.springframework.web.server.ServerWebExchange; @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目录。错误页可以是静态的HTML(即,添加到任何静态资源目录下),也可以是使用模板构建的。文件的名称应该是确切的状态代码或系列掩码。

例如,要将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>
              
              

2.1.7. Web Filters

Spring WebFlux提供了一个WebFilter接口,可以实现该接口来过滤HTTP请求-响应交换。WebFilter在应用程序上下文中找到的Bean将自动用于筛选每个交换。

在过滤器的顺序很重要的地方,它们可以实现ordered或使用@order进行注释。Spring Boot自动配置可以为您配置网络过滤器。执行此操作时,将使用下表中所示的订单:

Web Filter Order

WebFilterChainProxy(Spring Security)

-100

HttpExchangesWebFilter

Ordered.LOWEST_PRIORENCE-10

2.2. Embedded Reactive Server Support

Spring Boot包括对以下嵌入式反应式Web服务器的支持:Reader Netty、Tomcat、Jetty和Undertow。大多数开发人员使用适当的“启动器”来获得完全配置的实例。默认情况下,嵌入式服务器侦听端口8080上的HTTP请求。

2.3. Reactive Server Resources Configuration

当自动配置反应器Netty或Jetty服务器时,Spring Boot将创建特定的Bean,这些Bean将向服务器实例提供HTTP资源:ReacterResourceFactoryJettyResourceFactory

默认情况下,这些资源还将与反应堆Netty和Jetty客户端共享,以实现最佳性能,前提是:

  • 服务器和客户端使用相同的技术

  • 客户端实例是使用由Spring Boot自动配置的WebClient.BuilderBean构建的

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

您可以在WebClient运行时部分中了解有关客户端资源配置的更多信息。

3. Graceful Shutdown

所有四个嵌入式Web服务器(Jetty、Reactive Netty、Tomcat和Undertow)以及反应性Web应用程序和基于Servlet的Web应用程序都支持正常关闭。它发生在关闭应用程序上下文的过程中,并在停止SmartLifeccleBean的最早阶段执行。此停止处理使用超时,该超时提供了一段宽限期,在此期间将允许完成现有请求,但不允许任何新请求。不允许新请求的确切方式因所使用的Web服务器而异。Jetty、Reader Netty和Tomcat将停止在网络层接受请求。Untow将接受请求,但立即以服务不可用(503)响应响应。

Graceful shutdown with Tomcat requires Tomcat 9.0.33 or later.

要启用正常关闭,请配置server.Shutdown属性,如下例所示:

Properties
Yaml
server.shutdown=graceful
           
           

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

Properties
Yaml
spring.lifecycle.timeout-per-shutdown-phase=20s
           
           
Using graceful shutdown with your IDE may not work properly if it does not send a proper SIGTERM signal. See the documentation of your IDE for more details.

4. Spring Security

如果Spring Security在类路径上,则默认情况下Web应用程序是受保护的。Spring Boot依靠Spring Security的内容协商策略来确定是使用httpBasic还是使用formLogin。要向Web应用程序添加方法级安全性,还可以使用所需设置添加@EnableGlobalMethodSecurity。更多信息可以在Spring Security Reference Guide中找到。

默认UserDetailsService只有一个用户。用户名为user,密码是随机的,在应用程序启动时打印为警告级别,如下例所示:

Using generated security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35

This generated password is for development use only. Your security configuration must be updated before running your application in production.
If you fine-tune your logging configuration, ensure that the org.springframework.boot.autoconfigure.security category is set to log WARN-level messages. Otherwise, the default password is not printed.

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

默认情况下,您在Web应用程序中获得的基本功能包括:

  • 一个 SecurityProperties.User>UserDetailsService (或<代码>Reactive UserDetailsService ,如果是WebFlux应用程序)Bean,具有内存存储和具有生成的密码的单个用户(有关用户的属性,请参阅

  • 整个应用程序(包括执行器端点,如果执行器在类路径上)的基于表单的登录或HTTP基本安全性(取决于请求中的Accept头)。

  • 用于发布身份验证事件的DefaultAuthenticationEventPublisher

您可以通过为其添加一个Bean来提供不同的AuthenticationEventPublisher

4.1. MVC Security

默认安全配置在SecurityAutoConfigurationUserDetailsServiceAutoConfiguration.中实现安全自动配置导入用于Web安全的SpringBootWebSecurityConfigurationUserDetailsServiceAutoConfiguration配置身份验证,这也与非Web应用程序相关。要完全关闭默认的Web应用程序安全配置或组合多个Spring Security组件,如OAuth2客户端和资源服务器,添加一个SecurityFilterChain类型的Bean(这样做并不会禁用UserDetailsService配置或Actuator的安全性)。

若要同时关闭UserDetailsService配置,您可以添加UserDetailsServiceAuthenticationProviderAuthenticationManager类型的Bean。

可以通过添加自定义SecurityFilterChainBean来覆盖访问规则。Spring Boot提供了方便的方法,可用于覆盖执行器端点和静态资源的访问规则。EndpointRequest可用于创建基于management.endpoints.web.base-path属性的RequestMatcher路径请求可以为常用位置的资源创建RequestMatcher

4.2. WebFlux Security

与Spring MVC应用程序类似,您可以通过添加Spring-ot-starter-security依赖项来保护WebFlux应用程序。默认安全配置在ReactiveSecurityAutoConfigurationUserDetailsServiceAutoConfiguration.中实施ReactiveSecurityAutoConfiguration为Web安全导入WebFlosSecurityConfigurityUserDetailsServiceAutoConfiguration配置身份验证,这在非Web应用中也是相关的。要完全关闭默认的Web应用程序安全配置,您可以添加一个WebFilterChainProxy类型的Bean(这样做并不会禁用UserDetailsService配置或Actuator的安全性)。

若要同时关闭UserDetailsService配置,您可以添加Reactive UserDetailsServiceReactive AuthationManager类型的Bean。

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

路径请求可以为常用位置的资源创建ServerWebExchangeMatcher

例如,您可以通过添加以下内容来自定义您的安全配置:

Java
Kotlin
import org.springframework.boot.autoconfigure.security.reactive.PathRequest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; import static org.springframework.security.config.Customizer.withDefaults; @Configuration(proxyBeanMethods = false) public class MyWebFluxSecurityConfiguration { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http.authorizeExchange((exchange) -> { exchange.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll(); exchange.pathMatchers("/foo", "/bar").authenticated(); }); http.formLogin(withDefaults()); return http.build(); } } 
            
            

4.3. OAuth2

OAuth2是一个得到Spring支持的广泛使用的授权框架。

4.3.1. Client

如果您的类路径上有Spring-Security-OAuth2-Client,那么您可以利用一些自动配置来设置OAuth2/Open ID Connect客户端。此配置使用OAuth2ClientProperties下的属性。相同的属性适用于Servlet和反应式应用程序。

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

Properties
Yaml
spring.security.oauth2.client.registration.my-client-1.client-id=abcd
spring.security.oauth2.client.registration.my-client-1.client-secret=password
spring.security.oauth2.client.registration.my-client-1.client-name=Client for user scope
spring.security.oauth2.client.registration.my-client-1.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-1.scope=user
spring.security.oauth2.client.registration.my-client-1.redirect-uri=https://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-1.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-1.authorization-grant-type=authorization_code

spring.security.oauth2.client.registration.my-client-2.client-id=abcd
spring.security.oauth2.client.registration.my-client-2.client-secret=password
spring.security.oauth2.client.registration.my-client-2.client-name=Client for email scope
spring.security.oauth2.client.registration.my-client-2.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-2.scope=email
spring.security.oauth2.client.registration.my-client-2.redirect-uri=https://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-2.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-2.authorization-grant-type=authorization_code

spring.security.oauth2.client.provider.my-oauth-provider.authorization-uri=https://my-auth-server/oauth/authorize
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=https://my-auth-server/oauth/token
spring.security.oauth2.client.provider.my-oauth-provider.user-info-uri=https://my-auth-server/userinfo
spring.security.oauth2.client.provider.my-oauth-provider.user-info-authentication-method=header
spring.security.oauth2.client.provider.my-oauth-provider.jwk-set-uri=https://my-auth-server/token_keys
spring.security.oauth2.client.provider.my-oauth-provider.user-name-attribute=name
             
             

对于支持OpenID Connect发现的OpenID Connect提供商,可以进一步简化配置。提供者需要配置一个Issuer-uri,这是它断言为其颁发者标识符的URI。例如,如果提供的颁发者-uri是“https://example.com”,“,则将向”https://example.com/.well-known/openid-configuration“.发出OpenID提供者配置请求预期结果将是OpenID提供程序配置响应。以下示例显示如何使用Issuer-uri配置OpenID Connect提供程序:

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

默认情况下,Spring Security的OAuth2LoginAuthenticationFilter只处理与/login/OAuth2/code/*匹配的URL。如果您想要自定义重定向-uri以使用不同的模式,则需要提供处理该自定义模式的配置。例如,对于Servlet应用程序,您可以添加自己的SecurityFilterChain,如下所示:

Java
Kotlin
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration(proxyBeanMethods = false) public class MyOAuthClientConfiguration { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated()); http.oauth2Login((login) -> login.redirectionEndpoint().baseUri("custom-callback")); return http.build(); } } 
             
             
Spring Boot auto-configures an InMemoryOAuth2AuthorizedClientService which is used by Spring Security for the management of client registrations. The InMemoryOAuth2AuthorizedClientService has limited capabilities and we recommend using it only for development environments. For production environments, consider using a JdbcOAuth2AuthorizedClientService or creating your own implementation of OAuth2AuthorizedClientService.
OAuth2 Client Registration for Common Providers

对于常见的OAuth2和OpenID提供者,包括Google、Github、Facebook和Okta,我们提供了一组提供者默认设置(分别为GoogleGitHubFacebookOkta)。

如果不需要自定义这些提供程序,则可以将提供程序属性设置为需要推断其缺省值的属性。此外,如果客户端注册的键与默认支持的提供程序匹配,则Spring Boot也会推断出这一点。

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

Properties
Yaml
spring.security.oauth2.client.registration.my-client.client-id=abcd
spring.security.oauth2.client.registration.my-client.client-secret=password
spring.security.oauth2.client.registration.my-client.provider=google
spring.security.oauth2.client.registration.google.client-id=abcd
spring.security.oauth2.client.registration.google.client-secret=password
              
              

4.3.2. Resource Server

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

Properties
Yaml
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://example.com/oauth2/default/v1/keys
             
             
Properties
Yaml
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/
             
             
If the authorization server does not support a JWK Set URI, you can configure the resource server with the Public Key used for verifying the signature of the JWT. This can be done using the spring.security.oauth2.resourceserver.jwt.public-key-location property, where the value needs to point to a file containing the public key in the PEM-encoded x509 format.

相同的属性适用于Servlet和反应式应用程序。

或者,您可以为Servlet应用程序定义您自己的JwtDecoderBean,或者为反应式应用程序定义一个Reactive JwtDecoder

在使用不透明令牌而不是JWT的情况下,您可以配置以下属性以通过自检验证令牌:

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

同样,相同的属性也适用于Servlet和反应式应用程序。

或者,您可以为Servlet应用程序定义您自己的OpaqueTokenIntrospectorBean,或者为反应式应用程序定义一个Reactive OpaqueTokenIntrospector

4.3.3. Authorization Server

目前,Spring Security不支持实现OAuth 2.0授权服务器。然而,该功能可以从Spring Security OAuth项目中获得,该项目最终将被Spring Security完全取代。在此之前,您可以使用spring-security-oauth2-autoconfigure模块轻松设置OAuth2.0授权服务器;有关说明,请参阅其文档。

4.4. SAML 2.0

4.4.1. Relying Party

如果您的类路径上有spring-security-saml2-service-provider,则可以利用一些自动配置来设置SAML2.0依赖方。此配置使用Saml2RelyingPartyProperties下的属性。

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

Properties
Yaml
spring.security.saml2.relyingparty.registration.my-relying-party1.signing.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-party1.signing.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-party1.decryption.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-party1.decryption.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-party1.singlelogout.url=https://myapp/logout/saml2/slo
spring.security.saml2.relyingparty.registration.my-relying-party1.singlelogout.response-url=https://remoteidp2.slo.url
spring.security.saml2.relyingparty.registration.my-relying-party1.singlelogout.binding=POST
spring.security.saml2.relyingparty.registration.my-relying-party1.assertingparty.verification.credentials[0].certificate-location=path-to-verification-cert
spring.security.saml2.relyingparty.registration.my-relying-party1.assertingparty.entity-id=remote-idp-entity-id1
spring.security.saml2.relyingparty.registration.my-relying-party1.assertingparty.sso-url=https://remoteidp1.sso.url

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

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

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration(proxyBeanMethods = false) public class MySamlRelyingPartyConfiguration { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests().anyRequest().authenticated(); http.saml2Login(); http.saml2Logout((saml2) -> saml2.logoutRequest((request) -> request.logoutUrl("/SLOService.saml2")) .logoutResponse((response) -> response.logoutUrl("/SLOService.saml2"))); return http.build(); } } 
             
             

5. Spring Session

Spring Boot为各种数据存储提供了SpringSession自动配置。构建Servlet Web应用程序时,可以自动配置以下存储:

  • 雷迪斯人

  • JDBC

  • 黑兹卡斯特

  • MongoDB

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

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

如果类路径上存在单个Spring会话模块,则Spring Boot会自动使用该存储实现。如果您有多个实现,则Spring Boot使用以下顺序来选择特定的实现:

  1. 雷迪斯人

  2. JDBC

  3. 黑兹卡斯特

  4. MongoDB

  5. 如果Redis、JDBC、Hazelcast和MongoDB都不可用,则不配置SessionRepository

在构建反应式Web应用程序时,可以自动配置以下存储:

  • 雷迪斯人

  • MongoDB

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

与Servlet配置类似,如果您有多个实现,则Spring Boot使用以下顺序来选择特定的实现:

  1. 雷迪斯人

  2. MongoDB

  3. 如果Redis和MongoDB都不可用,则不配置Reactive SessionRepository

每个商店都有特定的附加设置。例如,可以定制JDBC存储的表名称,如下例所示:

Properties
Yaml
spring.session.jdbc.table-name=SESSIONS
           
           

要设置会话的超时,可以使用spring.ession.timeout属性。如果未使用Servlet Web应用程序设置该属性,则自动配置将恢复为server.servlet.ession.timeout的值。

您可以使用@Enable*HttpSession(Servlet)或@Enable*WebSession(被动)来控制Spring会话的配置。这将导致自动配置后退。然后,可以使用注释的属性来配置Spring会话,而不是使用前面描述的配置属性。

6. Spring for GraphQL

如果您想构建GraphQL应用程序,您可以利用Spring Boot对Spring for GraphQL的自动配置。Spring for GraphQL项目基于GraphQL Java。您至少需要Spring-Boot-starter-GraphQLstarter。因为GraphQL与传输无关,所以您还需要在应用程序中有一个或多个额外的启动器,才能在Web上公开您的GraphQL API:

Starter Transport Implementation

Spring-Boot-starter-web

HTTP

Spring MVC

Spring-Boot-starter-WebSocket

WebSocket

Servlet应用程序的WebSocket

Spring-boot-starter-webflow

HTTP、WebSocket

Spring WebFlux

Spring-Boot-starter-r套接字

TCP、WebSocket

反应堆网上的Spring WebFlux

6.1. GraphQL Schema

一个Spring GraphQL应用程序需要在启动时定义一个模式。默认情况下,您可以在src/main/resource/GraphQL/**下编写“.graph qls”或“.gqls”模式文件,Spring Boot会自动获取它们。您可以使用spring.graph ql.schema.Locations和使用spring.graphql.schema.file-extensions.的文件扩展名来自定义位置

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).

在接下来的部分中,我们将考虑这个样例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
}
            
            
By default, field introspection will be allowed on the schema as it is required for tools such as GraphiQL. If you wish to not expose information about the schema, you can disable introspection by setting spring.graphql.schema.introspection.enabled to false.

6.2. GraphQL RuntimeWiring

GraphQL JavaRounmeWiring.Builder可用于注册自定义标量类型、指令、类型解析器、DataFetcher等。您可以在您的Spring配置中声明`RounmeWiringConfigurerBean来访问RounmeWiring.Builder。Spring Boot检测到这样的Bean,并将它们添加到GraphQlSource构建器

然而,通常情况下,应用程序不会直接实现DataFetcher,而是创建注释控制器。Spring Boot将自动检测带有带注释的处理程序方法的@Controler类,并将这些类注册为DataFetcher的类。以下是带有`@Controler类的问候语查询的示例实现:

Java
Kotlin
import org.springframework.graphql.data.method.annotation.Argument; import org.springframework.graphql.data.method.annotation.QueryMapping; import org.springframework.stereotype.Controller; @Controller public class GreetingController { @QueryMapping public String greeting(@Argument String name) { return "Hello, " + name + "!"; } } 
            
            

6.3. Querydsl and QueryByExample Repositories Support

Spring Data提供了对Querydsl和QueryByExample存储库的支持。Spring GraphQL可以将Querydsl和QueryByExample存储库配置为DataFetcher

@GraphQlRepository注释并扩展以下内容之一的Spring数据存储库:

  • QuerydslPredicateExecutor

  • ReactiveQuerydslPredicateExecutor

  • QueryByExampleExecutor

  • Reactive QueryByExampleExecutor

被Spring Boot检测到,并被认为是匹配顶级查询的DataFetcher的候选者。

6.4. Transports

6.4.1. HTTP and WebSocket

默认情况下,GraphQL HTTP终结点位于HTTP POST“/GraphQL”。路径可以通过spring.graph ql.Path进行自定义。

The HTTP endpoint for both Spring MVC and Spring WebFlux is provided by a RouterFunction bean with an @Order of 0. If you define your own RouterFunction beans, you may want to add appropriate @Order annotations to ensure that they are sorted correctly.

默认情况下,GraphQL WebSocket终结点处于关闭状态。要启用它,请执行以下操作:

  • 对于Servlet应用程序,添加WebSocket starterSpring-ot-starter-web套接字

  • 对于WebFlux应用程序,不需要其他依赖项

  • 对于这两者,都必须设置spring.graph ql.websocket.Path应用程序属性

Spring GraphQL提供了一个Web拦截模型。这对于从HTTP请求报头中检索信息并将其设置在GraphQL上下文中,或者从相同的上下文中获取信息并将其写入响应报头非常有用。使用Spring Boot,您可以声明一个WebInterceptorBean,以便将其注册到Web传输。

Spring MVCSpring WebFlux支持CORS(跨域资源共享)请求。CORS是GraphQL应用程序Web配置的关键部分,可以从使用不同域的浏览器访问这些应用程序。

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

Properties
Yaml
spring.graphql.cors.allowed-origins=https://example.org
spring.graphql.cors.allowed-methods=GET,POST
spring.graphql.cors.max-age=1800s
             
             

6.4.2. RSocket

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

RSocketGraphQlClient.Builder<;?>;Boot自动配置您可以注入组件中的Spring Bean:

Java
Kotlin
@Component
public class RSocketGraphQlClientExample {

    private final RSocketGraphQlClient graphQlClient;

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

             
             

然后发送一个请求:

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

             
             

6.5. Exceptions Handling

Spring GraphQL使应用程序能够注册一个或多个按顺序调用的SpringDataFetcherExceptionResolver组件。必须将异常解析为graph ql.GraphQLError对象的列表,请参阅Spring GraphQL异常处理文档。Spring Boot将自动检测DataFetcherExceptionResolverBean,并使用GraphQlSource.Builder注册它们。

6.6. GraphiQL and Schema printer

Spring GraphQL提供了在使用或开发GraphQL API时帮助开发人员的基础设施。

Spring GraphQL附带了一个默认的GraphiQL页面,该页面默认显示在“/graph iql”。默认情况下,此页处于禁用状态,可以使用spring.graph ql.graph iql.Enabled属性打开它。许多公开此类页面的应用程序将倾向于自定义生成。默认实现在开发期间非常有用,这就是为什么它在开发期间自动用spring-boot-devtools公开的原因。

当启用spring.graphql.schema.printer.enabled属性时,您还可以选择在<代码>/GraphQL/SCHEMA处以文本格式公开GraphQL架构。

7. Spring HATEOAS

如果您开发了一个利用超媒体的RESTful API,那么Spring Boot为Spring HATEOAS提供了自动配置,可以很好地与大多数应用程序配合使用。自动配置取代了使用@EnableHypermediaSupport的需要,并注册了许多Bean来简化基于超媒体的应用程序的构建,包括LinkDiscoverers(用于客户端支持)和ObjectMapper,它们被配置为将响应正确地编组到所需的表示形式中。对象映射器是通过设置各种spring.jackson.*属性或Jackson2ObjectMapperBuilderBean(如果存在)来自定义的。

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

spring-boot-starter-hateoas is specific to Spring MVC and should not be combined with Spring WebFlux. In order to use Spring HATEOAS with Spring WebFlux, you can add a direct dependency on org.springframework.hateoas:spring-hateoas along with spring-boot-starter-webflux.

8. What to Read Next

您现在应该已经很好地理解了如何使用Spring Boot开发Web应用程序。接下来的几节描述了Spring Boot如何与各种数据技术消息传递系统和其他IO功能集成。您可以根据应用程序的需要选择其中的任何一种。