学习Tomcat动态加载JSP的Class类
今天在修改项目一个JSP文件时,突然想到Tomat是怎么实现动态实时加载JSP编译后的class类的?
查了半天资料,看了很多文章,终于明白是怎么回事了:ClassLoader,当tomcat发现jsp改变后,将用新的ClassLoader去加载新的类
具体原理我将单独总结一下,这里简单实现了动态加载类
1.定义服务类
public class Servlet {
public void service(){
System.out.println("运行服务方法");
}
}
2.定义服务线程
public class ServiceThread extends Thread{
public void run(){
try {
ClassLoader classLoader = this.getContextClassLoader();
Class clazz = classLoader.loadClass("Servlet");
Method service = clazz.getMethod("service", null);
service.invoke(clazz.newInstance(), null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.自定义ClassLoader
public class MyClassLoader extends ClassLoader{
@Override
public Class loadClass(String name, boolean resolve) throws ClassNotFoundException{
try {
// 我们要创建的Class对象
Class clasz = null;
// 必需的步骤1:如果类已经在系统缓冲之中
// 我们不必再次装入它
clasz = findLoadedClass(name);
if (clasz != null)
return clasz;
try {
// 读取经过加密的类文件
if(name.equals("Servlet")){
//加载class文件字节
byte classData[] = Util.readFile(ProgramPathHelper.getProgramPath()+"/"+name + ".class");
if (classData != null) {
// ... 再把它转换成一个类
clasz = defineClass(name, classData, 0,
classData.length);
}
}
} catch (Exception e) {
e.printStackTrace();
}
// 必需的步骤2:如果上面没有成功
// 我们尝试用默认的ClassLoader装入它
if (clasz == null)
clasz = findSystemClass(name);
// 必需的步骤3:如有必要,则装入相关的类
if (resolve && clasz != null)
resolveClass(clasz);
// 把类返回给调用者
return clasz;
} catch (Exception ie) {
throw new ClassNotFoundException(ie.toString());
}
}
}
4.实现文件监听类
public class CCFileListener implements FileAlterationListener{
public static HashMap<String,ClassLoader> claMap = new HashMap<String, ClassLoader>();
ZJPFileMonitor monitor = null;
@Override
public void onStart(FileAlterationObserver observer) {
//System.out.println("onStart");
}
@Override
public void onDirectoryCreate(File directory) {
System.out.println("onDirectoryCreate:" + directory.getName());
}
@Override
public void onDirectoryChange(File directory) {
System.out.println("onDirectoryChange:" + directory.getName());
}
@Override
public void onDirectoryDelete(File directory) {
System.out.println("onDirectoryDelete:" + directory.getName());
}
@Override
public void onFileCreate(File file) {
System.out.println("onFileCreate:" + file.getName());
dyncLoadClass(file.getName());
}
@Override
public void onFileChange(File file) {
//文件改变处理函数
System.out.println("onFileChange : " + file.getName());
dyncLoadClass(file.getName());
}
private void dyncLoadClass(String className){
if(className.contains("Servlet")){
// ZJPFileMonitor.thread.setContextClassLoader(new MyClassLoader());
claMap.put(className, new MyClassLoader());
}
}
@Override
public void onFileDelete(File file) {
System.out.println("onFileDelete :" + file.getName());
}
@Override
public void onStop(FileAlterationObserver observer) {
//System.out.println("onStop");
}
}
public class CCFileMonitor {
FileAlterationMonitor monitor = null;
public CCFileMonitor(long interval) throws Exception {
monitor = new FileAlterationMonitor(interval);
}
public void monitor(String path, FileAlterationListener listener) {
FileAlterationObserver observer = new FileAlterationObserver(new File(path));
monitor.addObserver(observer);
observer.addListener(listener);
}
public void stop() throws Exception{
monitor.stop();
}
public void start() throws Exception {
monitor.start();
}
public static void main(String[] args) throws Exception {
CCFileMonitor m = new CCFileMonitor(5000);
m.monitor(ProgramPathHelper.getProgramPath(),new CCFileListener());
m.start();
Servlet servlet = new Servlet();
servlet.service();
MyClassLoader defaultCl = new MyClassLoader();
while(true){
Thread.currentThread().sleep(3000);
Thread t = new ServiceThread();
//设置新线程的类加载器
ClassLoader classLoader = CCFileListener.claMap.get("Servlet.class");
if(classLoader==null){
classLoader = defaultCl;
}
t.setContextClassLoader(classLoader);
t.start();
}
}
}
public static HashMap<String,ClassLoader> claMap = new HashMap<String, ClassLoader>();
在监听到文件改变后,依据类名重new一个类加载器,用于加载类。
ClassLoader classLoader = CCFileListener.claMap.get("Servlet.class");
if(classLoader==null){
classLoader = defaultCl;
}
首先获取类名对应的加载器,如果没有使用默认的加载器
ClassLoader classLoader = this.getContextClassLoader();
Class clazz = classLoader.loadClass("Servlet");
Method service = clazz.getMethod("service", null);
service.invoke(clazz.newInstance(), null);
在线程内部使用刚才在外部设置的线程上下文加载器加载新的Servlet,并执行
学习Tomcat动态加载JSP的Class类的更多相关文章
- [WPF学习笔记]动态加载XAML
好久没写Blogs了,现在在看[WPF编程宝典],决定开始重新写博客,和大家一起分享技术. 在编程时我们常希望界面是动态的,可以随时变换而不需要重新编译自己的代码. 以下是动态加载XAML的一个事例代 ...
- 从高德 SDK 学习 Android 动态加载资源
前不久跑去折腾高德 SDK 中的 HUD 功能,相信用过该功能的用户都知道 HUD 界面上的导航转向图标是动态变化的.从高德官方导航 API 文档中 AMapNaviGuide 类的描述可知,导航转向 ...
- JS学习之动态加载script和style样式
前提:我们可以把一个网页里面的内容理解为一个XML或者说网页本身也就是一个XML文档,XML文档都有很特殊的象征:"标签"也叫"节点".我们都知道一个基本的网页 ...
- Android学习——Fragment动态加载
动态加载原理 利用FragmentManager来添加一套Fragment事务,最后通过commit提交该事务来执行对Fragment的相关操作. FragmentManager fragmentma ...
- tomcat解决加载JSP文件过大错误
当遇到多个Jsp include一起的时候加载时遇到如下错误: Error:SEVERE: Servlet.service() for servlet jsp threw exception org. ...
- asp.net动态加载程序集创建指定类的实例及调用指定方法
以下类中有三个方法: LoadAssembly:加载指定路径的程序集 GetInstance:根据Type动态获取实例,用泛型接到返回的类型 ExecuteMothod:执行实例中的指定方法 /// ...
- Vue – 基础学习(5):动态加载和注册组件
// var myComponent =() => import(`./../../components/custom_panel/${t_url}.vue`);// //var myCompo ...
- 启动Tomcat自动加载(运行)类
其实这是紧跟着我上次写的java计时器Timer的,因为Timer的测试类写好后,不可能要通过什么东西去触发,对已经存在的时间点进行监控 所以,在启动项目是自动运行此类 方法如下: 一.在web.xm ...
- 动态加载dll,并创建类对象放入到list中。
private List<IVisualControlsPlug> visualPlugs = new List<IVisualControlsPlug>(); public ...
随机推荐
- 22 nginx配置与集群
一:编译nginx ,并配置 Cd /app/pcre-8.12 ./configure Make && make install Cd nginx-1.2.7 ./configure ...
- matlab biplot 符号的困惑
在matlab中做Principal component Analysis 时,常要用biplot 函数来画图,表示原分量与主分量(principal component)之间的关系,以及原始观察数据 ...
- 关于一致/非一致代码段与TSS 关系的个人看法
[0]概念定义 0.1)一致代码段: 简单理解,就是操作系统拿出来被共享的代码段,可以被低特权级的用户直接调用访问的代码, 但是特权级高的程序不允许访问特权级低的数据. 通常这些共享代码,是" ...
- 多媒体开发之sps---解析sps得到图像的宽高
(1)通过块的宽高解析出真个h264的分辨率 如何解析SDP中包含的H.264的SPS和PPS串 http://www.pernet.tv.sixxs.org/thread-109-1-1.html ...
- 深入详解WPF ControlTemplate
WPF包含数据模板和控件模板,其中控件模板又包括ControlTemplate和ItemsPanelTemplate,这里讨论一下WPF ControlTemplate. 其实WPF的每一个控件都有一 ...
- Unity3D研究院编辑器之脚本设置ToolBar及脚本设置顶视图
Unity版本5.3.2 如下图所示,ToolBar就是Unity顶部的那一横条.这里的所有按钮一般情况下都得我们手动的用鼠标去点击.这篇文章我们说说如果自动操作它们 1.自动点击左边四个按钮 (拖动 ...
- strpos与strstr之间的区别
string strstr(string haystack,string needle) 返回haystack中从第一 个needle开头到haystack末尾的字符串. 如果未找到needle 返回 ...
- C# C/S程序使用HTML文件作为打印模板
C# C/S程序使用HTML文件作为打印模板 在网上找了一堆的资料,整理到郁闷呀,慢慢试慢慢改.哎,最终成功了,哈,菜鸟伤不起呀 public partial class Print : Form ...
- POJ 1163 The Triangle(经典问题教你彻底理解动归思想)
The Triangle Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 38195 Accepted: 22946 De ...
- Tomcat学习笔记【1】--- WEB服务器、JavaEE、Tomcat背景、Tomcat版本
本文主要讲学习Tomcat需要知道的基础知识. 一 Web服务器 1.1 简介 Web服务器可以解析HTTP协议.当Web服务器接收到一个HTTP请求,会返回一个HTTP响应,例如送回一个HTML页面 ...
