Spring Boot AOP 简易操作日志管理

AOP (Aspect Oriented Programming) 面向切面编程。

业务有核心业务和边缘业务。
比如用户管理,菜单管理,权限管理,这些都属于核心业务。
比如日志管理,操作记录管理,这些都是边缘业务,可以统一的提出来。

尝试使用SpringBoot +AOP 提出操作记录业务。

github aop_demo

package com.lick.aspect.lang.annotation;

import com.lick.aspect.lang.enums.BusinessType;

import java.lang.annotation.*;

/**
 * 自定义操作记录注解
 */
@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    /**
     * 模块
     */
    public String title() default "";

    /**
     * 功能
     */
    public BusinessType businessType() default BusinessType.OTHER;

}
package com.lick.aspect.lang.enums;

/**
 * 操作状态
 *
 */
public enum BusinessStatus {
    /**
     * 成功
     */
    SUCCESS,

    /**
     * 失败
     */
    FAIL,
}
package com.lick.aspect.lang.enums;

/**
 * 业务操作类型
 */
public enum BusinessType {
    /**
     * 其它
     */
    OTHER,

    /**
     * 新增
     */
    INSERT,

    /**
     * 修改
     */
    UPDATE,

    /**
     * 删除
     */
    DELETE,

    /**
     * 查询列表
     */
    LIST,

    /**
     * 登录
     */
    LOGIN,

    /**
     * 登出
     */
    LOGOUT,
}
package com.lick.aspect.lang;

import com.lick.aspect.lang.annotation.Log;
import com.lick.aspect.lang.enums.BusinessStatus;
import com.lick.domain.OperateLog;
import com.lick.domain.User;
import com.lick.service.OperateLogService;
import com.lick.utils.IpUtils;
import com.lick.utils.ServletUtils;
import com.lick.utils.StringUtils;
import eu.bitwalker.useragentutils.UserAgent;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 操作记录处理
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private OperateLogService operateLogService;

    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);

    //配置织入点
    @Pointcut("@annotation(com.lick.aspect.lang.annotation.Log)")
    public void logPointCut() {
    }

    /**
     * 处理玩请求后执行
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()")
    public void doAfterReturning(JoinPoint joinPoint){
        handleLog(joinPoint,null);
    }

    /**
     * 拦截异常操作
     * @param joinPoint 切点
     * @param e 异常
     */
    @AfterThrowing(value = "logPointCut()",throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint,Exception e){
        handleLog(joinPoint,e);
    }
    protected void handleLog(final JoinPoint joinPoint,final Exception e) {
        try{
            //获得注解
            Log controllerLog = getAnnotation(joinPoint);
            if(controllerLog == null) {
                return;
            }
            UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
            String hostIp = IpUtils.getHostIp();
            String os = userAgent.getOperatingSystem().getName();
            String browser = userAgent.getBrowser().getName();

            OperateLog operateLog = new OperateLog();
            //主机地址
            operateLog.setOperIP(hostIp);
            //事务状态
            operateLog.setStatus(BusinessStatus.SUCCESS.name());
            //浏览器类型
            operateLog.setBrowser(browser);
            //操作系统类型
            operateLog.setOs(os);

            HttpServletRequest request = ServletUtils.getRequest();
            //请求地址
            operateLog.setOperURL(request.getRequestURI());

            HttpSession session = ServletUtils.getSession();
            try {
                User currentUser = (User)session.getAttribute("currentUser");
                //操作人
                operateLog.setOperator(currentUser.getUsername());
            }
            catch(Exception exp) {
                exp.printStackTrace();
            }

            if (e != null)
            {   //事务状态 错误的情况
                operateLog.setStatus(BusinessStatus.FAIL.name());
                //错误消息
                operateLog.setErrorMSG(StringUtils.substring(e.getMessage(), 0, 2000));
            }
           //设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            //操作的方法
            operateLog.setMethod(className + "." + methodName + "()");

            //处理设置注解上的参数
            getControllerMethosDescription(controllerLog,operateLog);

            operateLog.setOperTime(new Date());
            //保存数据库
            operateLogService.insertOperateLog(operateLog);

        }catch (Exception exp){
            //记录本地异常日志
            log.error("==前置通知异常==");
            log.error("异常消息{}",exp.getMessage());
            exp.printStackTrace();
        }
    }
    public void getControllerMethosDescription(Log log, OperateLog operateLog) throws Exception {
        //设置action 动作
        //业务类型
        operateLog.setOperAction(log.businessType().name());
        //设置标题
        //模块标题
        operateLog.setTitle(log.title());

    }

    private Log getAnnotation(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if(method != null) {
            return method.getAnnotation(Log.class);
        }
        return null;
    }

}
package com.lick.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 配置
 */
@Configuration
// 表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
// 指定要扫描的Mapper类的包的路径
@MapperScan(basePackages = "com.lick.mapper")
public class ApplicationConfig {
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <contextName>Aop</contextName>

    <!-- 日志存放路径 -->
    <property name="log.path" value="C:\\aop\\logs" />

    <!--输出到控制台-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)</pattern>
            <charset>utf-8</charset>
        </encoder>
    </appender>

    <!-- 系统模块日志级别控制  -->
    <logger name="com.lick" level="debug" />

    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn" />

    <!--普通日志输出到控制台-->
    <root level="info">
        <appender-ref ref="console" />
    </root>

</configuration>
package com.lick.controller;

import com.lick.aspect.lang.annotation.Log;
import com.lick.aspect.lang.enums.BusinessType;
import com.lick.domain.User;
import com.lick.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Date;
import java.util.List;

@Controller
@RequestMapping(value = "/user/")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping(value = "/add")
    public String add() {
        return "addUser";
    }

    @Log(title="添加用户",businessType = BusinessType.INSERT)
    @PostMapping(value = "/add")
    public String add(User user) {
        user.setCreatedTime(new Date());
        user.setUpdatedTime(new Date());
        userService.insertUser(user);
        return "redirect:/user/list";
    }
    @Log(title="查询用户列表",businessType = BusinessType.LIST)
    @GetMapping(value = "/list")
    public String listUser(ModelMap map) {
        List<User> allUser = userService.findAllUser();
        map.put("userList",allUser);
        return "userList";
    }
}




原文地址:https://www.cnblogs.com/lick468/p/11022050.html

时间: 2024-08-09 06:27:29

Spring Boot AOP 简易操作日志管理的相关文章

【Spring Boot学习之五】日志管理

环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 一.log4j 常见方式:log4j.properties + org.apache.log4j.Logger比如:log4j.properties: log4j.rootLogger=info,error,CONSOLE,DEBUG log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.a

Spring boot学习(六)Spring boot实现AOP记录操作日志

前言 在实际的项目中,特别是管理系统中,对于那些重要的操作我们通常都会记录操作日志.比如对数据库的CRUD操作,我们都会对每一次重要的操作进行记录,通常的做法是向数据库指定的日志表中插入一条记录.这里就产生了一个问题,难道要我们每次在 CRUD的时候都手动的插入日志记录吗?这肯定是不合适的,这样的操作无疑是加大了开发量,而且不易维护,所以实际项目中总是利用AOP(Aspect Oriented Programming)即面向切面编程这一技术来记录系统中的操作日志. 日志分类 这里我把日志按照面向

Spring MVC 中使用AOP 进行统一日志管理--XML配置实现

1.介绍 上一篇博客写了使用AOP进行统一日志管理的注解版实现,今天写一下使用XML配置实现版本,与上篇不同的是上次我们记录的Controller层日志,这次我们记录的是Service层的日志.使用的工程还是原来的那个,具体的Spring mvc 工程搭建暂不介绍.上篇记录controller层日志的时候是将切面类组件叫给spring MVC 进行管理,因为 controller 也是交给spring MVC进行管理的,但是记录service 层日志的时候应该就应该再spring 容器中进行了,

Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理

Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理 本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 spring Aop切面中的@Before @Around等执行顺序与请求参数统一解码 https://www.cnblogs.com/newAndHui/p/11771035.h

Spring Boot AOP解析

Spring Boot AOP 面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. AOP(Aspect Oriented Program) 面向切面编程 在面向切面编程的思想里面,把功能分为核心业务功能和周边功能. 核心业务,比如登陆,增加数据,删除数据都叫核心业务 周边功能,比如性能统计,日志,事务管理等等 周边功能在 Spring Boot 的面向切面编程AOP思想里,即被定义为切面 在面向切

关于Spring Boot 多数据源的事务管理

自己的一些理解:自从用了Spring Boot 以来,这近乎零配置和“约定大于配置”的设计范式用着确实爽,其实对零配置的理解是:应该说可以是零配置可以跑一个简单的项目,因为Spring Boot 有默认的配置,当默认的配置满足不了你的时候,这时候所谓的零配置只是换了一种方式而已,我们都知道程序员最擅长的就是写代码,相比来说xml文件还是有点蛋疼的: 行啊,Spring Boot说你不是擅长写代码,那我就把配置给你转换为写代码的形式,所以你会发现在Spring Boot 中使用@Configura

spring boot配置mybatis和事务管理

spring boot配置mybatis和事务管理 一.spring boot与mybatis的配置 1.首先,spring boot 配置mybatis需要的全部依赖如下: <!-- Spring Boot 启动父依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId>

【Spring Boot】利用 Spring Boot Admin 进行项目监控管理

利用 Spring Boot Admin 进行项目监控管理 一.Spring Boot Admin 是什么 Spring Boot Admin (SBA) 是一个社区开源项目,用于管理和监视 Spring Boot 应用程序.应用程序通过 http 的方式注册到 Spring Boot 管理客户端,或者通过 Spring Cloud 的服务发现机制,然后针对 actuator 接口将数据通过 Vue.js 进行可视化管理. 对于我们来说,我们可以通过 Spring Boot Admin 浏览所有

spring boot aop打印http请求回复日志包含请求体

一.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>