众所周知微信公众号开发时,请求微信服务器需要携带token,如何在业务更好的使用token呢,引出下文(呵呵呵)。
这里介绍的token是使用readWrite锁的方式获取和释放,没有用这种方法的业务处理本次不做讨论(感觉没有读写锁,token的使用是不可靠的,详情请阅读我的博客‘微信开发-定时获取token,保证线程安全,高可用’),即处理业务前获取token并加锁,处理完毕后又要释放token并解锁,非常不方便那么如何让人更懒一些(懒惰推动科技进步),程序员只实现业务处理而不去管token的获取和释放问题呢?我想到的方法有2种。1:通过代理在方法前后做手脚,2:通过重写spring相关的参数处理类做手脚。此次先介绍第一种方法,第二种待续。。
首先使用切面是代理的最好选择,先配置好切面类在,在方法前注入token,方法完毕后释放token(包括异常情况),先配置一个切面类
@Aspect
@Order(1)
@Component
public class WeChatAspect {
//声明切面,使用方法同spring
@Pointcut("execution(* com.ccx.*.controller..*Controller.*(..))")
//需要加上
public void WeChatAspect() { }
//spring容器工具栏(上篇有介绍到)
@Autowired
private SpringContextsUtil springContextsUtil;
//前置方法
@Before("WeChatAspect()")
public void SetTokenBefore(JoinPoint point) {
Object[] args = point.getArgs();
if (null != args) {
for (Object arg : args) {
//实现思路同controler的参数注入
//用户写什么参数我们尽可能的为他注入,这里注入我们的Token类
if (arg.getClass().toString().equals(Token.class.toString())) {
//如果参数列表声明的Token类,那么我们为他注入
arg = springContextsUtil.getBean("token");
}
}
}
}
//后置方法
@AfterReturning("WeChatAspect()")
public void relaseTokenAfterReturn() {
//通过容器获取Token类
Token token = springContextsUtil.getBean("token", Token.class);
token.releaseTokenAndUnlock();
}
//异常也要释放
@AfterThrowing("WeChatAspect()")
public void relaseTokenAfterThrowing() {
//通过容器获取Token类
Token token = springContextsUtil.getBean("token", Token.class);
token.releaseTokenAndUnlock();
}
}
切面写好了再看看Token类,这里并不是真正的工具类,只是为了模拟效果写的,需要其他的东西自己搞定
@Component("token")
public class Token {
private static String token = "XXXXXXXXXXXXXXXXXXXXXXXX";
private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
/*
* @Description: 获取token的同时加读锁
* @Author: hendiaome
* @CreateDate: ${DATE} ${TIME}
* @Param: v1.0
* @Return token
*/
public String getTokenAndLock() {
lock.readLock().lock();
return token;
}
/*
* @Description: 释放token的同时关闭读锁
* @Author: hendiaome
* @CreateDate: ${DATE} ${TIME}
* @Param: v1.0
* @Return token
*/
public void releaseTokenAndUnlock() {
lock.readLock().unlock();
}
public void writeLock() {
lock.writeLock().lock();;
}
public void writeUnLock() {
lock.writeLock().unlock();;
}
}
最简单的就是这样,最后是controller,也是demo级别的,莫怪。
@Controller
@RequestMapping("/wechat")
public class WeChatController {
@RequestMapping("/test")
@ResponseBody
public Object Test(Token token) {
String tokenAcess = token.getTokenAndLock();
//拿着token去做自己的业务处理去吧
return "OK";
}
}
好了以上就是简单的实现了token的自动注入和释放,应该注意的是在释放token的时候,应该判读此方法是否注入了token,,如果没有声明token,而后置方法一味的去释放,是我们不想要的结果,所以应该加入判断,推荐使用threadlocal,仅当方法声明注入的时候,再释放。