资讯专栏INFORMATION COLUMN

慕课网_《Spring Boot热部署》学习总结

Channe / 1438人阅读

时间:2017年12月01日星期五
说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com
教学源码:无
学习源码:https://github.com/zccodere/s...

第一章:课程介绍 1-1 课程介绍

热部署的使用场景

本地调式
线上发布

热部署的使用优点

无论本地还是线上,都适用
无需重启服务器:提高开发、调式效率、提升发布、运维效率、降低运维成本

前置知识

掌握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.在%tomcat_home%/conf/Catalina/localhost中添加一个XML
第三章:案例分析 3-1 案例介绍

写一个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 Map loadTimeMap = 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页面





Index







4-3 部署实现

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就是这么简单

    摘要:热加载代表的是我们不需要重启服务器,就能够类检测得到,重新生成类的字节码文件无论是热部署或者是热加载都是基于类加载器来完成的。验证阶段字节码文件不会对造成危害准备阶段是会赋初始值,并不是程序中的值。 一、SpringBoot入门 今天在慕课网中看见了Spring Boot这么一个教程,这个Spring Boot作为JavaWeb的学习者肯定至少会听过,但我是不知道他是什么玩意。 只是大...

    whinc 评论0 收藏0
  • 课网_Spring Boot 2.0深度实践-初遇Spring Boot学习总结

    时间:2018年04月08日星期日说明:本文部分内容均来自慕课网。@慕课网:https://www.imooc.com 教学源码:无 学习源码:https://github.com/zccodere/s... 第一章:课程介绍 1-1 课程介绍 课程内容 Spring Boot介绍 环境准备 第一个Spring Boot项目 多模块项目 打包和运行 1-2 框架定位 showImg(https...

    hqman 评论0 收藏0
  • 课网_《Java模板引擎之Freemarker》学习总结

    摘要:时间年月日星期日说明本文部分内容均来自慕课网。整体目录结构如下项目文件用于数据持久化配置项目配置配置视图解析器配置静态资源映射配置配置配置自定义指令配置解析器配置,类似于项目启动类新建,注册配置类,并将其和当前关联。 时间:2017年3月19日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:无个人学习源码:https://githu...

    xumenger 评论0 收藏0
  • 课网_Spring Boot 发送邮件》学习总结

    摘要:慕课网发送邮件学习总结时间年月日星期六说明本文部分内容均来自慕课网。 慕课网《Spring Boot 发送邮件》学习总结 时间:2018年09月08日星期六 说明:本文部分内容均来自慕课网。@慕课网:https://www.imooc.com 教学源码:https://github.com/ityouknow/... 学习源码:https://github.com/zccoder...

    Meathill 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<