需求:

项目中需要记录用户操作信息,例如用户登陆系统后做了那些操作,需要有具体的日志记录。

解决办法:

1、编写操作记录日志业务类,在使用的方法中调用(一般记录方式)。

2、使用面向切面方式记录日志,例如针对某些业务处理方法进行日志记录。

3、通过注解方式,在调用的业务方法上增加日志类注解。

推荐使用第二、第三中方式,使用灵活,如果不需要日志记录,将切面取消即可,第一种不够灵活。一些介绍使用注解方式编写日志记录。

项目结构如下:

在pom.xml导入依赖包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example.springboot</groupId>
<artifactId>springboot-aop</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>springboot-aop</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.7</java.version>
</properties>

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- log4j 日志记录 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<!--aop依赖包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 引入mybatis 数据库操作包 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<!-- 引入mybatis 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
在application.properties配置文件中增加数据库连接
#server.port=8090

#标示使用的是mysql/oracle/sqlserver
datasource.type=mysql
#mysql数据连接
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
#spring.datasource.max-active=20
#spring.datasource.max-idle=8
#spring.datasource.min-idle=8
#spring.datasource.initial-size=20

#mybatis 配置
# 配置映射文件加载
mybatis.mapper-locations=classpath*:mapper/**/*.xml
# 实体类通过别名使用
#mybatis.type-aliases-package=

自定义注解类

package com.example.springboot.aop.annotation;

import java.lang.annotation.*;

/**
*自定义注解 拦截Controller
*/

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemControllerLog {
String LogAction() default "";
String LogContent() default "";
int ModuleID() default 0;
}
实体类

package com.example.springboot.aop.entity;

public class SystemLogModel {
private String LogAction;
private String LogContent;
private String FlagID;
private String FlagName;
private String LogIP;
private String TimeFlag;
private int ModuleID;

自定义切面类

package com.example.springboot.aop.aspect;

import com.example.springboot.aop.annotation.SystemControllerLog;
import com.example.springboot.aop.dao.SystemLogMapper;
import com.example.springboot.aop.entity.SystemLogModel;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
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.text.SimpleDateFormat;
import java.util.Date;

/**
* 切点类
*/
@Aspect
@Component
public class SystemLogAspect {

// 本地异常日志记录对象
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);

@Autowired
private SystemLogMapper systemLogMapper;

// Controller层切点,针对在业务模块标注SystemControllerLog注解记录日志
@Pointcut("@annotation( com.example.springboot.aop.annotation.SystemControllerLog )")
public void controllerAspect() {
}

/**
* 前置通知 用于拦截Controller层记录用户的操作
*
* @param joinPoint 切点
*/
@Before("controllerAspect()")
public void doBefore(JoinPoint joinPoint) {

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
try {
// 请求的IP
String logIP = request.getHeader("X-Real-IP");
// if (StringUtils.isEmpty(logIP)) {
// logIP = request.getRemoteAddr();
// }
String userID = request.getParameter("UserID");
String userName = request.getParameter("UserName");
// if (StringUtils.isEmpty(userID) || StringUtils.isEmpty(userName)) {
// logger.debug("操作日志-->日志添加:用户名或用户ID为空,返回不添加日志!");
// return;
// }

SystemLogModel slm = getControllerMethodDescription(joinPoint);
slm.setLogIP(logIP);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:MM:ss");
String date = dateFormat.format(new Date());
slm.setTimeFlag(date);
slm.setFlagID(userID);
slm.setFlagName(userName);

// *========控制台输出=========*//
logger.debug("=====注解参数获取开始=====");
logger.debug("请求方法:"
+ (joinPoint.getTarget().getClass().getName() + "."
+ joinPoint.getSignature().getName() + "()"));
logger.debug("操作模块:" + slm.getModuleID());
logger.debug("操作方法:" + slm.getLogAction());
logger.debug("操作内容:" + slm.getLogContent());
logger.debug("请求IP:" + slm.getLogIP());
logger.debug("FlagID:" + slm.getFlagID());
logger.debug("FlagName:" + slm.getFlagName());
// *========数据库日志=========*//
int res = systemLogMapper.saveOrUpdate(slm);
if (res > 0) {
logger.info(">>>>>>>>保存日志成功");
}
} catch (Exception e) {
// 记录本地异常日志
logger.error("前置通知异常,保存日志异常信息:{}", e.getMessage());
}
}

/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
*/
public static SystemLogModel getControllerMethodDescription(
JoinPoint joinPoint) throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
SystemControllerLog log;
SystemLogModel logM = new SystemLogModel();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
log = method.getAnnotation(SystemControllerLog.class);
logM.setModuleID(log.ModuleID());
logM.setLogAction(log.LogAction());
logM.setLogContent(log.LogContent());
break;
}
}
}
return logM;
}
}

mapper接口

package com.example.springboot.aop.dao;

import com.example.springboot.aop.entity.SystemLogModel;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface SystemLogMapper {

//保存日志
public int saveOrUpdate(SystemLogModel systemLogModel);
}
mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.springboot.aop.dao.SystemLogMapper">

<insert id="saveOrUpdate" parameterType="com.example.springboot.aop.entity.SystemLogModel">
insert into test_system_Operation_log(FlagID,FlagName,LogAction,LogContent,LogIP,ModuleID,TimeFlag)
values(#{FlagID},#{FlagName},#{LogAction},#{LogContent},#{LogIP},#{ModuleID},#{TimeFlag})
</insert>

</mapper>
创建controller类

package com.example.springboot.aop.controller;

import com.example.springboot.aop.annotation.SystemControllerLog;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
* @desc aop测试日志记录
* @Author wangsh
* @date 2018/5/7 20:57
*/
@RestController
@RequestMapping("/aop")
public class AopController {

@SystemControllerLog(LogAction = "查询", ModuleID = 12, LogContent = "测试aop示例")
@ResponseBody
@RequestMapping("/hello")
public String hello() {

return "hello";
}
}

创建启动服务类

package com.example.springboot.aop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

//配置扫描指定的包及包下的所以子集
@ComponentScan("com.example.springboot.aop")
@SpringBootApplication
public class SpringbootAopApplication {

public static void main(String[] args) {
SpringApplication.run(SpringbootAopApplication.class, args);
}
}
启动服务测试
浏览器访问: http://localhost:8080//aop/hello

查看数据库记录:

以上就是aop切面及注解的使用。
---------------------
作者:1057718341_h
来源:CSDN
原文:https://blog.csdn.net/seashouwang/article/details/80232811
版权声明:本文为博主原创文章,转载请附上博文链接!

springboot-aop面向切面编程的更多相关文章

  1. 基于SpringBoot AOP面向切面编程实现Redis分布式锁

    基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式 ...

  2. 极简SpringBoot指南-Chapter05-SpringBoot中的AOP面向切面编程简介

    仓库地址 w4ngzhen/springboot-simple-guide: This is a project that guides SpringBoot users to get started ...

  3. Spring Boot2(六):使用Spring Boot整合AOP面向切面编程

    一.前言 众所周知,spring最核心的两个功能是aop和ioc,即面向切面和控制反转.本文会讲一讲SpringBoot如何使用AOP实现面向切面的过程原理. 二.何为aop ​ aop全称Aspec ...

  4. 浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

    简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring ...

  5. AOP 面向切面编程, Attribute在项目中的应用

    一.AOP(面向切面编程)简介 在我们平时的开发中,我们一般都是面对对象编程,面向对象的特点是继承.多态和封装,我们的业务逻辑代码主要是写在这一个个的类中,但我们在实现业务的同时,难免也到多个重复的操 ...

  6. AOP面向切面编程的四种实现

     一.AOP(面向切面编程)的四种实现分别为最原始的经典AOP.代理工厂bean(ProxyFacteryBean)和默认自动代理DefaultAdvisorAutoProxyCreator以及Bea ...

  7. Javascript aop(面向切面编程)之around(环绕)

    Aop又叫面向切面编程,其中“通知”是切面的具体实现,分为before(前置通知).after(后置通知).around(环绕通知),用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被 ...

  8. Method Swizzling和AOP(面向切面编程)实践

    Method Swizzling和AOP(面向切面编程)实践 参考: http://www.cocoachina.com/ios/20150120/10959.html 上一篇介绍了 Objectiv ...

  9. [转] AOP面向切面编程

    AOP面向切面编程 AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...

  10. C# AOP 面向切面编程之 调用拦截

    有时候我们需要在代码中对方法调用进行拦截,并修改参数和返回值,这种操作叫做AOP(面向切面编程) 不过需要注意的是,AOP的效率很慢,在需要高效率场合慎用. 以下是C#的AOP方法: 首先建立一个控制 ...

随机推荐

  1. Android Studio 2.3 解决小米手机调试安装apk失败问题

    在开发者选项里面,拉到底,把miui优化选项去掉就好了. 参考资料 [问题反馈] Android Studio 2.3 在红米note3手机中 调试安装Apk失败

  2. Python内置模块的几点笔记

    1.shutil模块 import shutil shutil.make_archive('shutil_archive_test', 'zip', 'D:\pyworkspace\.idea') m ...

  3. JavaWeb之 JSP:自定义标签的创建和使用

    当jsp的内置标签和jstl标签库内的标签都满足不了需求,这时候就需要开发者自定义标签. 下面我们先来开发一个自定义标签,然后再说它的原理吧! 自定义标签的开发步骤 步骤一 编写一个普通的java类, ...

  4. db2 reorg详解

    reorgchk,检查table index 是否需要重组.reorg 重组,重新放置数据位置.runstats 统计信息,可以优化查询器 一个完整的日常维护规范可以帮助 DBA 理顺每天需要的操作, ...

  5. MiniUI破解方法

    解决JQuery MiniUI前端库到期alert弹窗 MINIUI的到期提示是通过JS的Alert 方法弹出的. 那么我们可以不可以截获所有Alert方法,过滤文本.然后….你们懂得 我们只需要在页 ...

  6. Java8 利用Lambda处理List集合

    List<User> list = new ArrayList<User>(); User user1 = new User("第一位","用户1 ...

  7. javacript onclick事件中传递对象参数

    var user = {id:1, name:'zs', age:20}; var ele = '<a onclick="edit(' + JSON.stringify(user).r ...

  8. 深度残差网络(DRN)ResNet网络原理

    一说起“深度学习”,自然就联想到它非常显著的特点“深.深.深”(重要的事说三遍),通过很深层次的网络实现准确率非常高的图像识别.语音识别等能力.因此,我们自然很容易就想到:深的网络一般会比浅的网络效果 ...

  9. PHP 实现自动加载

    自动载入主要是省去了一个个类去 include 的繁琐,在 new 时动态的去检查并 include 相应的 class 文件. 先上代码: //index.php <?php class Cl ...

  10. How to trigger a Kubernetes cronjob manually-手动触发一个cronjob

    What should you do when you’ve developed and installed a cron job for your Kubernetes application, a ...