博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Springboot AOP处理日志信息录入
阅读量:2048 次
发布时间:2019-04-28

本文共 7653 字,大约阅读时间需要 25 分钟。

现在凡是企业级的或者稍微大点项目,基本都需要日志管理. 我这边在springboot基础上做了个日志信息记录到数据库的功能,在这里备份一下,以后有需要就省的再重写了.

首先我们得准备好所需要的jar,当然了这里是pom.xml:

org.springframework.boot
spring-boot-starter-aop
org.springframework.boot
spring-boot-starter-web

这里的web是最基本的,后面也会用到的.

其实日志管理实现的方式有很多种,拦截器,aop切面等等,我这边用的就是aop切面实现的.既然要用到切面实现,那就必须要有切点,我这边是以自定义注解为切点(当然也可以切到指定路径下的文件夹哦)
下面为自定义切点:

package com.jshh.busness.LogAOP;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)     // 这个注解是用来规定注解的作用范围的,这里定义为method方法级别.@Retention(RetentionPolicy.RUNTIME)    // 这个注解可以理解为定义注解的生命周期,这里标识一直存在(编译和运行之后)public @interface LogAnnotation {
// 定义注解参数 public String operateContent() default ""; public String operateType() default "";}

这边简单的介绍下@Target和@Retention注解吧.

@Target 用来取值 注解使用范围:

METHOD  可用于方法上    TYPE    可用于类或者接口上    ANNOTATION_TYPE 可用于注解类型上(被@interface修饰的类型)    CONSTRUCTOR 可用于构造方法上    FIELD   可用于域上    LOCAL_VARIABLE  可用于局部变量上    PACKAGE 用于记录java文件的package信息    PARAMETER   可用于参数上

@Retention

1、RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;2、RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;3、RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;

回到正题,注解弄完了,现在要弄一个实体类来封装所需要的日志信息:

import com.jshh.entity.CommenEntity;import lombok.Getter;import lombok.Setter;@Setter@Getterpublic class LogEntity implements CommenEntity {
private String uuid; private String userid; private String username; private String ip; private String status; private String operatetype; private String detail; private String operatetime; private String operatecontent; private String subsystemid;}

基础准备都弄完了,现在就要去做切面的实现类了.废话不多说代码附上:

package com.jshh.busness.LogAOP;import com.alibaba.fastjson.JSON;import com.jshh.client.DataCommenServerClient;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.*;import org.aspectj.lang.reflect.CodeSignature;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.lang.reflect.Method;import java.util.HashMap;import java.util.Map;import java.util.UUID;/** * @author  一只会飞的猪 * @desc    日志录入aop实现类 * @time    2018/8/28 * */@Component@Aspectpublic class LogAspectClass {    @Autowired    LogAddService logAddService;    // 这里定义下切点的位置,也就是刚才我们自定义的注解.    @Pointcut("@annotation(com.jshh.busness.LogAOP.LogAnnotation)")    public  void mypointcut(){}    //消息通知 @AfterReturning,在切点方法运行之后触发returning 为目标函数返回值    @AfterReturning(returning = "result",value = "mypointcut()")    public  void addlog(JoinPoint joinPoint,Object result){        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();        HttpServletRequest request = attributes.getRequest();        //从切面织入点处通过反射机制获取织入点处的方法        MethodSignature signature = (MethodSignature) joinPoint.getSignature();        //获取切入点所在的方法        Method method = signature.getMethod();        String operatetype ="";         //  定义操作方式        String operatecontent="";       //  定义操作内容        // 获取注解中的操作方式        if(method!=null&&!"".equals(method)){            // 获取自定义注解操作            LogAnnotation  logAnnotation = method.getAnnotation(LogAnnotation.class);            // 获取用户操作方式             operatetype = logAnnotation.operateType();            // 获取用户操作内容             operatecontent = logAnnotation.operateContent();        }        // 获取请求的类名        String classname = joinPoint.getTarget().getClass().getName();        // 获取请求的方法名        String methodname = classname+"."+method.getName();        // 获取请求方式        String Method = request.getMethod();        // 获取请求url        String URL = request.getRequestURI().toString();        // 获取请求的ip地址        String IP  = request.getRemoteAddr();        // 获取userid        String userid = request.getParameter("userid");        // 获取子系统id        String subsystemid = request.getParameter("subsystemid");        // 生成uuid        String uuid = UUID.randomUUID().toString();        // 获取请求的参数        String argsname[] = ((CodeSignature) joinPoint.getSignature()).getParameterNames();        Map
parammap = new HashMap<>(); if(argsname.length>0){ parammap= getParam(joinPoint,argsname,methodname); } String detail = JSON.toJSONString(parammap); // 获取操作状态 Map
statusmap = new HashMap<>(); String status=""; statusmap = (Map
) result; Integer code= (Integer)statusmap.get("code"); if(code==0){ status = "失败"; }else{ status = "成功"; } // 日志实体类封装 LogEntity logEntity = new LogEntity(); logEntity.setUserid(userid); logEntity.setUuid(uuid); logEntity.setIp(IP); logEntity.setStatus(status); logEntity.setOperatetype(operatetype); logEntity.setOperatecontent(operatecontent); logEntity.setDetail(detail); logEntity.setSubsystemid(subsystemid); logAddService.addLogInfo(logEntity); System.out.println("aop+++++++++++++++++++++切面++++++++++++++++++++"); System.out.println("用户操作方式:----------"+operatetype); System.out.println("用户操作内容:----------"+operatecontent); System.out.println("请求方式:-------------"+Method); System.out.println("请求地址url:----------"+IP+URL); System.out.println("请求ip地址:------------"+IP); System.out.println("请求参数:------------"+request.getParameterNames().toString()); System.out.println("请求参数:============"+request.getQueryString()); System.out.println("请求方法名:============"+methodname); System.out.println("请求userid:============"+userid); System.out.println("返回参数:============"+detail); System.out.println("返回结果状态:============"+status); System.out.println("返回结果:============"+logEntity.toString()); } // 处理参数格式,并返回需要的参数 public static Map
getParam(JoinPoint joinPoint,String argsname[],String methodname) { Map
detailmap = new HashMap<>(); Map
map = new HashMap<>(); Map
mapCODE = new HashMap<>(); // 获取参数值 Object args[] = joinPoint.getArgs(); // 获取参数名 argsname = ((CodeSignature) joinPoint.getSignature()).getParameterNames(); String paramsString = ""; for(int i=0; i < argsname.length; i++) { if (!argsname[i].equals("model")) { map.put(argsname[i], args[i]); } } detailmap.put("method",methodname); detailmap.put("params",map); System.out.println("detail:====="+detailmap.toString()); return detailmap; }}

最后添加一个controller:

@GetMapping("queryRoleByUserid")    @LogAnnotation(operateType = "角色",operateContent = "根据用户id查询角色相关信息")    public Model queryRoleByUserid(Model model, @RequestParam("userid") String userid) throws Exception {        boolean ret = true;        String msg = "";        Object result = null;        try {            result = userService.queryRoleByUserid(userid);        } catch (Exception e) {            ret = false;            msg = e.getMessage();            e.printStackTrace();        }        model = buildModel(model, ret, result, msg);        return model;    }

至于保存数据的方法这个就不用多说了吧,该咋保存就咋保存,除了这个方法,其他代码拷贝就能用的哦.

整个操作,不需要编写什么配置文件的,以前的ssm的xml配置,现在都是几个注解搞定的事.

转载地址:http://knhof.baihongyu.com/

你可能感兴趣的文章
国内外helm源记录
查看>>
牛客网题目1:最大数
查看>>
散落人间知识点记录one
查看>>
Leetcode C++ 随手刷 547.朋友圈
查看>>
手抄笔记:深入理解linux内核-1
查看>>
内存堆与栈
查看>>
Leetcode C++《每日一题》20200621 124.二叉树的最大路径和
查看>>
Leetcode C++《每日一题》20200622 面试题 16.18. 模式匹配
查看>>
Leetcode C++《每日一题》20200625 139. 单词拆分
查看>>
Leetcode C++《每日一题》20200626 338. 比特位计数
查看>>
Leetcode C++ 《拓扑排序-1》20200626 207.课程表
查看>>
Go语言学习Part1:包、变量和函数
查看>>
Go语言学习Part2:流程控制语句:for、if、else、switch 和 defer
查看>>
Go语言学习Part3:struct、slice和映射
查看>>
Go语言学习Part4-1:方法和接口
查看>>
Leetcode Go 《精选TOP面试题》20200628 69.x的平方根
查看>>
Leetcode C++ 剑指 Offer 09. 用两个栈实现队列
查看>>
Leetcode C++《每日一题》20200707 112. 路径总和
查看>>
Leetcode C++ 《第198场周赛-2》 1519. 子树中标签相同的节点数
查看>>
Leetcode C++ 《第199场周赛》
查看>>