ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring-Boot原理及应用布署

2022-04-14 11:04:37  阅读:144  来源: 互联网

标签:Spring args boot jar Boot org 布署


 

 

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有