27. 开发Web应用
Spring Boot非常适合开发Web应用。你可以创建一个独立的(self-contained)HTTP服务器通过使用内嵌的Tomcat,Jetty,Undertow或者Netty。大部分Web应用使用spring-boot-starter-web
模块来开始并迅速运行。你也可以选择构建一个reactive web应用通过使用spring-boot-starter-webflux
模块。
如果你还没有开发过一个Spring Boot应用,你可以按照Getting started里的“Hello World”例子。
27.1 Spring Web MVC Framework
Spring Web MVC Framework(简称“Spring MVC”也是指它)是一个富“model view controller” Web框架。Spring MVC让你创建特别的@Controller
和@RestController
beans来处理到来的HTTP 请求。你的controller里面的方法映射到HTTP通过使用@RequestMapping
注解。
下面的代码展示了典型的@RestController
,它提供(返回)JSON数据:
- @RestController
- @RequestMapping(value="/users")
- public class MyRestController {
- @RequestMapping(value="/{user}", method=RequestMethod.GET)
- public User getUser(@PathVariable Long user) {
- // ...
- }
- @RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
- List
getUserCustomers(@PathVariable Long user) { // ... } @RequestMapping(value="/{user}", method=RequestMethod.DELETE) public User deleteUser(@PathVariable Long user) { // ... } }
Spring MVC是核心Spring Framework的一部分,在reference documentation可获得细节信息。在spring.io/guides也有一些Spring MVC指南可获得。
27.1.1 Spring MVC 自动配置
Spring Boot为Spring MVC提供大部分应用运转良好的自动配置。
该自动配置添加了下面特性在Spring的默认顶端:
- Inclusion of
ContentNegotiatingViewResolver
andBeanNameViewResolver
beans - Support for serving static resources, including support for WebJars (covered later in this document)
- Automatic registration of
Converter
,GenericConverter
, andFormatter
beans - Support for
HttpMessageConverters
(covered later in this document) - Automatic registration of
MessageCodesResolver
(covered later in this document) - Static
index.html
support. - Custom
Favicon
support(covered later in this document) - Automatic use of a
ConfigurableWebBindingInitializer
bean(covered later in this document)
如果你想保持Spring BootMVC的特性并添加额外的MVC配置(拦截器,格式化,视图控制器,和其他特性),你可以添加自己的WebMvcConfigurer
类型的@Configuration
类但不要有@EnableWebMvc
。If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.
如果你想要完全控制Spring MVC,你可以添加自己的@Configuration
注解和@EnableWebMvc
一起。
27.1.2 HttpMessageConverters
27.1.3 自定义JSON序列化和解析
27.1.4 MessageCodesResolver
27.1.5 静态内容
27.1.6 欢迎页面
27.1.7 自定义Favicon
27.1.8 路径匹配和内容协商
27.1.9 ConfigurableWebBindingInitializer
27.1.10 模板引擎
除REST web服务之外,你也可以使用Spring MVC来提供动态HTML内容。Spring MVC支持多种模板技术,包括Thymeleaf,FreeMarker,和JSPs。另外,许多其他的模板引擎包含它们自己的Spring MVC整合。
Spring Boot包含自动配置支持以下模板引擎:
如果可能,JSPs应该被避免。有几个已知的限制当和内嵌的容器一起使用它们时。
当你以默认配置使用这些模板引擎中的一个时,你的模板被自动收集从src/main/resources/templates
取决于你如何运行你的应用,IntelliJ IDEA orders the classpath differently。在IDE中从它的main方法运行你的应用导致一个不同的ordering与当你运行你的应用通过使用Maven或者Gradle或者从它的打包的jar。这会导致Spring Boot在classpath上找不到模板。如果你有这个问题,you can reorder the classpath in the IDE to place the module’s classes and resources first。或者,你可以配置模板前缀来搜索在classpath上的每个templates
目录,如下:classpath*:/templates
27.1.11 错误处理
默认地,Spring Boot提供一个/error
路由以明智的方式处理所有的错误,并且它被注册为“全局的”错误页面在Servlet容器中。对于机器客户端,它产生一个JSON回复关于错误细节的,HTTP状态,和异常信息。对于浏览器客户端,一个“whitelabel”错误视图以HTML格式渲染同样的数据(为了自定义它,可以添加一个View
处理error
)。为了完全取代默认地行为,你可以实现ErrorController
并注册一个那个类型的bean定义或者添加一个ErrorAttributes
类型的bean来使用存在的机制(but)取代该内容。
BasicErrorController
可以被用来作为一个基础类为一个自定义ErrorController
。这非常有用,如果你想添加一个handler为一个新的content type(默认地是处理text/html
,并为任何别的提供一个回退)。为了这么做,继承BasicErrorController
,添加一个有produces
属性的@RequestMapping
注解的公有方法,并创建一个你的新类型的bean。
你也可以定义一个注解为@ControllerAdvice
的类来定制JSON文档来返回对于一个特别的controller或者异常类型,如下例子所示:
- @ControllerAdvice(basePackageClasses = AcmeController.class)
- public class AcmeControllerAdvice extends ResponseEntityExceptionHandler {
- @ExceptionHandler(YourException.class)
- @ResponseBody
- ResponseEntity handleControllerException(HttpServletRequest request, Throwable ex) {
- HttpStatus status = getStatus(request);
- return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
- }
- private HttpStatus getStatus(HttpServletRequest request) {
- Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
- if (statusCode == null) {
- return HttpStatus.INTERNAL_SERVER_ERROR;
- }
- return HttpStatus.valueOf(statusCode);
- }
- }
在上面的例子中,如果YourException
被一个定义在相同的package作为AcmeController
的controller抛出,一个JSON CustomErrorType
POJO 的representation被用来代替ErrorAttributes
representation。
自定义错误页面
如果你想展示一个自定义HTML错误页面对于一个给定的状态码,你可以添加一个文件到一个/error
文件夹。错误页面可以基于HTML(that is, added under any of the static resource folders),或者使用模板构建。文件的名字应该是精确地状态码或者 a series mask。
举个例子,为了map
到一个静态HTML页面,你的文件夹结构将如下:
- src/
- +- main/
- +- java/
- | +
- +- resources/
- +- public/
- +- error/
- | +- 404.html
- +-
为了路由所有的5xx
错误通过使用一个FreeMarker模板,你的文件夹结构如下:
- src/
- +- main/
- +- java/
- | +
- +- resources/
- +- templates/
- +- error/
- | +- 5xx.ftl
- +-
对于更多混合路由,你也可以添加bean实现ErrorViewResolver
接口,如下例子所示:
- public class MyErrorViewResolver implements ErrorViewResolver {
- @Override
- public ModelAndView resolveErrorView(HttpServletRequest request,
- HttpStatus status, Map
model) { // Use the request or status to optionally return a ModelAndView return ... } }
你也可以使用通常地Spring MVC特性,如@ExceptionHandler
方法和@ControllerAdvice
。ErrorController
之后收集任何没有处理的异常。
在Spring MVC之外路由错误页面
27.1.12 Spring HATEOAS
27.1.13 CORS支持
27.2 Spring WebFlux Framework
27.2.1 Spring WebFlux自动配置
27.3 JAX-RS and Jersey
27.4 内嵌Servlet容器支持