我们在开发过程中经常使用到自定义注解来实现在一些类或者方法执行过程中切面,统一实现某些业务操作。例如自定义注解
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;import java.util.Map;@Documented@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface CtgEncrypt { Class> paramType() default Map.class; String securityType() default "AES"; String reType() default "";}
注解一般开门见山,说我要干一个什么事情。使用@interface来修饰。例如上面这个注解就是用来对方法上的参数进行加密的。
@Target({ElementType.METHOD,ElementType.TYPE})
这个代码作用的METHOD(方法)上
@Retention(RetentionPolicy.RUNTIME)
这个代码代码运行时执行操作。
自定义的注解需要实现它功能才能用,不是注解了注解本身就有这个功能,没那么强大。
第二步实现注解功能。
import java.util.Arrays;import java.util.List;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.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import org.springframework.util.AntPathMatcher;import com.alibaba.fastjson.JSONObject;import cn.ctg.common.response.ResponseCode;import cn.ctg.common.response.ResponseData;import cn.ctg.common.util.UserTokenUtils;import cn.ctg.common.util.XssUtils;import cn.hutool.json.JSONUtil;@Aspect@Componentpublic class SecurityAspect { @Value("${keys.aeskey:-1}") private String AES_KEY; @Value("${keys.jwtkey:-1}") private String JWT_KEY; @Value("${xss.url:-1}") private String xxsUrl; private AntPathMatcher antPathMatcher = new AntPathMatcher(); @Pointcut("@annotation(cn.ctg.common.util.security.CtgDecrypt) || @annotation(cn.ctg.common.util.security.CtgEncrypt)") public void pointCut(){ } @Around("execution(* cn.ctg.*.controller.*.*(..))") public Object doAroundHtml(ProceedingJoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); HttpServletRequest httpServletRequest = UserTokenUtils.getHttpServletRequest(); String requestURI = httpServletRequest.getRequestURI(); String[] split = xxsUrl.split("\\|"); if(split==null){ return joinPoint.proceed(args); } if(pathMatcher(Arrays.asList(split),requestURI)) { for (int i = 0; i < args.length; i++) { Object arg = args[i]; Map map = JSONUtil.parseObj(JSONObject.toJSONString(arg)); for (Map.Entry entry : map.entrySet()) { if (XssUtils.isStripXSS(entry.getValue().toString())) { ResponseData
代码中的这一句 @Pointcut("@annotation(cn.ctg.common.util.security.CtgDecrypt) || @annotation(cn.ctg.common.util.security.CtgEncrypt)")
就是用来实现CtgEncrypt这个注解的
再使用@Around("pointCut()")进行方法环绕。实现注解的动作。
@Around("pointCut()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { //执行方法,获取返回值 Object result = joinPoint.proceed(); String data = JSONUtil.toJsonStr(((ResponseData>) result).getData()); if(data.equals("{}")){ data = String.valueOf(((ResponseData>) result).getData()); } ((ResponseData>) result).setEncrypt(true); return result; }
这是我们看到一个重要类型ProceedingJoinPoint。执行当前切点的意思
这里就通过源码看看ProceedingJoinPoint能做什么东西。
package org.aspectj.lang;import org.aspectj.runtime.internal.AroundClosure;public interface ProceedingJoinPoint extends JoinPoint { void set$AroundClosure(AroundClosure arc); default void stack$AroundClosure(AroundClosure arc) { throw new UnsupportedOperationException(); } public Object proceed() throws Throwable; public Object proceed(Object[] args) throws Throwable;}
从源码上继承了JoinPoint
public Object proceed() throws Throwable;
Proceed with the next advice or target method invocation
继续执行下一个通知或目标方法调用
获取当前正在执行的对象(如果不可用则为空——例如静态上下文)
Object getThis();
获取目标对象(如果没有,则为空)
Object getTarget();
获取这个连接点上的参数
Object[] getArgs();
获取连接点上的签名。
Signature getSignature();
来源地址:https://blog.csdn.net/dongjing991/article/details/128654007