相关依赖文件
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--fastjson依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.44</version>
</dependency>
Controller测试类
package com.ljt.demo.controller;
@RestController public class DemoController { @GetMapping("/test/{name}") public String test(@PathVariable String name, @RequestParam String param){ name = "hello "+name+" "+param; return name; } }
AOP方式:
新建类WebcontrollerAop,代码如下:
@Aspect
@Component
public class WebControllerAop {
/**
* 指定切点
* 匹配 com.example.demo.controller包及其子包下的所有类的所有方法
*/
@Pointcut("execution(public * com.ljt.demo.controller.*.*(..))")
public void optlog(){
}
/**
* 前置通知,方法调用前被调用
* @param joinPoint
*/
@Before("optlog()")
public void doBefore(JoinPoint joinPoint){
// System.out.println("我是前置通知,方法执行前调用...");
//获取目标方法的参数信息
Object[] obj = joinPoint.getArgs();
Signature signature = joinPoint.getSignature();
//代理的是哪一个方法
String methodName = signature.getName();
//AOP代理类的名字
String className = signature.getDeclaringTypeName();
MethodSignature methodSignature = (MethodSignature) signature;
String[] strings = methodSignature.getParameterNames();
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest req = attributes.getRequest();
StringBuffer content = new StringBuffer();
content.append("url="+req.getRequestURI());
content.append(" ,paramName=").append(Arrays.toString(strings));
content.append(" ,paramValue=").append( Arrays.toString(joinPoint.getArgs()));
content.append( ", clientIp=").append( req.getRemoteAddr());
content.append(" ,HTTP_METHOD=").append(req.getMethod());
content.append(" ,methodName=").append(methodName);
content.append(" ,methodClassName=").append(className);
System.out.println("AOP方式:"+content);
//设置请求开始时间
req.setAttribute("STARTTIME2", System.currentTimeMillis());
}
/**
* 处理完请求返回内容
* @param ret
* @throws Throwable
*/
@AfterReturning(returning = "ret", pointcut = "optlog()")
public void doAfterReturning(Object ret) throws Throwable {
// 处理完请求,返回内容
// System.out.println("方法的返回值 : " + ret);
}
/**
* 后置异常通知
* @param jp
*/
@AfterThrowing("optlog()")
public void throwss(JoinPoint jp){
System.out.println("方法异常时执行.....");
}
/**
* 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
* @param jp
*/
@After("optlog()")
public void after(JoinPoint jp){
// System.out.println("方法最终执行.....");
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest req = attributes.getRequest();
//当前时间
long currentTime = System.currentTimeMillis();
long startTime = Long.valueOf(req.getAttribute("STARTTIME2").toString());
System.out.println("AOP方式请求耗时:"+(currentTime - startTime)+"ms");
}
/**
* 环绕通知,环绕增强,相当于MethodInterceptor
* @param pjp
* @return
*/
@Around("optlog()")
public Object arround(ProceedingJoinPoint pjp) {
try {
Object o = pjp.proceed();
return o;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
}
拦截器方式:
1.新建拦截器类WebInterceptor实现HandlerInterceptor接口
public class WebInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //请求路劲 String url = request.getRequestURI(); //获取请求参数信息 String paramData = JSON.toJSONString(request.getParameterMap(),SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.WriteMapNullValue); //获取请求客户都IP String clientIp = request.getRemoteAddr(); //请求方法 String methodName = request.getMethod(); // String requestType = request.getHeader("X-Requested-With"); StringBuffer content = new StringBuffer(); content.append("url="+url); content.append(" ,paramData=").append(paramData); content.append( ", clientIp=").append(clientIp); content.append(" ,HTTP_METHOD=").append(methodName); System.out.println("拦截器方式:"+content); //设置请求开始时间 request.setAttribute("STARTTIME", System.currentTimeMillis()); return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { //controller 方法处理完毕后,调用此方法 } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { //页面渲染完毕后调用次方法,通常用来清除某些资源,类似java中的finnally int status = response.getStatus(); //当前时间 long currentTime = System.currentTimeMillis(); long startTime = Long.valueOf(request.getAttribute("STARTTIME").toString()); System.out.println("拦截器方式请求耗时:"+(currentTime - startTime)+"ms"); } }
2.添加拦截器
@Configuration public class MvcConfigurer implements WebMvcConfigurer { //拦截器 public void addInterceptors(InterceptorRegistry registry){ //增加一个拦截器 registry.addInterceptor(new WebInterceptor()).addPathPatterns("/**"); } }
运行测试
- 启动项目
- 浏览器输入地址: http://localhost:8080/test/hello?param=123456
控制台打印输出:
总结:
- 一个controler方式的执行过程中,拦截器最先开始执行,最后执行完毕。
- 对于请求参数的获取,AOP方式更加的完整、准确,可以获取到@PathVariable 注解的参数。 如例子中hello就是一个参数。
- AOP方式对与请求信息获取的更加详细,可以获取到方法名称和所在的类。
完整代码见: https://gitee.com/freide/springboot