springboot 之Spring Web Mvc Framework
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.*; @Configurationpublic 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