学习目标:
Spring中AOP的注解实现方式简单示例
当我们在操作某些功能的时候有可能会发生异常,但是每次发生异常要定位找到原因我们都要到服务器去查询日志才能找到,而且也不能对发生的异常进行统计,从而改进我们的项目
——增加记录操作日志和异常日志的功能。
今天我们就用Spring AOP的思想来实现这个小功能:
学习内容:
下面是写的一个小Demo,供大家参考练习:
Aspect.java
package com.example.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @program: springstudy
* @description:
* @author:
* @create: 2021-04-05 14:57
**/
/**
* 切面
* 通知+切点的集合,定义在什么地方什么时间做什么事情。
*/
@org.aspectj.lang.annotation.Aspect //定义一个切面
@Component
public class Aspect {
/**
* 切点:定义了在“什么地方”进行切入,哪些连接点会得到通知
* execution :切点表达式
*/
@Pointcut("execution(* com.example.controller.*.*(..))")
public void logPointCut(){}
/**
* 通知方法在目标方法调用之前执行
*/
@Before("logPointCut()")
public void beforeAdvice() {
System.out.println("beforeAdvice...");
}
/**
* 通知方法会在目标方法返回或抛出异常后调用
*/
@After("logPointCut()")
public void afterAdvice() {
System.out.println("afterAdvice...");
}
@Around("logPointCut()")
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("before");
try {
proceedingJoinPoint.proceed();
} catch (Throwable t) {
t.printStackTrace();
}
System.out.println("after");
}
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String method = attributes.getRequest().getMethod();
System.out.println("(1)方法名:"+className + "." + methodName );
System.out.println("(2)方法的返回值:"+ jsonResult);
System.out.println("(3)请求类型:" + method);
}
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
System.out.println("e.getMessage():" + e.getMessage());
}
}
UserController.java
package com.example.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @program: springstudy
* @description:
* @author:
* @create: 2021-04-05 15:04
**/
@RestController
public class UserController {
@RequestMapping(value = {"/user","/"})
public String sayHello() throws Exception{
System.out.println("User");
return "admin";
}
}
测试结果
下面是增加了自定义操作日志注解的方式实现,供大家参考:
自定义操作日志注解——OperLog.java
package com.example;
import java.lang.annotation.*;
@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented
public @interface OperLog {
String operModul() default ""; // 操作模块
String operType() default ""; // 操作类型
String operDesc() default ""; // 操作说明
}
切面类——OperLogAspect.java
package com.example;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @program: generate_code
* @description: XXX
* @author:
* @create: 2020-12-31 17:45
**/
@Aspect
@Component
public class OperLogAspect {
@Value("${version}")
private String operVer;
/**
* 设置操作日志切入点 记录操作日志 在注解的位置切入代码
*/
@Pointcut("@annotation(com.example.OperLog)")
public void operLogPointCut(){}
@AfterReturning(pointcut = "operLogPointCut()", returning = "keys")
public void saveOperLog(JoinPoint joinPoint, Object keys){
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
OperationLog operationLog = new OperationLog();
operationLog.setOperId("123"); // 主键ID
//从切面织入点处通过反射机制获取织入点的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点的方法
Method method = signature.getMethod();
//获取操作
OperLog annotation = method.getAnnotation(OperLog.class);
if(null != annotation){
String operModul = annotation.operModul(); //操作模块
String operType = annotation.operType(); //操作类型
String operDesc = annotation.operDesc(); //操作描述
operationLog.setOperModul(operModul);
operationLog.setOperType(operType);
operationLog.setOperDesc(operDesc);
}
//获取请求的类
String className = joinPoint.getTarget().getClass().getName();
//获取请求的方法名
String methodName = method.getName();
methodName = className + "." +methodName;
operationLog.setOperMethod(methodName);
//获取请求的参数
Map<String, String> rtnMap = converMap(request.getParameterMap());
//将参数所在的数组转换成json
String params = JSON.toJSONString(rtnMap);
operationLog.setOperRequestParam(params); //请求参数
operationLog.setOperRespParam(JSON.toJSONString(keys)); // 返回结果
operationLog.setOperUserId("200000001"); //请求用户ID
operationLog.setOperUserName("admin"); //请求用户名称
operationLog.setOperIp("127.0.0.1"); //请求IP
operationLog.setOperUri(request.getRequestURI()); // 请求URI
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
operationLog.setOperCreateTime(df.format(new Date())); // 创建时间
operationLog.setOperVer(operVer); //操作版本
System.out.println(operationLog.toString());
}
/**
* 转换request 请求参数
* @param paramMap
* @return
*/
public Map<String,String> converMap(Map<String,String[]> paramMap){
Map<String,String > rtnMap = new HashMap<String,String>();
for(String key:paramMap.keySet()){
rtnMap.put(key,paramMap.get(key)[0]);
}
return rtnMap;
}
}
OperationLog.java
package com.example;
/**
* @program: generate_code
* @description: X
* @author:
* @create: 2020-12-31 17:55
**/
public class OperationLog {
private String operId;
private String operRequestParam; //请求参数
private String operRespParam; //返回结果
private String operUserId; //请求用户ID
private String operUserName; //请求用户名称
private String operIp; //请求IP
private String operModul; //操作模块
private String operType; //操作类型
private String operDesc; //操作描述
private String operMethod; //请求方法
private String operUri; //请求URI
private String operCreateTime; //创建时间
private String operVer; //操作版本
public String getOperId() {
return operId;
}
public void setOperId(String operId) {
this.operId = operId;
}
public String getOperRequestParam() {
return operRequestParam;
}
public void setOperRequestParam(String operRequestParam) {
this.operRequestParam = operRequestParam;
}
public String getOperRespParam() {
return operRespParam;
}
public void setOperRespParam(String operRespParam) {
this.operRespParam = operRespParam;
}
public String getOperUserId() {
return operUserId;
}
public void setOperUserId(String operUserId) {
this.operUserId = operUserId;
}
public String getOperUserName() {
return operUserName;
}
public void setOperUserName(String operUserName) {
this.operUserName = operUserName;
}
public String getOperIp() {
return operIp;
}
public void setOperIp(String operIp) {
this.operIp = operIp;
}
public String getOperModul() {
return operModul;
}
public void setOperModul(String operModul) {
this.operModul = operModul;
}
public String getOperType() {
return operType;
}
public void setOperType(String operType) {
this.operType = operType;
}
public String getOperDesc() {
return operDesc;
}
public void setOperDesc(String operDesc) {
this.operDesc = operDesc;
}
public String getOperMethod() {
return operMethod;
}
public void setOperMethod(String operMethod) {
this.operMethod = operMethod;
}
public String getOperUri() {
return operUri;
}
public void setOperUri(String operUri) {
this.operUri = operUri;
}
public String getOperCreateTime() {
return operCreateTime;
}
public void setOperCreateTime(String operCreateTime) {
this.operCreateTime = operCreateTime;
}
public String getOperVer() {
return operVer;
}
public void setOperVer(String operVer) {
this.operVer = operVer;
}
@Override
public String toString() {
return "OperationLog{" +
"操作ID='" + operId + '\'' +
", 请求参数='" + operRequestParam + '\'' +
", 返回结果='" + operRespParam + '\'' +
", 请求用户ID'" + operUserId + '\'' +
", 请求用户名称='" + operUserName + '\'' +
", 请求IP='" + operIp + '\'' +
", 操作模块='" + operModul + '\'' +
", 操作类型='" + operType + '\'' +
", 操作描述='" + operDesc + '\'' +
", 请求方法='" + operMethod + '\'' +
", 请求URI='" + operUri + '\'' +
", 创建时间='" + operCreateTime + '\'' +
", 操作版本='" + operVer + '\'' +
'}';
}
}
Result.java
package com.example.result;
/**
* @program: generate_code
* @description: XXX
* @author:
* @create: 2021-01-01 14:16
**/
public class Result {
private String code;
private String msg;
private Object data;
public Result() {
}
public Result(String code, String msg) {
this.code = code;
this.msg = msg;
}
public Result(String code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
UserController.java
package com.example.controller;
import com.example.OperLog;
import com.example.result.Result;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @program: generate_code
* @description: XXX
* @author:
* @create: 2021-01-01 14:11
**/
@RequestMapping(value = "/user")
@RestController
public class UserController {
@RequestMapping(value = "/add",method = RequestMethod.GET)
@OperLog(operModul = "用户管理",operType = "ADD",operDesc = "获取用户信息")
public Result getUserList(){
return new Result("200","操作成功",null);
}
}
测试
OperationLog{操作ID=‘123’, 请求参数=’{}’, 返回结果=’{“code”:“200”,“msg”:“操作成功”}’, 请求用户ID’200000001’, 请求用户名称=‘admin’, 请求IP=‘118.31.187.5’, 操作模块=‘用户管理’, 操作类型=‘ADD’, 操作描述=‘获取用户信息’, 请求方法=‘com.example.controller.UserController.getUserList’, 请求URI=’/user/add’, 创建时间=‘2021-04-05 21:36:52’, 操作版本=‘123’}
本篇文章到这里就基本结束了,如果这篇文章对你有帮助,希望大家能留下你的点赞、 关注、 分享、 留言❤️❤️❤️
![](https://img-blog.csdnimg.cn/2021040521432028.gif#pic_center)