1. 程式人生 > >springboot 之Spring Web Mvc Framework

springboot 之Spring Web Mvc Framework

fig ftl pathvaria nts bean ddr got del view

1、SpringMvc自動配置

Spring Boot 為SpringMvc提供了自動配置。

自動配置包含Spring的以下特征:

(1)視圖解析器ContentNegotiatingViewResolver或BeanNameViewResolver。

(2)支持靜態文件,包含對WebJar支持。

(3)自動註冊轉換器Converter、GenericConverter、Formatter。

(4)支持HttpMessageConverters(轉換request、response的數據格式)

(5)註冊MessageCodesResolver(轉換錯誤代碼)

(6)支持靜態index.html

(7)支持Favicon

(8)支持自動使用數據綁定器ConfigurableWebBindingInitializer

如果你想保持上述的特征並加入SpringMvc的其他配置(如interceptors、formatters、view controllers等),你要加入你自己的帶有@Configuration註解的WebMvcConfigurerAdapter,且要有註解@EnableWebMvc。如果你想提供常用的句柄如RequestMappingHandlerMapping、RequestMappingHandlerAdapter、ExceptionHandlerExceptionResolver,你可以定義一個WebMvcRegistrationsAdapter來提供這樣的組件(component)。

2、HttpMessageConverters

SpringMvc利用HttpMessageConverter接口來轉換HTTP request和response。對象會被自動轉換為JSON(使用Jackson),或者XML(用Jackson XML或JAXB)。字符串通常默認UTF-8編碼。

import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;

@Configuration
public class MyConfiguration { @Bean public HttpMessageConverters customConverters() { HttpMessageConverter<?> additional = ... HttpMessageConverter<?> another = ... return new HttpMessageConverters(additional, another); } }

任何Context中定義的HttpMessageConverter將會被添加到converters列表中。

3、JSON序列化和反序列化

如果你用Jackson進行數據序列化和反序列化,你可能會想建立自己的工具。其實Spring提供@JsonComponent來使對應類(實現serializers/deserializers接口)的Bean可以直接轉換為JSON。也可以對內部類為serializers/deserializers的類進行註解。

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;

@JsonComponent
public class Example {

    public static class Serializer extends JsonSerializer<SomeObject> {
        // ...
    }

    public static class Deserializer extends JsonDeserializer<SomeObject> {
        // ...
    }

}

所有@JsonComponent註解的beans會自動被Jackson註冊。

4、MessageCodesResolver

MessageCodesResolver可以將錯誤代碼轉換為錯誤信息。只要你設置spring.mvc.message-codes-resolver.format的值為PREFIX_ERROR_CODE或POSTFIX_ERROR_COD(DefaultMessageCodesResolver.Format中的枚舉),Spring Boot 會幫你創建一個。

5、靜態文件區

Spring Boot 會默認的classpath或應用根目錄下的/static(或者/public、/resources、/META-INF/resources)視為靜態文件區。他默認使用Spring Mvc的ResourceHttpRequestHandler,你可以通過在自己的WebMvcConfigurerAdapter添加一個並重寫addResourceHandlers實現修改默認的。

默認的,資源文件會匹配/**,你可以通過spring.mvc.static-path-pattern來設置,例如,設置resource下的所有文件為靜態可設置為:

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

你也可以通過設置spring.resources.static-locations的值來定制靜態資源區。

Spring Boot還支持WebJar目錄,/webjars/**下的任何以WebJar形式打包的文件都會被以jar形式來獲取。

Spring Boot支持對靜態文件進行版本管理,例如我們加入webjars-locator依賴後,"/webjars/jquery/dist/jquery.min.js"文件將會以地址"/webjars/jquery/x.y.z/dist/jquery.min.js"進行訪問,"x.y.z"是WebJar的版本。

如果你使用JBoss,你要用webjars-locator-jboss-vfs依賴代替webjars-locator依賴。某則你的/wenjars/**會一直報404。

可以通過以下配置來配置緩存碎片,有效地在URL上加入文件區哈希碼,如<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**

fixed策略將會只給URL增加版本但是不改變它的名稱。

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

上面的配置中,/js/lib/mymodule.js會變為/v12/js/lib/mymodule.js。

6、favicon.ico

Spring Boot 會自動在靜態文件區根目錄和classpath根目錄尋找favicon.ico文件,一旦找到,將之作為圖標。

7、ConfigurableWebBindingInitializer

SpringMvc通過使用WebBindingInitializer初始化一個WebDataBinder來處理特定的請求。你可以建立自己的ConfigurableWebBindingInitializer Bean,Spring Boot將會自動配置SpringMvc來使用它。

8、模板引擎

SpringBoot會自動使用下列模板引擎

FreeMaker

Groovy

Thymeleaf

Mustache

模板文件通常放在classpath*:templates目錄下。

9、錯誤處理

Spring Boot 提供/error 匹配所有的錯誤信息使得它們可視化。對於機器客戶端,頁面返回的是一個JSON字符串,包含狀態和異常信息;對於瀏覽器客戶端,頁面返回的是一個錯誤數據渲染的錯誤頁面(你可以通過自己定義/error controller來覆蓋)。如果你想要完全覆蓋其所有的行為,你可以實現ErrorController並註冊對應實現類的bean,你也可以通過定義ErrorAttributes類的bean,保留原來的機制,替換content(錯誤信息)。

你可以通過@ControllerAdvice來給指定的controller或exception類型。

@ControllerAdvice(basePackageClasses = FooController.class)
public class FooControllerAdvice 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);
    }

}

在上面的例子中,如果一個在FooController在的包下的Controller拋出YourException,返回結果將由基於ErrorAttributes的結果表現變成基於CustomerErrorType的JSON字符串。

自定義錯誤頁面

你可以在/error下定義錯誤頁面。錯誤頁面既不能為靜態HTML(即在任何靜態資源目錄下)也不能為模板。文件名應該為錯誤代碼值或錯誤代碼匹配值。

例如,404錯誤

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

5xx錯誤

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

你也可以通過實現ErrorViewResolver來配置你的錯誤信息

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
        return ...
    }

}

匹配SpringMvc外部的錯誤

對於不在SpringMvc內部的錯誤,你可以用ErrorPageRegistrar接口直接註冊錯誤頁面。該接口直接作用於嵌入的容器,因此即使你不創建DispatcherServlet它也能正常工作。

@Bean
public ErrorPageRegistrar errorPageRegistrar(){
    return new MyErrorPageRegistrar();
}

// ...

private static class MyErrorPageRegistrar implements ErrorPageRegistrar {

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
    }

}

註:你註冊的錯誤頁面最終將被過濾器處理,過濾器會被註冊為一個錯誤分發者(ERROR dispatcher)

@Bean
public FilterRegistrationBean myFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new MyFilter());
    ...
    registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
    return registration;
}

10、Spring HATEOAS

如果你正在編輯使用超媒體的RESTful API,Spring 為Spring HATEOAS提供自動配置,且能很好地與大部分應用工作。

使用@EnableHypermediaSupport註解可以使應用支持Spring HATEOAS。

11、支持CORS(跨域)

Spring 提供了對跨域的支持。

可以在Controller添加註解方式實現

@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin
    @RequestMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

也可以設置全局的

@Configuration
public class MyConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**");
            }
        };
    }
}

springboot 之Spring Web Mvc Framework