SpringMvc改裝爲SpringBoot的問題總結

#SpringMvc改造SpringBoot問題彙總

特殊說明

## 原來項目環境
1. spring-webmvc-4.0.4.RELEASE
2. mybatis-spring-1.2.2
    ↓↓↓↓↓↓
    ↓↓↓↓↓↓
    ↓↓↓↓↓↓
3. JSP頁面項目
## 改造環境信息
1. spring-webmvc-5.0.7.RELEASE
2. mybatis-spring-1.3.2; mybatis-spring-boot-starter-1.3.2
3. spring-boot-starter-2.0.2.RELEASE

首先需要SpringBoot的Jar包支持

    <!--SpringBoot的基礎支持-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
    </parent>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>


    
    <!--jsp頁面的jstl表達式的支持-->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    
    <!--jsp解析-->
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-jasper</artifactId>
      <!--如果採用內置Tomcat,不使用外部Tomcat請把此註釋掉-->
      <!--<scope>provided</scope>-->
    </dependency>

    <!--直接內嵌tomcat-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <!--如果採用內置Tomcat,不使用外部Tomcat請把此註釋掉-->
      <!--<scope>provided</scope>-->
    </dependency>

使用外置Tomcat特殊說明


## 說明:需要繼承SpringBootServletInitializer然後實現configure方法就可以了,示例如下



@EnableCat
@EnablePay
@EnableApolloConfig
@EnableRedisCache
@EnableRedisLock
@EnableElasticJob
@EnableGlobalTransaction
@EnableTransactionManagement
@SpringBootApplication
@ServletComponentScan(basePackages = {"com.hhz", "com.zhiyi"})
public class HhzAdminApplication extends SpringBootServletInitializer {

  public static void main(String[] args) {
    SpringApplication.run(HhzAdminApplication.class, args);
  }

  /**
   * @Description: 使用外置TOMCAT
   * @Param: builder
   * @return: org.springframework.boot.builder.SpringApplicationBuilder
   * @Author: peikunkun
   * @Date: 2020/6/8 0008 上午 9:54
   */
  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
    return builder.sources(HhzAdminApplication.class);
  }
}

logback的日誌配置

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日誌級別從低到高分爲TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果設置爲WARN,則低於WARN的信息都不會輸出 -->
<!-- debug:當此屬性設置爲true時,將打印出logback內部日誌信息,實時查看logback運行狀態。默認值爲false。 -->
<configuration scan = "true" scanPeriod = "10 seconds">
  <contextName>logback</contextName>

  <!-- name的值是變量的名稱,value的值時變量定義的值。通過定義的值會被插入到logger上下文中。定義後,可以使“${}”來使用變量。 -->
  <property name = "log.path" value = "logs" />

  <!--0. 日誌格式和顏色渲染 -->
  <!-- 彩色日誌依賴的渲染類 -->
  <conversionRule conversionWord = "clr" converterClass = "org.springframework.boot.logging.logback.ColorConverter" />
  <conversionRule conversionWord = "wex"
    converterClass = "org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
  <conversionRule conversionWord = "wEx"
    converterClass = "org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
  <!-- 彩色日誌格式 -->
  <property name = "CONSOLE_LOG_PATTERN"
    value = "${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />

  <!--1. 輸出到控制檯-->
  <appender name = "CONSOLE" class = "ch.qos.logback.core.ConsoleAppender">
    <!--此日誌appender是爲開發使用,只配置最底級別,控制檯輸出的日誌級別是大於或等於此級別的日誌信息-->
    <filter class = "ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>
    <encoder>
      <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
      <!-- 設置字符集 -->
      <charset>UTF-8</charset>
    </encoder>
  </appender>


  <appender name = "LOG_FILE" class = "ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 正在記錄的日誌文檔的路徑及文檔名 -->
    <file>${log.path}/log.log</file>
    <!--日誌文檔輸出格式-->
    <encoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
      <charset>UTF-8</charset>
    </encoder>
    <!-- 日誌記錄器的滾動策略,按日期,按大小記錄 -->
    <rollingPolicy class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- 每天日誌歸檔路徑以及格式 -->
      <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/log-%i.log</fileNamePattern>
      <timeBasedFileNamingAndTriggeringPolicy class = "ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <maxFileSize>50MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
      <!--日誌文檔保留天數-->
      <maxHistory>15</maxHistory>
    </rollingPolicy>
  </appender>

  <!--
      使用mybatis的時候,sql語句是debug下才會打印,而這裏我們只配置了info,所以想要查看sql語句的話,有以下兩種操作:
      第一種把<root level="info">改成<root level="DEBUG">這樣就會打印sql,不過這樣日誌那邊會出現很多其他消息
      第二種就是單獨給dao下目錄配置debug模式,代碼如下,這樣配置sql語句會打印,其他還是正常info級別:
      【logging.level.org.mybatis=debug logging.level.dao=debug】
   -->

  <!-- 4.1 開發環境:打印控制檯-->
  <springProfile name = "dev">
    <root level = "info">
      <appender-ref ref = "CONSOLE" />
    </root>
  </springProfile>


  <!--4.2 生產環境:輸出到文檔-->
  <springProfile name = "prod">
    <root level = "INFO">
      <appender-ref ref = "LOG_FILE" />
    </root>
  </springProfile>
</configuration>

改裝之後出現的問題

WebMvcConfigurationSupport,WebMvcConfigurerAdapter,WebMvcConfigurer配置多個不生效的問題的問題

-> 問題描述
> 在代碼中繼承WebMvcConfigurationSupport配置了jsp資源解析配置了,繼承WebMvcConfigurerAdapter這個配置了跨域了,繼承WebMvcConfigurer這個配置了靜態資源管理了

-> 簡單說明
> WebMvcConfigurationSupport:更豐富的配置,he 另外兩個沒有關係,內部有基礎的具體實現,我們可重寫方法實現自定義配置
> WebMvcConfigurer:是Spring內部的一種配置方式,採用JavaBean的形式來代替傳統的xml配置文件形式進行鍼對框架個性化定製。基於java-based方式的spring mvc配置,需要創建一個配置類並實現WebMvcConfigurer 接口
> WebMvcConfigurerAdapter :WebMvcConfigurer的默認實現,在SpringBoot2.0及Spring5.0中WebMvcConfigurerAdapter已被廢棄 。官方推薦直接實現WebMvcConfigurer(推薦)或者直接繼承WebMvcConfigurationSupport(配置齊全)
  • WebMvcConfigurerAdapter的繼承結構
    在這裏插入圖片描述
  • 問題關鍵點
    在這裏插入圖片描述

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
意思是項目中沒有WebMvcConfigurationSupport類型的bean時,自動配置類纔會生效;如果繼承 WebMvcConfigurationSupport,則需要自己再重寫相應的方法;

所以一般我們在項目中可以使用實現WebMvcConfigurer來配置我們的WebMvc(也可以繼承WebMvcConfigurerAdapter[這個已經被廢棄了在新版中,裏面沒有什麼具體實現]),或者繼承類WebMvcConfigurationSupport來重寫特定的方法來實現自己的配置,但是兩個不可衝突使用(混用),否則會導致一方配置失效;

SpringBoot啓動嵌入式Tomcat時出現jar包掃描找不到問題解決

springboot啓動嵌入式tomcat報錯找不到jar包,關鍵字:FileNotFoundException,derbyLocale_cs.jar,StandardJarScanner.scan…

因爲Tomcat在掃描包路徑的時候感覺,掃描路徑有問題,追蹤源碼在TomcatEmbeddedServletContainerFactory#prepareContext()有個tldSkipPatterns的東西,可以告訴Tomcat不掃描指定Jar包的配置

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.LegacyCookieProcessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @description: tomcat容器掃描包路徑配置問題
 * @author: peikunkun
 * @create: 2020-06-11 09:32
 **/
@Slf4j
@Configuration
public class TomcatContainerConfig {

  /**
   * 跳過tomcat的掃描配置
   */
  @Value("${com.pkk.tomcat.tldSkipPatterns:}")
  private String[] tldSkipPatterns;

  /**
   * @Description: tomcat的後置處理器
   * @return: org.springframework.beans.factory.config.BeanPostProcessor
   * @Author: peikunkun
   * @Date: 2020/6/11 0011 上午 9:38
   */
  @Bean
  public BeanPostProcessor tomcatContainerPostProcessor() {
    List<String> notEmptyTldSkipPatterns = Arrays.stream(tldSkipPatterns)
        .filter(tldSkipPattern -> !tldSkipPattern.trim().isEmpty())
        .collect(Collectors.toList());
    log.info("[Tomcat container scan]-[Postprocessing configuration]-Exclude jar package[{}]", notEmptyTldSkipPatterns);
    return new BeanPostProcessor() {
      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
      }

      @Override
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("tomcatServletWebServerFactory") && bean instanceof TomcatServletWebServerFactory) {
          TomcatServletWebServerFactory factory = (TomcatServletWebServerFactory) bean;
          if (!notEmptyTldSkipPatterns.isEmpty()) {
            factory.addTldSkipPatterns(notEmptyTldSkipPatterns.toArray(new String[0]));
          }
        }
        return bean;
      }
    };
  }
}



#然後在配置文件中配置就可以了
com.pkk.tomcat.tldSkipPatterns = mchange-commons-java-0.2.10.jar,jaxb-api.jar,activation.jar,jsr173_1.0_api.jar,jaxb1-impl.jar

Tomcat8.5前與後Cookie的處理機制改變,造成解析異常的處理

>異常信息:An invalid domain [.xxx.com] was specified for this cookie
>異常分析:tomcat8.5之後,其對cookie的處理機制就變的不同了
>解決方法:其實就兩種處理方式,一種Rfc6265CookieProcessor,一種是LegacyCookieProcessor,而8.5之後默認使用Rfc6265CookieProcessor;Rfc6265CookieProcessor的domain域只能以字母或數字開頭,LegacyCookieProcessor是以 . 開頭;



/**
   * @Description: 一種Rfc6265CookieProcessor,一種是LegacyCookieProcessor,而8.5之後默認使用前者,這兩種在用法上可以自行百度,前面一種的domain域只能以字母或數字開頭,而後者則是以
   * . 開頭,所以有兩種方法
   * <p>
   * 解析cookie的方式不同
   * @return: org.springframework.boot.web.server.WebServerFactoryCustomizer<org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory>
   * @Author: peikunkun
   * @Date: 2020/6/16 0016 下午 1:22
   */
  @Bean
  public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
    return (factory) -> factory.addContextCustomizers(
        //不以 . 開頭的用這個
        //(context) -> context.setCookieProcessor(new Rfc6265CookieProcessor()));
        //以.開頭用這個 
        (context) -> context.setCookieProcessor(new LegacyCookieProcessor()));
  }

Tomcat的外置內置的不同打包方式

  • jar打包方式[內置Tomcat],內置Tomcat上面也講過
<!--將packaging指定爲jar-->
<packaging>jar</packaging>



 <!--jsp解析-->
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-jasper</artifactId>
      <!--如果採用內置Tomcat,不使用外部Tomcat請把此註釋掉-->
      <!--<scope>provided</scope>-->
    </dependency>

    <!--直接內嵌tomcat-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <!--如果採用內置Tomcat,不使用外部Tomcat請把此註釋掉-->
      <!--<scope>provided</scope>-->
    </dependency>



  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
          <!-- 高版本springboot要訪問jsp頁面,只能用這個版本的打包插件,否則計算jsp打進入也訪問不了 -->
          <version>1.4.2.RELEASE</version>
          <configuration>
            <includeSystemScope>true</includeSystemScope>
          </configuration>
          <executions>
            <execution>
              <goals>
                <goal>repackage</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <!--打包web.xml沒有的問題-->
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>${maven-war-plugin.version}</version>
          <configuration>
            <!--如果想在沒有web.xml文件的情況下構建WAR,請設置爲false。-->
            <failOnMissingWebXml>false</failOnMissingWebXml>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>


    <!--maven編譯插件-->
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven-compiler-plugin.version}</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
          <encoding>UTF-8</encoding>
          <!--使項目是按照maven標準目錄結構來構建,即第三方jar包放在src/main/webapp/WEB-INF/lib中,maven-compiler-plugin仍然不會自動去尋找第三方jar包,仍然需要手動配置 < extdirs>-->
          <compilerArguments>
            <extdirs>${project.basedir}/src/main/lib</extdirs>
          </compilerArguments>
        </configuration>
      </plugin>
    </plugins>

    <!--資源打包資源管理-->
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
          <include>**/*</include>
        </includes>
      </resource>
      <!-- springboot訪問jsp頁面必須打包到META-INF/resources目錄下 -->
      <resource>
        <directory>src/main/webapp</directory>
        <targetPath>META-INF/resources</targetPath>
        <includes>
          <include>**/**</include>
        </includes>
      </resource>
    </resources>
  </build>

war打包方式[外部Tomcat]

<!--將packaging指定爲war-->
<packaging>war</packaging>


 <!--jsp解析-->
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-jasper</artifactId>
      <!--如果採用內置Tomcat,不使用外部Tomcat請把此註釋掉-->
      <scope>provided</scope>
    </dependency>

    <!--直接內嵌tomcat-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <!--如果採用內置Tomcat,不使用外部Tomcat請把此註釋掉-->
      <scope>provided</scope>
    </dependency>



<build>
    <plugins>
        <!--忽略Junit代碼-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.4.2</version>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
    </plugins>
</build>


//修改爲Tomcat外置容器啓動的配置
@SpringBootApplication
public class HhzAdminApplicationextends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(HhzAdminApplication.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(HhzAdminApplication.class);
    }
}

阿里雲的健康Http/Https健康檢測導致Nginx一會出現502

100.116.186.46 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.68 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.24 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.2 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.25 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.101 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.73 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.83 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.35 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.100 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.39 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.97 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.92 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.23 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.9 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.125 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.69 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.91 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.105 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.112 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.10 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.121 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.21 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.87 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.13 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.71 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.83 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.120 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.64 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.46 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.67 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.75 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.45 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.24 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.116 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"
100.116.186.25 - - [17/Jun/2020:11:22:14 +0800] "HEAD / HTTP/1.0" 404 0 "-" "-"

改造完成之後不上線上,一會請求就變成502了,打印nginx的請求日誌,發現大量的HEAD請求,並且返回404
原因分析:經過一番排查,發現是阿里雲的健康Http/Https檢測,發送head請求(路徑爲“/”),然後根據返回的狀態進行驗證服務的狀態是否正常
健康雲檢測的文檔:
在這裏插入圖片描述

是因爲SpringBoot的路徑“/”這邊我沒有配置,然後請求返回404和與設定的狀態不符,阿里雲負載認爲服務有問題,就不再往負載上操作了,就直接返回502了

 /**
   * @Description: 健康檢查
   * @Param: request
   * @return: void
   * @Author: peikunkun
   * @Date: 2020/6/17 0017 下午 10:02
   */
  @RequestMapping("/")
  @ResponseBody
  public void healthCheck(HttpServletRequest request) {
    log.debug(request.getRemoteAddr() + "--->HEALTH CHECK");
  }

異常的頁面的錯誤,比如404,502,500狀態碼的處理

import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @description: 異常控制處理器
 * @author: peikunkun
 * @create: 2020-06-17 16:30
 **/
@Slf4j
@Controller
public class ExceptionHandleController implements ErrorController {



  /**
   * 錯誤頁面路徑
   */
  public static final String ERROR_PATH = "/error";

  /**
   * Returns the path of the error page.
   *
   * @return the error path
   */
  @Override
  public String getErrorPath() {
    return ERROR_PATH;
  }


  /**
   * @Description: 重寫錯誤頁面
   * @Param: request
   * @return: java.lang.String
   * @Author: peikunkun
   * @Date: 2020/6/17 0017 下午 4:32
   */
  @RequestMapping("/error")
  public String handleError(HttpServletRequest request) {
    //獲取statusCode:401,404,500
    Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
    if (null == statusCode) {
      statusCode = 500;
    }

    String redirect = "";
    switch (statusCode) {
      case 401:
      case 404:
      case 403:
      case 500:
      default:
        redirect= "/badpage/index/noparam";
    }
    return "redirect:" + redirect;
  }
}

web端基礎設置,靜態資源配置,jsp解析配置->參考示例

/**
 * @description: 過濾器的配置
 * @author: peikunkun
 * @create: 2020-06-08 17:58
 **/
@Slf4j
public class WebMvcResolveConfig extends WebMvcConfigurationSupport {

  /**
   * @Description: jsp視圖解析器
   * @return: org.springframework.web.servlet.view.InternalResourceViewResolver
   * @Author: peikunkun
   * @Date: 2020/6/9 0009 上午 9:54
   */
  @Bean
  public InternalResourceViewResolver viewResolver() {
    log.info("[Resource Configuretion]-[Configure JSP resolution resource configuration]");
    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    viewResolver.setPrefix("/WEB-INF/jsp/");
    viewResolver.setSuffix(".jsp");
    return viewResolver;
  }


  /**
   * @Description: Override this method to add resource handlers for serving static resources.
   * <p>
   * 修改支持我們的靜態資源信息
   * @Param: registry
   * @return: void
   * @Author: peikunkun
   * @Date: 2020/6/9 0009 上午 9:58
   */
  @Override
  protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    log.info("[Resource Configuration]-[Configure static / profile resource path configuration]");
    //請求路徑
    registry.addResourceHandler("/**")
        //在項目中的資源路徑
        .addResourceLocations("classpath:/META-INF/resources/")
        .addResourceLocations("classpath:/resources/")
        .addResourceLocations("classpath:/static/")
        .addResourceLocations("classpath:/public/");
    super.addResourceHandlers(registry);
  }
}

------------------------


@Slf4j
@Configuration
public class WebConfigurationHandleConfig extends WebMvcResolveConfig {


  @Bean
  public LoginHandlerInterceptor loginHandlerInterceptor() {
    return new LoginHandlerInterceptor();
  }

  /**
   * Override this method to add Spring MVC interceptors for pre- and post-processing of controller invocation.
   *
   * @param registry
   * @see InterceptorRegistry
   */
  @Override
  protected void addInterceptors(InterceptorRegistry registry) {
    super.addInterceptors(registry);
    log.info("[Resource Configuretion]-[Resource configuration filter]");

    //攔截匹配PATH請求
    registry.addInterceptor(loginHandlerInterceptor())
        .addPathPatterns("/**/**")
        .excludePathPatterns("/static/**");
  }


  /**
   * @Description: 配置默認的靜態資源處理器[SpringMvc會默認的識別]
   * @Param: configurer
   * @return: void
   * @Author: peikunkun
   * @Date: 2020/6/17 0017 下午 7:54
   */
  @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable("default");
  }
}


擴展知識

  1. WebMvcConfigurer接口方法說明

public interface WebMvcConfigurer {
    void configurePathMatch(PathMatchConfigurer var1);
    //這個方法是專門用來配置內容裁決的一些參數的(/* 是否通過請求Url的擴展名來決定media type */configurer.favorPathExtension(true)  /* 不檢查Accept請求頭 */.ignoreAcceptHeader(true).parameterName("mediaType")/* 設置默認的media yype */.defaultContentType(MediaType.TEXT_HTML) /* 請求以.html結尾的會被當成MediaType.TEXT_HTML*/.mediaType("html", MediaType.TEXT_HTML)/* 請求以.json結尾的會被當成MediaType.APPLICATION_JSON*/.mediaType("json", MediaType.APPLICATION_JSON);)
    void configureContentNegotiation(ContentNegotiationConfigurer var1);
    void configureAsyncSupport(AsyncSupportConfigurer var1);
    /* 默認靜態資源處理器 (這個Handler也是用來處理靜態文件的,它會嘗試映射/。當DispatcherServelt映射/時(/ 和/ 是有區別的),並且沒有找到合適的Handler來處理請求時,就會交給DefaultServletHttpRequestHandler 來處理。注意:這裏的靜態資源是放置在web根目錄下,而非WEB-INF 下)*/
    void configureDefaultServletHandling(DefaultServletHandlerConfigurer var1);
    //類型轉換器和格式化器
    void addFormatters(FormatterRegistry var1);
    /* 攔截器配置addPathPatterns("/")對所有請求都攔截.excludePathPatterns("/index.html","/","/user/login","/static/");排除指定攔截*/
    void addInterceptors(InterceptorRegistry var1);
   /*靜態資源處理如registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");*/
    void addResourceHandlers(ResourceHandlerRegistry var1);
    //跨域
    void addCorsMappings(CorsRegistry var1);
   /* 視圖跳轉控制器 */
    void addViewControllers(ViewControllerRegistry var1);
   /* 配置視圖解析器 */
    void configureViewResolvers(ViewResolverRegistry var1);
    void addArgumentResolvers(List<HandlerMethodArgumentResolver> var1);
    void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> var1);
    //配置消息轉換器
    void configureMessageConverters(List<HttpMessageConverter<?>> var1);
    void extendMessageConverters(List<HttpMessageConverter<?>> var1);
    void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> var1);
    void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> var1);
    Validator getValidator();
    MessageCodesResolver getMessageCodesResolver();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章