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@RestControllerbeans来处理到来的HTTP 请求。你的controller里面的方法映射到HTTP通过使用@RequestMapping注解。

    下面的代码展示了典型的@RestController,它提供(返回)JSON数据:

    1. @RestController
    2. @RequestMapping(value="/users")
    3. public class MyRestController {
    4.  
    5. @RequestMapping(value="/{user}", method=RequestMethod.GET)
    6. public User getUser(@PathVariable Long user) {
    7. // ...
    8. }
    9.  
    10. @RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
    11. List getUserCustomers(@PathVariable Long user) {
    12. // ...
    13. }
    14. @RequestMapping(value="/{user}", method=RequestMethod.DELETE)
    15. public User deleteUser(@PathVariable Long user) {
    16. // ...
    17. }
    18. }

    Spring MVC是核心Spring Framework的一部分,在reference documentation可获得细节信息。在spring.io/guides也有一些Spring MVC指南可获得。

    27.1.1 Spring MVC 自动配置

    Spring Boot为Spring MVC提供大部分应用运转良好的自动配置。

    该自动配置添加了下面特性在Spring的默认顶端:

    • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans
    • Support for serving static resources, including support for WebJars (covered later in this document)
    • Automatic registration of Converter, GenericConverter, and Formatter 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或者异常类型,如下例子所示:

    1. @ControllerAdvice(basePackageClasses = AcmeController.class)
    2. public class AcmeControllerAdvice extends ResponseEntityExceptionHandler {
    3.  
    4. @ExceptionHandler(YourException.class)
    5. @ResponseBody
    6. ResponseEntity handleControllerException(HttpServletRequest request, Throwable ex) {
    7. HttpStatus status = getStatus(request);
    8. return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
    9. }
    10.  
    11. private HttpStatus getStatus(HttpServletRequest request) {
    12. Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
    13. if (statusCode == null) {
    14. return HttpStatus.INTERNAL_SERVER_ERROR;
    15. }
    16. return HttpStatus.valueOf(statusCode);
    17. }
    18.  
    19. }

    在上面的例子中,如果YourException被一个定义在相同的package作为AcmeController的controller抛出,一个JSON CustomErrorTypePOJO 的representation被用来代替ErrorAttributes representation。

    自定义错误页面 如果你想展示一个自定义HTML错误页面对于一个给定的状态码,你可以添加一个文件到一个/error文件夹。错误页面可以基于HTML(that is, added under any of the static resource folders),或者使用模板构建。文件的名字应该是精确地状态码或者 a series mask。

    举个例子,为了map到一个静态HTML页面,你的文件夹结构将如下:

    1. src/
    2. +- main/
    3. +- java/
    4. | +
    5. +- resources/
    6. +- public/
    7. +- error/
    8. | +- 404.html
    9. +-

    为了路由所有的5xx错误通过使用一个FreeMarker模板,你的文件夹结构如下:

    1. src/
    2. +- main/
    3. +- java/
    4. | +
    5. +- resources/
    6. +- templates/
    7. +- error/
    8. | +- 5xx.ftl
    9. +-

    对于更多混合路由,你也可以添加bean实现ErrorViewResolver接口,如下例子所示:

    1. public class MyErrorViewResolver implements ErrorViewResolver {
    2.  
    3. @Override
    4. public ModelAndView resolveErrorView(HttpServletRequest request,
    5. HttpStatus status, Map model) {
    6. // Use the request or status to optionally return a ModelAndView
    7. return ...
    8. }
    9. }

    你也可以使用通常地Spring MVC特性,如@ExceptionHandler方法@ControllerAdviceErrorController之后收集任何没有处理的异常。

    在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容器支持