通过自定义注解与aop统一存储操作记录

Posted zhlblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过自定义注解与aop统一存储操作记录相关的知识,希望对你有一定的参考价值。

模块开发完成后,接到通知需要添加操作记录功能,看着那一堆接口,如果一个方法一个方法的加,那真是太麻烦了。为了偷懒,就百度了一下,发现可以通过自定义注解和aop的形式来统一添加操作记录,只需要在每个方法上面添加自定义的注解就可以了。我在这里用的是springboot2.0以及jpa,废话不多说,直接上代码~

自定义注解serverLog

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 请输入一段话进行描述
 *
 * @author Holley
 * @create 2018-07-03 14:23
 **/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface serverLog {

    public String comment() default "";
}

aop

import com.springcloud.serviceclient01.dao.OperationDao;
import com.springcloud.serviceclient01.model.Operation;
import com.springcloud.serviceclient01.model.User;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Date;

/**
 * 请输入一段话进行描述
 *
 * @author Holley
 * @create 2018-07-03 16:57
 **/
@Aspect
@Order(2)
@Component
public class TestAop {

    @Autowired
    private OperationDao operationDao;
    /**
      * @Author holley
      * @Description 第一种设置切点的方式
      * 定义切点(添加severLog的方法),log是参数(该切点的serverLog注解的实例变量)
      * @Date 2018/7/3 17:09
      * @Param
      * @return
      */
    @Pointcut("@annotation(log)")
    public void severLog(serverLog log){ }

    /**
      * @Author holley
      * @Description JoinPoint joinPoint参数在所有类型通知中都可直接调用,表示和切面的连接点,可以通过词参数获取切面方法的参数等
      * @Date 2018/7/3 17:55
      * @Param
      * @return
      */
    @After("severLog(log)")
    public void rightback(JoinPoint joinPoint, serverLog log){
        // 可以在此处通过 获取token得到当前登陆人的信息,也可以通过缓存获取,然后存入操作记录
        Operation operation = new Operation();
        operation.setContent(log.comment());
        operation.setCreated(new Date());
        operationDao.save(operation);
        System.out.println("切面的所有参数:" + Arrays.toString(joinPoint.getArgs()));
    }

    /**
      * @Author holley
      * @Description returning 定义该切面(添加了severLog注解的方法)的返回结果
      * @Date 2018/7/3 17:41
      * @Param
      * @return
      */
    @AfterReturning(returning = "u", pointcut = "severLog(log)")
    public void endback(JoinPoint joinPoint,User u,serverLog log){
        System.out.println(u.toString()+"-----------------------"+log.comment());
        System.out.println("切面的所有参数:" + Arrays.toString(joinPoint.getArgs()));
    }

    /**
      * @Author holley
      * @Description 第二种设置切点的方式
      * 第一个星号:表示返回类型,*号表示所有类型
      *  第二个星号:表示设置为切点的类名,*号表示所有的类
      *  第三个星号:表示设置为切点的类的方法名,*号表示该类中所有的方法
      *  括弧里表示方法的参数,两个点表示任何参数
      * @Date 2018/7/3 17:48
      * @Param
      * @return
      */
    @Pointcut("execution(* com.springcloud.serviceclient01.service.impl..*.*(..))")
    public void severTest(){ }

}

controller层

import com.springcloud.serviceclient01.model.User;
import com.springcloud.serviceclient01.service.Helloservice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * 请输入一段话进行描述
 *
 * @author Holley
 * @create 2018-07-03 15:12
 **/
@RestController
@RequestMapping("/hello")
public class HelloController {

    @Autowired
    private Helloservice helloservice;

    @GetMapping("/{sid}")
    public String Hello(@PathVariable("sid") Long sid){
        User u = helloservice.getUserByid(sid);
        return u.toString();
    }

    @GetMapping("/test/{sid}")
    public String test1(@PathVariable("sid") Long sid){
        String name = helloservice.findByUid(sid);
        return name;
    }
    /**
      * @Author holley
      * @Description 注意:使用spring注解将变量直接用/加在地址栏后时,不能传字符串,如:localhost:18762/hello/name/2/川普
      * 正确如下
      *  localhost:18762/hello/name/2?name=川普
      * @Date 2018/7/3 16:19
      * @Param
      * @return
      */
    @GetMapping("/name/{sid}")
    public String test2(@PathVariable("sid") Long sid,@RequestParam("name")String name){
        String p = helloservice.findByUser(sid,name);
        return p;
    }

    /**
      * @Author holley
      * @Description 证明不能传字符串格式的参数
      * @Date 2018/7/3 16:23
      * @Param
      * @return
      */
    /*@GetMapping("/a/{name}")
    public String test3(@PathVariable("name")String name){
        System.out.print(name + "测试成功--------------");
        return name;
    }*/
}

serviceimpl层

import com.springcloud.serviceclient01.aop.serverLog;
import com.springcloud.serviceclient01.dao.UserDao;
import com.springcloud.serviceclient01.model.User;
import com.springcloud.serviceclient01.service.Helloservice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 请输入一段话进行描述
 *
 * @author Holley
 * @create 2018-07-03 14:33
 **/
@Service("helloservice")
public class HelloServiceImpl implements Helloservice{

    @Autowired
    private UserDao userDao;

    @serverLog(comment = "根据id查询用户")
    @Override
    public User getUserByid(Long id) {
        return userDao.getOne(id);
    }
    @Override
    public String findByUid(Long id) {
        return userDao.findByaa(id);
    }

    @Override
    public String findByUser(Long id, String name) {
       return userDao.findUser(id,name);
    }
}

dao层

import com.springcloud.serviceclient01.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;

/**
 * 继承JpaRepository,第二个泛型参数为User类主键的类型
 *
 * @author Holley
 * @create 2018-07-03 14:38
 **/

public interface UserDao extends JpaRepository<User,Long> {

    /**
      * @Author holley
      * @Description 注意:使用jpa时,User不是数据库中的表名,而是实体类的类名
      * @Date 2018/7/3 16:12
      * @Param
      * @return
      */
    @Transactional(timeout = 10)
    @Query("select name from User where uid = ?1")
    String findByaa(Long uid);
    @Transactional(timeout = 10)
    @Query("select password from User where uid = ?1 and name = ?2")
    String findUser(Long uid,String name);
}
import com.springcloud.serviceclient01.model.Operation;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * 继承JpaRepository,第二个泛型参数为User类主键的类型
 *
 * @author Holley
 * @create 2018-07-03 14:38
 **/

public interface OperationDao extends JpaRepository<Operation,Long> {

}

 

model

import javax.persistence.*;

/**
 * 请输入一段话进行描述
 *
 * @author Holley
 * @create 2018-07-03 14:34
 **/
@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long uid;

    private String name;

    private String password;

    @Column(name ="is_opt_required")
    private Integer isOptRequired;

    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getIsOptRequired() {
        return isOptRequired;
    }

    public void setIsOptRequired(Integer isOptRequired) {
        this.isOptRequired = isOptRequired;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", name=‘" + name + ‘‘‘ +
                ", password=‘" + password + ‘‘‘ +
                ", isOptRequired=" + isOptRequired +
                ‘}‘;
    }
}
import javax.persistence.*;
import java.util.Date;

/**
 * 操作表的实体类
 *
 * @author Holley
 * @create 2018-06-05 14:12
 **/
@Entity
public class Operation {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long opid;
    private Long sid;
    private Long oid;
    private Long pid;
    private Long uid;
    private String account;
    private String content;
    private Date created;
    @Transient
    private String orderCode;
    @Transient
    private String pname;
    @Transient
    private String sname;

    public Long getOpid() {
        return opid;
    }

    public void setOpid(Long opid) {
        this.opid = opid;
    }

    public Long getOid() {
        return oid;
    }

    public void setOid(Long oid) {
        this.oid = oid;
    }

    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }

    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Long getSid() {
        return sid;
    }

    public void setSid(Long sid) {
        this.sid = sid;
    }

    public String getOrderCode() {
        return orderCode;
    }

    public void setOrderCode(String orderCode) {
        this.orderCode = orderCode;
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    @Override
    public String toString() {
        return "Operation{" +
                "opid=" + opid +
                ", sid=" + sid +
                ", oid=" + oid +
                ", pid=" + pid +
                ", uid=" + uid +
                ", account=‘" + account + ‘‘‘ +
                ", content=‘" + content + ‘‘‘ +
                ", created=" + created +
                ", orderCode=‘" + orderCode + ‘‘‘ +
                ", pname=‘" + pname + ‘‘‘ +
                ", sname=‘" + sname + ‘‘‘ +
                ‘}‘;
    }
}

参考文档:

https://www.cnblogs.com/acm-bingzi/p/javaAnnotation.html

https://www.zifangsky.cn/788.html

https://blog.csdn.net/qq_34021712/article/details/78680915

经过测试,完全可以跑通,如果有什么问题,欢迎各位大神来拍砖~

以上是关于通过自定义注解与aop统一存储操作记录的主要内容,如果未能解决你的问题,请参考以下文章

JPOM - AOP+自定义注解实现操作日志记录

JPOM - AOP+自定义注解实现操作日志记录

aop日志(记录方法调用日志)

springboot—spring aop 实现系统操作日志记录存储到数据库

用户操作拦截并作日志记录--自定义注解+AOP拦截

自定义注解+AOP记录访问日志