失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Spring AOP 自定义注解记录操作日志

Spring AOP 自定义注解记录操作日志

时间:2018-11-25 19:26:31

相关推荐

Spring AOP 自定义注解记录操作日志

1.自定义注释

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Inheritedpublic @interface Log {LogType type() default LogType.SPACE;}

2.type值的枚举

public enum LogType {SPACE(""),INSERT("增加"),DELETE("删除"),UPDATE("修改"),QUERY("查询");private String description;private LogType( String string) {description=string;}public String GetDescription(){return description;}}

3.注释的使用

public abstract class AbstractService<T, M> implements IService<T, M>{@Override@Log(type = LogType.INSERT)public int add(T t){return getMapper().insert(t);}}

4.自定义切面(注意@Aspect 和@Component注解)

@Aspect@Componentpublic class OperateLogAspect {@Autowiredprivate IOperationLogService operationLogService;/*** 后置增强*/@After("@annotation(.reformer.annotation.Log) && @annotation(log)")private void after(JoinPoint joinPoint, Log log) {//读取中的用户HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();Admin user = (Admin) request.getAttribute(Constants.CURRENT_ADMIN);//未登录或登录操作if (null == user) {return;}//没有参数if (joinPoint.getArgs() == null) {return;}OperationLog operationLog = new OperationLog();operationLog.setUserId(user.getId());operationLog.setIpAddr(getIP(request));operationLog.setOpearteTime(new Date());Object[] os = joinPoint.getArgs();//获取类名String className = joinPoint.getTarget().getClass().getSimpleName();//获取方法名String methodName = joinPoint.getSignature().getName();String param = className + "." + methodName + ":";for (int i = 0; i < os.length; i++) {param += "参数[" + i + "]:" + os[i].toString();}operationLog.setOperation(log.type().GetDescription());operationLog.setOperateContent(param);//写入数据库operationLogService.insertSelective(operationLog);return;}//获取请求IPpublic String getIP(HttpServletRequest request) {String ip = request.getHeader("x-forwarded-for");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return ip;}}

</pre><p></p><pre>

5.配置Spring-mvc.xml

proxy-target-class="true"为开启CGLIB动态代理

<!--自定义切面所在包--><context:component-scan base-package=".reformer.service"/><!--识别切面,开启CGLIB动态代理--><aop:aspectj-autoproxy proxy-target-class="true"/>

6.此过程中遇到的麻烦

在数据库写操作日志时报read-only的错误,原因事务配置了read-only,如下:

<!-- 事务管理 通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- 对insert,update,delete 开头的方法进行事务管理,只要有异常就回滚 --><tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/><tx:method name="create*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/><tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/><tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/><tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/><!-- select,count开头的方法,开启只读,提高数据库访问性能 --><tx:method name="select*" read-only="true"/><tx:method name="query*" read-only="true"/><tx:method name="count*" read-only="true"/><tx:method name="find*" read-only="true"/><tx:method name="get*" read-only="true"/><!-- 对其他方法 使用默认的事务管理 --><tx:method name="*"/></tx:attributes></tx:advice>

解决方法:

1.此处设置read-only的地方全部都是查询,可以不记录查询日志,及查询方法前不加自定义注解@Log

2.去掉事务的read-only属性

如果觉得《Spring AOP 自定义注解记录操作日志》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。