使用SpringAOP切面实现对controller的拦截,并对url,参数和返回值记录
来源:互联网 发布:生成式对抗网络 应用 编辑:程序博客网 时间:2024/05/22 00:47
做这个功能之前 先讲一下AOP的环绕通知,因为这个功能我之前也想用springMVC的拦截器实现
AOP的环绕通知、切面的优先级以及重用切入点定义
一、环绕通知
环绕通知是所有通知类型中功能最为强大的, 能够全面地控制连接点. 甚至可以控制是否执行连接点.
对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint . 它是 JoinPoint 的子接口, 允许控制何时执行, 是否执行连接点.
在环绕通知中需要明确调用 ProceedingJoinPoint 的 proceed() 方法来执行被代理的方法. 如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行.
注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即调用 joinPoint.proceed(); 的返回值, 否则会出现空指针异常
(1)环绕通知需要携带 ProceedingJoinPoint 类型的参数.
(2)环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法.且环绕通知必须有返回值, 返回值即为目标方法的返回值
@Around("execution(* com..Spring4.AOP.*.*(..))") public Object aroundMethod(ProceedingJoinPoint pjd){ Object result = null; String methodName = pjd.getSignature().getName(); try { //前置通知 System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs())); //执行目标方法 result = pjd.proceed(); //返回通知 System.out.println("The method " + methodName + " ends with " + result); } catch (Throwable e) { //异常通知 System.out.println("The method " + methodName + " occurs exception:" + e); throw new RuntimeException(e); } //后置通知 System.out.println("The method " + methodName + " ends"); return result;
参考自:http://blog.csdn.net/snow_7/article/details/52077770
url获取必须通过request中获取,怎么获取request呢?
1.RequestContextHolder的使用
RequestContextHolder顾名思义,持有上下文的Request容器.使用是很简单的,具体使用如下:
//两个方法在没有使用JSF的项目中是没有区别的RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();// RequestContextHolder.getRequestAttributes();//从session里面获取对应的值String str = (String) requestAttributes.getAttribute("name",RequestAttributes.SCOPE_SESSION);HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();HttpServletResponse response = ((ServletRequestAttributes)requestAttributes).getResponse();
看到这一般都会想到几个问题:
request和response怎么和当前请求挂钩?
request和response等是什么时候设置进去的?
2.解决疑问
2.1 request和response怎么和当前请求挂钩?
首先分析RequestContextHolder这个类,里面有两个ThreadLocal保存当前线程下的request,关于ThreadLocal可以参考这篇博文
http://www.jianshu.com/p/5675690b351e
后面详细的结果可以看http://blog.csdn.net/zzy7075/article/details/53559902
有了上面两个基础知识我们就可以完成这个功能了
1.先配置切面
<aop:config> <aop:aspect id="OperationRecordAspect" ref="operationRecordAspect"> <aop:pointcut id="recordTask" expression="execution(* com.xx.xx.web.*.*.*(..))"/> <aop:around pointcut-ref="recordTask" method="aroundMethod"/> </aop:aspect></aop:config>
2.写切面类
public class OperationRecordAspect { private static final Logger logger = LoggerFactory.getLogger(OperationRecordAspect.class); @Autowired private IOperationRecordService OperationRecordService; public Object aroundMethod(ProceedingJoinPoint pjd) { Object result = null; //String methodName = pjd.getSignature().getName(); //获取request HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); //请求url String url = request.getRequestURI(); if(StrUtils.isNotNullOrBlank(url)){ try { result = pjd.proceed(); if(url.contains("get")||url.contains("to")||url.contains("search")){ return result; } } catch (Throwable throwable) { logger.error(throwable.toString()); } } logger.debug("拦截了员工从操作,url是:"+url); logger.info("返回的结果是"+result); //logger.info("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs())); //返回通知 //logger.info("The method " + methodName + " ends with " + result); //参数列表 String param = null; Map<String, String[]> parameterMap = request.getParameterMap(); if(parameterMap!=null&& parameterMap.size()>0 ){ param = JSON.toJSONString(parameterMap); if(StrUtils.isNotNullOrBlank(param)){ logger.info("请求中的参数param"+param); } } //操作人 Employee employee = (Employee)request.getSession().getAttribute("employee"); String employeeName = null; String loginName = null; if(employee!=null){ loginName = employee.getLoginName(); employeeName = employee.getEmployeeName(); logger.info("操作员工的登录名:"+loginName+"操作员工的姓名:"+employeeName); } OperationRecord operationRecord = new OperationRecord(); operationRecord.setLoginName(loginName); operationRecord.setEmployeeName(employeeName); operationRecord.setUrl(url); operationRecord.setOperationTime(new Date()); operationRecord.setParam(param); operationRecord.setResult(result.toString()); OperationRecordService.addOperationRecord(operationRecord); return result; }}
这样就实现AOP对SpringMVC controller的拦截,当然,我们的项目是统一管理Exception,所有没有对Exception进行拦截,如果有需要也可以配置
- 使用SpringAOP切面实现对controller的拦截,并对url,参数和返回值记录
- SpringAOP实现拦截Controller请求参数并输出到日志
- 使用Spring mvc 的返回值拦截器对controller的返回值做拦截处理
- Spring AOP 对Spring MVC的Controller切面拦截不起作用
- 使用 aop拦截 springMVC的controller并获取请求参数及返回结果
- SpringAOP使用入门,如何对自定义的注解进行切面编程
- SpringBoot中实现拦截器, 并实现对404和500等错误的拦截。
- SpringAop切面的简单使用
- 自定义Spring的Aop切面类拦截业务请求,并获取到请求的参数名和参数值
- springAOP拦截并打印controller层请求日志---注解方式实现
- SpringMVC 中 jsp 页面对 Controller 返回数据的使用
- SpringAOP拦截Controller总结
- Spring MVC下对Controller 的AOP切面
- SpringMvc中对Controller层进行拦截统计通用的耗时,操作日记记录等。
- springAop实现日志请求参数和返回结果打印
- 使用Spring AOP对url参数进行解密以及对返回结果进行加密
- springmvc中aop对controller切面编程
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- 如何使用优先级视图
- [NOIP2017][luogu3953]逛公园
- 自定义okhttp日志
- OpenCV-Python-Tutorial[5]
- 图之最短路径:弗洛伊德(Floyd)算法
- 使用SpringAOP切面实现对controller的拦截,并对url,参数和返回值记录
- TCP/IP详解卷1:协议(八)【广播和多播,ICMP:Internet组管理协议】
- 当一回诗人,基于TF写古诗
- javascript中数组(Array)对象和字符串(String)对象的常用方法总结
- Tomcat启动问题(debug无法启动,正常可以启动)
- ARM9(nuc972)ISP程序烧录
- Qt之调用zlib压缩与解压缩功能
- 数据结构 第12讲 二叉树的层次遍历
- 知识总结