SpringBoot Aop、Aspect注解

本文介绍了如何在Spring中使用AOP实现自定义注解`CheckParams`进行参数校验,以及使用`MLock`注解实现分布式锁,确保并发场景下的数据一致性。此外,还展示了按包进行切面操作,记录请求信息并进行非法Url检查。通过这些实践,可以提升应用的稳定性和安全性。
摘要由CSDN通过智能技术生成

execution参数

在这里插入图片描述

注解切面

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CheckParams {
}
@Slf4j
@Aspect
@Component
public class CheckParamsAspect {

    @Pointcut("@annotation(com.sinosig.manage.common.annotation.CheckParams)")
    public void operate() {

    }

    @Around("operate()")
    public Object around(ProceedingJoinPoint point) throws Exception {
        Object result = null;
        BindingResult bindingResult = null;
        String methodName = point.getSignature().getName();
        Object[] args = point.getArgs();//参数
        for (Object arg : args) {
            if (arg instanceof BindingResult) {
                bindingResult = (BindingResult) arg;
            }
        }
        try {
            for (Object arg : args) {
                if (arg instanceof BindingResult) {
                    bindingResult = (BindingResult) arg;
                }
                if (bindingResult != null && bindingResult.hasErrors()) {
                    for (ObjectError error : bindingResult.getAllErrors()) {
                        log.info("参数为空校验------{}------{}", methodName, error.getDefaultMessage());
                        return Result.err(error.getDefaultMessage());
                    }
                }
            }
            // 执行方法
            result = point.proceed();
        } catch (Throwable e) {
            log.error("执行方法出错:", e);
            throw new RuntimeException();
        }
        return result;
    }
}

自定义锁注解

MLock注解


import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface MLock {
    String value() default "";
}

MLockAspect


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.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Aspect
@Component
public class MLockAspect {
    private static final Logger log = LoggerFactory.getLogger(MLockAspect.class);

    @Resource
    private RedissonClient redissonClient;

    @Pointcut("@annotation(top.otc.core.aspect.MLock)")
    public void operate() {
    }

    @Around("operate()&&@annotation(mLock)")
    public void around(ProceedingJoinPoint point, MLock mLock) { //参数对应
        RLock rLock = redissonClient.getLock(mLock.value());
        if (!rLock.tryLock()) {
            log.info("任务其他节点执行中,本节点取消执行...");
            return;
        }
        try {
            point.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            rLock.unlock();
        }
    }
}

使用

    @Async
    @MLock(OPTIAML_LOCK)
    @Scheduled(cron = "0/10 * * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void m1() {
    //略
    }

按包切面

依赖


@Pointcut("execution(* com.zzz.controller.*.*(..))")
    public void pointcut() {

    }

    @Around("sentPointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long startTime = System.currentTimeMillis();
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        Map<String, String[]> parameterMap = request.getParameterMap();
        String requestId = UUID.randomUUID().toString();
        StringBuffer requInfo = new StringBuffer();
        requInfo.append("\nRequestURL:" + request.getRequestURL());
        requInfo.append("\nRequestClassName:" + point.getSignature().getDeclaringTypeName());
        requInfo.append("\nRequestMethodName:" + point.getSignature().getName());
        requInfo.append("\nRequestBody:" + JSON.toJSONString(point.getArgs()));
        log.info("[" + requestId + "]请求信息:" + requInfo);
        Object arg = point.getArgs()[0];
        if (arg instanceof LinkedHashMap) {
            String path = ((LinkedHashMap<String, Object>) arg).get("path").toString().toLowerCase().trim();
            log.info(JSON.toJSONString(urlWhiteList));
            if (!urlWhiteList.contains(path)) return "非法Url";
        }
        Object proceed = point.proceed();
        long endTime = System.currentTimeMillis();
        log.info("[" + requestId + "]请求完成,用时:" + (endTime - startTime) / 1000 + "S");
        return proceed;
    }

    private Map<String, Object> getRequestParams(ProceedingJoinPoint point, String requestId) {
        HashMap<String, Object> requestParams = new HashMap<>();
        String[] parameterNames = ((MethodSignature) point.getSignature()).getParameterNames();
        Object[] args = point.getArgs();
        for (int i = 0; i < parameterNames.length; i++) {
            requestParams.put(parameterNames[i], args[i]);
        }
        log.info("请求[" + requestId + "】参数:" + JSON.toJSONString(requestParams));
        return requestParams;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值