【SpringBoot】SpringBoot與SpringMVC自動配置及靜態資源(五)


  本文介紹SpringBoot對Spring MVC自動配置,SpringBoot自動配置原理可以參考:【SpringBoot】SpringBoot配置與單元測試(二)

  首先新建一個SpringBoot的web項目,參考:【SpringBoot】SpringBoot快速入門(一)

  本例pom文件如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.test</groupId>
 8     <artifactId>test-springboot-web</artifactId>
 9     <version>1.0-SNAPSHOT</version>
10 
11 
12     <parent>
13         <groupId>org.springframework.boot</groupId>
14         <artifactId>spring-boot-starter-parent</artifactId>
15         <version>2.1.8.RELEASE</version>
16     </parent>
17 
18     <properties>
19 
20         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
21         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
22         <java.version>1.8</java.version>
23     </properties>
24 
25     <dependencies>
26         <dependency>
27             <groupId>org.springframework.boot</groupId>
28             <artifactId>spring-boot-starter-web</artifactId>
29         </dependency>
30 
31         <!--引入jquery-webjar-->
32         <dependency>
33             <groupId>org.webjars</groupId>
34             <artifactId>jquery</artifactId>
35             <version>3.3.1</version>
36         </dependency>
37 
38         <dependency>
39             <groupId>org.springframework.boot</groupId>
40             <artifactId>spring-boot-starter-test</artifactId>
41             <scope>test</scope>
42         </dependency>
43 
44     </dependencies>
45 
46 
47     <!-- SpringBoot打包插件,可以將代碼打包成一個可執行的jar包 -->
48     <build>
49         <plugins>
50             <plugin>
51                 <groupId>org.springframework.boot</groupId>
52                 <artifactId>spring-boot-maven-plugin</artifactId>
53             </plugin>
54         </plugins>
55     </build>
56 </project>
View Code

SpringMVC自動配置

  自動配置在Spring的默認值之上添加了以下功能:

  • 包含ContentNegotiatingViewResolverBeanNameViewResolver
  • 支持服務靜態資源,包括對WebJars的支持
  • 自動注冊ConverterGenericConverterFormatter豆類。
  • 支持HttpMessageConverters
  • 自動注冊MessageCodesResolver
  • 靜態index.html支持。
  • 定制Favicon支持
  • 自動使用ConfigurableWebBindingInitializerbean

  如果想保留Spring Boot MVC功能,並且想要添加其他MVC配置(攔截器,格式化程序,視圖控制器和其他功能),則可以編寫一個配置類(@Configuration),實現WebMvcConfigurer接口的類,但不能加 @EnableWebMvc如果您希望提供,或的自定義實例RequestMappingHandlerMapping,則可以聲明一個實例來提供此類組件。RequestMappingHandlerAdapter、ExceptionHandlerExceptionResolver、WebMvcRegistrationsAdapter

  如果想完全控制Spring MVC,可以在配置類(@Configuration)添加上注釋@EnableWebMvc

  添加MVC配置類

  1、原理:

    1)、WebMvcAutoConfiguration是SpringMVC的自動配置類 

    2)、在做其他自動配置時會導入;@Import(EnableWebMvcConfiguration.class)

    3)、容器中所有的WebMvcConfigurer都會一起起作用; 

    4)、我們的配置類也會被調用;

  2、編寫一個配置類(@Configuration),實現WebMvcConfigurer接口;不能標注@EnableWebMvc; 

  這樣既保留了所有的自動配置(WebMvcAutoConfiguration),也能用我們擴展的配置;

 1 // @EnableWebMvc // 全面接管SpringMVC,所有的WebMvc自動配置都失效,如靜態資源的訪問都失效
 2 @Configuration
 3 public class MyMvcConfig implements WebMvcConfigurer {
 4 
 5     @Override
 6     public void addViewControllers(ViewControllerRegistry registry) {
 7         // 瀏覽器訪問 "/success2" 重定向到 "/success"
 8         registry.addRedirectViewController("/success2", "/success");
 9         // 瀏覽器訪問 "/success2" 轉發 "/success"
10         registry.addViewController("/success3").setViewName("/success");
11     }
12 }

  3、驗證:效果SpringMVC的自動配置和我們的擴展配置都會起作用

  重定向請求驗證地址:http://localhost:8080/success

  轉發請求驗證地址:http://localhost:8080/success

  全面接管SpringMVC

  1、原理

    1)、查看源碼WebMvcAutoConfiguration類,有條件注解,在沒有WebMvcConfigurationSupport類的情況下才注入

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
// 條件判斷:在沒有WebMvcConfigurationSupport類的情況下才注入
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
        ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

    2)、查看@EnableWebMvc注解源碼,發現它導入DelegatingWebMvcConfiguration類

1 @Retention(RetentionPolicy.RUNTIME)
2 @Target(ElementType.TYPE)
3 @Documented
4 // 導入DelegatingWebMvcConfiguration類
5 @Import(DelegatingWebMvcConfiguration.class)
6 public @interface EnableWebMvc {
7 }

      DelegatingWebMvcConfiguration類繼承了WebMvcConfigurationSupport類

1 @Configuration
2 public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

    3)、@EnableWebMvc將WebMvcConfigurationSupport組件導入進來,導入的WebMvcConfigurationSupport只是SpringMVC最基本的功能,WebMvcAutoConfiguration類又是在沒有WebMvcConfigurationSupport組件情況下生效,所以@EnableWebMvc能使WebMvcAutoConfiguration失效,並全面接管SpringMVC

靜態資源的映射規則

  SpringBoot對靜態文件映射都在類中WebMvcAutoConfiguration,自動配置好了,打開WebMvcAutoConfiguration類,並分析

  1、規則:/webjars/**

    規則:所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找資源;

   webjars:以jar包的方式引入靜態資源; 官網地址:http://www.webjars.org/

 1 // 添加靜態資源映射
 2 @Override
 3 public void addResourceHandlers(ResourceHandlerRegistry registry) {
 4     if (!this.resourceProperties.isAddMappings()) {
 5         logger.debug("Default resource handling disabled");
 6         return;
 7     }
 8     Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
 9     CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
10     if (!registry.hasMappingForPattern("/webjars/**")) {
11         // 添加映射
12         customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
13                 .addResourceLocations("classpath:/META-INF/resources/webjars/")
14                 .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
15     }
16     String staticPathPattern = this.mvcProperties.getStaticPathPattern();
17     if (!registry.hasMappingForPattern(staticPathPattern)) {
18         customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
19                 .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
20                 .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
21     }
22 }

    測試:在pom文件中引入依賴

1 <!--引入jquery-webjar-->
2 <dependency>
3     <groupId>org.webjars</groupId>
4     <artifactId>jquery</artifactId>
5     <version>3.3.1</version>
6 </dependency>

    可以看到jar包中有jquery.js文件

    

    驗證:重啟項目,瀏覽器上打開地址:http://localhost:8080/webjars/jquery/3.3.1/jquery.js,即可看到能獲取到js文件

  2、規則:/**

    "/**" 訪問當前項目的任何資源,都去(靜態資源的文件夾)找映射,靜態資源的文件夾如下:

1 "classpath:/META-INF/resources/",
2 "classpath:/resources/", 
3 "classpath:/static/", 
4 "classpath:/public/"

    測試:在類路徑中,創建static文件夾,在其中添加一個測試頁面test.html

    

    驗證:重啟項目,瀏覽器使用地址:http://localhost:8080/test.html,訪問,即可看到test頁面

  3、規則:首頁

    首頁映射規則代碼在類中WebMvcAutoConfiguration,如下,也在靜態文件夾(即規則2下的文件夾)下查找

1 // 添加首頁映射
2 @Bean
3 public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext) {
4     WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
5             new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
6             this.mvcProperties.getStaticPathPattern());
7     welcomePageHandlerMapping.setInterceptors(getInterceptors());
8     return welcomePageHandlerMapping;
9 }

    測試:在類路徑中的static文件夾,在其中添加一個歡迎頁面index.html

    

    驗證:重啟項目,瀏覽器使用地址:http://localhost:8080,訪問,即可看到歡迎頁面

  4、規則:**/favicon.ico

    所有的 **/favicon.ico 都是在靜態資源文件(即規則2下的文件夾)下找;

    首頁映射規則代碼在類中WebMvcAutoConfiguration,如下

 1 // 配置站點的圖標映射
 2 @Configuration
 3 @ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
 4 public static class FaviconConfiguration implements ResourceLoaderAware {
 5 
 6     private final ResourceProperties resourceProperties;
 7 
 8     private ResourceLoader resourceLoader;
 9 
10     public FaviconConfiguration(ResourceProperties resourceProperties) {
11         this.resourceProperties = resourceProperties;
12     }
13 
14     @Override
15     public void setResourceLoader(ResourceLoader resourceLoader) {
16         this.resourceLoader = resourceLoader;
17     }
18 
19     @Bean
20     public SimpleUrlHandlerMapping faviconHandlerMapping() {
21         SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
22         mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
23         mapping.setUrlMap(Collections.singletonMap("**/favicon.ico", faviconRequestHandler()));
24         return mapping;
25     }
26 
27     @Bean
28     public ResourceHttpRequestHandler faviconRequestHandler() {
29         ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
30         requestHandler.setLocations(resolveFaviconLocations());
31         return requestHandler;
32     }
33 
34     private List<Resource> resolveFaviconLocations() {
35         String[] staticLocations = getResourceLocations(this.resourceProperties.getStaticLocations());
36         List<Resource> locations = new ArrayList<>(staticLocations.length + 1);
37         Arrays.stream(staticLocations).map(this.resourceLoader::getResource).forEach(locations::add);
38         locations.add(new ClassPathResource("/"));
39         return Collections.unmodifiableList(locations);
40     }
41 
42 }

    測試:在類路徑中的static文件夾,在其中添加一個favicon.ico圖標

    驗證:重啟項目,瀏覽器使用地址:http://localhost:8080,訪問,即可看到瀏覽器標題上的站點圖標已改變

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM