最近因一个微信项目的升级需要,又打开了以前用Jodd写的一个小项目。Jodd这个微框架编译后,项目也就6到7M,麻雀虽小,五脏俱全。然而就一个weixin-java-tool就追加5M左右了。。。
是一个微信带参数二维码的问题:临时二维码有过期时间,然而只能带一个Int参数(坑爹,你TM让我传个字符串会死啊),但可以无限制生成。永久二维码可以传字符串,然而只能生成10万张。鉴于业务发展需要,10万张压根不可取,不过期也不安全。换言之只能生成临时二维码,传一个参数了。
项目的特性属于附属项目,需调用另一个项目的数据。但是两个项目依赖性比较大,使用rpc又得在两个项目集成rpc,通过http调用又太慢且要考虑安全问题。再说,传一个参数在那边执行几个sql查询再通过网络返回结果,这种损耗让人受不了。我想:要是Jodd支持多数据源那该多好啊!反正两个项目不需要分得太细,还不到拆分的时候。
于是,把Jodd的源码弄下来了:https://github.com/oblac/jodd.git
在官网上浏览了一遍,发现了这个叫Proxetta的组件:
官网上(http://jodd.org/doc/proxetta/)有详细的介绍,这里就不啰嗦了,直接引用原图:

有三种委托调用方式:
Proxy在程序启动的时候会生成一个目标类的子类,会重写父类需要代理执行的方法。Wrapper则会生成另一个类,持有对一个或多个目标类实例的引用,委托调用目标方法。InvokeReplacer会硬生生把目标类的方法替换掉。
于是,我选择Proxy的方式实现多数据源的切换:
1. 从官网得知,Jodd的切面可以通过自定义注解实现,从程序的入口DefaultAppCore.java中可以找到@Transaction是如何实现的。
protected ProxyAspect createTxProxyAspects() {
return new ProxyAspect(
AnnotationTxAdvice.class,
new MethodAnnotationPointcut(jtxAnnotations) {
@Override
public boolean apply(MethodInfo methodInfo) {
return
isPublic(methodInfo) &&
isTopLevelMethod(methodInfo) &&
super.apply(methodInfo);
}
});
}
重点是AnnotationTxAdvice.class:
import static jodd.jtx.proxy.AnnotationTxAdviceSupport.manager; //这个东西是静态的,SingletonScope,只管理一个数据源
public class AnnotationTxAdvice implements ProxyAdvice {
public Object execute() throws Exception {
Class type = targetClass();
String methodName = targetMethodName();
Class[] methodArgsTypes = createArgumentsClassArray();
String methodDescription = targetMethodDescription();
// read transaction mode from annotation
JtxTransactionMode txMode = manager.getTxMode(type, methodName, methodArgsTypes, methodDescription);
// request transaction
JtxTransaction tx = null;
try {
String scope = manager.resolveScope(type, methodName);
tx = manager.getJtxWorker().maybeRequestTransaction(txMode, scope);
Object result = invoke();
manager.getJtxWorker().maybeCommitTransaction(tx);
return result;
} catch (Exception ex) {
manager.getJtxWorker().markOrRollbackTransaction(tx, ex);
throw ex;
}
}
}
由此可得知在invoke()返回结果前,做了启动事务的操作,调用方法后,提交事务,发生异常则回滚。
到这一步一切都明了了,我需要替换AnnotationTxAdvice实现多数据源的切换。
2. 通过jndi的方式与mysql交互,在.props中定义多个数据源并在AppCore中获取,初始化多个数据源:
# 配置jndi数据源,第一个为默认数据源
hierarchical=test1,test2
test1.packageName=com.eyes.test1.entity
test1.dataSourceProvider=JNDI
test1.jndi=java:comp/env/TEST1
test1.tablePrefix=abc_
test1.tableUppercase=false
test1.columnUppercase=false
# 目录要与默认目录区分开,不能在子目录下
test2.packageName=com.eyes.test1.test2
test2.dataSourceProvider=JNDI
test2.jndi=java:comp/env/test2
test2.tablePrefix=haha_
test2.tableUppercase=false
test2.columnUppercase=false
3. 在重写的AppCore中一次性初始化多个AnnotationTxAdviceSupport放在一个Map中,并在PetiteContainer中注册为Bean。PetiteContainer的作用域也是SingletonScope,可以注册ThreadLocalScope的Bean,但这个map全局只有一个,无需考虑线程问题。
4. 自定义Annotation:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Source {
String value();
}
@Source的作用在于在事务调用之前决定切换的数据源,value为数据源的名称。
5. 定义SourceAdvice,使用ThreadLocalScope的变量存放要使用的manager
public class SourceAdvice implements ProxyAdvice {
@Override
public Object execute() throws Exception {
Class type = ProxyTarget.targetClass();
String methodName = ProxyTarget.targetMethodName();
Class[] methodArgsTypes = ProxyTarget.createArgumentsClassArray();
Method method = type.getMethod(methodName,methodArgsTypes);
Source source = method.getAnnotation(Source.class);
String name = source.value();
PetiteContainer pc = BeanUtil.declared.getProperty(ProxyTarget.target(), PetiteContainer.PETITE_CONTAINER_REF_NAME);
HashMap map = pc.getBean(ANNOTATION_MANAGERS);
AnnotationTxAdviceManager manager = (AnnotationTxAdviceManager) map.get(name);
ThreadAdviceManagerHolder.set(manager); //在这里决定使用哪个数据源管理器
ThreadAdviceManagerHolder.setKey(name);
Object result = ProxyTarget.invoke(); //@Transaction调用后。。。
ThreadAdviceManagerHolder.set(Hierarchical.DEFAULT); //恢复默认数据源
ThreadAdviceManagerHolder.setKey(Hierarchical.DEFAULT_KEY);
return result;
}
}
6. 配置proxetta:
ProxyAspect sourceProxy = new ProxyAspect(SourceAdvice.class,
new MethodAnnotationPointcut(Source.class) {
@Override
public boolean apply(MethodInfo mi) {
return isPublic(mi) &&
isTopLevelMethod(mi) &&
matchClassName(mi, "*Service") &&
super.apply(mi);
}
});
proxetta = ProxyProxetta.withAspects(sourceProxy,txProxy); //使@Source,@Transaction生效
proxetta.setClassLoader(this.getClass().getClassLoader());
7. 调用
@Source("test2")
@Transaction(propagation = PROPAGATION_SUPPORTS,readOnly = false)
public Hi nihaoma(Hi e){
...
return e;
}
总结:
在实现的过程中会遇到一些问题,然后把问题一一解决就OK了。
最好的学习方法就是看源码,参考源码,修改源码。本项目用的是Jodd v3.7.1,Jodd最新的版本是3.8.*,升级到java8了。
下班,回去吃麻麻寄来的粽子。
相关推荐
Jodd是一个全面的Java工具库,它为开发者提供了丰富的功能,包括但不限于对象处理、HTTP客户端、数据库操作、AOP(面向切面编程)支持以及更多实用工具类。在Jodd v5.3.0版本中,这个开源项目继续优化了性能,增强了...
Jodd的源码软件结构清晰,易于理解和扩展,对于想要深入学习Java编程和提高开发效率的开发者来说,Jodd是一个非常有价值的资源。通过研究和使用Jodd,你可以了解到如何设计高效、灵活的工具类库,同时也可以借鉴其...
**网络技术爱好者家园** 和 **红黑联盟 软件说明** 提示我们JODD可能与网络技术和社区支持有关。这可能意味着JODD开发者或用户群体积极参与在线讨论和技术分享,为初学者和经验丰富的开发者提供资源和帮助。`网络...
8. **AOP(面向切面编程)** - Madvoc支持AOP,你可以定义切面来拦截动作执行,进行日志记录、性能监控等操作。 9. **国际化与本地化(Internationalization and Localization)** - 支持通过资源包(Properties...
“Jodd 一套开源的Java微型的框架和大量的工具集”,这个框架集合了多种功能模块,包括 IOC(Inversion of Control)容器、MVC(Model-View-Controller)框架、数据库操作支持、AOP(Aspect-Oriented Programming)...
2. 可以从各种数据源加载Bean, 3. 简化JDBC的接连与代码, 4. 剖析SQL查询, 5. 处理时间与日期, 6. 操作与格式化String, 7. 搜索本地硬盘上的文件, 8. 帮助处理Servlet请求等。 除此之外还包含一个很小,...
2. 可以从各种数据源加载 Bean, 3. 简化 JDBC 的接连与代码, 4. 剖析 SQL 查询, 5. 处理时间与日期, 6. 操作与格式化 String, 7. 搜索本地硬盘上的文件, 8. 帮助处理 Servlet 请求等。 除此之外还包含一个很小...
无论是在简单的数据操作、对象处理还是性能分析方面,Jodd 都能提供强大的支持。如果你希望在项目中提高开发效率,同时保持代码的简洁性,Jodd 是一个值得考虑的选择。通过深入学习和实践,你会发现更多 Jodd 带来的...
赠送源代码:jodd-core-5.1.6-sources.jar; 赠送Maven依赖信息文件:jodd-core-5.1.6.pom; 包含翻译后的API文档:jodd-core-5.1.6-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jodd:jodd-core:5.1.6; ...
最新发布版,集成了所有工具集。...2. 可以从各种数据源加载Bean, 3. 简化JDBC的接连与代码, 4. 剖析SQL查询, 5. 处理时间与日期, 6. 操作与格式化String, 7. 搜索本地硬盘上的文件, 8. 帮助处理Servlet请求等。
获取函数参数名jodd-dboom 数据库访问的轻量级封装,可看作一个简单的ORMjodd-json JSON解析、序列化jodd-vtor 一个基于注解的字段验证框架了解更多: GitHub page (5 min overview): http://oblac.github.io/jodd...
Base64是一种网络上常见的数据编码方式,它将任意二进制数据转化为可打印的ASCII字符,主要用于在不支持二进制传输的环境下传递数据,比如电子邮件系统。Base64编码的基本原理是将每3个8位字节的数据转换为4个6位的...
赠送源代码:jodd-http-3.7.1-sources.jar; 赠送Maven依赖信息文件:jodd-http-3.7.1.pom; 包含翻译后的API文档:jodd-http-3.7.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jodd:jodd-http:3.7.1; ...
赠送源代码:jodd-bean-5.0.13-sources.jar; 赠送Maven依赖信息文件:jodd-bean-5.0.13.pom; 包含翻译后的API文档:jodd-bean-5.0.13-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jodd:jodd-bean:5.0.13;...
赠送源代码:jodd-core-3.7.1-sources.jar; 赠送Maven依赖信息文件:jodd-core-3.7.1.pom; 包含翻译后的API文档:jodd-core-3.7.1-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.jodd:jodd-core:...
Jodd是一个完全免费且开源的Java库,它包含了多个模块,如Http客户端、ORM框架、AOP(面向切面编程)、IoC( inversion of control)容器、Bean工具、日志系统、线程池等。这些模块覆盖了开发中的多个方面,使得Jodd...
赠送源代码:jodd-core-5.1.6-sources.jar; 赠送Maven依赖信息文件:jodd-core-5.1.6.pom; 包含翻译后的API文档:jodd-core-5.1.6-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.jodd:jodd-core:...
赠送源代码:jodd-upload-3.7.1-sources.jar; 赠送Maven依赖信息文件:jodd-upload-3.7.1.pom; 包含翻译后的API文档:jodd-upload-3.7.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jodd:jodd-upload:...
赠送源代码:jodd-http-3.7.1-sources.jar; 赠送Maven依赖信息文件:jodd-http-3.7.1.pom; 包含翻译后的API文档:jodd-http-3.7.1-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.jodd:jodd-...
标题中的"jodd-log-3.6.5-...这两个库都是Java社区中的优秀开源项目,它们的源代码是学习Java编程和库设计的好材料。对于希望在实际项目中应用或者对日期时间处理有特定需求的开发者来说,这两个库都是极具价值的资源。