当前位置: 首页 > news >正文

网站后缀是xyz指得是什么北京高端网页制作

网站后缀是xyz指得是什么,北京高端网页制作,做python项目的网站,做家政建网站一、概述 1、背景 目前数据治理服务中有众多治理任务#xff0c;当其中任一治理任务有改动需要升级或新增一个治理任务时#xff0c;都需要将数据治理服务重启#xff0c;会影响其他治理任务的正常运行。 2、目标 能够动态启动、停止任一治理任务 能够动态升级、添加治理…一、概述 1、背景 目前数据治理服务中有众多治理任务当其中任一治理任务有改动需要升级或新增一个治理任务时都需要将数据治理服务重启会影响其他治理任务的正常运行。 2、目标 能够动态启动、停止任一治理任务 能够动态升级、添加治理任务 启动、停止治理任务或升级、添加治理任务不能影响其他任务 3、方案 为了支持业务代码尽量的解耦把部分业务功能通过动态加载的方式加载到主程序中以满足可插拔式的加载、组合式的部署。 配合xxl-job任务调度框架将数据治理任务做成xxl-job任务的方式注册到xxl-job中方便统一管理。 二、动态加载 1、自定义类加载器 URLClassLoader 是一种特殊的类加载器可以从指定的 URL 中加载类和资源。它的主要作用是动态加载外部的 JAR 包或者类文件从而实现动态扩展应用程序的功。为了便于管理动态加载的jar包自定义类加载器继承URLClassloader。 package cn.jy.sjzl.util;import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.Map; import java.util.concurrent.ConcurrentHashMap;/*** 自定义类加载器** author lijianyu* date 2023/04/03 17:54**/ public class MyClassLoader extends URLClassLoader {private MapString, Class? loadedClasses  new ConcurrentHashMap();public MapString, Class? getLoadedClasses() {return loadedClasses;}public MyClassLoader(URL[] urls, ClassLoader parent) {super(urls, parent);}Overrideprotected Class? findClass(String name) throws ClassNotFoundException {// 从已加载的类集合中获取指定名称的类Class? clazz  loadedClasses.get(name);if (clazz ! null) {return clazz;}try {// 调用父类的findClass方法加载指定名称的类clazz  super.findClass(name);// 将加载的类添加到已加载的类集合中loadedClasses.put(name, clazz);return clazz;} catch (ClassNotFoundException e) {e.printStackTrace();return null;}}public void unload() {try {for (Map.EntryString, Class? entry : loadedClasses.entrySet()) {// 从已加载的类集合中移除该类String className  entry.getKey();loadedClasses.remove(className);try{// 调用该类的destory方法回收资源Class? clazz  entry.getValue();Method destory  clazz.getDeclaredMethod(destory);destory.invoke(clazz);} catch (Exception e ) {// 表明该类没有destory方法}}// 从其父类加载器的加载器层次结构中移除该类加载器close();} catch (Exception e) {e.printStackTrace();}} }自定义类加载器中为了方便类的卸载定义一个map保存已加载的类信息。key为这个类的ClassNamevalue为这个类的类信息。 同时定义了类加载器的卸载方法卸载方法中将已加载的类的集合中移除该类。由于此类可能使用系统资源或调用线程为了避免资源未回收引起的内存溢出通过反射调用这个类中的destroy方法回收资源。 最后调用close方法。 2、动态加载 由于此项目使用spring框架以及xxl-job任务的机制调用动态加载的代码因此要完成以下内容 将动态加载的jar包读到内存中 将有spring注解的类通过注解扫描的方式扫描并手动添加到spring容器中。 将XxlJob注解的方法通过注解扫描的方式手动添加到xxljob执行器中。 package com.jy.dynamicLoad;import com.jy.annotation.XxlJobCron; import com.jy.classLoader.MyClassLoader; import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; import com.xxl.job.core.handler.annotation.XxlJob; import com.xxl.job.core.handler.impl.MethodJobHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.core.MethodIntrospector; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.stereotype.Component;import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.JarURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Enumeration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.jar.JarEntry; import java.util.jar.JarFile;/*** author lijianyu* date 2023/04/29 13:18**/ Component public class DynamicLoad {private static Logger logger  LoggerFactory.getLogger(DynamicLoad.class);Autowiredprivate ApplicationContext applicationContext;private MapString, MyClassLoader myClassLoaderCenter  new ConcurrentHashMap();Value(${dynamicLoad.path})private String path;/*** 动态加载指定路径下指定jar包* param path* param fileName* param isRegistXxlJob  是否需要注册xxljob执行器项目首次启动不需要注册执行器* return mapjobHander, Cron 创建xxljob任务时需要的参数配置*/public void loadJar(String path, String fileName, Boolean isRegistXxlJob) throws ClassNotFoundException, InstantiationException, IllegalAccessException {File file  new File(path /  fileName);MapString, String jobPar  new HashMap();// 获取beanFactoryDefaultListableBeanFactory beanFactory  (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();// 获取当前项目的执行器try {// URLClassloader加载jar包规范必须这么写URL url  new URL(jar:file:  file.getAbsolutePath()  !/);URLConnection urlConnection  url.openConnection();JarURLConnection jarURLConnection  (JarURLConnection)urlConnection;// 获取jar文件JarFile jarFile  jarURLConnection.getJarFile();EnumerationJarEntry entries  jarFile.entries();// 创建自定义类加载器并加到map中方便管理MyClassLoader myClassloader  new MyClassLoader(new URL[] { url }, ClassLoader.getSystemClassLoader());myClassLoaderCenter.put(fileName, myClassloader);SetClass initBeanClass  new HashSet(jarFile.size());// 遍历文件while (entries.hasMoreElements()) {JarEntry jarEntry  entries.nextElement();if (jarEntry.getName().endsWith(.class)) {// 1. 加载类到jvm中// 获取类的全路径名String className  jarEntry.getName().replace(/, .).substring(0, jarEntry.getName().length() - 6);// 1.1进行反射获取myClassloader.loadClass(className);}}MapString, Class? loadedClasses  myClassloader.getLoadedClasses();XxlJobSpringExecutor xxlJobExecutor  new XxlJobSpringExecutor();for(Map.EntryString, Class? entry : loadedClasses.entrySet()){String className  entry.getKey();Class? clazz  entry.getValue();// 2. 将有spring注解的类交给spring管理// 2.1 判断是否注入springBoolean flag  SpringAnnotationUtils.hasSpringAnnotation(clazz);if(flag){// 2.2交给spring管理BeanDefinitionBuilder builder  BeanDefinitionBuilder.genericBeanDefinition(clazz);AbstractBeanDefinition beanDefinition  builder.getBeanDefinition();// 此处beanName使用全路径名是为了防止beanName重复String packageName  className.substring(0, className.lastIndexOf(.)  1);String beanName  className.substring(className.lastIndexOf(.)  1);beanName  packageName  beanName.substring(0, 1).toLowerCase()  beanName.substring(1);// 2.3注册到spring的beanFactory中beanFactory.registerBeanDefinition(beanName, beanDefinition);// 2.4允许注入和反向注入beanFactory.autowireBean(clazz);beanFactory.initializeBean(clazz, beanName);/*if(Arrays.stream(clazz.getInterfaces()).collect(Collectors.toSet()).contains(InitializingBean.class)){initBeanClass.add(clazz);}*/initBeanClass.add(clazz);}// 3. 带有XxlJob注解的方法注册任务// 3.1 过滤方法MapMethod, XxlJob annotatedMethods  null;try {annotatedMethods  MethodIntrospector.selectMethods(clazz,new MethodIntrospector.MetadataLookupXxlJob() {Overridepublic XxlJob inspect(Method method) {return AnnotatedElementUtils.findMergedAnnotation(method, XxlJob.class);}});} catch (Throwable ex) {}// 3.2 生成并注册方法的JobHanderfor (Map.EntryMethod, XxlJob methodXxlJobEntry : annotatedMethods.entrySet()) {Method executeMethod  methodXxlJobEntry.getKey();// 获取jobHander和CronXxlJobCron xxlJobCron  executeMethod.getAnnotation(XxlJobCron.class);if(xxlJobCron  null){throw new CustomException(500, executeMethod.getName()  ()没有添加XxlJobCron注解配置定时策略);}if (!CronExpression.isValidExpression(xxlJobCron.value())) {throw new CustomException(500, executeMethod.getName()  (),XxlJobCron参数内容错误);}XxlJob xxlJob  methodXxlJobEntry.getValue();jobPar.put(xxlJob.value(), xxlJobCron.value());if (isRegistXxlJob) {executeMethod.setAccessible(true);// registMethod initMethod  null;Method destroyMethod  null;xxlJobExecutor.registJobHandler(xxlJob.value(), new CustomerMethodJobHandler(clazz, executeMethod, initMethod, destroyMethod));}}}// spring bean实际注册initBeanClass.forEach(beanFactory::getBean);} catch (IOException e) {logger.error(读取{} 文件异常, fileName);e.printStackTrace();throw new RuntimeException(读取jar文件异常:   fileName);}} }以下是判断该类是否有spring注解的工具类 apublic class SpringAnnotationUtils {private static Logger logger  LoggerFactory.getLogger(SpringAnnotationUtils.class);/*** 判断一个类是否有 Spring 核心注解** param clazz 要检查的类* return true 如果该类上添加了相应的 Spring 注解否则返回 false*/public static boolean hasSpringAnnotation(Class? clazz) {if (clazz  null) {return false;}//是否是接口if (clazz.isInterface()) {return false;}//是否是抽象类if (Modifier.isAbstract(clazz.getModifiers())) {return false;}try {if (clazz.getAnnotation(Component.class) ! null ||clazz.getAnnotation(Repository.class) ! null ||clazz.getAnnotation(Service.class) ! null ||clazz.getAnnotation(Controller.class) ! null ||clazz.getAnnotation(Configuration.class) ! null) {return true;}}catch (Exception e){logger.error(出现异常{},e.getMessage());}return false;} }注册xxljob执行器的操作是仿照的xxljob中的XxlJobSpringExecutor的注册方法。 3、动态卸载 动态卸载的过程就是将动态加载的代码从内存spring以及xxljob中移除。 代码如下 /*** 动态卸载指定路径下指定jar包* param fileName* return mapjobHander, Cron 创建xxljob任务时需要的参数配置*/ public void unloadJar(String fileName) throws IllegalAccessException, NoSuchFieldException {// 获取加载当前jar的类加载器MyClassLoader myClassLoader myClassLoaderCenter.get(fileName);// 获取jobHandlerRepository私有属性,为了卸载xxljob任务Field privateField XxlJobExecutor.class.getDeclaredField(jobHandlerRepository);// 设置私有属性可访问privateField.setAccessible(true);// 获取私有属性的值jobHandlerRepositoryXxlJobExecutor xxlJobSpringExecutor new XxlJobSpringExecutor();MapString, IJobHandler jobHandlerRepository (ConcurrentHashMapString, IJobHandler) privateField.get(xxlJobSpringExecutor);// 获取beanFactory准备从spring中卸载DefaultListableBeanFactory beanFactory (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();MapString, Class? loadedClasses myClassLoader.getLoadedClasses();SetString beanNames new HashSet();for (Map.EntryString, Class? entry: loadedClasses.entrySet()) {// 1. 将xxljob任务从xxljob执行器中移除// 1.1 截取beanNameString key entry.getKey();String packageName key.substring(0, key.lastIndexOf(.) 1);String beanName key.substring(key.lastIndexOf(.) 1);beanName packageName beanName.substring(0, 1).toLowerCase() beanName.substring(1);// 获取bean如果获取失败表名这个类没有加到spring容器中则跳出本次循环Object bean null;try{bean applicationContext.getBean(beanName);}catch (Exception e){// 异常说明spring中没有这个beancontinue;}// 1.2 过滤方法MapMethod, XxlJob annotatedMethods null;try {annotatedMethods MethodIntrospector.selectMethods(bean.getClass(),new MethodIntrospector.MetadataLookupXxlJob() {Overridepublic XxlJob inspect(Method method) {return AnnotatedElementUtils.findMergedAnnotation(method, XxlJob.class);}});} catch (Throwable ex) {}// 1.3 将job从执行器中移除for (Map.EntryMethod, XxlJob methodXxlJobEntry : annotatedMethods.entrySet()) {XxlJob xxlJob methodXxlJobEntry.getValue();jobHandlerRepository.remove(xxlJob.value());}// 2.0从spring中移除这里的移除是仅仅移除的bean并未移除bean定义beanNames.add(beanName);beanFactory.destroyBean(beanName, bean);}// 移除bean定义Field mergedBeanDefinitions beanFactory.getClass().getSuperclass().getSuperclass().getDeclaredField(mergedBeanDefinitions);mergedBeanDefinitions.setAccessible(true);MapString, RootBeanDefinition rootBeanDefinitionMap ((MapString, RootBeanDefinition) mergedBeanDefinitions.get(beanFactory));for (String beanName : beanNames) {beanFactory.removeBeanDefinition(beanName);// 父类bean定义去除rootBeanDefinitionMap.remove(beanName);}// 卸载父任务子任务已经在循环中卸载jobHandlerRepository.remove(fileName);// 3.2 从类加载中移除try {// 从类加载器底层的classes中移除连接Field field ClassLoader.class.getDeclaredField(classes);field.setAccessible(true);VectorClass? classes (VectorClass?) field.get(myClassLoader);classes.removeAllElements();// 移除类加载器的引用myClassLoaderCenter.remove(fileName);// 卸载类加载器myClassLoader.unload();} catch (NoSuchFieldException e) {logger.error(动态卸载的类从类加载器中卸载失败);e.printStackTrace();} catch (IllegalAccessException e) {logger.error(动态卸载的类从类加载器中卸载失败);e.printStackTrace();}logger.error({} 动态卸载成功, fileName);} 4、动态配置 使用动态加载时为了避免服务重新启动后丢失已加载的任务包使用动态配置的方式加载后动态更新初始化加载配置。 以下提供了两种自己实际操作过的配置方式。 4.1 动态修改本地yml 动态修改本地yml配置文件需要添加snakeyaml的依赖 4.1.1 依赖引入 dependencygroupIdorg.yaml/groupIdartifactIdsnakeyaml/artifactIdversion1.29/version /dependency4.1.2 工具类 读取指定路径下的配置文件并进行修改。 package com.jy.util;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml;import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors;/*** 用于动态修改bootstrap.yml配置文件* author lijianyu* date 2023/04/18 17:57**/ Component public class ConfigUpdater {public void updateLoadJars(ListString jarNames) throws IOException {// 读取bootstrap.ymlYaml yaml  new Yaml();InputStream inputStream  new FileInputStream(new File(src/main/resources/bootstrap.yml));MapString, Object obj  yaml.load(inputStream);inputStream.close();obj.put(loadjars, jarNames);// 修改FileWriter writer  new FileWriter(new File(src/main/resources/bootstrap.yml));DumperOptions options  new DumperOptions();options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);options.setPrettyFlow(true);Yaml yamlWriter  new Yaml(options);yamlWriter.dump(obj, writer);} }4.2 动态修改nacos配置 Spring Cloud Alibaba Nacos组件完全支持在运行时通过代码动态修改配置还提供了一些API供开发者在代码里面实现动态修改配置。在每次动态加载或卸载数据治理任务jar包时执行成功后都会进行动态更新nacos配置。 package cn.jy.sjzl.config;import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.exception.NacosException; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration;import java.util.Properties;Configuration public class NacosConfig {Value(${spring.cloud.nacos.server-addr})private String serverAddr;Value(${spring.cloud.nacos.config.namespace})private String namespace;public ConfigService configService() throws NacosException {Properties properties  new Properties();properties.put(serverAddr, serverAddr);properties.put(namespace, namespace);return NacosFactory.createConfigService(properties);} }package cn.jy.sjzl.util;import cn.jy.sjzl.config.NacosConfig; import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.api.config.ConfigService; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors;/*** nacos配置中修改sjzl-loadjars.yml** author lijianyu* date 2023/04/19 17:59**/ Component public class NacosConfigUtil {private static Logger logger  LoggerFactory.getLogger(NacosConfigUtil.class);Autowiredprivate NacosConfig nacosConfig;private String dataId  sjzl-loadjars.yml;Value(${spring.cloud.nacos.config.group})private String group;/*** 从nacos配置文件中添加初始化jar包配置* param jarName 要移除的jar包名* throws Exception*/public void addJarName(String jarName) throws Exception {ConfigService configService  nacosConfig.configService();String content  configService.getConfig(dataId, group, 5000);// 修改配置文件内容YAMLMapper yamlMapper  new YAMLMapper();ObjectMapper jsonMapper  new ObjectMapper();Object yamlObject  yamlMapper.readValue(content, Object.class);String jsonString  jsonMapper.writeValueAsString(yamlObject);JSONObject jsonObject  JSONObject.parseObject(jsonString);ListString loadjars;if (jsonObject.containsKey(loadjars)) {loadjars  (ListString) jsonObject.get(loadjars);}else{loadjars  new ArrayList();}if (!loadjars.contains(jarName)) {loadjars.add(jarName);}jsonObject.put(loadjars , loadjars);Object yaml  yamlMapper.readValue(jsonMapper.writeValueAsString(jsonObject), Object.class);String newYamlString  yamlMapper.writeValueAsString(yaml);boolean b  configService.publishConfig(dataId, group, newYamlString);if(b){logger.info(nacos配置更新成功);}else{logger.info(nacos配置更新失败);}} }三、分离打包 分离打包时根据实际情况在pom.xml中修改以下配置 buildpluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-shade-plugin/artifactIdversion3.2.4/versionexecutionsexecutionphasepackage/phasegoalsgoalshade/goal/goalsconfigurationfiltersfilterartifact*:*/artifactincludesincludecom/jy/job/demo/**/include/includes/filter/filtersfinalNamedemoJob/finalName/configuration/execution/executions/plugin/plugins /build
http://www.zqtcl.cn/news/33333/

相关文章:

  • 网站维护服务内容wordpress主题制作视频教程
  • 网站建设岗位绩效做电子请柬用什么网站
  • 网站备案多长时间网页设计公司注册
  • 医院网站建设的好处用手机制作网站
  • 二手网站模板没有网站怎么做网推
  • 集宁有做蒙古黑石材网站的嘛海口wordpress培训
  • 做携程网站的技术北京网站建设及推广招聘
  • 国外网站源码wordpress 分类 无侧边栏
  • 自己做的网站怎么上传网络iis wordpress 多站点
  • 自贡做网站公司南昌哪家做网站好
  • 网站分站的实现方法免费的推广引流软件下载
  • 门户网站建设工作室在线制作动态图片自动生成
  • 天津网络网站制作公司公共资源交易中心职能
  • wordpress微信域名回调宁波做网站seo
  • 怎么做网站描述如何将公司网站做的更好看
  • 深圳网站建设zvge代理公司招标流程
  • 办公用品企业网站建设方案网站建设推广优化有哪些基本方法
  • 下沙网站优化商城网站开发费用一般是多少
  • 微信小程序源代码北海seo快速排名
  • 上海网站开发哪家好wordpress慢
  • 上海网站建设官方网站看网站有没有做404
  • 做网站 深圳深圳建站公司服务
  • 制作外贸网站公司58同城app下载安装手机版
  • seo做的比较好的网站顺德大良网站建设
  • wordpress qq登录微信登录企业网站排名优化
  • 东营网站seo服务目前做网站最好的语言是
  • 天津市建设工程备案网站页面设计软件教程
  • 上海市工程建设监理协会网站程序员外包是什么意思
  • 做时时的网站上海企业服务云app
  • 做ppt哪个网站的图片好2022重大时政热点事件简短