通过自定义注解与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

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

原文地址:https://www.cnblogs.com/zhlblogs/p/9260039.html

时间: 2024-10-28 23:26:07

通过自定义注解与aop统一存储操作记录的相关文章

SpringBoot利用自定义注解实现AOP

SpringBoot利用自定义注解实现AOP java 本文主要讲解利用SpringBoot的自定义注解来实现AOP思想. 在开始所有的操作之前,需要导入aop坐标: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 如何自定义注解? 实际上注解本

使用自定义注解和AOP管理shiro权限

一.场景 在使用shiro框架的时候,遇到了这样的需求:本系统有多个用户,每个用户分配不同角色,每个角色的权限也不一致.比如A用户拥有新闻列表的增删改查权限,而B用户只有查看新闻列表的权限,而没有删除.新增.修改的权限,此时有3种方案:1.不给B用户分配删除.新增.修改的菜单,这样用户就无法点击从而无法操作.2.给B用户分配菜单,后台中进行增删改查操作时都要进行权限验证.  3.给B用户分配菜单并且进行操作的时候校验权限. 显然,第2.3种方案比第1中方案要安全.本系统中使用第二种方案. 二.为

基于 自定义注解 和 aop 实现使用memcache 对数据库的缓存 示例

好久没更新blog了,在新公司打拼了两个月,每天都从早忙到晚,学到了很多东西,但是没有时间来更新blog了.... 下面开始讲解这次的主题 公司老大让我研究 ocs 就是阿里云的 开放缓存服务 点击打开链接 其实就是一个memcache的服务 memchech 就是用内存来存放 key -value  在一些情况下就不必频繁的访问 数据库了(其实就是个map) 如何在常用的Dao中方便的使用这个map呢,我首先想到了 aop,然后又想到了自定义注解,那么就开始干吧.... aop动态代理要使用的

自定义注解实现AOP日志记录

自定义注解 package com.annotation; import java.lang.annotation.*; /** *自定义注解 拦截Controller */ @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SystemLog { String module() default ""

Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录

目的: 需要对一些事物的操作进行日志记录,如果在service内进行记录,大量的代码重复,并且维护比较麻烦.所以采用AOP的方式对service进行拦截.使用自定义注解的目的则是判断是否需要记录日志和传递额外的信息. 方式 本次解决方案十分感谢博主-跳刀的兔子的博文 本文绝大部分参考与本文,略有不同,所以做一些整理,博主的文章更详细一些. 1.首先新建自定义注解 @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @

自定义注解-基于AOP

依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 注解1(不带参数): /** * sea test 使用 AOP 自定义注解(不带参数) * @author sea * */ @Target({ElementType.METHOD}) @

Linux下IP SAN共享存储操作记录

一.简单介绍SAN,即存储区域网络(storage area network and SAN protocols),它是一种高速网络实现计算机与存储系统之间的数据传输.常见的分类是FC-SAN和IP-SAN两种.FC-SAN通过光纤通道协议转发scsi协议:IP-SAN通过TCP协议转发scsi协议,也就是IP 地址.存储设备是指一台或多台用以存储计算机数据的磁盘设备,通常指磁盘阵列,主要厂商EMC.日立等. iSCSI(internet SCSI)技术由IBM公司研究开发,是一个供硬件设备使用

参数上使用自定义注解在aop中无法获取到该参数

https://ask.csdn.net/questions/769477 /** * 环绕增强,验证权限 * @param joinPoint 目标对象 * @param authCheck 自定义的注解,Around必须这样写,否则自定义的注解无法传入 * */ @Around("pointAll() && @annotation(authCheck)") public Object before(ProceedingJoinPoint joinPoint, Aut

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

作为运营除了处理系统生产问题,还要处理大量的用户上报事件,这部分工作占用了大量的人力.所有考虑把一部分事件查询处理做成一个自助平台,让用户自行核查处理.于是就有了用户自助系统.考虑到如何计量这个工具平台具体的实现价值,需要做用户操作统计才能给出可信服的数据. 以上就是本文的背景.自助系统的架构就是传统的springmvc+spinrg+mybatis+oracle.想到日志记录首先想到的就是AOP拦截处理.网上相关的技术贴很多.简单的小项目遇到的问题一般度娘都能给解决了~\(≧▽≦)/~ 自定义