【java】aop中使用spel表达式工具类

package com.demo.common;

import java.lang.annotation.*;

/**
 * <p>
 * <code>TokenCheck</code>
 * </p>
 * Description: 校验token注解
 * <p>
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TokenCheck {
	/** 当前登录人账号 */
    String account() default "";
	/** 当前登录人token */
    String token() default "";
	/** 是否触发校验,默认true(true:校验,false:不校验),可以是条件表达式 */
    String condition() default "true";
    /** 其他信息 */
    String extra() default "";
}

package com.demo.common;

import com.demo.service.TokenCheckService;
import com.demo.result.RestResponse;
import lombok.extern.slf4j.Slf4j;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * <p>
 * <code>TokenCheckAspect</code>
 * </p>
 * Description: token校验切面
 */
@Slf4j
@Aspect
@Component
public class TokenCheckAspect {

    /** 解析方法 */
    private final ExpressionParser parser = new SpelExpressionParser();
    private final LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
    /** 上下文 */
    private final EvaluationContext context = new StandardEvaluationContext();
    /** 默认解析模板 */
    private final TemplateParserContext templateParserContext = new TemplateParserContext();

    @Autowired
    private TokenCheckService tokenCheckService;

    @Pointcut("@annotation(com.demo.common.TokenCheck)")
    public void tokenPointCut() {
    }

    @Around("tokenPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        try {
            Method method = ((MethodSignature) point.getSignature()).getMethod();
            Object[] args = point.getArgs();
            TokenCheck annotation = method.getAnnotation(TokenCheck.class);
            // 获取注解参数
            String account = executeTemplate(annotation.account(), method, args);
            String token = executeTemplate(annotation.token(), method, args);
            String condition = executeTemplate(annotation.condition(), method, args);
            String extra = executeTemplate(annotation.extra(), method, args);
            
            // 调用业务接口进行相关校验
            boolean check = tokenCheckService.tokenCheck(account, token);
            if (check) {
            	// 校验通过后执行原有逻辑
                Object result = point.proceed();
                return Objects.isNull(result) ? new RestResponse<>(false, "请求失败") : result;
            } else {
                return check;
            }
        } catch (Exception e) {
            return new RestResponse<>(false, "非法请求");
        }
    }

    /**
     * 解析字符串
     *
     * @param message 待解析字符串
     * @param method  方法
     * @param args    方法参数
     * @return
     */
    private String executeTemplate(String message, Method method, Object[] args) {
        String[] params = discoverer.getParameterNames(method);
        for (int len = 0; len < Objects.requireNonNull(params).length; len++) {
            context.setVariable(params[len], args[len]);
        }
        return parser.parseExpression(message, templateParserContext).getValue(context, String.class);
    }
}

    使用方法如下:

	1、入参为对象:#{#形参.属性}
    @Override
    @TokenCheck(account = "#{#input.userAccount}", token = "#{#input.token}", extra = "这是其他信息:#{#input.id}")
    public RestResponse<String> aa(InputQuery input) {
    		// 相关业务逻辑
    		return null;
    }

	2、入参为单个字符串:#{#形参}
    @Override
    @TokenCheck(account = "#{#userAccount}", token = "#{#token}", condition = "'#{#userAccount}'!='' && " + "'#{#userAccount}'!=null")
    public RestResponse<String> bb(String userAccount, String token) {
    		// 相关业务逻辑
    		return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值