心之所向,素履以往。生如逆旅,一苇以航。
面试经常会被问到“你对spring是怎样理解的。”谈及spring,就不得不说它的两大核心spring的IOC(控制反转)和AOP(面向切面)。一直对于AOP的理解仅仅只是局限与它的基本概念,最近在实际项目中刚好用到,抽空整理下查找到的资料。
什么是AOP
AOP(Aspect-OrientedProgramming,面向切面编程),是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。使用AOP,可以将一些重复性的操作提取到主程序之外,这样可以降低模块之间的耦合度,使系统容易扩展同时也能使代码得到更好的复用。
AOP的主要应用场景为:日志记录,权限验证,接口调用情况监控,系统统一异常处理…
aop实践
本文主要使用aop面向切面的特点来实现监控接口的调用详情,以及系统统一的异常处理。
pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
具体实现
创建SectionMonitor类来进行接口调用监控
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
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.util.Enumeration;
/*
*@name springboot AOP切面监控接口调用详情
*@author: lyh_liu
*@create 2020-05-19
*
**/
@Aspect
@Component
public class SectionMonitor {
private static final ThreadLocal<Long> timeTreadLocal = new ThreadLocal<>();
@Pointcut("execution(* com.lyh.aopdemo.controller..*.*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void log() {
}
@Before("log()")
public void before(JoinPoint joinPoint) {
timeTreadLocal.set(System.currentTimeMillis());
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//获取请求的request
HttpServletRequest request = attributes.getRequest();
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//获取被拦截的方法
Method method = methodSignature.getMethod();
//获取被拦截的方法名
String methodName = method.getName();
System.out.println("接口方法名称:" + methodName + "()");
//获取所有请求参数key和value
String keyValue = getReqParameter(request);
System.out.println("url = "+ request.getRequestURL().toString());
System.out.println("方法类型 = "+ request.getMethod());
System.out.println("请求参数 key:value = "+ keyValue);
}
@After("log()")
public void after() {
System.out.println("aop的after()方法");
}
//controller请求结束返回时调用
@AfterReturning(returning = "result", pointcut = "log()")
public Object afterReturn(Object result) {
System.out.println("返回值result ="+ result.toString());
long startTime = timeTreadLocal.get();
double callTime = (System.currentTimeMillis() - startTime) / 1000.0;
System.out.println("调用接口共花费时间time = "+ callTime+" s");
return result;
}
/**
* 获取所有请求参数,封装为map对象
*
* @return
*/
public Map<String, Object> getParameterMap(HttpServletRequest request) {
if (request == null) {
return null;
}
Enumeration<String> enumeration = request.getParameterNames();
Map<String, Object> parameterMap = new HashMap<String, Object>();
StringBuilder stringBuilder = new StringBuilder();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getParameter(key);
String keyValue = key + " : " + value + " ; ";
stringBuilder.append(keyValue);
parameterMap.put(key, value);
}
return parameterMap;
}
public String getReqParameter(HttpServletRequest request) {
if (request == null) {
return null;
}
Enumeration<String> enumeration = request.getParameterNames();
//StringBuilder stringBuilder = new StringBuilder();
JSONArray jsonArray = new JSONArray();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getParameter(key);
JSONObject json = new JSONObject();
json.put(key, value);
jsonArray.add(json);
}
return jsonArray.toString();
}
}
@Pointcut("execution(* com.lyh.aopdemo.controller….(…))是用来设置具体的切面位置。具体的介绍可参考:Pointcut表达式介绍
controller层
@Controller
@RequestMapping("/text")
public class TestController {
@RequestMapping(value="/aspectJMethod",method = RequestMethod.POST)
public String aspectJMethod(){
return "hello AOP";
}
}
注:在接口使用注解@PostMapping或@GetMapping时aop时会出现切面不起作用需使用@RequestMapping。
2020 在学习的道路勇往直前。
版权声明:本文为LYH_Loner原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。