前言
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 指向一個日志文件,我們為該日志文件設定了滾動的規則:
- 當大小超過50M時會生成新的日志;
- 每小時生成一個新的日志;
******指定了最多存在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篇"