使用aop以及自定义注解实现业务日志的收集(代码片段)

吹灭读书灯一身都是月 吹灭读书灯一身都是月     2022-12-14     665

关键词:

直接上代码

自定义注解:MyLog

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog 
    String value() default "";    //value值是说明,会被记录到数据库里面

自定义日志的实体类SysLog

@Data
@TableName("sys_log")
public class SysLog 
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @TableField(value = "visit_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date visitTime;
    @TableField(value = "execution_time")
    private Long executionTime;
    @TableField(value = "email")
    private String email;
    private String ip;
    private String url;
    private String method;
    /**
     * 日志标题
     */
    private String title;
    private String params;
    /**
     * 请求类型
     */
    private String type;

编写的切面类:LogAspect

@Aspect
@Order(5)
@Component
public class LogAspect 
    private final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Autowired
    SysLogService sysLogService;
    //可以直接注入HttpServletRequest 来获取当前的请求
    @Autowired
    HttpServletRequest request;

    private Date visitTime;

    private Class<?> clazz;

    private Method method;

    private String myLogValue;

    @Pointcut("@annotation(com.example.controller.sys.MyLog)")
    public void pointcut() 
    

    /**
     * 前置通知,在Controller层操作前拦截
     *
     * @param joinPoint 切入点
     */
    @Before("pointcut()")
    public void doBefore(JoinPoint joinPoint) throws NoSuchMethodException 
        // 获取当前调用时间
        visitTime = new Date();
        clazz = joinPoint.getTarget().getClass();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        if (methodSignature == null || methodSignature.getMethod().getAnnotation(MyLog.class) == null) 
            return;
        
        MyLog myLog = methodSignature.getMethod().getAnnotation(MyLog.class);
        myLogValue = myLog.value();
        String methodName = methodSignature.getName();
        Object[] args = joinPoint.getArgs();
        //获取具体执行的方法的Method对象
        if (args == null || args.length == 0) 
            //只能获取无参数的方法
            this.method = clazz.getMethod(methodName);
         else 
            Class<?>[] classArgs = new Class<?>[args.length];
            for (int i = 0; i < args.length; i++) 
                classArgs[i] = args[i].getClass();
            
            this.method = clazz.getMethod(methodName, classArgs);
        
    


    @After("pointcut()")
    public void doAfter(JoinPoint jp) throws Exception 
        long time = System.currentTimeMillis() - visitTime.getTime();
        String url = "";
        /*获取url*/
        if (clazz != null && method != null && clazz != LogAspect.class) 
            Subject currentUser = SecurityUtils.getSubject();
            String username = (String) currentUser.getPrincipal();
            SysLog sysLog = new SysLog();
            sysLog.setVisitTime(visitTime);
            sysLog.setEmail(username);
            sysLog.setUrl(request.getRequestURL().toString());
            sysLog.setExecutionTime(System.currentTimeMillis() - visitTime.getTime());
            //什么类的什么方法
            sysLog.setMethod("[类名]:" + clazz.
                    getName() + ", [方法名]:" + method.getName());
            sysLog.setTitle(myLogValue);
            Object[] args = jp.getArgs();
            if (args == null || args.length == 0) 
                sysLog.setParams("无参数");
            
            //设置不能超过500长度,防止插入数据库抛异常
            String s = Arrays.toString(args);
            if (s.length() > 485) 
                s = s.substring(0, 480);
            
            sysLog.setParams(s);
            sysLog.setType(request.getMethod());
            sysLog.setIp(request.getRemoteAddr());

            System.out.println(sysLog);
            //调用Service完成操作,调用dao将sysLog insert数据库
            sysLogService.save(sysLog);
        

    

ServiceImpl类:

@Service
public class SysLogServiceImpl implements SysLogService 
    @Autowired
    SysLogMapper sysLogMapper;

    @Override
    public void save(SysLog sysLog) 
        sysLogMapper.insert(sysLog);
    
	/**
	 * 这里就是一个简单的分页查询了。PageResultDTO是自定义的分页返回类
	 */
    @Override
    public PageResultDTO<SysLog> pageSysLogs(Long pageNum, Long pageSize) 
        Page<SysLog> page = new Page<>(pageNum, pageSize);
        Page<SysLog> sysLogPage = sysLogMapper.selectPage(page, null);
        return PageUtil.convertToPageResult(sysLogPage);
    


使用时,只要把@MyLog注解标在自己想要记录日志的方法上,就可以了。
例如:

    @MyLog("测试aaa接口的日志输出")
    @PostMapping("/aaa")
    public RetJson<Object> aaa(@RequestBody User user)
        return RetJson.success(user);
    

不过,当我使用AOP之后,发现我代码中使用了Shiro的controller全都404了,很奇怪,后面看别人的博客,改了配置才好了

ShiroConfig中加入配置:

    @Bean
    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() 
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setUsePrefix(true);
        return defaultAdvisorAutoProxyCreator;
    

同时我也在application.yml中加入了配置:

  aop:
    auto: true
    proxy-target-class: true

springboot自定义注解收集操作日志(代码片段)

...0c;那么如何实现简易的日志收集呢。市面上最常见的就是使用自定义注解。本文将介绍如何使用自定义注解收集日志。1.添加自定义注解@Target(ElementType.PARAMETER,ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@int... 查看详情

springboot自定义注解收集操作日志(代码片段)

...0c;那么如何实现简易的日志收集呢。市面上最常见的就是使用自定义注解。本文将介绍如何使用自定义注解收集日志。1.添加自定义注解@Target(ElementType.PARAMETER,ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@int... 查看详情

aop注解实现日志收集(代码片段)

1.问题描述  需要对日常使用对接口进行出入参数、请求结果、请求耗时、请求关键信息等的记录2.解决方案  利用注解标示出接口中的关键信息。利用AOP进行方法前后的拦截记录请求入参以及处理结果。利用SPEL解析参数中... 查看详情

springboot自定义注解+异步+观察者模式实现业务日志保存(代码片段)

...注解进行保存,但是考虑到程序的流畅和效率,我们可以使用异步进行保存,在高并发情况不建议异步,对应一般的管理系统还是可以的,小编最近在spring和springboot源码中看到有很多的监听处理贯穿前后:这就是著名的观察者... 查看详情

实现自定义springaop注解(代码片段)

...接ImplementingaCustomSpringAOPAnnotation1.介绍在本文中,我们将使用Spring中的AOP支持来实现自定义AOP注解。首先,我们将给出AOP的高级概述,解释它是什么及其优点。在此之后,我们将逐步实现我们的注解,逐步建立对AOP概念的更深入... 查看详情

自定义注解结合springaop实现权限,参数校验,日志等等功能(代码片段)

文章目录Aop(AspectOrientProgramming)使用场景实现一些共性需求:1.参数校验实现1.自定义注解参数,集合等等校验注解1.1FiledCheck字段校验注解1.2ListCheck集合校验注解1.3方法参数校验注解ModelCheck1.4参数校验注解2.定义Aop并且通... 查看详情

使用springapi以及自定义类实现aop的一个例子-aop编程

...是spring4,在配置文件上较之之前的版本可能有些不同.  使用s 查看详情

jpom-aop+自定义注解实现操作日志记录

文章目录地址版本源码解析-AOP+自定义注解实现操作日志记录地址Gitee:https://gitee.com/dromara/Jpom官网:https://jpom.io/一款简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件。版本我们以2.8.12为例子,鉴赏学... 查看详情

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

一,使用aop记录方法调用日志  1)使用注解与aop做方法调用日志,只需要把注解添加在要记录的方法上就可以,不会影响代码结构  2)实现思路数据库表建立>>配置需要环境>>自定义注解>>定义切点与操作(包含... 查看详情

基于aop注解实现业务功能的动态配置(代码片段)

一、导入jar包<dependency><!--4.引入AOP--><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency> 二、自定义注解package 查看详情

实现自定义springaop注解(代码片段)

实现自定义SpringAOP注解翻译原文链接ImplementingaCustomSpringAOPAnnotation1.介绍在本文中,我们将使用Spring中的AOP支持来实现自定义AOP注解。Inthisarticle,we’llimplementacustomAOPannotationusingtheAOPsupportinSpring.首先,我们将给出AOP的 查看详情

springboot+aop+自定义注解

  为了记录日志的使用常常需要写大量而又重复的代码,而通过注解的形式可以大量的减少代码量;  一.maven引入AOP的依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>&... 查看详情

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

作为运营除了处理系统生产问题,还要处理大量的用户上报事件,这部分工作占用了大量的人力。所有考虑把一部分事件查询处理做成一个自助平台,让用户自行核查处理。于是就有了用户自助系统。考虑到如何计量这个工具平... 查看详情

springaop自定义注解实现日志管理

...灵活,可扩展的方式了,就拿日志管理来说,用SpringAOP自定义注解形式实现日志管理。废话不多说,直接开始!!!关于配置我还是的再说一遍。 在applicationContext-mvc.xml中要添加的    <mvc:annotation-driven/>&nbs... 查看详情

spring自定义注解

Spring面向切面编程(AOP)的基本用法:基于注解的实现一简介在软件开发中,分散于应用中多出的功能被称为横切关注点(如:事务、安全、缓存等)。通常来讲,这些横切关注点从概念上是与应用的业务逻辑相分离的(但是往... 查看详情

使用springaop自定义注解实现自动记录日志

百度加自己琢磨,以下亲测有效,所以写下来记录,也方便自己回顾浏览加深印象之类,有什么问题可以评论一起解决,不完整之处也请大佬指正,一起进步哈哈(1)首先配置文件:<!--声明自动为spring容器中配置@aspectj切面... 查看详情

[杂记]自定义注解以及反射的应用

...间对于这块有了比较好的理解,故做潦草记录。 项目使用自定义注解和反射主要是为了在webSocket请求发过来的时候,通过请求中 查看详情

springboot系列(二十一):基于aop实现自定义注解且记录接口日志|超级超级详细,建议收藏(代码片段)

👨‍🎓作者:bug菌🎉简介:在CSDN、掘金等社区优质创作者,全网合计6w粉+,对一切技术都感兴趣,重心偏java方向,目前运营公众号[猿圈奇妙屋],欢迎小伙伴们的加入,一起秃头。... 查看详情