Spring BootTakes an opinionated view of building production-ready Spring applications. Spring Boot favors convention over configuration and is designed to get you up and running as quickly as possible.html
SpringBoot項目爲咱們構建Spring應用帶來了極大的方便,同時SpringBoot在構建Spring應用方面也作出了很大建樹java
衆所周知,SpringBoot能夠經過gradle或者maven插件構建Executable Jar/War Spring Boot Gradle Plugin Reference Guide
除了傳統方式java -jar myapp.jar
運行外,還能夠經過myapp.jar start|stop|restart
運行,安裝爲systemd服務,經過同名文件myapp.conf配置運行時參數等等高級功能 Installing Spring Boot Applications
講到這裏不少童鞋都會問,這一切都是如何作到的?linux
首先,咱們建立一個簡單的示例git
package com.manerfan.springboot.theory; /** * @author manerfan * @date 2018/3/2 */ public class RunnableApp { public static void main(String[] args) { System.out.println("Hello You!"); } }
使用eclipse或idea或其餘工具,編譯並打包爲jar(spring-boot-theory.jar),打包時選擇main-class爲com.manerfan.springboot.theory.RunnableAppgithub
對於Runnable Jar,總有一個META-INF/MANIFEST.MF文件,記錄Main-Class、Class-Path等信息web
咱們能夠經過java -jar spring-boot-theory.jar
來運行,但嘗試直接運行spring-boot-theory.jar
時便會報錯spring
這代表,spring-boot-theory.jar
僅僅爲Runnable Jar,而不是Executable Jarshell
通常狀況,咱們都會藉助shell腳原本運行咱們的jar,以下 runJar.sh
springboot
#!/bin/sh JAR="/usr/local/spring-boot-theory.jar" java=java if test -n "$JAVA_HOME"; then java="$JAVA_HOME/bin/java" fi exec "$java" -jar $JAR "$@" exit 1
在此基礎上,咱們能夠加入更多控制,以實現runJar.sh start | stop | restart等特性bash
#!/bin/bash # chkconfig: 2345 85 85 # description: spring boot theory # processname: spring-boot-theory # Created By: manerfan (manerfan.china@gmail.com) JAR="/usr/local/spring-boot-theory.jar" PIDFILE=/data/sms-service/smss.pid java=java if test -n "$JAVA_HOME"; then java="$JAVA_HOME/bin/java" fi start() {} stop() {} restart() {} status() {} case "$action" in start) start "$@"; exit $?;; stop) stop "$@"; exit $?;; restart) restart "$@"; exit $?;; status) status "$@"; exit $?;; *) echo "Usage: $0 {start|stop|force-stop|restart|force-reload|status|run}"; exit 1; esac exit 0
能夠參考 http://blog.csdn.net/zhanngle...
但這樣也只是經過shell腳本控制jar的啓動中止,如何作到Executable Jar呢?
一樣,首先是一段shell腳本 runJar.sh
#!/bin/sh JAR =`which "$0" 2>/dev/null` [ $? -gt 0 -a -f "$0" ] && JAR="./$0" java=java if test -n "$JAVA_HOME"; then java="$JAVA_HOME/bin/java" fi exec "$java" -jar $JAR "$@" exit 1
經過如下語句將shell腳本與jar文件整合到一塊兒 ~劃重點~
cat runJar.sh spring-boot-theory.jar > exec-spring-boot-theory.jar && chmod +x exec-spring-boot-theory.jar
大功告成!
一樣,在此基礎上,咱們能夠加入更多控制,以實現exec-spring-boot-theory.jar start | stop | restart等特性
能夠參考 https://coderwall.com/p/ssuax...
springboot項目源碼在https://github.com/spring-pro...,能夠對照查看
咱們從 JarWriter 開始
public JarWriter(File file, LaunchScript launchScript) throws FileNotFoundException, IOException { FileOutputStream fileOutputStream = new FileOutputStream(file); if (launchScript != null) { // 將啓動腳本寫入文件 fileOutputStream.write(launchScript.toByteArray()); // 設置文件可執行屬性 setExecutableFilePermission(file); } this.jarOutput = new JarArchiveOutputStream(fileOutputStream); this.jarOutput.setEncoding("UTF-8"); }
當執行gradle build或mvn package時,會使用JarWriter從新生成jar文件。JarWrite構造函數中,會首先將啓動腳本寫入文件,並設置文件的可執行屬性。
除此以外,JarWriter還有衆多方法,如writeManifest寫入manifest文件、writeNestedLibrary寫入第三方依賴等等,經過JarWriter以構建Executable Jar.
此過程,與上述將shell腳本與jar文件整合效果一致。
可是,launchScript又是什麼?
public DefaultLaunchScript(File file, Map<?, ?> properties) throws IOException { // 加載啓動腳本 String content = loadContent(file); this.content = expandPlaceholders(content, properties); } private String loadContent(File file) throws IOException { if (file == null) { // 默認launch.script return loadContent(getClass().getResourceAsStream("launch.script")); } return loadContent(new FileInputStream(file)); }
默認的LaunchScript爲DefaultLaunchScript,在構造DefaultLaunchScript時,若不指定啓動腳本,則取默認的launch.script,內容見 launch.script
launch.script實現較爲複雜,此處不作解析,launch.script與上述shell腳本的實現思路基本相同,一樣實現了start stop restart等功能,方便安裝爲systemd服務
不一樣的是,launch.script會解析與jar文件同名的conf文件,以實現啓動腳本定製化 Customizing a Script When It Runs
如,咱們實現一個簡單的web接口
@SpringBootApplication @RestController public class WebApp { public static void main(String[] args) { SpringApplication.run(WebApp.class, args); } @RequestMapping("/") @GetMapping public String hello() { return "Hello You!"; } }
使用spring-boot-gradle-plugin插件打包,執行./spring-boot-theory-1.0.0.jar
,能夠看到輸出
訪問 http://localhost:8080 能夠看到 Hello You! 字樣
若要對啓動參數,如監聽端口作修改,除了使用java -jar spring-boot-theory-1.0.0.jar --server.port=8000
外,還能夠新建同名文件 spring-boot-theroy-1.0.0.conf
,填入內容
RUN_ARGS="--server.port=8000"
再次執行./spring-boot-theory-1.0.0.jar
監聽端口由默認的8080變爲指定的8000
conf配置文件可配置的內容較多,如使用JAVA_OPTS配置jvm運行參數,使用MODE=service
可將程序放入後臺運行等等 Customizing a Script When It Runs
以以下conf配置爲例
MODE=service JAVA_OPTS="-Xms1g -Xmx1g -Dfile.encoding=utf-8" RUN_ARGS="--server.port=8000"
執行./spring-boot-theory-1.0.0.jar start
查看該進程運行參數
/usr/bin/java -Dsun.misc.URLClassPath.disableJarChecking=true -Xms1g -Xmx1g -Dfile.encoding=utf-8 -jar /Users/manerfan/Project/learning/javaspring-boot-theory/build/libs/spring-boot-theory-1.0.0.jar --server.port=8000
SpringBoot實現ExecutableJar的原理,即是將啓動腳本及原有的jar文件(以及第三方依賴包)寫入同一個文件,並給該文件賦可執行權限,結合conf配置文件,使RunnableJar變爲ExecutableJar的同時,得以更加便捷的控制程序的啓動/運行參數