当前位置: 首页 > 工具软件 > TODAY AOP > 使用案例 >

SpringBoot AOP 自定义注解

养淇
2023-12-01

对请求进行访问权限校验

自定义一个忽略校验的注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 忽略验证
 *
 * @author Administrator
 * @version V1.0
 * @date 2022/3/16
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotVerify {
    boolean required() default true;
}

创建拦截器

import com.ddz.project.common.aop.annotation.NotVerify;
import com.ddz.project.common.utils.JWTUtil;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;

/**
 * @author Administrator
 * @version V1.0
 * @date 2022/3/16
 */
public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        try {
            // 如果不是映射到方法直接通过
            if (!(object instanceof HandlerMethod)) {
                return true;
            }
            HandlerMethod handlerMethod = (HandlerMethod) object;
            Method method = handlerMethod.getMethod();
            //检查是否有NotVerify注释,有则跳过认证
            if (method.isAnnotationPresent(NotVerify.class)) {
                NotVerify annotation = method.getAnnotation(NotVerify.class);
                if (annotation.required()) {
                    return true;
                }
            }
            String token = request.getHeader("token");
            boolean verify = JWTUtil.verify(token);
            if (verify) {
                return true;
            }
        } catch (Exception e) {
            return false;
        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("token验证失败");
        writer.close();
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

在控制器的方法上加上注解就不需要验证权限了

    @NotVerify
    @ApiOperation(value = "login")
    @PostMapping("login")
    public String login(HttpServletRequest request, HttpServletResponse response, String id, String userName) {
        System.out.println("id = " + id + ", userName = " + userName);
        return JWTUtil.jwtCreateExpired(userName, id, 10);
    }

日志收集

创建自定义注解

package com.ddz.project.common.aop.annotation;

import java.lang.annotation.*;

/**
 * @author Administrator
 * @version V1.0
 * @date 2022/3/16
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    String value() default "ddz log";
}

定义AOP

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.ddz.project.common.aop.annotation.Log;
import com.ddz.project.common.utils.IPUtils;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 顺序
 * around =>  doBefore => after
 *
 * @author Administrator
 * @version V1.0
 * @date 2022/3/16
 */
@Aspect
@Component
public class LogAop {
    /**
     * 定义切面
     */
    @Pointcut(value = "@annotation(com.ddz.project.common.aop.annotation.Log)&&execution(com.ddz.project.common.aop.aspect.LogAop)")
    public void access() {

    }

//    @Before("access()")
//    public void doBefore() {
//        System.out.println("aop 日志启动");
//    }

    /**
     * 定义切面 并携带log注解的才会被收集
     * @param pjp 入参
     * @param logger 注解
     */
    @SneakyThrows
    @Around("execution(public * com.ddz.project.controller.*.*(..)) && @annotation(log)")
    public Object around(ProceedingJoinPoint pjp, Log log) {
        System.out.println("****aop 日志环绕阶段****" + DateUtil.today());
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

//        GET 请求其实可以从request里获取出参数
//       Map<String,String[]> map=request.getParameterMap();
//        System.out.println("获取参数:"+map.get("username")[0])

        String url = request.getRequestURL().toString();
        String ip = IPUtils.getIpAddr(request);
        String logTrackValue = logger.value();
        Object[] pipArrary = pjp.getArgs();
        if (pipArrary.length > 1) { //多参,不是Map/JsonObject方式
            List<Object> argList = new ArrayList<>();
            for (Object arg : pjp.getArgs()) {
                // request/response无法使用toJSON
                if (arg instanceof HttpServletRequest) {
                    argList.add("request");
                } else if (arg instanceof HttpServletResponse) {
                    argList.add("response");
                } else {
                    argList.add(JSON.toJSON(arg));
                }
            }
            Signature signature = pjp.getSignature();
            // 参数名数组
            String[] parameterNames = ((MethodSignature) signature).getParameterNames();
            System.out.println("参数名数组:" + new ArrayList<>(Arrays.asList(parameterNames)));
            System.out.println("参数是:" + argList);
            System.out.println("logTrackValue:" + logTrackValue);
            System.out.println("url:" + url);
            System.out.println("ip:" + ip);
            return pjp.proceed();

        }
        Object param = pipArrary[0];
        System.out.println("logTrackValue:" + logTrackValue);
        System.out.println("url:" + url);
        System.out.println("ip:" + ip);
        System.out.println("param:" + param);
        return pjp.proceed();
    }

//    @After("access()")
//    public void after() {
//        System.out.println("aop 日志结束");
//    }
}

在控制器里面添加注解就会被收集日志

    @Log("测试的")
    @ApiOperation(value = "get")
    @RequestMapping("get")
    @NotVerify
    public String get(@RequestBody Map<String, Object> map) {
        System.out.println("map = " + map);
        return "not token";
    }
 类似资料: