前言
最近有這么個功能缩宜,由于使用了thymeleaf锻煌,多個頁面遇到要使用同一個數(shù)據(jù)的問題,但是如果在每個Controller下都要向Model放數(shù)據(jù)匣沼,那么就有很多重復(fù)代碼捂龄,不太優(yōu)雅倦沧,所以想到了AOP,在進(jìn)入方法前取到Model實例局荚,向他增加數(shù)據(jù)即可愈污。
引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
doBefore中的代碼也可以放入到@After下執(zhí)行暂雹。
@Aspect
@Component
public class ResultAop {
@Pointcut("execution(public * com.he.edu.edu.controller.IndexController.*(..)))")
public void BrokerAspect(){
}
@Before("BrokerAspect()")
public void doBefore(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
if (arg instanceof Model){
Model model = (Model) arg;
model.addAttribute("test","存放公共參數(shù)");
}
}
}
@After("BrokerAspect()")
public void doAfter(JoinPoint joinPoint){
}
}
@Controller
public class IndexController {
Logger logger = LoggerFactory.getLogger(IndexController.class);
@GetMapping("test")
public String test(Model model){
logger.info("{}",model.getAttribute("test"));
return "test";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div th:text="${test}"></div>
</body>
</html>
這樣杭跪,每個方法下的Model中都有了這份數(shù)據(jù)涧尿,取出渲染即可。
獲取請求參數(shù)
我們可以通過RequestContextHolder獲取url中的參數(shù)缺亮,RequestContextHolder就是一個典型的ThreadLocal應(yīng)用萌踱,用于在當(dāng)前線程中獲取當(dāng)前請求及其屬性,如果要在service層中使用request鸳粉,或者其他任何地方园担,都可以直接調(diào)用RequestContextHolder來獲取request對象和response對象粉铐。
@Aspect
@Component
public class TestAop {
private Logger logger = LoggerFactory.getLogger(TestAop.class);
@Pointcut("execution(public * com.he.edu.edu.controller.IndexController.*(..)))")
public void BrokerAspect(){
}
@Before("BrokerAspect()")
public void doBefore(JoinPoint joinPoint){
ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
logger.info("URL參數(shù)={}",requestAttributes.getRequest().getQueryString());
}
}
@GetMapping("test")
public String test(Model model,@RequestParam("id") Integer id){
logger.info("id={}",id);
model.addAttribute("test",id);
return "test";
}
修改請求參數(shù)
可以利用@Around來修改請求參數(shù)蝙泼,@Around功能非常強(qiáng)大汤踏,作用如下:
可以在目標(biāo)方法之前增加邏輯舔腾,也可以在執(zhí)行目標(biāo)方法之后增加邏輯.
可以決定目標(biāo)方法在什么時候執(zhí)行稳诚,如何執(zhí)行,也可以阻止目標(biāo)目標(biāo)方法執(zhí)行.
可以改變執(zhí)行目標(biāo)方法的參數(shù)值才避,也可以改變執(zhí)行目標(biāo)方法之后的返回值.
使用ProceedingJoinPoint時如果要改變參數(shù)氨距,必須調(diào)用 proceed(Object[] var1)方法俏让,傳入新的參數(shù)數(shù)組首昔,數(shù)組元素類型必須和目標(biāo)方法相互對應(yīng),否則會報ClassCastException異常预鬓。
下面是將傳入的id擴(kuò)大十倍撬陵。
@Aspect
@Component
public class TestAop {
private Logger logger = LoggerFactory.getLogger(TestAop.class);
@Pointcut("execution(public * com.he.edu.edu.controller.IndexController.*(..)))")
public void BrokerAspect(){
}
@Around("BrokerAspect()")
public void doAround(ProceedingJoinPoint proceedingJoinPoint){
Object[] sourceObject =proceedingJoinPoint.getArgs();
sourceObject[1] =new Integer(((Integer) sourceObject[1])*10);
try {
proceedingJoinPoint.proceed(sourceObject);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
@GetMapping("test")
public String test(Model model,@RequestParam("id") Integer id){
logger.info("id={}",id);
model.addAttribute("test",id);
return "test";
}
修改返回值
proceed方法的返回值就是目標(biāo)方法的返回值蟋定,我們可以拿到他做一些修改驶兜,或者返回新的數(shù)據(jù)。
下面加了ResponseBody注解屠凶,會將對象轉(zhuǎn)換成json矗愧,將返回user1唉韭,user2犯犁,user3酸役。
@GetMapping("listUser")
@ResponseBody
public List<String> listUser(){
return Stream.of("user1","user2","user3").collect(Collectors.toList());
}
在切入點(diǎn)進(jìn)行修改,返回user4贱呐,user5吼句,user6惕艳。
@Around("BrokerAspect()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint){
try {
Object proceed = proceedingJoinPoint.proceed();
return Stream.of("user4","user5","user6").collect(Collectors.toList());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
打印帶有指定注解方法的參數(shù)
首先自定義一個注解远搪,最終將做到打印標(biāo)有這個注解的請求參數(shù)谁鳍。
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodLog {
}
@MethodLog
@GetMapping("log")
public String log(Model model,@RequestParam("id") Integer id){
model.addAttribute("test",id);
return "test";
}
@GetMapping("noLog")
public String noLog(Model model,@RequestParam("id") Integer id){
model.addAttribute("test",id);
return "test";
}
接下來取到目標(biāo)方法倘潜,從方法中判斷是否存有MethodLog注解涮因,有的話就通過RequestContextHolder來獲取請求參數(shù)养泡。
@Before("BrokerAspect()")
public void doBefore(JoinPoint joinPoint) throws NoSuchMethodException {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Method targetMethod = methodSignature.getMethod();
if (((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaredAnnotation(MethodLog.class)!=null){
ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
logger.info("URL參數(shù)={}",requestAttributes.getRequest().getQueryString());
}
}
訪問不帶注解方法時:
訪問帶有注解方法時:
版權(quán)聲明:本文為HouXinLin_CSDN原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議肩榕,轉(zhuǎn)載請附上原文出處鏈接和本聲明点把。
本文鏈接:https://blog.csdn.net/HouXinLin_CSDN/article/details/108430756