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 简易操作日志管理的更多相关文章

  1. Spring boot AOP 记录请求日志

    如何将所有的通过url的请求参数以及返回结果都输出到日志中? 如果在controller的类中每个方法名都写一个log输出肯定是不明智的选择. 使用spring的AOP功能即可完成. 1. 在pom. ...

  2. 四、spring boot 1.5.4 日志管理

    spring boot日志默认采用logback进行输出,你可以对logback进行定制化,方法如下: 在resources文件夹下建立logback.xml配置文件 <?xml version ...

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

    1.介绍 上一篇博客写了使用AOP进行统一日志管理的注解版实现,今天写一下使用XML配置实现版本,与上篇不同的是上次我们记录的Controller层日志,这次我们记录的是Service层的日志.使用的 ...

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

    Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理   本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...

  5. Spring Boot系列一:默认日志logback配置解析

    前言 今天来介绍下Spring Boot如何配置日志logback,我刚学习的时候,是带着下面几个问题来查资料的,你呢 如何引入日志? 日志输出格式以及输出方式如何配置? 代码中如何使用? 正文 Sp ...

  6. Spring Boot AOP解析

    Spring Boot AOP 面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. AOP(Aspec ...

  7. Spring Boot集成Shrio实现权限管理

    Spring Boot集成Shrio实现权限管理   项目地址:https://gitee.com/dsxiecn/spring-boot-shiro.git   Apache Shiro是一个强大且 ...

  8. Spring Boot Logback几种日志详解

    日志对于应用程序来说是非常重要的,Spring框架本身集成了不少其他工具,我们自身的应用也会使用到第三方库,所以我们推荐在Spring应用中使用SLF4J/Logback来记录日志. SLF4J与Lo ...

  9. Spring boot使用log4j打印日志

    先将maven中spring-boot-starter的日志spring-boot-starter-logging去掉 <dependency> <groupId>org.sp ...

随机推荐

  1. urlib库

    urllib库是python中最基本的网络请求库,可以模拟浏览器的行为,向指定的服务器发送请求,并可以保存服务器返回的数据. urlopen() urllib.request模块提供了最基本的构造ht ...

  2. Js获取url问号(View_Detail?data='+data.zjb_ID+'&'+data.D_Name)传值

    Js逻辑 View_Detail?data='+data.zjb_ID+'&'+data.D_Name <script> $(function () { var url = dec ...

  3. 怎么查看二进制文件内容?linux下nm命令告诉你!

    linux下强大的文件分析工具 -- nm 什么是nm nm命令是linux下自带的特定文件分析工具,一般用来检查分析二进制文件.库文件.可执行文件中的符号表,返回二进制文件中各段的信息. 目标文件. ...

  4. centos 安装vsftp 服务

    安装软件yum install vsftpd -y 启动测试 # systemctl start vsftpd# netstat -nultp | grep 21tcp 0 0 0.0.0.0:21 ...

  5. 思想家:一个http接口的设计

    一个简单的接口,反应出来一些简单的思想. auth_token= xxx post  response (命令) 记住:我们是给第3方提供接口,不是自己使用 问题:平时就知道写代码,文档重视不够,有一 ...

  6. 圆柱模板行业B2B站点打造MIP推送+熊掌号推送+历史普通推送插件

    最近因为做聚合页面http://zhimo.yuanzhumuban.cc/hotkey/list-951.html  内部站点关键词拥有5万的行业词库,所以这么多搜索词库,如何让百度第一时间抓取呢? ...

  7. java设计模式解析(1) Observer观察者模式

      设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析( ...

  8. [JSOI2015]最大公约数

    题意:给一个序列a[1],a[2],a[3]...a[n],求其中连续的子序列A[L],A[L+1],...,A[R],使其权值 W(L,R)=(R-L+1)×gcd(A[L],...,A[R])最大 ...

  9. Java - 框架之 Maven

     一. 下载依赖包 mvn help:system  2. 配置下载路径到 aliy (可选) <!-- 阿里云仓库 --> <mirror> <id>alimav ...

  10. python递归的最大层数?

    Python的最大递归层数是可以设置的,默认的在window上的最大递归层数是 998. 可以通过sys.setrecursionlimit()进行设置,但是一般默认不会超过3925-3929这个范围 ...