SpringBoot初体验-自定义切面

775 阅读1分钟

前言

自定义切面在实际应用中非常广泛,通常都是用作登录鉴权统一拦截,接口日志统一打印等,下面示范的是一个简单的登录鉴权切面,如需更多功能,例如权限,token校验也可以做在切面里。

一、引入Maven依赖

<!-- 切面依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

二、创建自定义注解

import java.lang.annotation.*;

/**
 * 权限校验注解
 * 使用该注解的类或者方法会被拦截鉴权
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface WebAccess {

    /**
     * 是否校验登录
     *
     * @return
     */
    boolean login() default false;

}

三、创建切面

import com.mimoprint.ecdiyweb.annotation.WebAccess;
import com.mimoprint.ecdiyweb.common.UserContext;
import com.mimoprint.ecdiyweb.common.exception.BusinessException;
import com.mimoprint.ecdiyweb.common.model.LoginUser;
import com.mimoprint.ecdiyweb.common.model.ResponseCodeEnum;
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.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(1)
@Slf4j
public class AuthorizeCheckAspect {

    // 切点定义,top.haostore.web包下,所有以Controller结尾的类的所有方法
    @Pointcut("execution(* top.haostore.web..*Controller.*(..))")
    public void excudeService() {
    }

    // 切面增强,环绕增强
    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取方法的签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 获取方法@WebAccess注解
        WebAccess webAccess = methodSignature.getMethod().getAnnotation(WebAccess.class);
        // 没有方法注解,获取类@WebAccess注解
        if (webAccess == null) {
            Class clazz = joinPoint.getTarget().getClass();
            webAccess = clazz.getAnnotation(WebAccess.class);
        }
        // @WebAccess注解为空,直接放行
        if (webAccess == null || !webAccess.login()) {
            return joinPoint.proceed();
        }
        // 否则,从登录态获取用户信息
        LoginUser loginUser = UserContext.getLoginUser();
        // 用户信息为空,说明用户未登录,抛出异常
        if (loginUser == null) {
            throw new BusinessException(ResponseCodeEnum.PAYMENT_REQUIRED.getCode(), ResponseCodeEnum.PAYMENT_REQUIRED.getMsg());
        }
        // 用户信息存在,放行
        return joinPoint.proceed();
    }
}

@各位掘金的小伙伴,如有任何Java技术方面疑问可私聊本人(wx:haostudydaydayup),一起探讨一起进步。