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