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

1.自定义注释

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @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
@Component
public class OperateLogAspect {

    @Autowired
    private IOperationLogService operationLogService;

    /**
     * 后置增强
     */
    @After("@annotation(cn.com.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;
    }

    //获取请求IP
    public 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="cn.com.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属性







  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值