其他分享
首页 > 其他分享> > Spring-Boot原理及应用布署

Spring-Boot原理及应用布署

作者:互联网

 

 

1.FAT JAR目录结构
解压后结果

drwxr-xr-x 5 hjq staff 160 Dec 3 09:57 .
drwxr-xr-x 10 hjq staff 320 Dec 4 11:42 ..
drwxr-xr-x 5 hjq staff 160 Dec 2 23:41 BOOT-INF
drwxr-xr-x 5 hjq staff 160 Dec 2 23:41 META-INF
drwxr-xr-x 3 hjq staff 96 Feb 1 1980 org
//BOOT-INF目录下
drwxr-xr-x 5 hjq staff 160 Dec 2 23:41 .
drwxr-xr-x 5 hjq staff 160 Dec 3 09:57 ..
drwxr-xr-x 5 hjq staff 160 Dec 2 23:41 classes
-rw-r--r-- 1 hjq staff 5466 Dec 2 23:41 classpath.idx
drwxr-xr-x 166 hjq staff 5312 Dec 2 23:41 lib
//META-INF目录下
drwxr-xr-x 5 hjq staff 160 Dec 2 23:41 .
drwxr-xr-x 5 hjq staff 160 Dec 3 09:57 ..
-rw-r--r-- 1 hjq staff 399 Dec 2 23:41 MANIFEST.MF
drwxr-xr-x 3 hjq staff 96 Dec 2 23:41 maven
-rw-r--r-- 1 hjq staff 109 Dec 2 17:57 spring.factories

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2查看MANIFEST.MF
已知jar采用java的Fat jar启动规范。是读取MANIFEST.MF文件

Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Archiver-Version: Plexus Archiver
Built-By: hjq
Start-Class: com.hjq.whyshare.home.DemoApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.3.2.RELEASE
Created-By: Apache Maven 3.6.1
Build-Jdk: 1.8.0_131
Main-Class: org.springframework.boot.loader.JarLauncher

1
2
3
4
5
6
7
8
9
10
11
12
命令行java-jar 会读取到Main-Class,作为启动类。
证明了main入口,在JarLauncher上
观察到Start-Class是我们编写的程序入口。查看其中实现逻辑。
JarLauncher的依赖,在pom上并没有添加,是spring-boot-maven-plugin插件打包时添加。

为了查看源码分析,添加引导项的依赖。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
</dependency>
1
2
3
4
3.分析JarLauncher实现原理

查看类继承关系。可知spring-boot打包有两种,传统的war包和jar包。该篇文章主要分析jar包方式。

3.1JarLauncher的main方法分析
//JarLauncher的main方法
public static void main(String[] args) throws Exception {
new JarLauncher().launch(args);
}

//构建JarLauncher对象前,先执行父类ExecutableArchiveLauncher构造函数
public class JarLauncher extends ExecutableArchiveLauncher

public ExecutableArchiveLauncher() {
try {
this.archive = createArchive();
this.classPathIndex = getClassPathIndex(this.archive);
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
archive是一个springboot loader库的类,表示档案。当生成jar时,createArchive()是指向该jar包的对象。后续archive上读取MANIFEST.MF等信息。以下是源码

protected final Archive createArchive() throws Exception {
ProtectionDomain protectionDomain = getClass().getProtectionDomain();
CodeSource codeSource = protectionDomain.getCodeSource();
URI location = (codeSource != null) ? codeSource.getLocation().toURI() : null;
String path = (location != null) ? location.getSchemeSpecificPart() : null;
if (path == null) {
throw new IllegalStateException("Unable to determine code source archive");
}
File root = new File(path);
if (!root.exists()) {
throw new IllegalStateException("Unable to determine code source archive from " + root);
}
//ExplodedArchive是文件以解压后的形式运行;JarFileArchive是以jar的形式
return (root.isDirectory() ? new ExplodedArchive(root) : new JarFileArchive(root));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
再查看launch()实现源码

protected void launch(String[] args) throws Exception {
//jar包形式才执行
if (!isExploded()) {
//用于系统设置java.protocol.handler.pkgs为org.springframework.boot.loader
JarFile.registerUrlProtocolHandler();
}
//Iterator迭代器是用于迭代jar包中的第三方依赖包,返回包含依赖包的classLoader。
ClassLoader classLoader = createClassLoader(getClassPathArchivesIterator());
String jarMode = System.getProperty("jarmode");
//从MANIFEST.MF上读取到start-class配置
String launchClass = (jarMode != null && !jarMode.isEmpty()) ? JAR_MODE_LAUNCHER : getMainClass();
launch(args, launchClass, classLoader);
}

protected String getMainClass() throws Exception {
Manifest manifest = this.archive.getManifest();
String mainClass = null;
if (manifest != null) {
mainClass = manifest.getMainAttributes().getValue(START_CLASS_ATTRIBUTE);
}
if (mainClass == null) {
throw new IllegalStateException("No 'Start-Class' manifest entry specified in " + this);
}
return mainClass;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
获取到包含依赖的classLoader,启动参数还有我们编写的启动类(start-class),就会采用反射进行调用。

//基类Launcher的实现
protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception {
Thread.currentThread().setContextClassLoader(classLoader);
//调用业务编写的启动类入口main
createMainMethodRunner(launchClass, args, classLoader).run();
}


//MainMethodRunner类
public MainMethodRunner(String mainClass, String[] args) {
this.mainClassName = mainClass;
this.args = (args != null) ? args.clone() : null;
}
public void run() throws Exception {
Class<?> mainClass = Class.forName(this.mainClassName, false, Thread.currentThread().getContextClassLoader());
Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
mainMethod.setAccessible(true);
mainMethod.invoke(null, new Object[] { this.args });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
从run()方法,可以看到,通过反射start-class对应的类,再调用main方法。

这个过程中最复杂的实现是JarFileArchive的内部实现,读取MANIFEST.MF,加载第三方依赖。后续再详细分析。 

 

 

 

 

 

一、Spring Boot的理念

    从最根本上来讲,Spring Boot就是一些库的集合,它能够被任意项目的构建系统所使用。简便起见,该框架也提供了命令行界面,它可以用来运行和测试Boot应用。框架的发布版本,包括集成的CLI(命令行界面),可以在Spring仓库中手动下载和安装。

   实际中springboot将应用打包之后,会生成一个fat jar,里面包含了应用依赖的jar包,还有Spring boot loader相关的类Fat jar的启动Main函数是JarLauncher,它负责创建一个LaunchedURLClassLoader来加载/lib下面的jar,并以一个新线程启动应用的Main函数。LaunchedURLClassLoader和普通的URLClassLoader的不同之处是,它提供了从Archive里加载.class的能力。结合Archive提供的getEntries函数,就可以获取到Archive里的Resource。当然里面的细节还是很多的。

二、Spring Boot 实现 

   Spring Boot 推荐采用基于 Java 注解的配置方式,而不是传统的 XML。只需要在主配置 Java 类上添加“@EnableAutoConfiguration”注解就可以启用自动配置。Spring Boot 的自动配置功能是没有侵入性的,只是作为一种基本的默认实现。开发人员可以通过定义其他 bean 来替代自动配置所提供的功能。比如当应用中定义了自己的数据源 bean 时,自动配置所提供的 HSQLDB 就不会生效。这给予了开发人员很大的灵活性。既可以快速的创建一个可以立即运行的原型应用,又可以不断的修改和调整以适应应用开发在不同阶段的需要。可能在应用最开始的时候,嵌入式的内存数据库(如 HSQLDB)就足够了,在后期则需要换成 MySQL 等数据库。Spring Boot 使得这样的切换变得很简单。

  @EnableAutoConfiguration”注解的作用在于让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置,这就减少了开发人员的工作量。

  @EnableAutoConfiguration注解会告知Boot要采用一种特定的方式来对应用进行配置。这种方法会将其他样板式的配置均假设为框架默认的约定,因此能够聚焦于如何尽快地使应用准备就绪以便运行起来。

  Spring Boot 的这个配置优先级看似复杂,其实是快速地修改配置参数值,而不需要重新打包和部署应用。

  Spring的运行方式包括:

  第一种方式:通过在UserController中加上@EnableAutoConfiguration开启自动配置,然后通过SpringApplication.run(UserController.class);运行这个控制器;这种方式只运行一个控制器比较方便。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @RestController   @EnableAutoConfiguration   public class Application {   @RequestMapping("user")   public static StringSayHello() {           return"Hello Word!";   }   public static voidmain(String[] args){           SpringApplication.run(Application.class,args);   }   }

第二种方式:通过@Configuration+@ComponentScan开启注解扫描并自动注册相应的注解Bean。

1 2 3 4 5 6 7 8 9 10 11 12 13 @Configuration   @ComponentScan   @EnableAutoConfiguration   public class Application {   public static voidmain(String[] args){           SpringApplication.run(Application.class,args);   }

 将工程打包成独立运行jar包,进入cmd 定位到项目目录下然后执行 mvn clean package –DskipTests

    然后会在项目的target文件夹下出现jar包例如(spingboot-demo-0.0.1-SNAPSHOT.jar)

    然后再cmd 的C盘 用户目录下执行命令$ java –jar (jar包的目录)E:\program\spingboot-demo\target\spingboot-demo-0.0.1-SNAPSHOT.jar

    即可完成布署。

三、Spring Boot布署

  在开发Spring Boot应用的过程中,Spring Boot直接执行public static void main()函数并启动一个内嵌的应用服务器(取决于类路径上的以来是Tomcat还是jetty)来处理应用请求。对于生产环境,这样的部署方式同样有效,同时Spring Boot也支持传统的部署方式——将war包放入应用服务器中启动运行.

A.内嵌应用服务器

   在使用Maven或Gradle构建Spring Boot应用的过程中,Spring Boot插件提供了巨大的帮助,除了生命各类预定义的依赖,它还能够构建可以直接运行的jar包——包含了所有的依赖以及内嵌应用服务器。应用的分发也就变得非常简单,任何人拿到了这个jar包,只需要简单运行java -jar your.jar就可以启动应用,无需任何构建工具、安装过程以及应用服务器。

B.内嵌应用服务器配置

  在生产环境中,应用服务器需要各类配置,Spring Boot本身提供了一种非常简单的配置机制——application.properties/application.yaml

1 2 3 4 5 server.port=8080 # 监听端口 server.address= # 绑定的地址 server.session-timeout= #session有效时长 server.context-path= #默认为/ server.ssl.* #ssl相关配置

Tomcat

   默认情况下,Spring Boot启动的内嵌容器就是Tomcat,对于Tomcat有几个非常重要的配置:

1 server.tomcat.basedir=/tmp

  tomcat的baseDir,日志、dump等文件都存在于这个目录中,一般是系统的临时文件夹/tmp,但也可以按照自己的需求变更位置.

1 2 server.tomcat.access-log-pattern= # log pattern of the access log server.tomcat.access-log-enabled=false is access logging enabled

 这两个配置打开Tomcat的Access日志,并可以设置日志格式。

Jetty

 如果你不喜欢Tomcat,Jetty也是一个非常不错的选择。使用Jetty的方式也非常简单——把tomcat依赖从Maven或Gradle中移除,加入Jetty内嵌容器的依赖:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <dependencies>   <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-web</artifactId>     <exclusions>       <exclusion>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-tomcat</artifactId>       </exclusion>     </exclusions>   </dependency>   <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-jetty</artifactId>   </dependency> <dependencies>

C.Java EE应用服务器

   除了内嵌容器的部署模式,Spring Boot也支持将应用部署至已有的Tomcat容器, 或JBoss, WebLogic等传统Java EE应用服务器。以Maven为例,首先需要将<packaging>从jar改成war,然后取消spring-boot-maven-plugin,然后修改Application.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;   @Configuration @ComponentScan @EnableAutoConfiguration public class Application extends SpringBootServletInitializer {       public static void main(String[] args) {         SpringApplication.run(applicationClass, args);     }       @Override     protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {         return application.sources(applicationClass);     }       private static Class<Application> applicationClass = Application.class; }

 接下来打包应用,将生成的war包放入应用服务器目录即可。

D.使用外部配置文件

 在应用程序中有很多配置项,例如数据库连接地址、日志文件位置、应用服务器配置等等。为了安全与灵活性,我们推荐将Spring Boot的配置文件放在生产环境的服务器上,并严格控制访问权限。在运行应用时可以通过命令行参数指定配置文件:

1 java -jar location_of_your_jar_file.jar --spring.config.location=location_of_your_config_file.properties

 

 

参考:Spring-Boot原理及应用布署

参考:spring-boot Fat JAR启动原理

 

标签:Spring,args,boot,jar,Boot,org,布署
来源: https://www.cnblogs.com/aspirant/p/16143539.html