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

wordpress 编辑器推动门户网站建设不断优化升级

wordpress 编辑器,推动门户网站建设不断优化升级,怎么做asp网站,微山县建设.局网站实现效果 先说效果#xff0c;要实现方法级别注解切换当前数据源#xff0c;不设置注解时走默认数据源#xff0c;同时支持JNDI源。 总体思路 Spring框架中存在一个抽象类AbstractRoutingDataSource#xff0c;他是一个可以动态选择当前DataSource的路由类#xff0c;我…实现效果 先说效果要实现方法级别注解切换当前数据源不设置注解时走默认数据源同时支持JNDI源。 总体思路 Spring框架中存在一个抽象类AbstractRoutingDataSource他是一个可以动态选择当前DataSource的路由类我们就是要从这里入手重新实现数据源的切换选择逻辑。然后借助注解和切面将当前需要的数据源名称放在ThreadLocal中需要时从当前线程取得即可完成数据源的切换。 注解部分比较简单不再详说看AbstractRoutingDataSource。该类文档写的非常全面自行翻译一下就可以看懂。主要看其中的几个关键方法。 setTargetDataSources 类中存在一个成员变量targetDataSources结合之后的setTargetDataSources方法可知这里用来保存目标数据源。 根据注释我们可以知道targetDataSources的key可以是数据源的名字value是相应数据源的实例。 当然这里也可是使用其他的保存方式然后自行改写用来查找数据源的determineCurrentLookupKey方法默认场景就足够我们使用了。所以我们要构建一个Map出来其中key用来区分数据源的名字value放入对应数据源的实例有几个数据源就放几个进去。 Nullableprivate MapObject, Object targetDataSources;/*** Specify the map of target DataSources, with the lookup key as key.* The mapped value can either be a corresponding {link javax.sql.DataSource}* instance or a data source name String (to be resolved via a* {link #setDataSourceLookup DataSourceLookup}).* pThe key can be of arbitrary type; this class implements the* generic lookup process only. The concrete key representation will* be handled by {link #resolveSpecifiedLookupKey(Object)} and* {link #determineCurrentLookupKey()}.*/public void setTargetDataSources(MapObject, Object targetDataSources) {this.targetDataSources targetDataSources;}setDefaultTargetDataSource 上面说了如何设置当前数据源那如果在开发的时候每一个方法都要声明一下使用哪个源就太麻烦了所以Spring提供了一个方法用来设置默认的数据源没啥可说的传入DataSource实例就好了。 Nullableprivate Object defaultTargetDataSource;/*** Specify the default target DataSource, if any.* pThe mapped value can either be a corresponding {link javax.sql.DataSource}* instance or a data source name String (to be resolved via a* {link #setDataSourceLookup DataSourceLookup}).* pThis DataSource will be used as target if none of the keyed* {link #setTargetDataSources targetDataSources} match the* {link #determineCurrentLookupKey()} current lookup key.*/public void setDefaultTargetDataSource(Object defaultTargetDataSource) {this.defaultTargetDataSource defaultTargetDataSource;}determineCurrentLookupKey 在设置好数据源之后接下来这几个寻路方法则是能实现动态数据源切换的重点。afterPropertiesSet方法对我们以配置的数据源进行校验如果我们在第一步配置数据源map的时候对key有特殊处理则要自己实现抽象方法resolveSpecifiedLookupKey告诉Spring应该怎么解析这个key值determineTargetDataSource则最终确定要使用哪一个数据源其中有一个方法determineCurrentLookupKey需要关注这个方法会返回当前要使用的数据源名字但他是个抽象方法所以我们需要给他重写一下改为从当前线程获取数据源名称。 Overridepublic void afterPropertiesSet() {if (this.targetDataSources null) {throw new IllegalArgumentException(Property targetDataSources is required);}this.resolvedDataSources CollectionUtils.newHashMap(this.targetDataSources.size());this.targetDataSources.forEach((key, value) - {Object lookupKey resolveSpecifiedLookupKey(key);DataSource dataSource resolveSpecifiedDataSource(value);this.resolvedDataSources.put(lookupKey, dataSource);});if (this.defaultTargetDataSource ! null) {this.resolvedDefaultDataSource resolveSpecifiedDataSource(this.defaultTargetDataSource);}}Overridepublic Connection getConnection(String username, String password) throws SQLException {return determineTargetDataSource().getConnection(username, password);}/*** Retrieve the current target DataSource. Determines the* {link #determineCurrentLookupKey() current lookup key}, performs* a lookup in the {link #setTargetDataSources targetDataSources} map,* falls back to the specified* {link #setDefaultTargetDataSource default target DataSource} if necessary.* see #determineCurrentLookupKey()*/protected DataSource determineTargetDataSource() {Assert.notNull(this.resolvedDataSources, DataSource router not initialized);Object lookupKey determineCurrentLookupKey();DataSource dataSource this.resolvedDataSources.get(lookupKey);if (dataSource null (this.lenientFallback || lookupKey null)) {dataSource this.resolvedDefaultDataSource;}if (dataSource null) {throw new IllegalStateException(Cannot determine target DataSource for lookup key [ lookupKey ]);}return dataSource;}/*** Determine the current lookup key. This will typically be* implemented to check a thread-bound transaction context.* pAllows for arbitrary keys. The returned key needs* to match the stored lookup key type, as resolved by the* {link #resolveSpecifiedLookupKey} method.*/Nullableprotected abstract Object determineCurrentLookupKey();代码实现 思路理顺了代码写起来就比较快直接贴最后代码部分地方保留了注释。 数据源切换注解 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 数据源切换注解默认为primary*/ Target({ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface TargetDataSource {DataSourceEnum value() default DataSourceEnum.PRIMARY; }数据源切换切面 这里需要特别提醒一下事务注解Transactional默认处于切面代理的最后一个所以我们需要保证数据源切换注解优先级要高于事务注解。 import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component;/*** 数据源切换切面*/ Aspect Component Order(1) public class DynamicDataSourceAspect {private final static Logger log LoggerFactory.getLogger(DynamicDataSourceAspect.class);Before(value annotation(targetDataSource))public void beforePointCut(TargetDataSource targetDataSource) {log.debug(数据源切换为 targetDataSource.value().getDataSourceName());DynamicDataSourceContextHolder.setDataSource(targetDataSource.value().getDataSourceName());}After(value annotation(targetDataSource))public void afterPointCut(TargetDataSource targetDataSource) {log.debug(数据源恢复为 DataSourceEnum.PRIMARY.getDataSourceName());DynamicDataSourceContextHolder.clearDataSource();} }数据源枚举类 /*** 数据源枚举类*/ public enum DataSourceEnum {PRIMARY(primary), SECONDARY(secondary);private final String dataSourceName;public String getDataSourceName() {return dataSourceName;}DataSourceEnum(String dataSourceName) {this.dataSourceName dataSourceName;} }数据源上下文保持类 /*** 数据源上下文线程持有类*/ public class DynamicDataSourceContextHolder {/*** 存放当前线程使用的数据源类型信息*/private static final ThreadLocalString CONTEXT_HOLDER new ThreadLocal();public static void setDataSource(String dataSourceType) {CONTEXT_HOLDER.set(dataSourceType);}public static String getDataSource() {return CONTEXT_HOLDER.get();}public static void clearDataSource() {CONTEXT_HOLDER.remove();} }AbstractRoutingDataSource自定义实现 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;import javax.sql.DataSource; import java.util.Map;/*** 动态数据源切换类** author liuenqi*/ public class DynamicDataSource extends AbstractRoutingDataSource {Overrideprotected Object determineCurrentLookupKey() {return DynamicDataSourceContextHolder.getDataSource();}public DynamicDataSource(DataSource defaultTargetDataSource, MapObject, Object targetDataSources) {// 默认数据源super.setDefaultTargetDataSource(defaultTargetDataSource);// 所有目标数据源super.setTargetDataSources(targetDataSources);// 后处理super.afterPropertiesSet();} }数据源注册 注意使用jndi源的时候需要加一个特定前缀。 import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotationMetadata;import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; import java.util.Objects;/*** 多数据源注册类*/ public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {private DataSource primaryDataSource;private DataSource secondaryDataSource;Overridepublic void setEnvironment(Environment environment) {initPrimaryDataSource(environment);initSecondaryDataSource(environment);}/*** 组装主数据源参数兼容jdbc-url与jndi** param env Environment*/private void initPrimaryDataSource(Environment env) {MapString, String paramMap new HashMap(4);if (StringUtils.isNotBlank(env.getProperty(spring.datasource.primary.url))) {paramMap.put(url, env.getProperty(spring.datasource.primary.url));paramMap.put(userName, env.getProperty(spring.datasource.primary.username));paramMap.put(password, env.getProperty(spring.datasource.primary.password));paramMap.put(driverClassName, env.getProperty(spring.datasource.primary.driver-class-name));} else {paramMap.put(jndi, env.getProperty(spring.datasource.primary.jndi-name));}primaryDataSource buildDataSource(paramMap);}/*** 组装辅数据源参数兼容jdbc-url与jndi** param env Environment*/private void initSecondaryDataSource(Environment env) {if (StringUtils.isNotBlank(env.getProperty(spring.datasource.secondary.url))) {MapString, String paramMap new HashMap(4);paramMap.put(url, env.getProperty(spring.datasource.secondary.url));paramMap.put(userName, env.getProperty(spring.datasource.secondary.username));paramMap.put(password, env.getProperty(spring.datasource.secondary.password));paramMap.put(driverClassName, env.getProperty(spring.datasource.secondary.driver-class-name));secondaryDataSource buildDataSource(paramMap);} else if (StringUtils.isNotBlank(env.getProperty(spring.datasource.secondary.jndi-name))) {MapString, String paramMap new HashMap(2);paramMap.put(jndi, env.getProperty(spring.datasource.secondary.jndi-name));secondaryDataSource buildDataSource(paramMap);}}Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {MapObject, Object targetDataSource new HashMap(2);targetDataSource.put(primary, primaryDataSource);if (Objects.nonNull(secondaryDataSource)) {targetDataSource.put(secondary, secondaryDataSource);}// 为DynamicDataSource构造参数注意参数顺序ConstructorArgumentValues constructorArgumentValues new ConstructorArgumentValues();constructorArgumentValues.addGenericArgumentValue(primaryDataSource);constructorArgumentValues.addGenericArgumentValue(targetDataSource);// 构造bean放入IOCGenericBeanDefinition beanDefinition new GenericBeanDefinition();beanDefinition.setBeanClass(DynamicDataSource.class);beanDefinition.setConstructorArgumentValues(constructorArgumentValues);beanDefinition.setSynthetic(true);registry.registerBeanDefinition(dataSource, beanDefinition);}/*** 使用HikariDataSource** param paramMap {url:JDBC-URL,userName:数据库用户名,password:密码,driverClassName:驱动名,jndi:jndi源}* return HikariDataSource*/private DataSource buildDataSource(MapString, String paramMap) {HikariConfig hikariConfig new HikariConfig();if (paramMap.containsKey(url)) {hikariConfig.setJdbcUrl(paramMap.get(url));hikariConfig.setUsername(paramMap.get(userName));hikariConfig.setPassword(paramMap.get(password));hikariConfig.setDriverClassName(paramMap.get(driverClassName));} else {hikariConfig.setDataSourceJNDI(java:comp/env/ paramMap.get(jndi));}return new HikariDataSource(hikariConfig);} }application.yml配置 spring:datasource:primary:url: jdbc:mysql://xxxxxusername: xxxxpassword: xxxxxdriver-class-name: com.mysql.cj.jdbc.Driversecondary: jndi-name: jdbc/db
http://www.w-s-a.com/news/219849/

相关文章:

  • 做游戏网站的前景温江区建设局网站
  • 济南做微网站推广做网站seo优化总结
  • 巢湖网站建设电话长沙大型互联网公司
  • wordpress站群主机海南人
  • 云南网站建设维护商业网站建设教程
  • 云南省滇中引水工程建设管理局网站jsp个人网站设计
  • 网站建设 域名业务 邮箱互联网装饰网站
  • 建设厅技工在哪个网站上查询有了网站模板 还要怎样做
  • 城市联盟网站怎么做百度云网站建设视频教程
  • 织梦cms 官方网站网页视频如何下载到电脑
  • 查询建设公司业绩网站国外外链平台
  • 搭建直播网站需要怎么做做石材网站步骤
  • 移动网站如何做权重wordpress 统计字数 插件
  • 编写网站的软件百度指数教程
  • 网站改版建议策划书做设计什么兼职网站
  • 北京做兼职网站文创产品设计流程
  • 南阳做玉器网站wordpress 图片被缩小
  • 自己做网站卖衣服cms做网站容易不
  • 安徽安搜做的网站怎么样手机网站商城建设答辩问题
  • 分析不同网站的优缺点房产网站定制
  • 深圳工业设计大展2021论坛与网站做优化哪个更好
  • 什么网站做招聘比较好网络营销渠道管理
  • 网站建设选择什么模式淘宝网站可以做轮播吗
  • 山西免费网站制作乌市高新区建设局网站
  • 公司网站建设费用会计处理手机app免费下载
  • 网站的做网站的公司网站有些什么内容
  • 网站新类型wordpress 随机文章
  • 电商网站建设会计分录朝阳市网站公司
  • 正邦网站建设 优帮云百姓网征婚
  • 企业网站有哪些举几个例子端午节网站建设目的