在开始之前,我们先把需要的jar包添加到工程里。新增Maven依赖如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
接下来,我们进入正题。这里的涉及的通知类型有:前置通知、后置最终通知、后置返回通知、后置异常通知、环绕通知,下面我们就具体的来看一下怎么在SpringBoot中添加这些通知。
首先我们先创建一个Aspect切面类:
@Component
@Aspect
public class WebControllerAop {
}
指定切点:
//匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法
@Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
public void executeService(){
}
接着我们再创建一个Controller请求处理类:
package com.zkn.learnspringboot.web.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by zkn on 2016/11/19.
*/
@RestController
@RequestMapping("/aop")
public class AopTestController {
}
前置通知
配置前置通知:
/**
* 前置通知,方法调用前被调用
* @param joinPoint
*/
@Before("executeService()")
public void doBeforeAdvice(JoinPoint joinPoint){
System.out.println("我是前置通知!!!");
//获取目标方法的参数信息
Object[] obj = joinPoint.getArgs();
//AOP代理类的信息
joinPoint.getThis();
//代理的目标对象
joinPoint.getTarget();
//用的最多 通知的签名
Signature signature = joinPoint.getSignature();
//代理的是哪一个方法
System.out.println(signature.getName());
//AOP代理类的名字
System.out.println(signature.getDeclaringTypeName());
//AOP代理类的类(class)信息
signature.getDeclaringType();
//获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
//如果要获取Session信息的话,可以这样写:
//HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
Enumeration<String> enumeration = request.getParameterNames();
Map<String,String> parameterMap = Maps.newHashMap();
while (enumeration.hasMoreElements()){
String parameter = enumeration.nextElement();
parameterMap.put(parameter,request.getParameter(parameter));
}
String str = JSON.toJSONString(parameterMap);
if(obj.length > 0) {
System.out.println("请求的参数信息为:"+str);
}
}
注意:这里用到了JoinPoint和RequestContextHolder。通过JoinPoint可以获得通知的签名信息,如目标方法名、目标方法参数信息等。通过RequestContextHolder来获取请求信息,Session信息。
接下来我们在Controller类里添加一个请求处理方法来测试一下前置通知:
@RequestMapping("/testBeforeService.do")
public String testBeforeService(String key,String value){
return "key="+key+" value="+value;
}
前置通知拦截结果如下所示:
后置返回通知
配置后置返回通知的代码如下:
/**
* 后置返回通知
* 这里需要注意的是:
* 如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
* 如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
* returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
* @param joinPoint
* @param keys
*/
@AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys")
public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
System.out.println("第一个后置返回通知的返回值:"+keys);
}
@AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argNames = "keys")
public void doAfterReturningAdvice2(String keys){
System.out.println("第二个后置返回通知的返回值:"+keys);
}
Controller里添加响应的请求处理信息来测试后置返回通知:
@RequestMapping("/testAfterReturning.do")
public String testAfterReturning(String key){
return "key=: "+key;
}
@RequestMapping("/testAfterReturning01.do")
public Integer testAfterReturning01(Integer key){
return key;
}
当发送请求为:http://localhost:8001/aop/testAfterReturning.do?key=testsss&value=855sss时,处理结果如图所示:
当发送请求为:http://localhost:8001/aop/testAfterReturning01.do?key=55553&value=855sss时,处理结果如图所示:
后置异常通知
后置异常通知的配置方式如下:
/**
* 后置异常通知
* 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
* throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,
* 对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
* @param joinPoint
* @param exception
*/
@AfterThrowing(value = "executeService()",throwing = "exception")
public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
//目标方法名:
System.out.println(joinPoint.getSignature().getName());
if(exception instanceof NullPointerException){
System.out.println("发生了空指针异常!!!!!");
}
}
Controller里配置响应的请求处理类:
@RequestMapping("/testAfterThrowing.do")
public String testAfterThrowing(String key){
throw new NullPointerException();
}
后置异常通知方法的处理结果如下所示:
后置最终通知
后置最终通知的配置方式如下:
/**
* 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
* @param joinPoint
*/
@After("executeService()")
public void doAfterAdvice(JoinPoint joinPoint){
System.out.println("后置通知执行了!!!!");
}
Controller类配置相应的请求处理类:
@RequestMapping("/testAfter.do")
public String testAfter(String key){
throw new NullPointerException();
}
@RequestMapping("/testAfter02.do")
public String testAfter02(String key){
return key;
}
当发送请求为:http://localhost:8001/aop/testAfter.do?key=55553&value=855sss
当发送请求为:http://localhost:8001/aop/testAfter02.do?key=55553&value=855sss
环绕通知
环绕通知的配置方式如下:
/**
* 环绕通知:
* 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。
* 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
*/
@Around("execution(* com.zkn.learnspringboot.web.controller..*.testAround*(..))")
public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName());
try {
Object obj = proceedingJoinPoint.proceed();
return obj;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
Controller对应的请求处理类如下:
@RequestMapping("/testAroundService.do")
public String testAroundService(String key){
return "环绕通知:"+key;
}
当发送请求为:http://localhost:8001/aop/testAroundService.do?key=55553
当发送请求为:http://localhost:8001/aop/testAfter02.do?key=55553&value=855sss时,不符合环绕通知的切入规则,所以环绕通知不会 执行。
完整的AOP配置代码如下:
package com.zkn.learnspringboot.aop;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
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 javax.servlet.http.HttpSession;
import java.util.Enumeration;
import java.util.Map;
/**
* Created by zkn on 2016/11/18.
*/
@Component
@Aspect
public class WebControllerAop {
//匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法
@Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
public void executeService(){
}
/**
* 前置通知,方法调用前被调用
* @param joinPoint
*/
@Before("executeService()")
public void doBeforeAdvice(JoinPoint joinPoint){
System.out.println("我是前置通知!!!");
//获取目标方法的参数信息
Object[] obj = joinPoint.getArgs();
//AOP代理类的信息
joinPoint.getThis();
//代理的目标对象
joinPoint.getTarget();
//用的最多 通知的签名
Signature signature = joinPoint.getSignature();
//代理的是哪一个方法
System.out.println(signature.getName());
//AOP代理类的名字
System.out.println(signature.getDeclaringTypeName());
//AOP代理类的类(class)信息
signature.getDeclaringType();
//获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
//如果要获取Session信息的话,可以这样写:
//HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
Enumeration<String> enumeration = request.getParameterNames();
Map<String,String> parameterMap = Maps.newHashMap();
while (enumeration.hasMoreElements()){
String parameter = enumeration.nextElement();
parameterMap.put(parameter,request.getParameter(parameter));
}
String str = JSON.toJSONString(parameterMap);
if(obj.length > 0) {
System.out.println("请求的参数信息为:"+str);
}
}
/**
* 后置返回通知
* 这里需要注意的是:
* 如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
* 如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
* returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
* @param joinPoint
* @param keys
*/
@AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys")
public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
System.out.println("第一个后置返回通知的返回值:"+keys);
}
@AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argNames = "keys")
public void doAfterReturningAdvice2(String keys){
System.out.println("第二个后置返回通知的返回值:"+keys);
}
/**
* 后置异常通知
* 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
* throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,
* 对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
* @param joinPoint
* @param exception
*/
@AfterThrowing(value = "executeService()",throwing = "exception")
public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
//目标方法名:
System.out.println(joinPoint.getSignature().getName());
if(exception instanceof NullPointerException){
System.out.println("发生了空指针异常!!!!!");
}
}
/**
* 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
* @param joinPoint
*/
@After("executeService()")
public void doAfterAdvice(JoinPoint joinPoint){
System.out.println("后置通知执行了!!!!");
}
/**
* 环绕通知:
* 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。
* 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
*/
@Around("execution(* com.zkn.learnspringboot.web.controller..*.testAround*(..))")
public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName());
try {//obj之前可以写目标方法执行前的逻辑
Object obj = proceedingJoinPoint.proceed();//调用执行目标方法
return obj;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
}
完整的Controller类代码如下:
package com.zkn.learnspringboot.web.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by zkn on 2016/11/19.
*/
@RestController
@RequestMapping("/aop")
public class AopTestController {
@RequestMapping("/testBeforeService.do")
public String testBeforeService(String key,String value){
return "key="+key+" value="+value;
}
@RequestMapping("/testAfterReturning.do")
public String testAfterReturning(String key){
return "key=: "+key;
}
@RequestMapping("/testAfterReturning01.do")
public Integer testAfterReturning01(Integer key){
return key;
}
@RequestMapping("/testAfterThrowing.do")
public String testAfterThrowing(String key){
throw new NullPointerException();
}
@RequestMapping("/testAfter.do")
public String testAfter(String key){
throw new NullPointerException();
}
@RequestMapping("/testAfter02.do")
public String testAfter02(String key){
return key;
}
@RequestMapping("/testAroundService.do")
public String testAroundService(String key){
return "环绕通知:"+key;
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# SpringBoot集成Spring
# AOP
# SpringBoot集成AOP
# Springboot接口项目如何使用AOP记录日志
# SpringBoot使用AOP+注解实现简单的权限验证的方法
# SpringBoot AOP使用笔记
# 浅谈springboot之JoinPoint的getSignature方法
# 第一个
# 返回值
# 的是
# 抛出
# 第二个
# 时才
# 我是
# 就会
# 最多
# 什么时候
# 不为
# 所示
# 需要注意
# 将把
# 其子
# 如图所示
# 发生了
# 不符合
# 先把
# 可以获得
相关文章:
代刷网站制作软件,别人代刷火车票靠谱吗?
建站主机CVM配置优化、SEO策略与性能提升指南
香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧
手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?
保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?
免费视频制作网站,更新又快又好的免费电影网站?
实例解析Array和String方法
婚礼视频制作网站,学习*后期制作的网站有哪些?
网站制作说明怎么写,简述网页设计的流程并说明原因?
如何在建站宝盒中设置产品搜索功能?
大学网站设计制作软件有哪些,如何将网站制作成自己app?
Swift中switch语句区间和元组模式匹配
如何快速搭建个人网站并优化SEO?
网站制作服务平台,有什么网站可以发布本地服务信息?
定制建站模板如何实现SEO优化与智能系统配置?18字教程
如何用花生壳三步快速搭建专属网站?
在线制作视频的网站有哪些,电脑如何制作视频短片?
太平洋网站制作公司,网络用语太平洋是什么意思?
昆明网站制作哪家好,昆明公租房申请网上登录入口?
b2c电商网站制作流程,b2c水平综合的电商平台?
大连网站制作公司哪家好一点,大连买房网站哪个好?
盐城做公司网站,江苏电子版退休证办理流程?
威客平台建站流程解析:高效搭建教程与设计优化方案
全景视频制作网站有哪些,全景图怎么做成网页?
制作证书网站有哪些,全国城建培训中心证书查询官网?
C#怎么使用委托和事件 C# delegate与event编程方法
,购物网站怎么盈利呢?
如何在Golang中实现微服务服务拆分_Golang微服务拆分与接口管理方法
专业的网站制作设计是什么,如何制作一个企业网站,建设网站的基本步骤有哪些?
魔方云NAT建站如何实现端口转发?
个人网站制作流程图片大全,个人网站如何注销?
微信推文制作网站有哪些,怎么做微信推文,急?
建站之星×万网:智能建站系统+自助建站平台一键生成
专业网站建设制作报价,网页设计制作要考什么证?
小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建
网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?
Swift开发中switch语句值绑定模式
ppt在线制作免费网站推荐,有什么下载免费的ppt模板网站?
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
建站之星安全性能如何?防护体系能否抵御黑客入侵?
利用JavaScript实现拖拽改变元素大小
建站之星安装路径如何正确选择及配置?
建站之星好吗?新手能否轻松上手建站?
如何在万网自助建站平台快速创建网站?
专业网站制作服务公司,有哪些网站可以免费发布招聘信息?
自助网站制作软件,个人如何自助建网站?
建站之星如何实现PC+手机+微信网站五合一建站?
如何实现建站之星域名转发设置?
c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
*请认真填写需求信息,我们会在24小时内与您取得联系。