前言
之前也学习过validate注解去校验一些参数的必要条件,这回工作中用的时候遇到了一些问题。这里都是使用spring boot框架去做的切面,省去了很多不需要的配置。这里去记录一下。
两个切面
validate注解
这里主要是去使用了hibernate中的注解而去做的切面,之前在博客中写到的整合了两个标准的注解的切面(注意区分下)。看一下切面的代码:
1 | @Aspect |
这个可以去实现validate注解的切面配置。
访问接口信息注解
还有就是参考翟DD博客中的spring boot配置的一个记录访问接口信息的切面,这里在配置了之后遇到了两个问题,去记录一下。
切面配置
1 | @Aspect |
问题1 fastJson去打印入参
在doBefore方法中去做了对方法参数的打印,这里没有思索去用了fastJson去打印参数,但是当去访问一个参数中带有response对象的时,会发生报错。
接口:
1 | //========================= 测试web log切面 ===================== |
报错:
这个错误在网上找了比较久,也跟进去源码看了,reponse的getOutputSteam在走到切面的这个输出的时候,已经被调用过了,会有一个标志位标志其被调用过,这里如果用fastJson去序列化这个response对象,这里会报错。这就提醒我们这里输出参数不能去使用fastJson去序列化。(有的mapping还是会去用到response对象)。修改方法就是可以把输出参数的部分改成Arrays.toString进行输出。
1 | Arrays.toString(joinPoint.getArgs())); |
这里要注意参数内部的toString方法的实现。
request对象获取的问题
这个切面中因为要记录访问的url,所以用到了HttpServletRequest对象,这里获取的方式是:RequestContextHolder.getRequestAttributes();这个实现的原理就是请求到来的时候去使用ThreadLocal放入request对象,所以在@AfterReturning中也可以去使用这个对象(因为这次请求还没有结束)。但是在项目初始化时,这个切面就会被加载一次,此时并没有请求所以ThreadLocal中也不会有这个request对象。
解决办法:我这里去对request对象做了判断,如果是null的话,那么方法直接返回。
这里也可以去写一下@AfterThrowing之后的处理,可以直接throw出去交给统一异常处理。这里注意切面的order属性和数据层面的事务的order大小顺序。order越小,执行的越靠前。
当你的切面order>数据层面的事务order时,执行顺序是:
transaction -> doBefore -> Exception -> @AfterThrowing -> rollback。注意这个时候会造成你的@AfterThrowing内容不生效,一起rollback了。
而当你的切面order < 数据层面事务order时,执行顺序是:
dobefore -> transaction -> exception -> rollback -> @AfterThrowing
所以要配置你的webLog切面的order小一些。在spring boot框架中可以通过@Order(level)在类上加上注解进行order控制。