20191128 Spring Boot官方文档学习(9.4-9.8)
9.4。Spring MVC
Spring Boot有许多启动器包含Spring MVC。请注意,一些启动器包括对Spring MVC的依赖,而不是直接包含它。
9.4.1。编写JSON REST服务
只要Jackson2
在类路径上,Spring Boot应用程序中的任何Spring @RestController
默认情况下都应呈现JSON响应,如以下示例所示:
@RestController
public class MyController {
@RequestMapping("/thing")
public MyThing thing() {
return new MyThing();
}
}
只要MyThing可以由Jackson2序列化(对于普通的POJO或Groovy对象为true),则localhost:8080/thing
默认情况下会为其提供JSON表示。请注意,在浏览器中,有时可能会看到XML响应,因为浏览器倾向于发送XML的接受标头。
9.4.2。编写XML REST服务
如果类路径上具有Jackson XML扩展(jackson-dataformat-xml
),则可以使用它来呈现XML响应。我们用于JSON的先前示例可以正常工作。要使用Jackson XML渲染器,请将以下依赖项添加到您的项目中:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
如果无法使用Jackson的XML扩展而可以使用JAXB,则可以将MyThing注释为@XmlRootElement
,如以下示例所示:
@XmlRootElement
public class MyThing {
private String name;
// .. getters and setters
}
JAXB仅在Java 8中是开箱即用的。如果您使用的是较新的Java版本,请在项目中添加以下依赖项:
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
要使服务器呈现XML而不是JSON,您可能必须发送Accept: text/xml
标头(或使用浏览器)。
9.4.3。自定义Jackson ObjectMapper
Spring MVC(客户端和服务器端)使用HttpMessageConverters
来协商HTTP交换中的内容转换。如果Jackson在类路径中,则您已经获得Jackson2ObjectMapperBuilder
所提供的默认转换器,该转换器的实例已为您自动配置。
ObjectMapper
(或Jackson XML转换器XmlMapper)实例(默认创建)具有以下定义的属性:
MapperFeature.DEFAULT_VIEW_INCLUSION
被禁用DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
被禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
被禁用
Spring Boot还具有一些功能,可以更轻松地自定义此行为。
您可以使用Environment配置ObjectMapper
和XmlMapper
实例。Jackson提供了一套广泛的简单的开/关功能,可用于配置其处理的各个方面。在六个枚举(在Jackson中)中描述了这些功能,这些枚举映射到环境中的属性:
Enum | 属性 | 值域 |
---|---|---|
com.fasterxml.jackson.databind.DeserializationFeature | spring.jackson.deserialization.<feature_name> | true,false |
com.fasterxml.jackson.core.JsonGenerator.Feature | spring.jackson.generator.<feature_name> | true,false |
com.fasterxml.jackson.databind.MapperFeature | spring.jackson.mapper.<feature_name> | true,false |
com.fasterxml.jackson.core.JsonParser.Feature | spring.jackson.parser.<feature_name> | true,false |
com.fasterxml.jackson.databind.SerializationFeature | spring.jackson.serialization.<feature_name> | true,false |
com.fasterxml.jackson.annotation.JsonInclude.Include | spring.jackson.default-property-inclusion | always,non_null,non_absent,non_default,non_empty |
例如,要启用漂亮打印,请设置spring.jackson.serialization.indent_output=true
。请注意,由于使用了宽松绑定,indent_output的大小写不必与相应的枚举常量INDENT_OUTPUT的大小写匹配。
这种基于Environment的配置适用于自动配置的Jackson2ObjectMapperBuilder
Bean,并且适用于使用构建器创建的任何映射器,包括自动配置的ObjectMapper
Bean。
上下文中的Jackson2ObjectMapperBuilder
可以由一个或多个Jackson2ObjectMapperBuilderCustomizer
bean 自定义。可以对此类定制器beans进行排序(SpringBoot自己的定制器的顺序为0),从而可以在SpringBoot定制之前和之后应用其他定制。
任何类型的com.fasterxml.jackson.databind.Module
bean都会自动向自动配置的Jackson2ObjectMapperBuilder
中注册,并应用于它创建的任何ObjectMapper
实例。当您向应用程序中添加新功能时,这提供了一种用于贡献自定义模块的全局机制。
如果要ObjectMapper完全替换默认值,请定义该类型的@Bean并将其标记为@Primary
,或者,如果您更喜欢基于构建器的方法,请定义一个Jackson2ObjectMapperBuilder
@Bean。请注意,无论哪种情况,这样做都会禁用ObjectMapper的所有自动配置。
如果提供任何MappingJackson2HttpMessageConverter
类型的@Bean,它们将替换MVC配置中的默认值。另外,还提供了一种HttpMessageConverters
类型的便捷bean (如果使用默认的MVC配置,该bean 始终可用)。它提供了一些有用的方法来访问默认的和用户增强的消息转换器。
有关更多详细信息,请参见WebMvcAutoConfiguration
源代码。
源码学习:
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonProperties
9.4.4。自定义@ResponseBody渲染
Spring使用HttpMessageConverters
渲染@ResponseBody
(或@RestController
的响应)。您可以通过在Spring Boot上下文中添加适当类型的bean来贡献额外的转换器。如果您添加的bean的类型无论如何都是默认包含的(例如用于JSON转换的MappingJackson2HttpMessageConverter
),它将替换默认值。如果您使用默认的MVC配置,HttpMessageConverters
类型的便捷bean将始终可用。它提供了一些有用的方法来访问默认的和用户增强的消息转换器(例如,如果您想将它们手动注入到custom RestTemplate中,可能会很有用)。
与正常的MVC用法一样,您提供的任何WebMvcConfigurer
bean也可以通过重写configureMessageConverters
方法来贡献转换器。但是,与普通的MVC不同,您只能提供所需的其他转换器(因为Spring Boot使用相同的机制来提供其默认值)。最后,如果您通过提供自己的@EnableWebMvc
配置来退出Spring Boot默认MVC 配置,则可以使用WebMvcConfigurationSupport
的getMessageConverters
方法完全控制并手动完成所有操作。
请参阅WebMvcAutoConfiguration
源代码以获取更多详细信息。
9.4.5。处理分段文件上传
Spring Boot包含Servlet 3 的 javax.servlet.http.Part
API以支持上传文件。默认情况下,Spring Boot将Spring MVC配置为单个请求中每个文件最大大小为1MB,最大文件数据为10MB。您可以覆盖这些值,使用MultipartProperties
类公开的属性覆盖中间数据的存储位置(例如,存储到/tmp目录)以及将数据刷新到磁盘的阈值。例如,如果您要指定文件不受限制,请将spring.servlet.multipart.max-file-size
属性设置为-1。
当您想在Spring MVC控制器处理程序方法中将多部分编码的文件数据作为带@RequestParam
注释的MultipartFile
类型的参数来接收时,多部分支持会很有帮助。
有关MultipartAutoConfiguration
更多详细信息,请参见源码。
建议使用容器的内置支持进行分段上传,而不要引入其他依赖项,例如Apache Commons File Upload。
9.4.6。关闭Spring MVC DispatcherServlet
默认情况下,所有内容均从应用程序的根目录(/)提供。如果您希望映射到其他路径,则可以如下配置:
spring.mvc.servlet.path=/acme
如果您有其他servlet,则可以声明一个类型为Servlet或ServletRegistrationBean
的@Bean,然后Spring Boot会将它们透明地注册到容器。由于Servlet是通过这种方式注册的,因此可以将它们映射到DispatcherServlet
的子上下文而无需调用它。
配置您自己的DispatcherServlet是不寻常的,但是如果您确实需要这样做,则还必须提供一个 DispatcherServletPath
类型的@Bean来提供自定义DispatcherServlet的路径。
9.4.7。关闭默认的MVC配置
完全控制MVC配置的最简单方法是为您自己的@Configuration
提供@EnableWebMvc
注释。这样做会使您掌握所有MVC配置。
9.4.8。自定义ViewResolvers
ViewResolver
是Spring MVC的核心组件,将@Controller
中的视图名称转换为实际的View实现。请注意,ViewResolvers主要用于UI应用程序,而不是REST风格的服务(View不用于呈现@ResponseBody
)。有很多ViewResolver实现可供选择,Spring本身对是否应使用哪个没有意见。另一方面,Spring Boot根据在类路径和应用程序上下文中找到的内容为您安装一个或两个。DispatcherServlet会使用它在应用程序上下文中找到的所有解析器,依次尝试每个解析器,直到获得结果为止。如果添加自己的解析器,则必须知道其顺序以及解析器的添加位置。
WebMvcAutoConfiguration
将以下ViewResolvers添加到您的上下文中:
- 一个名为
defaultViewResolver
的InternalResourceViewResolver
。此Resolver查找可以通过使用DefaultServlet渲染的物理资源(包括静态资源和JSP页面,如果使用的话)。它将一个前缀和一个后缀应用于视图名称,然后在Servlet上下文中查找具有该路径的物理资源(默认值均为空,但可以通过spring.mvc.view.prefix
和spring.mvc.view.suffix
进行外部配置访问)。您可以通过提供相同类型的bean覆盖它。 - 一个名为
beanNameViewResolver
的BeanNameViewResolver
。这是视图解析器链的有用成员,可以拾取与被解析View名称相同的所有bean 。不必重写或替换它。 - 仅当实际存在类型为View的 bean的情况下,才添加一个名为
viewResolver
的ContentNegotiatingViewResolver
。这是一个“主”解析器,委派给所有其他解析器,并尝试查找与客户端发送的“Accept” HTTP标头匹配的内容。您可以通过定义一个名为viewResolver
的ContentNegotiatingViewResolver
bean 来关闭自动配置。 - 如果您使用
Thymeleaf
,则还有一个名为thymeleafViewResolver
的ThymeleafViewResolver
。它通过在视图名称前后加上前缀和后缀来查找资源。前缀为spring.thymeleaf.prefix
,后缀为spring.thymeleaf.suffix
。前缀和后缀的值分别默认为classpath/templates/
和.html
。您可以通过提供相同名称的bean 来覆盖ThymeleafViewResolver
。 - 如果您使用
FreeMarker
,则还有一个名为freeMarkerViewResolver
的FreeMarkerViewResolver
。它通过在视图名称前加上前缀和后缀来在加载程序路径spring.freemarker.templateLoaderPath
(已外部化并具有默认值classpath:/templates/
)中查找资源。前缀被外部化为spring.freemarker.prefix
,后缀被外部化为spring.freemarker.suffix
。前缀和后缀的默认值分别为空和.ftlh
。您可以通过提供相同名称的bean 来覆盖FreeMarkerViewResolver
。 - 如果您使用
Groovy
模板(实际上,如果groovy-templates
在类路径中),则还具有一个名为groovyMarkupViewResolver
的GroovyMarkupViewResolver
。它通过在视图名称周围加上前缀和后缀(并扩展为spring.groovy.template.prefix
和spring.groovy.template.suffix
)来在加载器路径中查找资源。前缀和后缀分别具有默认值classpath:/templates/
和.tpl
。您可以通过提供相同名称的bean 来覆盖GroovyMarkupViewResolver
。 - 如果您使用
Mustache
,那么您还将有一个名为mustacheViewResolver
的MustacheViewResolver
。它通过在视图名称前后加上前缀和后缀来查找资源。前缀为spring.mustache.prefix
,后缀为spring.mustache.suffix
。前缀和后缀的值分别默认为classpath:/templates/
和.mustache
。您可以通过提供相同名称的bean 来覆盖MustacheViewResolver
。
有关更多详细信息,请参见以下部分:
- WebMvcAutoConfiguration
- ThymeleafAutoConfiguration
- FreeMarkerAutoConfiguration
- GroovyTemplateAutoConfiguration
9.5。使用Spring Security进行测试
Spring Security提供了对以特定用户身份运行测试的支持。例如,下面的代码段中的测试将与具有ADMIN角色的经过身份验证的用户一起运行。
@Test
@WithMockUser(roles="ADMIN")
public void requestProtectedUrlWithUser() throws Exception {
mvc
.perform(get("/"))
...
}
Spring Security提供了与Spring MVC Test的全面集成,并且在使用@WebMvcTest
slice和MockMvc进行测试控制器时也可以使用它。
有关Spring Security的测试支持的更多详细信息,请参阅Spring Security的参考文档。
9.6。Jersey
9.6.1。使用Spring Security保护Jersey端点
可以使用Spring Security来保护基于Jersey的Web应用程序,其方式与用来保护基于Spring MVC的Web应用程序的方式几乎相同。但是,如果您想在Jersey上使用Spring Security的方法级安全性,则必须将Jersey配置为使用setStatus(int)
而不是sendError(int)
。这可以防止Jersey在Spring Security有机会向客户端报告身份验证或授权失败之前提交响应。
jersey.config.server.response.setStatusOverSendError
属性必须在应用程序的ResourceConfig
Bean 上设置为true,如以下示例所示:
@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(Endpoint.class);
setProperties(Collections.singletonMap("jersey.config.server.response.setStatusOverSendError", true));
}
}
9.7。HTTP客户端
Spring Boot提供了许多可与HTTP客户端一起使用的启动器。本节回答与使用它们有关的问题。
9.7.1。配置RestTemplate使用代理
如RestTemplate
自定义中所述,您可以使用带RestTemplateCustomizer
的RestTemplateBuilder
来构建自定义RestTemplate。这是创建RestTemplate配置为使用代理的推荐方法。
代理配置的确切详细信息取决于所使用的基础客户端请求工厂。以下示例使用HttpClient
进行配置HttpComponentsClientRequestFactory
,该HttpClient代理除192.168.0.5以下主机之外的所有主机:
static class ProxyCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
HttpHost proxy = new HttpHost("proxy.example.com");
HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {
@Override
public HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context)
throws HttpException {
if (target.getHostName().equals("192.168.0.5")) {
return null;
}
return super.determineProxy(target, request, context);
}
}).build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
}
9.7.2。配置基于Reactor Netty的WebClient使用的TcpClient
当Reactor Netty
在类路径上时,将自动配置基于Reactor Netty的WebClient。要自定义客户端对网络连接的处理,请提供一个ClientHttpConnector
bean。以下示例配置60秒的连接超时并添加ReadTimeoutHandler
:
@Bean
ClientHttpConnector clientHttpConnector(ReactorResourceFactory resourceFactory) {
TcpClient tcpClient = TcpClient.create(resourceFactory.getConnectionProvider())
.runOn(resourceFactory.getLoopResources()).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60000)
.doOnConnected((connection) -> connection.addHandlerLast(new ReadTimeoutHandler(60)));
return new ReactorClientHttpConnector(HttpClient.from(tcpClient));
}
请注意ReactorResourceFactory
对连接提供程序和事件循环资源的使用。这确保了用于服务器接收请求和客户端发出请求的资源的有效共享。
9.8。日志记录
除了通常由Spring Framework的spring-jcl
模块提供的Commons Logging API之外,Spring Boot没有强制性的日志记录依赖项。要使用Logback,您需要将其包括spring-jcl在类路径中。最简单的方法是通过启动器,这都取决于spring-boot-starter-logging
。对于Web应用程序,您仅需要spring-boot-starter-web
,因为它暂时依赖于日志记录启动器。如果使用Maven,则以下依赖项会为您添加日志记录:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Spring Boot有一个LoggingSystem
抽象,它试图根据类路径的内容来配置日志记录。如果Logback可用,则它是首选。
如果您需要对日志记录进行的唯一更改是设置各种记录器的级别,则可以在application.properties里使用logging.level
前缀来进行设置,如以下示例所示:
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
您还可以使用logging.file.name
来设置要写入日志的文件的位置(除了控制台)。
要配置日志记录系统的更细粒度的设置,您需要使用LoggingSystem
所支持的本机配置格式。默认情况下,Spring Boot从系统的默认位置(例如Logback的classpath:logback.xml
)拾取本地配置,但是您可以使用logging.config
属性设置配置文件的位置。
9.8.1。配置Logback以进行日志记录
如果您需要将自定义设置超出application.properties可以设置的范围,则需要添加标准的Logback配置文件。您可以将logback.xml
文件添加到类路径的根目录中,以供Logback查找。如果您想使用Spring Boot Logback扩展,也可以使用logback-spring.xml
。
Logback文档有一个专用部分,其中详细介绍了配置。
Spring Boot提供了许多可以包含在您自己配置中的logback 配置。这些includes旨在允许重新应用某些常见的Spring Boot约定。
org/springframework/boot/logging/logback/
下提供了以下文件:
defaults.xml
-提供转换规则,模式属性和通用记录器配置。console-appender.xml
- 使用CONSOLE_LOG_PATTERN
添加了一个ConsoleAppender
。file-appender.xml
- 使用通过适当的设置的FILE_LOG_PATTERN
和ROLLING_FILE_NAME_PATTERN
添加了一个RollingFileAppender
。
此外,还提供了一个过时的 base.xml
文件以与早期版本的Spring Boot兼容。
一个典型的自定义logback.xml文件如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
<logger name="org.springframework.web" level="DEBUG"/>
</configuration>
您的Logback配置文件也可以利用LoggingSystem为您创建的System属性:
${PID}
:当前进程ID。${LOG_FILE}
:是否在Boot的外部配置中设置logging.file.name
。${LOG_PATH}
:是否在Boot的外部配置中设置了logging.file.path
(表示用于存放日志文件的目录)。${LOG_EXCEPTION_CONVERSION_WORD}
:是否在Boot的外部配置中设置logging.exception-conversion-word
。${ROLLING_FILE_NAME_PATTERN}
:是否在Boot的外部配置中设置logging.pattern.rolling-file-name
。
通过使用自定义的Logback转换器,Spring Boot还可以在控制台上提供一些不错的ANSI颜色终端输出(但不在日志文件中)。例如在defaults.xml
中的CONSOLE_LOG_PATTERN
配置。
如果Groovy在类路径上,那么您也应该能够使用logback.groovy
配置Logback 。如果存在,则优先考虑此设置。
Groovy配置不支持Spring扩展。将不会检测logback-spring.groovy
文件。
配置仅文件输出的Logback
如果要禁用控制台日志记录并且仅将输出写入文件,则需要一个logback-spring.xml
导入file-appender.xml
但不导入console-appender.xml
的自定义,如以下示例所示:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</configuration>
您还需要将logging.file.name
添加到application.properties中,如以下示例所示:
logging.file.name=myapplication.log
9.8.2。配置Log4j进行日志记录
如果Log4j2在类路径上,则Spring Boot支持Log4j2进行日志记录配置。如果使用启动器来组装依赖项,则必须排除Logback,然后改为包括log4j2。如果您不使用启动器,还需要提供至少spring-jcl
和Log4j2
。
最简单的方法可能是通过启动器,即使它需要对排除对象进行微调。以下示例显示了如何在Maven中设置启动器:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
以下示例显示了在Gradle中设置启动器的一种方法:
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-log4j2'
}
configurations {
all {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
}
Log4j启动器将依赖关系集中在一起,以满足常见的日志记录要求(例如Tomcat使用java.util.logging
,但配置Log4j2输出)。
为确保将使用java.util.logging
进行的调试日志记录路由到Log4j2中,请将系统属性java.util.logging.manager
设置为 org.apache.logging.log4j.jul.LogManager
,以配置其JDK日志记录适配器。
使用YAML或JSON配置Log4j2
除了默认的XML配置格式外,Log4j2还支持YAML和JSON配置文件。要将Log4j2配置为使用备用配置文件格式,请将适当的依赖项添加到类路径中,并命名您的配置文件以匹配您选择的文件格式,如以下示例所示:
格式 | 依赖项 | 文件名称 |
---|---|---|
YAML | com.fasterxml.jackson.core:jackson-databind +com.fasterxml.jackson.dataformat:jackson-dataformat-yaml | log4j2.yaml +log4j2.yml |
JSON | com.fasterxml.jackson.core:jackson-databind | log4j2.json +log4j2.jsn |