Spring Boot打成war包引入外部配置文件部署Tomcat


前言:Spring Boot因其特定的配置方式,受到了Java開發者們的熱捧,成為了近年來最受歡迎的Java開發框架,當下的Coder如果要新創建項目,首選都是Spring Boot,而且與微服務有着完美的切入口。Spring Boot中內置的Tomcat插件,使得開發者不需要進行額外的Tomcat配置,就可一鍵啟動項目。

Spring Boot可以打包成jar或者war的形式部署,現在生產很大一部分也是通過打包成war包的形式去進行部署,Spring Boot項目 也可以直接打包成可執行的jar或者war包,直接使用java -jar xx.jar/xx.war。

這種方式的話,Spring Boot項目的配置依賴之類的都在jar或war之內,如果需要更改配置,則需要從重新打包重啟,不利於運維。

 

下面介紹如何將Spring Boot和配置分離打包成war,放入Tomcat中運行,引入外部配置。

前提條件:一個SpringBoot項目+Tomcat容器(我用的是8.5.53

 

1.先去除spring-boot-starter-web依賴中內置的tomcat容器

<dependency>
    <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
<!-- 移除嵌入式tomcat插件 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
 
        

2.添加javax.servlet-api或者tomcat-servlet-api依賴

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

3.修改項目默認啟動方式,啟動類繼承SpringBootServletInitializer類重寫configure()方法,也可以新建類繼承SpringBootServletInitializer類重寫configure()方法,兩種方式如下分別如下展示

啟動類繼承SpringBootServletInitializer類

package com.xiaochun;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

/**
 * 啟動類繼承SpringBootServletInitializer, 重寫configure(SpringApplicationBuilder builder)方法,返回當前啟動類
 */
@SpringBootApplication
public class XiaochunApplication extends SpringBootServletInitializer {

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

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(XiaochunApplication.class);
    }
}

新建類繼承SpringBootServletInitializer類

package com.xiaochun;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

/**
 * 取代原先SpringBoot啟動XiaochunApplication.main()方法啟動整個項目的方式
 * 修改啟動類,繼承 SpringBootServletInitializer 並重寫 configure 方法
 */
public class XiaochunStartApplication extends SpringBootServletInitializer {

    /**
     * 默認返回return super.configure(builder);
     * 現指向XiaochunApplication.main()啟動方法
     * @param builder
     * @return
     */
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
//        return super.configure(builder);
        return builder.sources(XiaochunApplication.class);
    }
}

4.配置文件分離,在pom文件build標簽中加入以下配置

<resources>
    <resource>
        <directory>src/main/resources</directory>
        <!--打包時排除src/main/resources下的所有以.properties .yml .xml為后綴的配置文件-->
        <excludes>
            <exclude>**/*.properties</exclude>
            <exclude>**/*.yml</exclude>
            <exclude>**/*.xml</exclude>
        </excludes>
    </resource>
</resources>

5.創建外部配置文件xiaochun.properties,我把他放在D盤下,內容如下

xiaochun.version=0.0.1.release
xiaochun.descriprtion=How to package SpringBoor project to war;

6.使用EnvironmentPostProcessor實現程序啟動時自動加載自定義屬性文件,新建EnvironmentPostProcessorConfig類,指定外部配置文件絕對路徑(全路徑),內容如下

package com.xiaochun.config;

import
com.xiaochun.enums.ResourcesEnum; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.PropertiesPropertySource; import org.springframework.stereotype.Component; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * 配置啟動監聽器,用於加載外部配置文件 */ @Component public class EnvironmentPostProcessorConfig implements EnvironmentPostProcessor { private Logger logger = LoggerFactory.getLogger(this.getClass()); public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { try {        //ResourcesEnum為枚舉類
InputStream inputStream
= new FileInputStream(ResourcesEnum.PROPERTIES_PATH.getPath()); Properties properties = new Properties(); properties.load(inputStream); PropertiesPropertySource propertiesPropertySource = new PropertiesPropertySource("my",properties); environment.getPropertySources().addLast(propertiesPropertySource); } catch (IOException e) { logger.error("讀取自定義配置異常"); } } }

枚舉類內容如下

package com.xiaochun.enums;

import lombok.Data;

/**
 * 外部配置文件枚舉類,外部配置文件path從這里獲取
 */
public enum ResourcesEnum {

    PROPERTIES_PATH("全局配置文件", "D:\\xiaochun.properties");

    private String label;
    private String path;

    ResourcesEnum(String label, String path) {
        this.label = label;
        this.path = path;
    }

    public String getLabel() {
        return label;
    }

    public String getPath() {
        return path;
    }
}

 

7.在resources下新建META-INF\spring.factories,文件內容為如下,用於指定項目啟動的監聽器,也就是上一步我們自定義的EnvironmentPostProcessorConfig

org.springframework.boot.env.EnvironmentPostProcessor=com.xiaochun.config.EnvironmentPostProcessorConfig

8.打包成war放在tomcat容器的webapps目錄下,啟動tomcat

9.啟動tomcat,訪問/home/index接口,驗證我們剛配置的那些內容,接口內容如下

package com.xiaochun.controller;

import com.fasterxml.jackson.databind.util.JSONPObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.json.GsonJsonParser;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/home")
public class HomeController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${xiaochun.version}")
    private String version;

    @Value("${xiaochun.descriprtion}")
    private String description;

    @GetMapping("/index")
    public String index(){
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("index", "index");
        map.put("version", version);
        map.put("description", description);
        return map.toString();
    }
}

訪問結果如下

可以看出,我們的配置是有效的,這樣就可以實現不同的環境,我們只需要打包業務相關的代碼,不需要去理會配置如何,同一個包,可在測試、生產等不同的環境部署。


免責聲明!

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



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