2018-12-28
spring boot就是一(yī)個大(dà)框架裏面包含了許許多多的東西,其中(zhōng)spring就是最核心的内容之一(yī),當然就包含spring mvc。spring mvc 是隻是spring 處理web層請求的一(yī)個模塊。因此他們的關系大(dà)概就是這樣:spring mvc < spring <springboot。
理清SpringBoot與SpringMVC的關系
Spring 框架就像一(yī)個家族,有衆多衍生(shēng)産品例如 boot、security、jpa等等。但他們的基礎都是Spring 的 ioc和 aop ioc 提供了依賴注入的容器 aop ,解決了面向橫切面的編程,然後在此兩者的基礎上實現了其他延伸産品的高級功能。
Spring MVC是基于 Servlet 的一(yī)個 MVC 框架 主要解決 WEB 開(kāi)發的問題,因爲 Spring 的配置非常複雜(zá),各種XML、 JavaConfig、hin處理起來比較繁瑣。
于是爲了簡化開(kāi)發者的使用,從而創造性地推出了Spring boot,約定優于配置,簡化了spring的配置流程。
說得更簡便一(yī)些:Spring 最初利用“工(gōng)廠模式”(DI)和“代理模式”(AOP)解耦應用組件。
大(dà)家覺得挺好用,于是按照這種模式搞了一(yī)個 MVC框架(一(yī)些用Spring 解耦的組件),用開(kāi)發 web 應用( SpringMVC )。
然後有發現每次開(kāi)發都寫很多樣闆代碼,爲了簡化工(gōng)作流程,于是開(kāi)發出了一(yī)些“懶人整合包”(starter),這套就是 Spring Boot。
Spring MVC的功能Spring MVC提供了一(yī)種輕度耦合的方式來開(kāi)發web應用。Spring MVC是Spring的一(yī)個模塊,式一(yī)個web框架。
通過Dispatcher Servlet, ModelAndView 和 View Resolver,開(kāi)發web應用變得很容易。解決的問題領域是網站應用程序或者服務開(kāi)發——URL路由、Session、模闆引擎、靜态Web資(zī)源等等。
Spring Boot的功能Spring Boot實現了自動配置,降低了項目搭建的複雜(zá)度。
衆所周知(zhī)Spring框架需要進行大(dà)量的配置,Spring Boot引入自動配置的概念,讓項目設置變得很容易。
Spring Boot本身并不提供Spring框架的核心特性以及擴展功能,隻是用于快速、敏捷地開(kāi)發新一(yī)代基于Spring框架的應用程序。也就是說,它并不是用來替代Spring的解決方案,而是和Spring框架緊密結合用于提升Spring開(kāi)發者體(tǐ)驗的工(gōng)具。
同時它集成了大(dà)量常用的第三方庫配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot應用中(zhōng)這些第三方庫幾乎可以零配置的開(kāi)箱即用(out-of-the-box),大(dà)部分(fēn)的Spring Boot應用都隻需要非常少量的配置代碼,開(kāi)發者能夠更加專注于業務邏輯。
Spring Boot隻是承載者,輔助你簡化項目搭建過程的。如果承載的是WEB項目,使用Spring MVC作爲MVC框架,那麽工(gōng)作流程和你上面描述的是完全一(yī)樣的,因爲這部分(fēn)工(gōng)作是Spring MVC做的而不是Spring Boot。對使用者來說,換用Spring Boot以後,項目初始化方法變了,配置文件變了,另外(wài)就是不需要單獨安裝Tomcat這類容器服務器了,maven打出jar包直接跑起來就是個網站,但你最核心的業務邏輯實現與業務流程實現沒有任何變化。
所以,用最簡練的語言概括就是:
Spring 是一(yī)個“引擎”;
Spring MVC 是基于Spring的一(yī)個 MVC 框架 ;
Spring Boot 是基于Spring4的條件注冊的一(yī)套快速開(kāi)發整合包。
Spring MVC自動配置
Spring Boot爲Spring MVC提供的auto-configuration适用于大(dà)多數應用,并在Spring默認功能上添加了以下(xià)特性:
1.引入
ContentNegotiatingViewResolver和BeanNameViewResolver beans。
2.對靜态資(zī)源的支持,包括對WebJars的支持。
3.自動注冊Converter,GenericConverter,Formatter beans。
4.對HttpMessageConverters的支持。
5.自動注冊
MessageCodeResolver。
6.對靜态index.html的支持。
7.對自定義Favicon的支持。
8.自動使用
ConfigurableWebBindingInitializer bean。
如果保留Spring Boot MVC特性,你隻需添加其他的MVC配置(攔截器,格式化處理器,視圖控制器等)。
你可以添加自己的WebMvcConfigurerAdapter類型的@Configuration類,而不需要注解@EnableWebMvc。如果希望使用自定義的RequestMappingHandlerMapping,RequestMappingHandlerAdapter,或ExceptionHandlerExceptionResolver,你可以聲明一(yī)個WebMvcRegistrationsAdapter實例提供這些組件。
如果想全面控制Spring MVC,你可以添加自己的@Configuration,并使用@EnableWebMvc注解。
HttpMessageConverters
Spring MVC使用HttpMessageConverter接口轉換HTTP請求和響應,合适的默認配置可以開(kāi)箱即用,例如對象自動轉換爲JSON(使用Jackson庫)或XML(如果Jackson XML擴展可用,否則使用JAXB),字符串默認使用UTF-8編碼。
可以使用Spring Boot的HttpMessageConverters類添加或自定義轉換類:
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); } }
上下(xià)文中(zhōng)出現的所有HttpMessageConverter bean都将添加到converters列表,你可以通過這種方式覆蓋默認的轉換器列表(converters)。
自定義JSON序列化器和反序列化器
如果使用Jackson序列化,反序列化JSON數據,你可能想編寫自己的JsonSerializer和JsonDeserializer類。自定義序列化器(serializers)通常通過Module注冊到Jackson,但Spring Boot提供了@JsonComponent注解這一(yī)替代方式,它能輕松的将序列化器注冊爲Spring Beans。
MessageCodesResolver
Spring MVC有一(yī)個實現策略,用于從綁定的errors産生(shēng)用來渲染錯誤信息的錯誤碼:MessageCodesResolver。Spring Boot會自動爲你創建該實現,隻要設置spring.mvc.message-codes-resolver.format屬性爲PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE(具體(tǐ)查看DefaultMessageCodesResolver.Format枚舉值)。
靜态内容
默認情況下(xià),Spring Boot從classpath下(xià)的/static(/public,/resources或/META-INF/resources)文件夾,或從ServletContext根目錄提供靜态内容。這是通過Spring MVC的ResourceHttpRequestHandler實現的,你可以自定義WebMvcConfigurerAdapter并覆寫addResourceHandlers方法來改變該行爲(加載靜态文件)。
在單機web應用中(zhōng),容器會啓動默認的servlet,并用它加載ServletContext根目錄下(xià)的内容以響應那些Spring不處理的請求。大(dà)多數情況下(xià)這都不會發生(shēng)(除非你修改默認的MVC配置),因爲Spring總能夠通過DispatcherServlet處理這些請求。
你可以設置spring.resources.staticLocations屬性自定義靜态資(zī)源的位置(配置一(yī)系列目錄位置代替默認的值),如果你這樣做,默認的歡迎頁面将從自定義位置加載,所以隻要這些路徑中(zhōng)的任何地方有一(yī)個index.html,它都會成爲應用的主頁。
此外(wài),除了上述标準的靜态資(zī)源位置,有個例外(wài)情況是Webjars内容。任何在/webjars/**路徑下(xià)的資(zī)源都将從jar文件中(zhōng)提供,隻要它們以Webjars的格式打包。
注 如果你的應用将被打包成jar,那就不要使用src/main/webapp文件夾。盡管該文件夾是通常的标準格式,但它僅在打包成war的情況下(xià)起作用,在打包成jar時,多數構建工(gōng)具都會默認忽略它。
Spring Boot也支持Spring MVC提供的高級資(zī)源處理特性,可用于清除緩存的靜态資(zī)源或對WebJar使用版本無感知(zhī)的URLs。
如果想使用針對WebJars版本無感知(zhī)的URLs(version agnostic),隻需要添加webjars-locator依賴,然後聲明你的Webjar。以jQuery爲例,"/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,否則所有的Webjars将解析爲404。
以下(xià)的配置爲所有的靜态資(zī)源提供一(yī)種緩存清除(cache busting)方案,實際上是将内容hash添加到URLs中(zhōng),比如<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>:
spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/**
注 實現該功能的是ResourceUrlEncodingFilter,它在模闆運行期會重寫資(zī)源鏈接,Thymeleaf,Velocity和FreeMarker會自動配置該filter,JSP需要手動配置。其他模闆引擎還沒自動支持,不過你可以使用ResourceUrlProvider自定義模塊宏或幫助類。
當使用比如JavaScript模塊加載器動态加載資(zī)源時,重命名文件是不行的,這也是提供其他策略并能結合使用的原因。下(xià)面是一(yī)個"fixed"策略,在URL中(zhōng)添加一(yī)個靜态version字符串而不需要改變文件名:
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
使用以上策略,JavaScript模塊加載器加載"/js/lib/"下(xià)的文件時會使用一(yī)個固定的版本策略"/v12/js/lib/mymodule.js",其他資(zī)源仍舊(jiù)使用内容hash的方式<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>。查看ResourceProperties獲取更多支持的選項。
歡迎頁面
Spring Boot支持靜态和模闆歡迎頁面。它首先index.html在配置的靜态内容位置中(zhōng)查找 文件。如果找不到,則會查找index模闆。如果找到任何一(yī)個,它将自動用作應用程序的歡迎頁面。、
自定義Favicon
Spring Boot favicon.ico在配置的靜态内容位置和類路徑的根目錄(按此順序)中(zhōng)查找a 。如果存在這樣的文件,它會自動用作應用程序的圖标。
路徑匹配和内容協商(shāng)
Spring MVC可以通過查看請求路徑并将它匹配到應用程序中(zhōng)定義的映射(例如@GetMapping Controller方法上的注釋),将傳入的HTTP請求映射到處理程序。
Spring Boot選擇默認禁用後綴模式匹配,這意味着請求"GET /projects/spring-boot.json"不會匹配 @GetMapping("/projects/spring-boot")映射。這被認爲是Spring MVC應用程序的 最佳實踐。此功能在過去(qù)對于沒有發送正确的“Accept”請求标頭的HTTP客戶端來說非常有用; 我(wǒ)們需要确保将正确的内容類型發送到客戶端。如今,内容協商(shāng)更可靠。
還有其他一(yī)些方法可以處理不一(yī)緻地發送适當的“接受”請求标頭的HTTP客戶端。我(wǒ)們可以使用查詢參數來确保類似的請求"GET /projects/spring-boot?format=json" 将映射到@GetMapping("/projects/spring-boot")以下(xià)内容,而不是使用後綴匹配:
spring.mvc.contentnegotiation.favor-parameter = true #我(wǒ)們可以更改參數名稱,默認爲“格式”: #spring.mvc.contentnegotiation.parameter-name = myparam #我(wǒ)們還可以通過以下(xià)方式注冊其他文件擴展名/媒體(tǐ)類型: spring.mvc.contentnegotiation.media-types.markdown = text / markdown
如果您了解注意事項并仍然希望應用程序使用後綴模式匹配,則需要進行以下(xià)配置:
spring.mvc.contentnegotiation.favor-path-extension = true #您也可以将該功能限制爲已知(zhī)擴展 #spring.mvc.pathmatch.use-registered-suffix-pattern = true #我(wǒ)們還可以通過以下(xià)方式注冊其他文件擴展名/媒體(tǐ)類型: #spring.mvc.contentnegotiation.media-types.adoc = text / asciidoc
ConfigurableWebBindingInitializer
Spring MVC使用WebBindingInitializer爲每個特殊的請求初始化相應的WebDataBinder,如果你創建自己的ConfigurableWebBindingInitializer @Bean,Spring Boot會自動配置Spring MVC使用它。
模闆引擎
正如REST web服務,你也可以使用Spring MVC提供動态HTML内容。Spring MVC支持各種各樣的模闆技術,包括Velocity, FreeMarker和JSPs,很多其他的模闆引擎也提供它們自己的Spring MVC集成。
Spring Boot爲以下(xià)的模闆引擎提供自動配置支持:
FreeMarker
Groovy
Thymeleaf
Velocity(1.4已不再支持)
Mustache
注:由于在内嵌servlet容器中(zhōng)使用JSPs存在一(yī)些已知(zhī)的限制,所以建議盡量不使用它們。
使用以上引擎中(zhōng)的任何一(yī)種,并采用默認配置,則模塊會從src/main/resources/templates自動加載。
注:IntelliJ IDEA根據你運行應用的方式會對classpath進行不同的排序。在IDE裏通過main方法運行應用,跟從Maven,或Gradle,或打包好的jar中(zhōng)運行相比會導緻不同的順序,這可能導緻Spring Boot不能從classpath下(xià)成功地找到模闆。
如果遇到這個問題,你可以在IDE裏重新對classpath進行排序,将模塊的類和資(zī)源放(fàng)到第一(yī)位。或者,你可以配置模塊的前綴爲classpath*:/templates/,這樣會查找classpath下(xià)的所有模闆目錄。
錯誤處理
Spring Boot默認提供一(yī)個/error映射用來以合适的方式處理所有的錯誤,并将它注冊爲servlet容器中(zhōng)全局的 錯誤頁面。對于機器客戶端(相對于浏覽器而言,浏覽器偏重于人的行爲),它會産生(shēng)一(yī)個具有詳細錯誤,HTTP狀态,異常信息的JSON響應。
對于浏覽器客戶端,它會産生(shēng)一(yī)個白(bái)色标簽樣式(whitelabel)的錯誤視圖,該視圖将以HTML格式顯示同樣的數據(可以添加一(yī)個解析爲'error'的View來自定義它)。爲了完全替換默認的行爲,你可以實現ErrorController,并注冊一(yī)個該類型的bean定義,或簡單地添加一(yī)個ErrorAttributes類型的bean以使用現存的機制,隻是替換顯示的内容。
注BasicErrorController可以作爲自定義ErrorController的基類,如果你想添加對新context type的處理(默認處理text/html),這會很有幫助。
你隻需要繼承BasicErrorController,添加一(yī)個public方法,并注解帶有produces屬性的@RequestMapping,然後創建該新類型的bean。
你也可以定義一(yī)個@ControllerAdvice去(qù)自定義某個特殊controller或exception類型的JSON文檔:
@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); } }
在以上示例中(zhōng),如果跟FooController相同package的某個controller抛出YourException,一(yī)個CustomerErrorType類型的POJO的json展示将代替ErrorAttributes展示。
自定義錯誤頁面
如果想爲某個給定的狀态碼展示一(yī)個自定義的HTML錯誤頁面,你需要将文件添加到/error文件夾下(xià)。錯誤頁面既可以是靜态HTML(比如,任何靜态資(zī)源文件夾下(xià)添加的),也可以是使用模闆構建的,文件名必須是明确的狀态碼或一(yī)系列标簽。
例如,映射404到一(yī)個靜态HTML文件,你的目錄結構可能如下(xià):
src/ +- main/ +- java/ | + <source code> +- resources/ +- public/ +- error/ | +- 404.html +- <other public assets>
使用FreeMarker模闆映射所有5xx錯誤,你需要如下(xià)的目錄結構:
src/ +- main/ +- java/ | + <source code> +- resources/ +- templates/ +- error/ | +- 5xx.ftl +- <other templates>
對于更複雜(zá)的映射,你可以添加實現ErrorViewResolver接口的beans:
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 ... } }
你也可以使用Spring MVC特性,比如@ExceptionHandler方法和@ControllerAdvice,ErrorController将處理所有未處理的異常。
映射Spring MVC以外(wài)的錯誤頁面
對于不使用Spring MVC的應用,你可以通過ErrorPageRegistrar接口直接注冊ErrorPages。該抽象直接工(gōng)作于底層内嵌servlet容器,即使你沒有Spring MVC的DispatcherServlet,它們仍舊(jiù)可以工(gōng)作。
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 ... } } @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")); } }
注.如果你注冊一(yī)個ErrorPage,該頁面需要被一(yī)個Filter處理(在一(yī)些非Spring web框架中(zhōng)很常見,比如Jersey,Wicket),那麽該Filter需要明确注冊爲一(yī)個ERROR分(fēn)發器(dispatcher),例如:
@Bean public FilterRegistrationBean myFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter()); ... registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class)); return registration; }
(默認的FilterRegistrationBean不包含ERROR dispatcher類型)。
WebSphere應用服務器的錯誤處理
當部署到一(yī)個servlet容器時,Spring Boot通過它的錯誤頁面過濾器将帶有錯誤狀态的請求轉發到恰當的錯誤頁面。request隻有在response還沒提交時才能轉發(forwarded)到正确的錯誤頁面,而WebSphere應用服務器8.0及後續版本默認情況會在servlet方法成功執行後提交response,你需要設置com.ibm.ws.webcontainer.invokeFlushAfterService屬性爲false來關閉該行爲。
Spring HATEOAS
如果正在開(kāi)發基于超媒體(tǐ)的RESTful API,你可能需要Spring HATEOAS,而Spring Boot會爲其提供自動配置,這在大(dà)多數應用中(zhōng)都運作良好。 自動配置取代了@EnableHypermediaSupport,隻需注冊一(yī)定數量的beans就能輕松構建基于超媒體(tǐ)的應用,這些beans包括LinkDiscoverers(客戶端支持),ObjectMapper(用于将響應編排爲想要的形式)。ObjectMapper可以根據spring.jackson.*屬性或Jackson2ObjectMapperBuilder bean進行自定義。
通過注解@EnableHypermediaSupport,你可以控制Spring HATEOAS的配置,但這會禁用上述ObjectMapper的自定義功能。
CORS支持
跨域資(zī)源共享(CORS)是一(yī)個大(dà)多數浏覽器都實現了的W3C标準,它允許你以靈活的方式指定跨域請求如何被授權,而不是采用那些不安全,性能低的方式,比如IFRAME或JSONP。
從4.2版本開(kāi)始,Spring MVC對CORS提供開(kāi)箱即用的支持。不用添加任何特殊配置,隻需要在Spring Boot應用的controller方法上注解@CrossOrigin,并添加CORS配置。通過注冊一(yī)個自定義addCorsMappings(CorsRegistry)方法的WebMvcConfigurer bean可以指定全局CORS配置:
@Configuration public class MyConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**"); } }; } }
上一(yī)篇:數據結構(一(yī))--入門和預備知(zhī)識
下(xià)一(yī)篇:讓網站高效運作的六大(dà)設計技巧
*請認真填寫需求,我(wǒ)們會在24小(xiǎo)時内與您取得聯系。