java自定义classloader

首先继承ClassLoader类,如果不希望双亲委派,重写loadClass方法,否则重写findClass方法,以下是一次业务中的使用

import org.springframework.util.Base64Utils;

// 此classloader用于网络传输,从服务器下载licenseFilter
public class NetworkClassLoader extends ClassLoader {
	// 根路径
	private String rootUrl;

	public NetworkClassLoader(String rootUrl) {
		super(NetworkClassLoader.class.getClassLoader());
		this.rootUrl = rootUrl;
	}

	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		byte[] classData = getClassData(name);
		if (classData == null) {
			throw new ClassNotFoundException();
		}
		return defineClass(name, classData, 0, classData.length);
	}

	// 获取class二进制数据
	private byte[] getClassData(String name) {
		try {
			// 下载源class文件
			/*String path = classNameToPath(name);
			URL url = new URL(path);
			InputStream is = url.openStream();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			IOUtils.copy(is, baos);
			IOUtils.closeQuietly(is);
			return baos.toByteArray();*/
			
			// 源licenseFilter字节码文件使用了aes加密,从服务器获取加密后的数据
			String s = HttpTookit.doGet(AdminManageConfig.ADMIN_MANAGE_LOAD_CLASS, null);
			// aes解密
			String ss = EncrypAES.decrypt(s);
			return Base64Utils.decodeFromString(ss);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/*private String classNameToPath(String name) {
		return rootUrl + name.replace(".", "/") + ".class";
	}*/

}

filterconfig中使用

import javax.servlet.DispatcherType;
import javax.servlet.Filter;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

@Configuration
public class FilterConfig {
	// 注入配置文件中的license和私钥
	@Value("${license.license}")
	private String license;
	@Value("${license.private_key}")
	private String private_key;

	@Bean
	public FilterRegistrationBean licenseFilterRegistration() throws Exception {
		FilterRegistrationBean registration = new FilterRegistrationBean();
		registration.addInitParameter("license", license);
		registration.addInitParameter("private_key", private_key);
		registration.setDispatcherTypes(DispatcherType.REQUEST);
		// 使用自定义classloader加载licenseFilter
		NetworkClassLoader loader = new NetworkClassLoader(AdminManageConfig.ADMIN_MANAGE_URL);
		registration.setFilter((Filter) loader.loadClass("LicenseFilter").newInstance());
		registration.addUrlPatterns("/*");
		registration.setName("licenseFilter");
		registration.setOrder(Integer.MAX_VALUE - 2);
		return registration;
	}
}

注:
自定义NetworkClassLoader构造方法中,使用了super(NetworkClassLoader.class.getClassLoader());,如果使用super(),在tomcat中会报NoClassDefFoundError异常,而springboot中没报异常,原因加载继承的filter时,双亲委派由父级加载,由于tomcat中filter由URLClassLoader加载,不指定父级加载器,默认是AppClassLoader,都加载不成功报错,而springboot中使用RestartClassLoader,父级也是AppClassLoader,导致在AppClassLoader可以获取到filter而不报错
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值