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";
    }
}




Spring Boot AOP 简易操作日志管理的更多相关文章
- Spring boot AOP 记录请求日志
		
如何将所有的通过url的请求参数以及返回结果都输出到日志中? 如果在controller的类中每个方法名都写一个log输出肯定是不明智的选择. 使用spring的AOP功能即可完成. 1. 在pom. ...
 - 四、spring boot 1.5.4 日志管理
		
spring boot日志默认采用logback进行输出,你可以对logback进行定制化,方法如下: 在resources文件夹下建立logback.xml配置文件 <?xml version ...
 - Spring MVC 中使用AOP 进行统一日志管理--XML配置实现
		
1.介绍 上一篇博客写了使用AOP进行统一日志管理的注解版实现,今天写一下使用XML配置实现版本,与上篇不同的是上次我们记录的Controller层日志,这次我们记录的是Service层的日志.使用的 ...
 - Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理
		
Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理 本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...
 - Spring Boot系列一:默认日志logback配置解析
		
前言 今天来介绍下Spring Boot如何配置日志logback,我刚学习的时候,是带着下面几个问题来查资料的,你呢 如何引入日志? 日志输出格式以及输出方式如何配置? 代码中如何使用? 正文 Sp ...
 - Spring Boot AOP解析
		
Spring Boot AOP 面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. AOP(Aspec ...
 - Spring Boot集成Shrio实现权限管理
		
Spring Boot集成Shrio实现权限管理 项目地址:https://gitee.com/dsxiecn/spring-boot-shiro.git Apache Shiro是一个强大且 ...
 - Spring Boot Logback几种日志详解
		
日志对于应用程序来说是非常重要的,Spring框架本身集成了不少其他工具,我们自身的应用也会使用到第三方库,所以我们推荐在Spring应用中使用SLF4J/Logback来记录日志. SLF4J与Lo ...
 - Spring boot使用log4j打印日志
		
先将maven中spring-boot-starter的日志spring-boot-starter-logging去掉 <dependency> <groupId>org.sp ...
 
随机推荐
- js实现frame框架部分页面的刷新
			
一.先来看一个简单的例子: 下面以三个页面分别命名为frame.html.top.html.bottom.html为例来具体说明如何做. frame.html 由上(top.html)下(bottom ...
 - 【idea】scala&sbt+idea安装配置与测试
			
一.IDEA安装 下载Community版的IDEA,Ultimate是免费试用版(相当于用到后面要给钱的) ideaIC-2019.2.3.tar.gz 解压IDEA: tar -zxvf idea ...
 - CentOS7搭建git服务器
			
在CentOS7上搭建git服务器, 1.在Linux上安装git yum install -y git 验证是否安装成功,出现版本号即成功 git --version 2.创建版本库和用户 创建用户 ...
 - Django中多对多关系的orm表设计
			
作者的管理 1.设计表结构 出版社 书籍 作者 一个出版社出版多个书籍 1对多 书籍和作者的关系:一个作者写多本书,一本书可以是多个作者写.多对多 1)创建一张表,表中多对多的数据关系.使用 多对多 ...
 - ISCC之Re1
			
IDA打开,调试选ELF,跟踪main函数 发现有一个not_the_flag函数,跟进去 这里判断了一下a1的值是否为42,大致判断引号里面的有可能是flag,直接放到Linux下运行 提交不要有任 ...
 - 使用LM386制作Arduino音乐播放器
			
在我们的项目中添加声音或音乐总是会使其看起来更酷一些,听上去更有吸引力.特别是如果您使用的是Arduino开发板,并且有很多空余的引脚,只需要添加一个SD卡模块和一个普通的扬声器即可轻松添加音效.在本 ...
 - python高级特性-列表生成
			
概述 [x *x for x in range(1,11)][k+'='+v for k,v in d.items()] [s.lower() for s in L] 详解 1.单层迭代 >&g ...
 - python中的exec和eval
			
exec 描述 exec 执行储存在字符串或文件中的 Python 语句,相比于 eval,exec可以执行更复杂的 Python 代码. 返回值 exec 返回值永远为 None. 需要说明的是在 ...
 - win32gui.EnumWindows
			
python2 import win32gui, win32con, win32api import time, math, random def _MyCallback( hwnd, extra ) ...
 - bug的编写技巧与级别划分
			
一.bug编写技巧 确.清晰.简洁.完整.一致 二.bug包含的要素 缺陷ID.缺陷标题.测试环境.缺陷发现日期时间.缺陷提交人 缺陷优先级.缺陷严重等级.发现缺陷软件版本.测试类型 缺陷复现步骤.期 ...