一、jar
主要是用了aop原理
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
二、注解
annotation提供了四种元注解,专门注解其他的注解(在自定义注解的时候,需要使用到元注解):
@Documented –注解是否将包含在JavaDoc中
@Retention –什么时候使用该注解
@Target –注解用于什么地方,方法上METHOD、TYPE类上(类上不管不用,不知道为啥)
package net.cnki.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author ZhiPengyu
* @ClassName: [UrlVerify.java]
* @Description: [自定义注解-标注需要校验接口多次重复无效请求的方法]
* @CreateDate: [2020年12月16日 上午9:27:27]
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UrlVerify {
boolean required() default true;
}
三、执行
代码里也有注解,可以自行尝试。根据情况采用不同的方法,我一般使用环绕拦截。
package net.cnki.common.aspect;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 获取方法请求头指定参数,根据自定义规则处理
* @author ZhiPengyu
* @ClassName: [UrlVerifyAspect.java]
* @Description: [自定义切面]
* @CreateDate: [2020年12月16日 上午9:27:49]
*/
@Aspect
@Component
public class UrlVerifyAspect {
public static final Logger logger = LoggerFactory.getLogger(UrlVerifyAspect.class);
@Pointcut("@annotation(net.cnki.common.annotation.UrlVerify)")//切入点 自定义注解
public void pointCut(){}
//前置通知:方法执行前调用
@Before("pointCut()")
public String doBefore(){
System.out.println("执行了before方法....");
return "123";
}
//后置通知: 方法执行后调用,若方法出现异常,不执行
@AfterReturning("pointCut()")
public void doAfterReturning(){
System.out.println("执行了doAfterReturning方法....");
}
//最终通知:无论无何都会调用,类似于:try/catch中的finally
@After("pointCut()")
public void doAfter(){
System.out.println("执行了after....");
}
//异常通知:方法抛出异常时执行
@AfterThrowing("pointCut()")
public void doAfterThrowing(){
System.out.println("执行AfterThrowing方法....");
}
/**
* 环绕通知
* 既可以在目标方法之前织入增强动作,也可以在执行目标方法之后织入增强动作;
* 可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标目标方法的执行;
* 可以改变执行目标方法的参数值,也可以改变执行目标方法之后的返回值; 当需要改变目标方法的返回值时,只能使用Around方法;
*/
@Around("pointCut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
try {
//--------------------方法执行前------------------------
String packageName = joinPoint.getSignature().getDeclaringTypeName();
String methodName = joinPoint.getSignature().getName();
//--------------------方法执行后------------------------
Object resultObject = joinPoint.proceed();
return resultObject;
} catch (Exception e) {
return resultGenerator.getFreeResult(ResultCode.API_EXCEPTION);
}
}
}
四、使用
比较简单了
@UrlVerify
@RequestMapping(value = "test")
public void test() {
// 自己的逻辑
}