动态扩展Rest接口地址,动态卸载Rest接口

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import sun.misc.ClassLoaderUtil;import java.io.File;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;/*** 加载后台插件,热发布** @author caigaoqing*/
@Service
public class LoadPluginServiceImpl  {@Autowiredprivate GenericApplicationContext annotationConfigWebApplicationContext;@AutowiredApplicationContext context;/*** 注册插件,注册bean,注册springmvc的 bean** @param url      上传oss的地址* @param scanPath 扫描路径* @return 注册成功的beans*/public List<String> register(String url, String scanPath) {//注册的 BeanList<String> beans = new ArrayList<>();try {URL[] urls = scanUrl(url);//新建classloader 核心URLClassLoader urlClassLoader = new URLClassLoader(urls, annotationConfigWebApplicationContext.getClassLoader());//  获取导入的jar的controller  service  dao 等类,并且创建BeanDefinitionSet<BeanDefinition> beanDefinitions = getBeanDefinitions(urlClassLoader, scanPath);beanDefinitions.forEach(item -> {registerBean(beans, urlClassLoader, item);//根据beanDefinition通过BeanFactory注册beanannotationConfigWebApplicationContext.getDefaultListableBeanFactory().registerBeanDefinition(item.getBeanClassName(), item);});//修改BeanFactory的ClassLoaderannotationConfigWebApplicationContext.getDefaultListableBeanFactory().setBeanClassLoader(urlClassLoader);//获取requestMappingHandlerMapping,用来注册HandlerMappingRequestMappingHandlerMapping requestMappingHandlerMapping = annotationConfigWebApplicationContext.getBean(RequestMappingHandlerMapping.class);beanDefinitions.forEach(item -> {registerController(beans, urlClassLoader, requestMappingHandlerMapping, item);});urlClassLoader.close();ClassLoaderUtil.releaseLoader(urlClassLoader);} catch (Exception e) {e.printStackTrace();}return beans;}/*** 卸载插件,卸载bean,卸载springmvc的 bean** @param url      上传oss的地址* @param scanPath 扫描路径* @return 卸载成功的beans*/public List<String> unregisterBean(String url, String scanPath) {List<String> beanList = new ArrayList<>();try {URL[] urls = scanUrl(url);//新建classloader 核心URLClassLoader urlClassLoader = new URLClassLoader(urls, annotationConfigWebApplicationContext.getClassLoader());//  获取导入的jar的controller  service  dao 等类,并且创建BeanDefinitionSet<BeanDefinition> beanDefinitions = getBeanDefinitions(urlClassLoader, scanPath);beanDefinitions.forEach(item -> {//根据beanDefinition通过BeanFactory注册beanannotationConfigWebApplicationContext.getDefaultListableBeanFactory().removeBeanDefinition(item.getBeanClassName());});//修改BeanFactory的ClassLoaderannotationConfigWebApplicationContext.getDefaultListableBeanFactory().setBeanClassLoader(urlClassLoader);//获取requestMappingHandlerMapping,用来注册HandlerMappingRequestMappingHandlerMapping requestMappingHandlerMapping = annotationConfigWebApplicationContext.getBean(RequestMappingHandlerMapping.class);beanDefinitions.forEach(item -> {unRegisterController(beanList, urlClassLoader, requestMappingHandlerMapping, item);});} catch (Exception e) {e.printStackTrace();}return beanList;}/*** 注册 接口** @param beans                        统计加载的Bean列表* @param urlClassLoader               url类加载器* @param requestMappingHandlerMapping requestMapping映射* @param item                         Bean定义*/private void registerController(List<String> beans, URLClassLoader urlClassLoader, RequestMappingHandlerMapping requestMappingHandlerMapping, BeanDefinition item) {String classname = item.getBeanClassName();beans.add(classname);try {Class<?> c = Class.forName(classname, false, urlClassLoader);Controller controllerAnnotation = c.getAnnotation(Controller.class);RestController restControllerAnnotation = c.getAnnotation(RestController.class);//获取该bean 真正的创建Object proxy = annotationConfigWebApplicationContext.getBean(item.getBeanClassName());//如果此bean是Controller,则注册到RequestMappingHandlerMapping里面if (controllerAnnotation != null || restControllerAnnotation != null) {Method getMappingForMethod = ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingForMethod", Method.class, Class.class);getMappingForMethod.setAccessible(true);try {Method[] methodArr = c.getMethods();for (Method md : methodArr) {AnnotatedType annotatedReturnType = md.getAnnotatedReturnType();annotatedReturnType.getType();RequestMapping aliasAnnotation = AnnotationUtils.findAnnotation(md, RequestMapping.class);if (aliasAnnotation != null) {//创建RequestMappingInfoRequestMappingInfo mappingInfo = (RequestMappingInfo) getMappingForMethod.invoke(requestMappingHandlerMapping, md, c);//注册requestMappingHandlerMapping.registerMapping(mappingInfo, proxy, md);}}} catch (Exception e) {e.printStackTrace();}}} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** 注册Bean** @param list           列表* @param urlClassLoader url类加载器* @param item           bean定义*/private void registerBean(List<String> list, URLClassLoader urlClassLoader, BeanDefinition item) {try {Class<?> c = Class.forName(item.getBeanClassName(), false, urlClassLoader);//处理@service指定beanName的注册别名if (c.getAnnotation(Service.class) != null) {String beanName = c.getAnnotation(Service.class).value();list.add("AliasBean>>" + beanName);annotationConfigWebApplicationContext.getDefaultListableBeanFactory().registerAlias(item.getBeanClassName(), beanName);}//处理接口注册别名if (c.getInterfaces().length > 0) {AnnotatedType[] annotatedInterfaces = c.getAnnotatedInterfaces();for (int i = 0; i < annotatedInterfaces.length; i++) {Type type = annotatedInterfaces[i].getType();String typeName = type.getTypeName();list.add("AliasBean>>" + typeName);annotationConfigWebApplicationContext.getDefaultListableBeanFactory().registerAlias(item.getBeanClassName(), typeName);}}} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** 统计** @param beanList                     bean列表* @param urlClassLoader               url类装入器* @param requestMappingHandlerMapping 请求映射处理程序映射* @param item                         项*/private void unRegisterController(List<String> beanList, URLClassLoader urlClassLoader, RequestMappingHandlerMapping requestMappingHandlerMapping, BeanDefinition item) {String classname = item.getBeanClassName();beanList.add(classname);try {Class<?> c = Class.forName(classname, false, urlClassLoader);Controller controllerAnnotation = c.getAnnotation(Controller.class);RestController restControllerAnnotation = c.getAnnotation(RestController.class);//获取该bean 真正的创建//如果此bean是Controller,则注册到RequestMappingHandlerMapping里面if (controllerAnnotation != null || restControllerAnnotation != null) {Method getMappingForMethod = ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingForMethod", Method.class, Class.class);getMappingForMethod.setAccessible(true);try {Method[] methodArr = c.getMethods();for (Method md : methodArr) {AnnotatedType annotatedReturnType = md.getAnnotatedReturnType();annotatedReturnType.getType();RequestMapping aliasAnnotation = AnnotationUtils.findAnnotation(md, RequestMapping.class);if (aliasAnnotation != null) {//创建RequestMappingInfoRequestMappingInfo mappingInfo = (RequestMappingInfo) getMappingForMethod.invoke(requestMappingHandlerMapping, md, c);//卸载requestMappingHandlerMapping.unregisterMapping(mappingInfo);}}} catch (Exception e) {e.printStackTrace();}urlClassLoader.close();ClassLoaderUtil.releaseLoader(urlClassLoader);}} catch (Exception e) {e.printStackTrace();}}/*** @param url* @return* @throws MalformedURLException*/public URL[] scanUrl(String url) throws MalformedURLException {File file = new File(FilenameUtils.getName(url));//查找依赖的jar包,同级目录下的lib/List<URL> dependencyJar = findDependencyJar(file);URL[] urls = dependencyJar.toArray(new URL[dependencyJar.size()]);return urls;}/*** 查看jar中类** @param file 文件* @return 返回地址* @throws MalformedURLException*/private static List<URL> findDependencyJar(File file) throws MalformedURLException {List<URL> list = new ArrayList<>();File parentFile = file.getParentFile();File libFile = new File(FilenameUtils.getName(file.getParent() + File.separator + "lib"));if (libFile.exists() && parentFile.isDirectory()) {for (File jar : libFile.listFiles()) {if (jar.isFile()&& jar.getName().toLowerCase().endsWith(".jar")) {list.add(jar.toURI().toURL());}}}list.add(file.toURI().toURL());return list;}/*** 加载BeanDefinition** @param classLoader 类加载器* @param scanPath    扫描路径* @return 生成BeanDefinition* @throws Exception*/public Set<BeanDefinition> getBeanDefinitions(ClassLoader classLoader, String scanPath) throws Exception {Set<BeanDefinition> candidates = new LinkedHashSet<>();ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(classLoader);Resource[] resources = resourcePatternResolver.getResources("classpath*:" + scanPath + "/*.**");MetadataReaderFactory metadata = new SimpleMetadataReaderFactory();for (Resource resource : resources) {MetadataReader metadataReader = metadata.getMetadataReader(resource);ScannedGenericBeanDefinition beanDefinition = new ScannedGenericBeanDefinition(metadataReader);String classname = beanDefinition.getBeanClassName();Class<?> aClass = Class.forName(classname, false, classLoader);if (aClass.isInterface()) {continue;}beanDefinition.setResource(resource);beanDefinition.setSource(resource);candidates.add(beanDefinition);}return candidates;}}

动态扩展Rest接口地址,动态卸载Rest接口相关推荐

  1. java动态扩展_java栈内存动态扩展要怎么理解?要如何实现?

    小伙伴们知道如何在java栈中内存动态扩展吗?这是虚拟机中的一个概念,下面让我们一起来看看该如何实现吧. 一.内存概念 在java中,我们一般会简单把java内存区域划为两种:堆内存与栈内存.其实这种 ...

  2. mysql分表动态扩展_小星星 的动态 - SegmentFault 思否

    DolphinDB支持动态加载外部插件,以扩展系统功能.插件用C++编写,需要编译成".so"或".dll"共享库文件.本文着重介绍开发插件的方法和注意事项,并 ...

  3. UNIX网络编程读书笔记:套接口地址结构

    前言 大多数套接口函数都需要一个指向套接口地址结构的指针作为参数.每个协议族都定义它自己的套接口地址结构.这些结构的名字均以"sockaddr_"开头,并以对应每个协议族的唯一后缀 ...

  4. Telnet,命令级别,DHCP (动态主机配置协议),DHCP租期, 地址池,全局配置,接口配置,DHCP中继代理,网络三要素,路由项匹配算法

    Telnet Tcp协议 自带mac 缺少ip 手动配置ip 客户端配置: System-view //进入系统模式 interface GigabitEthernet 0/0/0 //进入端口 ip ...

  5. OpenFeign中动态URl、动态传递接口地址

    前言: 在微服务盛行的今天,做接口开发请求第三方服务的接口,大概率会用feign做请求,而feign也是最常用的一种rpc框架: 这里主要是说明在进行feign请求的时候,第三方服务的url和接口如何 ...

  6. vue中使用pdf.js插件打包后不显示插件及打包后动态修改接口地址

    最近写了一个项目 需要在线展示pdf 实现方法是下载该插件并解压放到 static文件夹中 地址:http://mozilla.github.io/pdf.js/ 我在项目中使用iframe嵌套的方式 ...

  7. java 接口权限控制_手把手教你搞定权限管理,结合Spring Security实现接口的动态权限控制!...

    SpringBoot实战电商项目mall(30k+star)地址:github.com/macrozheng/- 摘要 权限控管理作为后台管理系统中必要的功能,mall项目中结合Spring Secu ...

  8. 如何打造真正可动态扩展的服务架构

    在互联网应用领域,服务的动态性需求十分常见,这就对服务的自动发现和可动态扩展提出了很高的要求. Docker 的出现,以及微服务架构的兴起,让众多开源项目开始关注在松耦合的架构前提下,如何基于 Doc ...

  9. java笔记之数组的概念、声明、初始化、访问方式、复制和动态扩展算法以及递归...

    1.数组的概念: 一组相同类型的数据堆积在一起 2.数组的声明: 1)数据类型 [] 数组名: 2)数据类型 数组名[]:(不推荐) 注:数据类型 可以使简单数据类型,也可以使引用数据类型 简单数据类 ...

最新文章

  1. android tv 悬浮窗口,android TV的自定义关机弹出框
  2. Zencart的首页php 301,Zencart 做了301重定向后不能登陆网站后台的解决方案
  3. 更新Docker中的Jenkins版本
  4. 从零开始学习python | 实例讲解如何制作Python模式程序
  5. 第一视角玩无人机,parrot推出配备VR眼镜的bebop2
  6. 高级Linux Kernel Inline Hook技术分析与实现
  7. 深入理解Core Data
  8. 关于计算机病毒的试题,计算机病毒测试题.doc
  9. fdfs_upload_file发送内存文件
  10. 金蝶K3服务器安装与配置方法详细图解
  11. Xposed框架安装、使用及插件开发
  12. Source Files 与 Resource Files 的区别
  13. Vivado时序约束之—— set_max_delay、set_min_dealy(最大最小延迟约束)
  14. USB3.0:VL817Q7-C0的LAYOUT指南
  15. 中国民营医院行业市场运营模式与发展动向展望报告2022~2027年
  16. android版本14,TeamViewer14
  17. 机械革命 Code Go 评测
  18. leetcode 1658
  19. 5D摇杆模块(HAL)
  20. java 约瑟夫单循环_约瑟夫问题(Josephus问题)的递推O(n)解法、循环解法、单循环链表解法 | 学步园...

热门文章

  1. 实用英语:办公用品的地道英语说法汇总
  2. 代替YCM,当前vim最强自动补全方案
  3. 公众号关键词文章排名,公众号文章排名靠什么决定
  4. Matplotlib修改默认字体
  5. 动画设计与制作 作业一plus
  6. vb.net 教程 2-12 程序的调试
  7. 电脑上计算机软件一直自动弹出,WinXP光驱总是自动弹出来怎么办?电脑光驱老是自动弹出解决方法...
  8. 网络抓包原理及Fiddler的使用
  9. 织梦装修网站设计师与案例相关联的数据调用教程
  10. 抖音赚钱记,新手如何玩转抖音,每天赚300起(连载二)