一、 热部署和热加载的区别

1.定义区别

热部署:是指在服务器运行时重新部署项目
热加载:是指在运行时重新加载class

2.实现原理区别

热部署:直接重新加载整个应用,会直接释放内存,比热加载更加干净彻底,但是浪费时间;

热加载:在运行时重新加载class,依赖java的内加载机制,在容器启动时后台起一个线程用于定时检测类文件的时间戳的变化,如果时间戳变化了则加载最新的class;

3.Java类的热部署

两种方式:
1.类的热加载
1.自定义类类加载器,通过继承java.lang.ClassLoader,重写其中的findClass方法,一旦发现字节码立刻调用defineClass方法,主要代码如下:

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
	System.out.println("加载类===" + name);
	byte[] data = loadClassData(name);
	return this.defineClass(name, data, 0,data.length);
}

2. 配置Tomcat
通过配置Tomcat实现热部署,三种方式:

  1. 直接将项目web文件夹放到Tomcat的webapps目录下即可;
    这种方式就是使用的Tomcat自带的热部署实现的

2.在Tomcat\conf\server.xml文件中的<host></host>内部添加<context/>标签;

<Context debug="0" docBase="D:/Test/Hotweb" path="/hot" privileged="true" reloadable="true"/>

其中docBase是指Tomcat热部署的文件夹(即将项目的中的文件夹(不包括项目的根目录,正常就是META-INF和WEB-INF两个文件夹)丢到这个目录下面即可),path是配置了虚拟访问路径,这时候就不能通过访问webapp来访问项目了,并且在访问路径下需要加上/hot,即localhost:8080/hot/…

3.在Tomcat\conf\Catalina\localhost目录下添加一个xml文件作为它一部分路径来访问.
比如在该目录下面创建hot.xml文件,其中的内容为

<?xml Version="1.0" encoding="UTF-8">
<Context docBase="D:/Test/Hotweb" reloadable="true"/>

4.java类热加载的是实例

这里跑测试程序ClassLoaderTest时,注意使用debug模式(如果需要直接Run as java application则需要更改MannagerFactory中的loadClass = myClassloader.findClass(MY_MANAGER);改为loadClass = myClassloader.loadClass(className);),否则无法实现热加载,Eclipse需要开启自动编译的功能,可以改变MyMannager类中的打印内容查看控制台的输出是否改变来验证热加载是否成功。主要代码如下:

package com.hhu.classloader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;

/**
 * 自定义类加载器来是实现java类的热加载
 * 继承java.lang.ClassLoader,重写其中
 * 的findClass方法
 * 
 * @author Weiguo Liu
 * @data 2017年11月29日
 */
public class MyClassloader extends ClassLoader {

	//要加载的Java类的classpath路径
	private String classpath;
	
	public MyClassloader(String classpath) {
		super(ClassLoader.getSystemClassLoader());
		this.classpath = classpath;
	}
	
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		// TODO Auto-generated method stub
		byte[] data = this.loadClassData(name);
		return super.defineClass(name, data, 0, data.length);
	}
	
	/*
	 * 记载class文件中的内容
	 */
	private byte[] loadClassData(String name) {
		try {
			//因为包名包含.要将它替换成//
			name = name.replace(".", "//");
			//文件输入流
			FileInputStream is =new FileInputStream(new File(classpath + name + ".class"));
			//字节数组输出流
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			int b = 0;
			while((b=is.read())!=-1) {
				baos.write(b);
			}
			is.close();
			return baos.toByteArray();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return null;
	}

}

完整工程见:https://github.com/Jacksonary/CodeRepository/tree/master/classloader

二、SpringBoot热部署的实现

主要有两种方式:1.使用Spring Loaded 2.使用Spring-boot-devtools

1.SpringLoaded热部署的实现(未实现)

(1)第一种方式:Maven启动方式
在pom.xml中添加Springloaded依赖,这种方式必须使用Maven指令启动:mvn spring-boot:run
在dos窗口下,进入工程目录运行上述命令即可,也可以直接在Eclipse中,Run As–>maven build…->在Goals中填写spring-boot:run。
这种方法我测试没有通过,还没找到原因

<!--引入spring-boot热部署的依赖,这种方式必须使用maven启动 -->
		
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>springloaded</artifactId>
</dependency>

(2)第二种方式:也可以Run As -->Java Application来实现
需要下载一个Springloaded的jar包,放在自己笔记本的任意目录下即可,然后右击Run Configuration,在Springboot下一栏中找到对应的Application点击Arguments,在VM一栏中填写如下
这里写图片描述

2.Spring-boot-devtools热部署(可实现)

直接在pom.xml中添加依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-devtools</artifactId>
	<optional>true</optional>
</dependency>
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐