補習系列(1)-springboot項目基礎搭建課


前言

springboot 最近火的不行,目前幾乎已經是 spring 家族最耀眼的項目了。拋開微服務、技術社區這些推廣因素不說,框架本身的確有非常多的優點。比如

  • 更簡化的配置,摒除了許多繁雜的xml配置(事實證明,越簡單的東西越容易讓人記住);
  • 內置Servlet容器,不再依賴外部環境
  • 大量的starter模塊,隨手拈來
  • 支持熱部署

作為一名老程序員來說,仍然需要保持一個積極學習的態度。
哎,簡單點說就是少點傷感,認清現實。你曾經引以為傲的某某EE 技術已經被顛覆了,趕緊換車道 .....

廢話不多說,以下內容主要講的是怎么利用springboot 這個腳手架搭建一個最精簡的項目。
其中幾個模塊會非常實用,這包括結構、配置、日志、部署..

一、基礎結構

springboot 項目仍然是使用maven 進行初始化及構建,下面是一個典型的結構:

目錄文件 說明
pom.xml 依賴文件
src/main/java 代碼目錄
src/main/resources 配置目錄,包含application.properties、log4j2.xml
src/main/build 定義構建文件目錄
src/test/java 測試代碼
src/test/resources 測試配置

大致看一下就行了,不了解maven的話,點擊這里先學習入門,項目的構建工具是一定要先了解的。
可以通過eclipse 或idea 創建一個maven項目,再引入springboot依賴,pom文件的定義參考如下:

<?xml version="1.0"?>
<project
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.zales</groupId>
   <artifactId>dmo-boot</artifactId>
   <version>0.0.1-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot.version>1.5.1.RELEASE</spring-boot.version>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
	<dependencies>
		<!-- springboot application dependencies -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-dependencies</artifactId>
			<version>${spring-boot.version}</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- springweb -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <!-- exclude the default logging module -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

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

        <!-- used for livereload -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- used for template -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

springboot 官方的示例是讓你繼承一個spring-boot-parent,但這個很雞肋,通常的項目都會有自己的繼承結構。
所以我們間接利用spring-boot-dependencies將所有依賴引入,其他模塊的引入都是按需。
maven-compiler-plugin的定義用於將項目指定為Java1.8的編譯級別

其他途徑
你還可以利用spring的在線網站初始化一個springboot項目,點擊這里

二、添加代碼

啟動代碼非常簡單,新建一個名為"DemoBoot**的類:

/**
 * 入口類
 *
 */
@SpringBootApplication
public class DemoBoot {

    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication(DemoBoot.class);

        // 指定PID生成,默認輸出到application.pid
        app.addListeners(new ApplicationPidFileWriter());
        app.run(args);
    }
}

再創建一個DemoController類:

@Controller
public class DemoController {
    
    @RequestMapping("/")
    @ResponseBody
    String home() {
        return "Hello World! ";
    }
}

至此,我們已經完成了框架代碼!

熱部署
我們在定義項目依賴時添加了springboot-devtools,該模塊可以實現熱部署的功能,即在開發過程中可以不重啟應用令代碼生效,非常方便
livereload 組件會定時掃描類路徑下的class,一旦發現變更即重啟服務,默認1000毫秒檢測一次。
在定義依賴時指定optional 選項使得該模塊僅在開發時啟用。
livereload 在掃描會自動忽略以下范圍的變更:

META-INF/maven/**
META-INF/resources/**
resources/**,static/**
public/**
templates/**
**/*Test.class
**/*Tests.class
git.properties
META-INF/build-info.properties 

三、應用配置

在src/main/resources/下新建一個application.properties文件,內容如下:
application.properties

server.address=0.0.0.0
server.port=8090
參數名稱 參數說明
server.address 監聽地址,不配置或0.0.0.0即不限制
server.port 監聽端口

此時在IDE執行"DemoBoot",你應該可以看到一些描述程序啟動的日志信息,訪問本機的8090端口能看到"HelloWorld“輸出。

application.properties可包含大量的配置,你可以在這里找到全部的配置

四、日志配置

接下來需要為應用准備一個日志配置用於定制,springboot 默認是使用logback的,但由於更加熟悉log4j的緣故,我們選用了log4j2.x
在src/main/resources/下新建一個log4j2.xml文件,內容如下:

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" monitorInterval="300">  
    <properties>  
        <property name="LOG_ROOT">log</property>  
        <property name="FILE_NAME">application</property>  
    </properties>  
    <Appenders>  
        <Console name="Console" target="SYSTEM_OUT">  
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}–[%t] %-5level -%l - %msg%n" />  
        </Console>  
        <RollingRandomAccessFile name="MainFile"  
            fileName="${LOG_ROOT}/${FILE_NAME}.log"  
            filePattern="${LOG_ROOT}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd HH}-%i.log">  
            <PatternLayout  
                pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}–[%t] %-5level -%l - %msg%n" />  
            <Policies>  
                <TimeBasedTriggeringPolicy interval="1" />  
                <SizeBasedTriggeringPolicy size="50 MB" />  
            </Policies>  
            <DefaultRolloverStrategy max="20" />  
        </RollingRandomAccessFile>  
    </Appenders>  

    <Loggers>  
        <Logger name="org.zales" level="info" additivity="true">  
            <AppenderRef ref="MainFile" />  
        </Logger>  
        <Root level="info">  
            <AppenderRef ref="Console" />  
            <AppenderRef ref="MainFile" />  
        </Root>  
    </Loggers>  
</Configuration>  

這里配置了兩個日志記錄方式,Console是控制台打印,RollingRandomAccessFile 指向一個日志文件,我們為該日志文件設定了滾動的規則:

  1. 當大小超過50M時會生成新的日志;
  2. 每小時生成一個新的日志;
    *** ***指定了最多存在20個日志文件。
    之后,我們為主模塊(這里是org.zales,你可以定義自己的包名)和ROOT都分別做了關聯和日志級別定義。
    關於log4j2的用法,可以參考這個文章

五、打包部署

應用最終需要發布到某個環境,那么我們怎么對springboot應用進行打包呢?
利用spring-boot-maven-plugin可以將springboot項目達成jar包。
隨后執行java -jar xxx.jar的方式即可以啟動應用。
這看起來好像很美好,但真實的項目發布並非這么簡單。

  • 首先是配置,springboot的maven插件會將所有配置文件都打進jar包內,而某些配置可能與環境相關。
    比如應用端口,安全證書、或是日志配置等,這時我們希望在jar包外部存放這些文件;
  • 其次是執行腳本,在雲環境上發布應用,通常需要提供啟停腳本,包括一些監控功能腳本,這些需要作為項目打包的一部分
  • 最后,將應用程序發布為tgz或zip格式的壓縮包會更加靈活,你可以添加更多的東西。

為實現靈活的打包方式,我們需要同時引用spring-boot-maven-plugin和maven-assembly-plugin兩個插件,如下:
pom.xml

<build>
        <plugins>
            <!-- build for springboot jar -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- build for application package -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <executions>
                    <execution>
                        <id>bundle</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <descriptors>
                                <descriptor>${basedir}/src/main/build/assembly.xml</descriptor>
                            </descriptors>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

plugin可以實現在maven的某個生命周期綁定一組動作,如上面的兩個插件都綁定到了package階段,執行順序由聲明的先后決定。
於是項目在執行mvn package這樣的命令時,會先執行springboot插件的repackage動作,將程序打包成jar文件;隨后通過assembly插件執行bundle任務,
再作最終的組裝。
/src/main/build/assembly.xml定義了程序包的結構,如下:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    <id>bundle</id>
    <formats>
        <format>tar.gz</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory> <!-- disable the creation of root's distribution dir in the archive -->

     <fileSets>  
        <!-- config files -->
        <fileSet>  
            <directory>${basedir}/src/main/build/config</directory>  
            <excludes></excludes>  
             <includes>
                <include>application*.properties</include>
                <include>log4j2.xml</include> 
            </includes>
            <fileMode>0644</fileMode>
            <outputDirectory>/</outputDirectory>  
        </fileSet>  
        <!-- scripts -->
        <fileSet>
            <directory>${basedir}/src/main/build/bin</directory>
            <includes>
                <include>*.sh</include>
            </includes>
            <fileMode>0755</fileMode>
            <outputDirectory>/</outputDirectory>
        </fileSet>
        <!-- executable jar -->
         <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>${project.artifactId}-${project.version}.jar</include>
            </includes>
            <fileMode>0755</fileMode>
        </fileSet>
    </fileSets>  

</assembly>

assembly文件的定義比較簡單,目標程序包中除了jar文件之外,還會包含幾個腳本和配置文件。

  • 啟動腳本
    /src/main/build/bin/start.sh
nohup java -jar dmo-boot-0.0.1-SNAPSHOT.jar > console.log &
tail -n100 -f console.log
  • 停止腳本
    /src/main/build/bin/stop.sh
kill `cat application.pid`
rm application.pid
  • 配置文件
    /src/main/build/application.properties
    /src/main/build/log4j2.xml

最終執行"mvn package"打包,會輸出壓縮包文件,結構如下:

dmo-boot.0.0.1-SNAPSHOT.jar
application.properties
log4j2.xml
start.sh
stop.sh

碼雲同步代碼

小結

本文將一個springboot項目從初始化、開發、配置、打包的整個流程進行了詳細介紹,希望讀者對該框架能產生整體性的了解。
由於篇幅有限,部分章節僅做了簡單說明。springboot是一個優秀的腳手架,借助於框架可以快速的完成各種特性的實現。
在隨后的文章里,將會跟大家一起繼續深入學習,歡迎隨時關注"美碼師的補習系列-springboot篇"


免責聲明!

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



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