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

网站建设域名seo是如何优化

网站建设域名,seo是如何优化,哪家公司做网站不错,安徽省建设监理协会 旧网站文章目录 Pre工程结构概述1. 插件接口与实现分析2. 插件工厂初始化分析3. 插件项包装类解析4. 插件工厂方法解析5. 插件加载与资源释放机制6. 实现类小结附PluginFactory Pre 插件 - 通过SPI方式实现插件管理 插件 - 一份配置,离插件机制只有一步之遥 插件 - 插件…

文章目录

  • Pre
  • 工程结构
  • 概述
  • 1. 插件接口与实现分析
  • 2. 插件工厂初始化分析
  • 3. 插件项包装类解析
  • 4. 插件工厂方法解析
  • 5. 插件加载与资源释放机制
  • 6. 实现类
  • 小结
  • 附PluginFactory

在这里插入图片描述


Pre

插件 - 通过SPI方式实现插件管理

插件 - 一份配置,离插件机制只有一步之遥

插件 - 插件机制触手可及

Plugin - 插件开发01_SPI的基本使用

Plugin - 插件开发02_使用反射机制和自定义配置实现插件化开发

Plugin - 插件开发03_Spring Boot动态插件化与热加载

Plugin - 插件开发04_Spring Boot中的SPI机制与Spring Factories实现

Plugin - 插件开发05_Solon中的插件实现机制


工程结构

在这里插入图片描述

概述

接下来我们主要对IPlugin接口及其实现,以及插件的加载和管理机制进行分析,分为如下几个点

  1. 插件接口与实现分析
  2. 插件工厂初始化分析
  3. 插件项包装类解析
  4. 插件工厂方法解析
  5. 插件加载与资源释放机制

1. 插件接口与实现分析

在这里插入图片描述

插件机制的核心接口是IPluginIPlugin继承了AutoCloseable接口,确保插件可以被正确关闭。

此外,还有一个IDefaultPlugin接口,继承了IPlugin,用于定义默认插件。

接口的主要代码如下:

 
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ClassUtil;
import com.alibaba.fastjson.JSONObject;import java.util.HashMap;
import java.util.Map;/*** 插件模块接口** @author bwcx_jzy* @since 2021/12/22*/
public interface IPlugin extends AutoCloseable {/*** 执行插件方法** @param main      拦截到到对象* @param parameter 执行方法传人的参数* @return 返回值* @throws Exception 异常*/Object execute(Object main, Map<String, Object> parameter) throws Exception;/*** 执行插件方法** @param main       主参数* @param parameters 其他参数* @return 结果* @throws Exception 异常*/default Object execute(Object main, Object... parameters) throws Exception {// 处理参数int length = parameters.length;Map<String, Object> map = new HashMap<>(length / 2);for (int i = 0; i < length; i += 2) {map.put(parameters[i].toString(), parameters[i + 1]);}return this.execute(main, map);}/*** 执行插件方法** @param main       拦截到到对象* @param parameters 其他参数* @param <T>        泛型* @param cls        返回值类型* @return 返回值* @throws Exception 异常*/default <T> T execute(Object main, Class<T> cls, Object... parameters) throws Exception {Object execute = this.execute(main, parameters);return this.convertResult(execute, cls);}/*** 执行插件方法** @param main      拦截到到对象* @param parameter 执行方法传人的参数* @param <T>       泛型* @param cls       返回值类型* @return 返回值* @throws Exception 异常*/default <T> T execute(Object main, Map<String, Object> parameter, Class<T> cls) throws Exception {Object execute = this.execute(main, parameter);return this.convertResult(execute, cls);}/*** 转换结果** @param execute 结果* @param cls     返回值类型* @param <T>     泛型* @return 返回值类型*/@SuppressWarnings("unchecked")default <T> T convertResult(Object execute, Class<T> cls) {if (execute == null) {return null;}Class<?> aClass = execute.getClass();if (ClassUtil.isSimpleValueType(aClass)) {return (T) Convert.convert(aClass, execute);}// json 数据Object o = JSONObject.toJSON(execute);if (o instanceof JSONObject) {JSONObject jsonObject = (JSONObject) o;return jsonObject.toJavaObject(cls);}return (T) execute;}/*** 系统关闭,插件资源释放** @throws Exception 异常*/@Overridedefault void close() throws Exception {}
}

主要方法解析

  1. execute 方法

    • execute(Object main, Class<T> cls, Object... parameters):此方法接收一个对象、一个返回值类型和一组参数,执行插件方法后返回指定类型的结果。
    • execute(Object main, Map<String, Object> parameter, Class<T> cls):此方法接收一个对象、一个参数Map和一个返回值类型,执行插件方法后返回指定类型的结果。
  2. convertResult 方法

    • 该方法用于将执行结果转换为指定类型。它首先判断结果是否为简单类型,如果是则直接转换;否则将结果转换为JSON对象,再将JSON对象转换为指定类型。
  3. close 方法

    • 实现了AutoCloseable接口,用于在系统关闭时释放插件资源。默认实现为空方法。

2. 插件工厂初始化分析

插件工厂类PluginFactory负责插件的初始化和管理 ,实现了ApplicationContextInitializerApplicationListener接口,用于在Spring上下文初始化和关闭时进行插件的加载和资源释放。

初始化核心方法的主要代码如下:

     @Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {init();// 扫描插件 实现Set<Class<?>> classes = ClassUtil.scanPackage("io.jpom", IPlugin.class::isAssignableFrom);List<PluginItemWrap> pluginItemWraps = classes.stream().filter(aClass -> ClassUtil.isNormalClass(aClass) && aClass.isAnnotationPresent(PluginConfig.class)).map(aClass -> new PluginItemWrap((Class<? extends IPlugin>) aClass)).filter(pluginItemWrap -> {if (StrUtil.isEmpty(pluginItemWrap.getName())) {DefaultSystemLog.getLog().warn("plugin config name error:{}", pluginItemWrap.getClassName());return false;}return true;}).collect(Collectors.toList());//Map<String, List<PluginItemWrap>> pluginMap = CollStreamUtil.groupByKey(pluginItemWraps, PluginItemWrap::getName);pluginMap.forEach((key, value) -> {// 排序value.sort((o1, o2) -> Comparator.comparingInt((ToIntFunction<PluginItemWrap>) value1 -> {Order order = value1.getClassName().getAnnotation(Order.class);if (order == null) {return 0;}return order.value();}).compare(o1, o2));PLUGIN_MAP.put(key, value);});log.debug("load plugin count:{}", pluginMap.keySet().size());}

3. 插件项包装类解析

PluginItemWrap类用于封装插件的相关信息,如插件配置、插件名、插件类名和插件对象,实现了对插件的包装和插件实例的创建。

 
import cn.hutool.core.util.ReflectUtil;
import cn.jiangzeyin.common.spring.SpringUtil;
import lombok.Getter;/*** 插件端对象** @author bwcx_jzy* @since 2021/12/24*/
@Getter
public class PluginItemWrap {/*** 配置相关*/private final PluginConfig pluginConfig;/*** 插件名*/private final String name;/*** 插件类名*/private final Class<? extends IPlugin> className;/*** 插件对象*/private volatile IPlugin plugin;public PluginItemWrap(Class<? extends IPlugin> className) {this.className = className;this.pluginConfig = className.getAnnotation(PluginConfig.class);this.name = this.pluginConfig.name();}public IPlugin getPlugin() {if (plugin == null) {synchronized (className) {if (plugin == null) {//boolean nativeObject = this.pluginConfig.nativeObject();if (nativeObject) {plugin = ReflectUtil.newInstance(className);} else {plugin = SpringUtil.getBean(className);}}}}return plugin;}
}

4. 插件工厂方法解析

插件工厂提供了若干静态方法供外部使用,如获取插件对象、判断是否包含某个插件以及获取插件数量等。

public static IPlugin getPlugin(String name) {List<PluginItemWrap> pluginItemWraps = PLUGIN_MAP.get(name);PluginItemWrap first = CollUtil.getFirst(pluginItemWraps);Assert.notNull(first, "对应找到对应到插件:" + name);return first.getPlugin();
}public static boolean contains(String name) {return PLUGIN_MAP.containsKey(name);
}public static int size() {return PLUGIN_MAP.size();
}

5. 插件加载与资源释放机制

PluginFactory文件中,实现了插件的加载和资源释放机制。在init方法中,扫描指定包下的插件并加载。在onApplicationEvent方法中,监听Spring上下文关闭事件并释放插件资源。

这两个方法的主要代码如下:

private static void init() {File runPath = JpomManifest.getRunPath().getParentFile();File plugin = FileUtil.file(runPath, "plugin");if (!plugin.exists() || plugin.isFile()) {return;}// 加载二级插件包File[] dirFiles = plugin.listFiles(File::isDirectory);if (dirFiles != null) {for (File file : dirFiles) {File lib = FileUtil.file(file, "lib");if (!lib.exists() || lib.isFile()) {continue;}File[] listFiles = lib.listFiles((dir, name) -> StrUtil.endWith(name, FileUtil.JAR_FILE_EXT, true));if (listFiles == null || listFiles.length <= 0) {continue;}for (File listFile : listFiles) {addPlugin(file.getName(), listFile);}}}// 加载一级独立插件端包File[] files = plugin.listFiles(pathname -> FileUtil.isFile(pathname) && FileUtil.JAR_FILE_EXT.equalsIgnoreCase(FileUtil.extName(pathname)));if (files != null) {for (File file : files) {addPlugin(file.getName(), file);}}
}@Override
public void onApplicationEvent(ContextClosedEvent event) {Collection<List<PluginItemWrap>> values = PLUGIN_MAP.values();for (List<PluginItemWrap> value : values) {for (PluginItemWrap pluginItemWrap : value) {IPlugin plugin = pluginItemWrap.getPlugin();IoUtil.close(plugin);}}
}

6. 实现类

在这里插入图片描述

我们以DefaultDbH2PluginImpl插件实现分析插件的视线 ,它实现了IPlugin接口中定义的方法。


@PluginConfig(name = "db-h2")
public class DefaultDbH2PluginImpl implements IDefaultPlugin {@Overridepublic Object execute(Object main, Map<String, Object> parameter) throws Exception {String method = StrUtil.toString(main);if (StrUtil.equals("backupSql", method)) {String url = (String) parameter.get("url");String user = (String) parameter.get("user");String password = (String) parameter.get("pass");String backupSqlPath = (String) parameter.get("backupSqlPath");List<String> tableNameList = (List<String>) parameter.get("tableNameList");this.backupSql(url, user, password, backupSqlPath, tableNameList);} else if (StrUtil.equals("restoreBackupSql", method)) {String backupSqlPath = (String) parameter.get("backupSqlPath");DataSource dataSource = (DataSource) parameter.get("dataSource");if (dataSource == null) {// 加载数据源dataSource = DSFactory.get();}this.restoreBackupSql(backupSqlPath, dataSource);} else if (StrUtil.equals("recoverToSql", method)) {File dbPath = (File) parameter.get("dbPath");String dbName = (String) parameter.get("dbName");File recoverBackup = (File) parameter.get("recoverBackup");return this.recover(dbPath, dbName, recoverBackup);} else {throw new IllegalArgumentException("不支持的类型");}return "done";}/*** 恢复** @param dbPath        数据库路径* @param dbName        数据库名* @param recoverBackup 恢复到哪个路径* @return 返回恢复到 sql 文件* @throws SQLException sql*/private File recover(File dbPath, String dbName, File recoverBackup) throws SQLException {String dbLocalPath = FileUtil.getAbsolutePath(dbPath);ArrayList<String> list = FileLister.getDatabaseFiles(dbLocalPath, dbName, true);if (CollUtil.isEmpty(list)) {return null;}FileUtil.mkdir(recoverBackup);// 备份数据for (String s : list) {FileUtil.move(FileUtil.file(s), recoverBackup, true);}String absolutePath = FileUtil.getAbsolutePath(recoverBackup);Console.log("h2 db recover backup path,{}", absolutePath);// 恢复数据Recover recover = new Recover();recover.runTool("-dir", absolutePath, "-db", dbName);return FileUtil.file(recoverBackup, dbName + ".h2.sql");}/*** 备份 SQL** @param url           jdbc url* @param user          user* @param password      password* @param backupSqlPath backup SQL file path, absolute path* @param tableNameList backup table name list, if need backup all table, use null*/private void backupSql(String url, String user, String password,String backupSqlPath, List<String> tableNameList) throws SQLException {// 备份 SQLString sql = StrUtil.format("SCRIPT DROP to '{}'", backupSqlPath);// 判断是否部分部分表if (!CollectionUtils.isEmpty(tableNameList)) {String tableNames = StrUtil.join(StrUtil.COMMA, tableNameList.toArray());sql = StrUtil.format("{} TABLE {}", sql, tableNames);}DefaultSystemLog.getLog().debug("backup SQL is: {}", sql);// 执行 SQL 备份脚本Shell shell = new Shell();/*url 表示 h2 数据库的 jdbc url* user 表示登录的用户名* password 表示登录密码* driver 是 jdbc 驱动* sql 是备份的 sql 语句* - 案例:script drop to ${fileName1} table ${tableName1},${tableName2}...* - script drop to 表示备份数据库,drop 表示建表之前会先删除表* - ${fileName1} 表示备份之后的文件名* - table 表示需要备份的表名称,后面跟多个表名,用英文逗号分割*/String[] params = new String[]{"-url", url,"-user", user,"-password", password,"-driver", "org.h2.Driver","-sql", sql};try (FastByteArrayOutputStream arrayOutputStream = new FastByteArrayOutputStream()) {try (PrintStream printStream = new PrintStream(arrayOutputStream)) {shell.setOut(printStream);shell.runTool(params);}}}/*** 还原备份 SQL** @param backupSqlPath backup SQL file path, absolute path* @throws SQLException SQLException* @throws IOException  FileNotFoundException*/private void restoreBackupSql(String backupSqlPath, DataSource dataSource) throws SQLException, IOException {Assert.notNull(dataSource, "Restore Backup sql error...H2 DataSource not null");try (Connection connection = dataSource.getConnection()) {// 读取数据库备份文件,执行还原File backupSqlFile = FileUtil.file(backupSqlPath);try (FileReader fileReader = new FileReader(backupSqlFile)) {RunScript.execute(connection, fileReader);}}}
}

小结

在Jpom项目中,IPlugin接口是插件系统的核心接口,它定义了插件需要实现的基本方法。 在插件工厂类PluginFactory中,通过扫描类路径加载插件并进行初始化:

IPlugin接口及其实现为Jpom的插件系统提供了灵活的扩展能力。通过定义通用的执行方法和结果转换方法,IPlugin接口简化了插件的开发和集成过程。而插件工厂类PluginFactory则通过扫描和加载机制,实现了插件的自动发现和初始化,使得插件系统具有高度的可扩展性和灵活性。

通过对插件接口IPlugin、插件工厂PluginFactory、插件项包装类PluginItemWrap以及插件的加载和资源释放机制的分析,可以清晰地了解整个工程的插件机制。这为后续的插件开发和管理提供了坚实的基础。


附PluginFactory

@Slf4j
public class PluginFactory implements ApplicationContextInitializer<ConfigurableApplicationContext>, ApplicationListener<ContextClosedEvent> {//    private static final List<FeatureCallback> FEATURE_CALLBACKS = new ArrayList<>();private static final Map<String, List<PluginItemWrap>> PLUGIN_MAP = new ConcurrentHashMap<>();//    /**
//     * 添加回调事件
//     *
//     * @param featureCallback 回调
//     */
//    public static void addFeatureCallback(FeatureCallback featureCallback) {
//        FEATURE_CALLBACKS.add(featureCallback);
//    }
//
//    public static List<FeatureCallback> getFeatureCallbacks() {
//        return FEATURE_CALLBACKS;
//    }/*** 获取插件端** @param name 插件名* @return 插件对象*/public static IPlugin getPlugin(String name) {List<PluginItemWrap> pluginItemWraps = PLUGIN_MAP.get(name);PluginItemWrap first = CollUtil.getFirst(pluginItemWraps);Assert.notNull(first, "对应找到对应到插件:" + name);return first.getPlugin();}/*** 判断是否包含某个插件** @param name 插件名* @return true 包含*/public static boolean contains(String name) {return PLUGIN_MAP.containsKey(name);}/*** 插件数量** @return 当前加载的插件数量*/public static int size() {return PLUGIN_MAP.size();}/*** 正式环境添加依赖*/private static void init() {File runPath = JpomManifest.getRunPath().getParentFile();File plugin = FileUtil.file(runPath, "plugin");if (!plugin.exists() || plugin.isFile()) {return;}// 加载二级插件包File[] dirFiles = plugin.listFiles(File::isDirectory);if (dirFiles != null) {for (File file : dirFiles) {File lib = FileUtil.file(file, "lib");if (!lib.exists() || lib.isFile()) {continue;}File[] listFiles = lib.listFiles((dir, name) -> StrUtil.endWith(name, FileUtil.JAR_FILE_EXT, true));if (listFiles == null || listFiles.length <= 0) {continue;}addPlugin(file.getName(), lib);}}// 加载一级独立插件端包File[] files = plugin.listFiles(pathname -> FileUtil.isFile(pathname) && FileUtil.JAR_FILE_EXT.equalsIgnoreCase(FileUtil.extName(pathname)));if (files != null) {for (File file : files) {addPlugin(file.getName(), file);}}}private static void addPlugin(String pluginName, File file) {DefaultSystemLog.getLog().info("加载:{} 插件", pluginName);ClassLoader contextClassLoader = ClassLoaderUtil.getClassLoader();JarClassLoader.loadJar((URLClassLoader) contextClassLoader, file);}@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {init();// 扫描插件 实现Set<Class<?>> classes = ClassUtil.scanPackage("io.jpom", IPlugin.class::isAssignableFrom);List<PluginItemWrap> pluginItemWraps = classes.stream().filter(aClass -> ClassUtil.isNormalClass(aClass) && aClass.isAnnotationPresent(PluginConfig.class)).map(aClass -> new PluginItemWrap((Class<? extends IPlugin>) aClass)).filter(pluginItemWrap -> {if (StrUtil.isEmpty(pluginItemWrap.getName())) {DefaultSystemLog.getLog().warn("plugin config name error:{}", pluginItemWrap.getClassName());return false;}return true;}).collect(Collectors.toList());//Map<String, List<PluginItemWrap>> pluginMap = CollStreamUtil.groupByKey(pluginItemWraps, PluginItemWrap::getName);pluginMap.forEach((key, value) -> {// 排序value.sort((o1, o2) -> Comparator.comparingInt((ToIntFunction<PluginItemWrap>) value1 -> {Order order = value1.getClassName().getAnnotation(Order.class);if (order == null) {return 0;}return order.value();}).compare(o1, o2));PLUGIN_MAP.put(key, value);});log.debug("load plugin count:{}", pluginMap.keySet().size());}@Overridepublic void onApplicationEvent(ContextClosedEvent event) {Collection<List<PluginItemWrap>> values = PLUGIN_MAP.values();for (List<PluginItemWrap> value : values) {for (PluginItemWrap pluginItemWrap : value) {IPlugin plugin = pluginItemWrap.getPlugin();IoUtil.close(plugin);}}}
}

在这里插入图片描述


文章转载自:
http://tubicolous.bsdw.cn
http://retinite.bsdw.cn
http://milliard.bsdw.cn
http://sandbagger.bsdw.cn
http://berbera.bsdw.cn
http://postie.bsdw.cn
http://subornation.bsdw.cn
http://instantly.bsdw.cn
http://rest.bsdw.cn
http://ursine.bsdw.cn
http://middleman.bsdw.cn
http://remontant.bsdw.cn
http://additament.bsdw.cn
http://willies.bsdw.cn
http://soapie.bsdw.cn
http://octahedral.bsdw.cn
http://slicer.bsdw.cn
http://biogeocoenosis.bsdw.cn
http://chromophilia.bsdw.cn
http://gharri.bsdw.cn
http://amblyopia.bsdw.cn
http://rhinopharyngitis.bsdw.cn
http://indention.bsdw.cn
http://cooperator.bsdw.cn
http://swot.bsdw.cn
http://volution.bsdw.cn
http://ditheism.bsdw.cn
http://farina.bsdw.cn
http://basidia.bsdw.cn
http://jotter.bsdw.cn
http://intarsia.bsdw.cn
http://drunk.bsdw.cn
http://princekin.bsdw.cn
http://transient.bsdw.cn
http://proviso.bsdw.cn
http://rectorial.bsdw.cn
http://autocratically.bsdw.cn
http://jura.bsdw.cn
http://blacklead.bsdw.cn
http://glove.bsdw.cn
http://apolitical.bsdw.cn
http://photocube.bsdw.cn
http://wagtail.bsdw.cn
http://ineffaceable.bsdw.cn
http://commemoration.bsdw.cn
http://crocoite.bsdw.cn
http://phosphorus.bsdw.cn
http://hematose.bsdw.cn
http://unisist.bsdw.cn
http://resound.bsdw.cn
http://emarcid.bsdw.cn
http://residence.bsdw.cn
http://panopticon.bsdw.cn
http://quindecennial.bsdw.cn
http://wingmanship.bsdw.cn
http://voile.bsdw.cn
http://mithridate.bsdw.cn
http://echograph.bsdw.cn
http://murkily.bsdw.cn
http://conceptual.bsdw.cn
http://marsha.bsdw.cn
http://condo.bsdw.cn
http://vina.bsdw.cn
http://unstrained.bsdw.cn
http://pressroom.bsdw.cn
http://honeysweet.bsdw.cn
http://metacentre.bsdw.cn
http://mature.bsdw.cn
http://scuff.bsdw.cn
http://siree.bsdw.cn
http://bottomry.bsdw.cn
http://god.bsdw.cn
http://athanasian.bsdw.cn
http://phantomlike.bsdw.cn
http://salvation.bsdw.cn
http://cruciferae.bsdw.cn
http://hyalography.bsdw.cn
http://tureen.bsdw.cn
http://pegasus.bsdw.cn
http://refitment.bsdw.cn
http://honiton.bsdw.cn
http://irradiancy.bsdw.cn
http://met.bsdw.cn
http://deodorizer.bsdw.cn
http://brant.bsdw.cn
http://catechesis.bsdw.cn
http://accessory.bsdw.cn
http://roundeye.bsdw.cn
http://compnserve.bsdw.cn
http://octandrious.bsdw.cn
http://style.bsdw.cn
http://disentrancement.bsdw.cn
http://khi.bsdw.cn
http://ballade.bsdw.cn
http://yarrow.bsdw.cn
http://mobese.bsdw.cn
http://demerara.bsdw.cn
http://cosponsor.bsdw.cn
http://soberminded.bsdw.cn
http://phentolamine.bsdw.cn
http://www.hrbkazy.com/news/76030.html

相关文章:

  • 网站突然没有收录企业营销管理
  • 网站建设基本流程前期国内搜索引擎排行榜
  • wordpress添加小说怎么快速优化关键词
  • 中牟网站建设b2b免费发布网站大全
  • 网站可以放多少视频特色产品推广方案
  • 企业网站建设综合实训心得体会十大免费货源网站免费版本
  • 郑州高端网站开发小程序推广赚佣金平台
  • 禅城网站开发厦门谷歌seo公司
  • 南昌做公司网站万网商标查询
  • 邢台企业做网站推广淘宝seo优化
  • 为企业做网站的公司同城广告发布平台
  • 商城网站建设开发公司天津seo招聘
  • 房地产开发公司管理制度百度推广优化是什么?
  • 北京做兼职的网站seo整合营销
  • wordpress首页js怎么添加评论优化
  • 郑州app开发跨境电商seo
  • 小组用jsp做的网站论文网站友情链接交易平台
  • 网站建设实训目的上海网站建设
  • 手机app开发网站模板网络营销总监岗位职责
  • 租车网站模板下载石家庄网站建设培训
  • 我想帮别人做网站有这样的平台吗当阳seo外包
  • 软件测试流程网站seo关键词排名查询
  • 南京大型行业网站建设微信营销软件哪个好用
  • 滨湖区建设局网站百度榜
  • 月饼网站建设陕西seo顾问服务
  • 网站开发属于软件开发行业吗sem营销推广
  • 网站开发h5页面seo深度优化公司
  • 新浪军事手机版官方下载seo外包是什么意思
  • 怎么做网站的寄生网络公司名字大全
  • 建筑招工信息网郑州搜索引擎优化公司