Springboot 的一些默認配置規則


說明

本文樣例說明僅適用 maven 環境和語法,但所述內容也適用 gradle

原文地址:https://www.cnblogs.com/qnlcy/p/15905544.html

一、日志

1. logback

日志默認為 slf4j + logback 框架,引入如下 jar 之后,就自動引入了 logback

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>

默認配置文件名稱如下,在 classpath 目錄下存在對應文件名即可,無需額外通過配置指定

  • logback-spring.xml (官方推薦,可以添加 spring boot 的 springProfile 配置項)
  • logback.xml

2. log4j2

請在大流量應用當中使用 log4j2 而不是使用 log4jlog4j 在並發寫文件上有嚴重的性能問題,而且,她已經退役了。

首先要排除默認日志框架 logback ,如下為樣例代碼

請不要照抄到項目當中而帶來不必要的 spring-boot-starter-web 及其系列 web 功能的引用
你需要掌握的是如何排除一個 jar 和引入另外一個 jar

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

默認配置文件名稱如下,同樣在 classpath 目錄下存在對應文件名即可,無需額外通過配置指定

  • log4j2-spring.xml(官方推薦,可以添加 spring boot 的 springProfile 配置項)
  • log4j2.xm

二、項目配置文件

1. 配置文件路徑

springboot 默認從如下位置加載配置文件,按 優先級 排序為

  1. 當前 jar 目錄下的 config 子目錄
  2. 當前 jar 目錄下的 config/* 目錄,注意,此時會合並 config 的子目錄下的所有 application 配置文件
  3. 當前 jar 目錄
  4. classpath 下的 config 目錄
  5. classpath 目錄

找尋的 默認配置文件 名稱,優先級 為:

  1. application.properties
  2. application.yml
  3. application.yaml

相同配置屬性下,優先級高的配置會覆蓋優先級低的配置,但是不同的配置屬性會合並

比如,在 applicaiton.properties 里有:

name=qnlcy

application.yml 里有:

name: cnblog
age: 18

這時候,spring 讀取到的 nameage 值分別為 qnlcy18

2. 環境配置

指定 spring 加載的環境,可以使用如下配置

yml / yaml

spring:
  profiles:
    active: dev

properties

spring.profiles.active=dev

命令行參數形式

-Dspring.profiles.active=dev
#或
--spring.profiles.active=dev

然后 spring 會在 上述 第1小節 配置文件目錄 下,同樣 優先 查找對應的如下文件

  1. application-${profiles}.properties
  2. application-${profiles}.yml
  3. application-${profiles}.yaml

對應上述配置,找尋的配置文件即為:application-dev.propertiesapplication-dev.ymlapplication.yaml

三、spring默認依賴介紹和項目划分

項目可以粗略划分為

  • web 項目
  • 非 web 項目

兩種類型的項目,如果使用 spring 管理依賴版本,則 pom.xml 需要加上 <parent> 相關配置:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.5.RELEASE</version>
</parent>

這里默認使用 spring 管理依賴版本,各個項目也應當繼承 spring-boot-starter-parent, 下面不再寫各個依賴的版本

1. 非web項目

先說下非 web 項目,非 web 項目使用 springboot,只需要引入如下 jar 即可

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

它顯式依賴如下包:

  • spring-boot springboot項目核心包
  • spring-boot-autoconfigure springboot項目的自動配置包,包含datasource、http、session等等等自動配置相關代碼
  • spring-boot-starter-logging springboot項目的日志包,默認實現為 logback
  • spring-core spring核心包

其中,spring-boot-autoconfigure 又自動依賴 spring-boot

spring-boot 依賴 springframework 的系列包,其依賴及其子依賴分別為

  • spring-context
  • spring-beans
  • spring-core
  • spring-aop
  • spring-expresion

2. web項目

web項目引用如下 jar 即可

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

它顯式依賴了如下 jar

  • spring-boot-starter
  • spring-boot-starter-json 這里引入 jackson
  • spring-boot-starter-tomcat 默認內置 tomcat,切換web容器時候需要排除此包
  • spring-webmvc
  • spring-web

傳統的 dubbo 服務提供者項目、RocketMq 消息消費服務、批處理服務,就不要再引用 spring-boot-starter-web 包了,它默認會引入 web 容器,並開放 web 服務和端口,這是危險和不必要的

四、springboot 啟動類和其注解

1. 啟動類

springboot 的啟動類不能直接放在 src/main/java 目錄下,即:

springboot 的啟動類的 包路徑 不能為空

如果這樣做的話,會出現意想不到的錯誤,感興趣的同學可以試一下。

通常的,我們會把啟動類放到諸如 com.xxx.xxx 之類頂級路徑下,如:com.xxx.xxx.App.class

然后再在頂級路徑下新建如 configbusinessutilsconstantenums 之類的包,結構如下:

com.xxx.xxx
  + config/
  + business/
  + utils/
  + constant/
  + enums/
  App.class

spring 默認會自動掃描啟動類的同級目錄及其子目錄下的 spring bean 定義,並裝載到 spring 容器當中

因此,如果要引用外部包內的 spring bean ,則需要通過如下方式告知包掃描路徑給 spring

@SpringBootApplication
@ComponentScan({"com.xxx.yyy","com.xxx.zzz"})
public class Application {
  public static void main(String[] args) {
  SpringApplication.run(Application.class, args);
  }
}

其中,com.xxx.zzz 為風控 jar 包的路徑,在注解 @ComponentScan 當中添加該路徑,即可使用該 jar 包內的 spring bean 組件

2. 啟動類注解

通常,springboot 啟動類注解只需要一個 @SpringBootApplication 即可,觀其定義,可以發現,它自動包含了 @ComponentScan@EnableAutoConfiguration 等注解,已經包含 包掃描自動配置 功能

//...
@EnableAutoConfiguration
@ComponentScan(
   //...
)
public @interface SpringBootApplication {
    //...
}

關於 dubbo

如果使用 dubbo 包里的 @Service (注意不是 spring 的 @Service)@Reference 來暴露和引用服務,則需手動開啟 dubbo 功能,來使 dubbo 掃描到上述注解開啟的 dubbo 服務

@SpringBootApplication
@EnableDubbo
public class Application {
    public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
    }
}

如果 dubbo 服務不在當前項目路徑下,則額外添加 @DubboComponentScan({"com.xxx.xxx"}) 注解來指定 dubbo 掃描路徑

通常我們使用 xml 配置文件的形式來歸納 dubbo 的相關服務,此時,只要在 spring 啟動時候,把 dubbo bean 相關配置引入到 spring 容器中即可。

常用做法如下,定義個 springboot 配置類來導入 dubbo bean

@Configuration
@ImportResource({"classpath:dubbo/config.xml", "classpath:dubbo/consumer.xml", "classpath:dubbo/provider.xml"})
public class DubboConfig {

}

關於事務

如果引用了 spring-jdbc 並且配置了 DataSource,則 springboot 默認會開啟事務支持,不需要再使用 @EnableTransactionManagement 顯式開啟事務了

五、MVC中的錯誤處理

在 web 項目當中,springboot 對異常粗略划分,可以有如下處理

  • 使用 @ControllerAdvice + @ExceptionHandler 來處理已到達controller層級的業務異常
  • 自定義 error controller 來處理其他系統級異常

感興趣的同學可以追蹤 DispatcherServlet.doDispatch() 方法來查看具體錯誤處理過程

1. ControllerAdvice 的用法

在項目當中,使用 @ControllerAdvice 注解指定一個 異常處理器,它自動交給了 spring 管理,其本質是一個 spring bean

@ControllerAdvice
public class ExceptionResolver {

    //因為是 spring bean,所以可以注入自己需要的資源

    @ExceptionHandler(value = BusinessException.class) //指定攔截的異常
    @ResponseBody //指定返回頁面為json串
    //方法名可以自定義,但參數不能變,可選參數尚有 HttpServletRequest
    public String businessExceptionHandler(HandlerMethod handlerMethod, Exception e) throws Exception {
        //處理異常
    }

    //可以定義多個異常處理方法,spring 會自動尋找對應的異常處理器
    //切記最后要有一個處理Exception的兜底

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public String defaultErrorHandler(HandlerMethod handlerMethod, Exception e) throws Exception {
    }
}

2. 自定義 error controller 來處理其他系統級異常

在出現 controller 層級之外的異常之后,springboot加載的內置容器會轉發異常到 springboot 指定的 errorPath 路徑上,默認為 /error ,可以通過如下配置修改

server.error.path=/err1

轉發過來的請求可以這樣處理

@Controller
@RequestMapping("/err1") //上述定義的錯誤路徑
public class CustomErrorController{

    @RequestMapping(produces = "text/html")
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        //request中含有 狀態碼 和 錯誤信息
        return new ModelAndView("500.html");
    }
}

六、JSON

springboot 支持三種 JSON 框架,默認為 Jackson

1. Jackson

當項目當中引入了 spring-boot-starter-json 包后, springboot 會自動創建一個 ObjectMapper bean 來使用。可以通過 spring.jackson 的相關配置來 定義該 bean,祥見 org.springframework.boot.autoconfigure.jackson.JacksonProperties

2. Gson

當項目當中引入了 Gson 包后,springboot 會自動創建一個 Gson bean。通過 spring.gson 的相關配置或 GsonBuilderCustomizer 來定義該 bean

3. JSON-B

JSON-b 是一種 json api 規范,當 javax.json-api jar包存在項目當中,並且其實現類也存在,Springboot就會創建一個 Jsonb 來使用。這種不常見,不再介紹。

七、測試

1. 單元測試

使用單元測試,需引用 spring-boot-starter-test,並指定其范圍為 test

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <!-- 如果是junit5 則排除如下依賴 -->
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>

maven 管理的依賴對其 scope 做了划分,有如下幾種

編譯 測試 打包 運行 說明
compile 默認的范圍
test √(測試代碼) × × 如:junit
runtime × 如:jdbc驅動
provided × × 運行時使用別的包代替,如:servlet-api,在tomcat容器中已有此包
system × × 跟provided相同,只不過從本地文件系統拉包,而不是從maven倉庫(本地和遠程)拉取

創建 test 類,使用 @SpringBootTest 注解來聲明該類為測試類


//@@RunWith(SpringRunner.class) 如果使用 junit4 則需要添加此注解,junit5 則不再需要
@SpringBootTest //不用再指定啟動類,springboot 會自動找到啟動類並啟動 spring
public class PaHttpServiceTest {

    //可以正常引用其他 spring 資源

    //方法必須為public,返回值必須為 void , junit5 可以不寫 public
    @Test
    public void testHttp() {
        //
    }
}

2. benchmark 基准測試

此類測試為代碼性能測試服務,不適用與業務測試。此類測試會分析每個基准測試方法的單位時間吞吐量、執行耗時等,方便我們提升自己代碼的性能。

引入相關依賴

<!-- JMH-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <encoding>UTF-8</encoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>

        <jmh.version>1.21</jmh.version>
    </properties>

    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-core</artifactId>
        <version>${jmh.version}</version>
    </dependency>
    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-generator-annprocess</artifactId>
        <version>${jmh.version}</version>
        <scope>provided</scope>
    </dependency>

創建測試類,main 方法執行,所有被注解 @Benchmark 標注的方法都會進行性能測試

@BenchmarkMode(Mode.Throughput)  //基准測試類型。這里選擇的是吞吐量
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)  //預熱,輪數:5輪,每次預熱時間:1,單位:秒(默認)
@Measurement(iterations = 10, time = 5, timeUnit = TimeUnit.SECONDS) //進行10輪測試,每次時間:5,單位,秒
@Threads(8) //一般CPU*2 每個fork所用的線程數量
@Fork(2) //JMH分出2個 “進程”進行測試
@OutputTimeUnit(TimeUnit.NANOSECONDS)  //基准測試結果里面的時間類型
public class StringAppend {

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(StringAppend.class.getSimpleName())
                .build();
        new Runner(options).run();
    }


    @Benchmark
    public void testStringAdd() {
        String a = "";
        for (int i = 0; i < 10; i++) {
            a += i;
        }
    }

}

下面測試結果說明,平均每納秒,能執行4次

方法名 測試類型 測試次數 得分 錯誤 單位
StringAppend.testStringAdd thrpt 4 0.010 ± 0.001 ops/ns


免責聲明!

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



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