时间:2017年12月01日星期五
说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com
教学源码:无
学习源码:https://github.com/zccodere/s...
热部署的使用场景
本地调式 线上发布
热部署的使用优点
无论本地还是线上,都适用 无需重启服务器:提高开发、调式效率、提升发布、运维效率、降低运维成本
前置知识
掌握Java语言 有一定的Spring开发经验 掌握构建Spring Boot项目的方法
课程提纲
原理解析 案例分析 项目演示 测试验证 发布程序 课程总结第二章:原理解析 2-1 部署加载
Java热部署与热加载联系
不重启服务器编译或部署项目 基于Java的类加载器实现
Java热部署与热加载的区别
部署方式 --热部署在服务器运行时重新部署项目 --热加载在运行时重新加载class 实现原理 --热部署直接重新加载整个应用 --热加载在运行时重新加载class 使用场景 --热部署更多的是在生产环境使用 --热加载则更多的是在开发环境使用2-2 原理解析
Java类的加载过程
类加载的五个阶段
Java类加载器特点
1.由AppClassLoader(系统类加载器)开始加载指定的类 2.类加载器将加载任务交给其父类,如果其父类找不到,再由自己去加载 3.BootstrapLoader(启动类加载器)是最顶级的类加载器
Java类的热部署
类的热加载 配置Tomcat
通过类的热加载实现热部署
通过配置Tomcat实现热部署
1.直接把项目web文件夹放在webapps里 2.在tomcat/conf/server.xml中的第三章:案例分析 3-1 案例介绍内部添加 标签 3.在%tomcat_home%/conf/Catalina/localhost中添加一个XML
写一个Java类热加载的实际案例,要求如下
1.类层次结构清晰,修改某一个Java类文件不需要重启服务或者重新编译运行程序 2.可适当的运用一些设计模式使代码结构更加清晰明了,比如工厂模式等3-2 案例实现
创建名为classloader的gradle工程build.gradle脚本如下
apply plugin: "java" apply plugin: "eclipse" group = "com.myimooc" version = "0.0.1-SNAPSHOT" sourceCompatibility = 1.8 repositories { maven{ url "http://maven.aliyun.com/nexus/content/groups/public/"} mavenCentral() } dependencies { }
代码编写
1.编写MyClassLoader类
package com.myimooc.classloader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; /** * @title 自定义Java类加载器 * @describe 来实现Java类的热加载 * @author zc * @version 1.0 2017-12-01 */ 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 { byte[] data = this.loadClassData(name); return this.defineClass(name, data, 0, data.length); } /** * @title 加载class文件中的内容 * @describe 加载class文件中的内容 * @author zc * @version 1.0 2017-12-01 */ private byte[] loadClassData(String name) { try{ name = name.replace(".", "//"); FileInputStream is = new FileInputStream(new File(this.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) { e.printStackTrace(); } return null; } }
2.编写BaseManager类
package com.myimooc.classloader; /** * @title 标识接口 * @describe 实现这个接口的子类需要动态更新 * @author zc * @version 1.0 2017-12-01 */ public interface BaseManager { public void logic(); }
3.编写MyManager类
package com.myimooc.classloader; /** * @title 接口实现类 * @describe BaseManager的子类,此类需要实现Java类的热加载功能 * @author zc * @version 1.0 2017-12-01 */ public class MyManager implements BaseManager { @Override public void logic() { System.out.println("学习如何实现Java类的热加载案例"); } }
4.编写LoadInfo类
package com.myimooc.classloader; /** * @title 类加载信息 * @describe 封装加载类的信息 * @author zc * @version 1.0 2017-12-01 */ public class LoadInfo { /** 自定义的类加载器 */ private MyClassLoader myLoader; /** 记录要加载类的时间戳,加载的时间 */ private long loadTime; private BaseManager manager; public LoadInfo(MyClassLoader myLoader, long loadTime) { super(); this.myLoader = myLoader; this.loadTime = loadTime; } public MyClassLoader getMyLoader() { return myLoader; } public void setMyLoader(MyClassLoader myLoader) { this.myLoader = myLoader; } public long getLoadTime() { return loadTime; } public void setLoadTime(long loadTime) { this.loadTime = loadTime; } public BaseManager getManager() { return manager; } public void setManager(BaseManager manager) { this.manager = manager; } }
5.编写ManagerFactory类
package com.myimooc.classloader; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; /** * @title Manager工厂类 * @describe 加载manager的工厂 * @author zc * @version 1.0 2017-12-01 */ public class ManagerFactory { /** 记录热加载类的加载信息 */ private static final MaploadTimeMap = new HashMap (); /** 要加载的类的classpath路径 */ public static final String CLASS_PATH = "D:/AllSpace/ByStudy/classloader/bin/"; /** 实现热加载的类的全名称(包名+类名) */ public static final String MY_MANAGER = "com.myimooc.classloader.MyManager"; public static BaseManager getManager(String className){ File loadFile = new File(CLASS_PATH + className.replaceAll(".", "/")+".class"); long lastModified = loadFile.lastModified(); if(loadTimeMap.get(className)== null){ // loadTimeMap不包含className为key的LoadInfo信息。 // 证明这个类没有被加载,那么需要加载这个类到JVM中 load(className,lastModified); }else if(loadTimeMap.get(className).getLoadTime()!=lastModified){ // 加载类的时间戳变化了,同样要重新加载 load(className,lastModified); } return loadTimeMap.get(className).getManager(); } private static void load(String className, long lastModified) { MyClassLoader myClassLoader = new MyClassLoader(CLASS_PATH); Class> loadClass = null; try { loadClass = myClassLoader.findClass(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } BaseManager manager = newInstance(loadClass); LoadInfo loadInfo = new LoadInfo(myClassLoader,lastModified); loadInfo.setManager(manager); loadTimeMap.put(className, loadInfo); } /** * @title 创建实例对象 * @describe 以反射的方式创建BaseManager子类对象 * @author zc * @version 1.0 2017-12-01 */ private static BaseManager newInstance(Class> loadClass) { try { return (BaseManager)loadClass.getConstructor(new Class[]{}).newInstance(new Object[]{}); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { e.printStackTrace(); } return null; } }
6.编写MsgHandler类
package com.myimooc.classloader; /** * @title 后台线程 * @describe 后台启动一条线程不断刷新加载实现了热加载的类 * @author zc * @version 1.0 2017-12-01 */ public class MsgHandler implements Runnable{ @Override public void run() { while(true){ BaseManager manager = ManagerFactory.getManager(ManagerFactory.MY_MANAGER); manager.logic(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
7.编写ClassLoaderTest类
package com.myimooc.classloader; /** * @title 测试类 * @describe 测试Java类的热加载 * @author zc * @version 1.0 2017-12-01 */ public class ClassLoaderTest { public static void main(String[] args) { new Thread(new MsgHandler()).start(); } }第四章:项目演示 4-1 简单介绍
Spring Boot简单介绍
是一个全新框架,目的是简化Spring应用的搭建与开发过程 该框架开发人员不需要定义样板化的配置 从根本上讲,是一些库的集合,构建项目,无须自行管理这些库的版本
Spring Boot特点
创建独立的Spring应用程序 嵌入的Tomcat,无须部署war文件 简化Maven配置和Gradle配置 自动配置Spring 提供生产就绪功能,如指标、健康检查和外部配置
Spring Boot使用场景
开发Restful风格的微服务架构 微服务、自动化、横向扩展 精简配置与整合其他工具4-2 项目搭建
创建名为hotdeploy的gradle工程build.gradle脚本如下
buildscript { ext { springBootVersion = "1.5.6.RELEASE" } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: "java" apply plugin: "eclipse" apply plugin: "org.springframework.boot" group = "com.myimooc" version = "0.0.1-SNAPSHOT" sourceCompatibility = 1.8 repositories { maven{ url "http://maven.aliyun.com/nexus/content/groups/public/"} mavenCentral() } dependencies { compile("org.springframework.boot:spring-boot-starter") compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-data-jpa") compile("org.springframework.boot:spring-boot-starter-thymeleaf") compile("org.springframework.boot:spring-boot-devtools") compile("com.h2database:h2") testCompile("org.springframework.boot:spring-boot-starter-test") }
代码编写
1.编写HotDeployApplication类
package com.myimooc.hotdeploy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; /** * @title Spring Boot 热启动 * @describe 启动类 * @author zc * @version 1.0 2017-12-01 */ @SpringBootApplication public class HotDeployApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(HotDeployApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(HotDeployApplication.class); } }
2.编写HotDeployController类
package com.myimooc.hotdeploy.web.controller; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; /** * @title 控制器 * @describe * @author zc * @version 1.0 2017-12-01 */ @Controller public class HotDeployController { // 等价于 @RequestMapping(value="/say",method=RequestMethod.GET) @GetMapping("/say") public String say(HttpServletRequest request){ request.setAttribute("say", "Hello Spring Boot!"); return "index"; } }
3.编写index.html页面
4-3 部署实现Index
Spring Boot热部署实现的方式
使用Spring Loaded:1.添加依赖,2.设置JVM参数 使用spring-boot-devtools:1.添加依赖4-4 项目发布
发布方式
构建jar包,命令行运行Spring Boot程序 构建war包,发布到Tomcat第五章:课程总结 5-1 课程总结
课程总结
课程介绍 热部署与热加载 热部署原理解析 Java类热加载案例分析 Spring Boot简单介绍 Spring Boot项目搭建 Spring Boot项目构建过程解析 Spring Boot热部署的实现 Spring Boot发布方式
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/70697.html
摘要:热加载代表的是我们不需要重启服务器,就能够类检测得到,重新生成类的字节码文件无论是热部署或者是热加载都是基于类加载器来完成的。验证阶段字节码文件不会对造成危害准备阶段是会赋初始值,并不是程序中的值。 一、SpringBoot入门 今天在慕课网中看见了Spring Boot这么一个教程,这个Spring Boot作为JavaWeb的学习者肯定至少会听过,但我是不知道他是什么玩意。 只是大...
时间:2018年04月08日星期日说明:本文部分内容均来自慕课网。@慕课网:https://www.imooc.com 教学源码:无 学习源码:https://github.com/zccodere/s... 第一章:课程介绍 1-1 课程介绍 课程内容 Spring Boot介绍 环境准备 第一个Spring Boot项目 多模块项目 打包和运行 1-2 框架定位 showImg(https...
摘要:时间年月日星期日说明本文部分内容均来自慕课网。整体目录结构如下项目文件用于数据持久化配置项目配置配置视图解析器配置静态资源映射配置配置配置自定义指令配置解析器配置,类似于项目启动类新建,注册配置类,并将其和当前关联。 时间:2017年3月19日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:无个人学习源码:https://githu...
摘要:慕课网发送邮件学习总结时间年月日星期六说明本文部分内容均来自慕课网。 慕课网《Spring Boot 发送邮件》学习总结 时间:2018年09月08日星期六 说明:本文部分内容均来自慕课网。@慕课网:https://www.imooc.com 教学源码:https://github.com/ityouknow/... 学习源码:https://github.com/zccoder...
阅读 2204·2021-10-18 13:28
阅读 2514·2021-10-11 10:59
阅读 2342·2019-08-29 15:06
阅读 1134·2019-08-26 13:54
阅读 810·2019-08-26 13:52
阅读 3150·2019-08-26 12:02
阅读 3001·2019-08-26 11:44
阅读 2513·2019-08-26 10:56