SpringBoot项目中通过注解实现Aop编程实战

SpringBoot项目中通过注解实现Aop编程实战。
项目结构如图:
项目实现:在接口前构造aop切面,实现不同身份用户的鉴权
在这里插入图片描述

1、新建maven工程testAspect

然后在pom文件中引入aop依赖和其他基础依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

此处没有写版本,是因为引入了springboot的parent:spring-boot-starter-parent

2、新建一个自定义注解AuthToken

注解:AuthToken
后面实现被AuthToken注解的方法都是切点(Pointcut)
自定义注解参考:java自定义注解@annotation

package com.tzq.aspect.annotation;

import java.lang.annotation.*;

/**
 * @Author tangzhiqian
 * @CreateTime 2021/6/8 15:31
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthToken {
    /**
     * 访问所需的身份,默认为空,为登录即可访问,可以多个定义
     *
     */
    String[] role_name() default "";
}

3、新建MyController类

该类中写了三个接口:无需验证的登录、普通user登录、管理员admin登录
在user登录接口方法上面加上注解@AuthToken
在admin登录接口方法上面加上注解@AuthToken(role_name = {“admin”, “Administrator”})

package com.tzq.aspect.controller;

import com.tzq.aspect.annotation.AuthToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author tangzhiqian
 * @CreateTime 2021/6/8 15:31
 */
@RestController
public class MyController {
    /**
     * 无需校验,不加注解
     */
    @GetMapping("hello")
    public String hello(Integer id, String name, Integer age) {
        System.out.println("hello方法执行:id==>" + id + ",name==>" + name + ",age==>" + age);
        return "hi~ 我不需要用户权限";
    }

    /**
     * 需要登录校验,加上注解,但不传所需角色
     */
    @GetMapping("user")
    @AuthToken
    public String user(Integer id, String name, Integer age) {
        System.out.println("user方法执行:id==>" + id + ",name==>" + name + ",age==>" + age);
        return "hi~ 我需要登陆后才可以访问";
    }

    /**
     * 需要角色校验,加上注解,并且写入两个角色,本文演示两个角色有一个即可访问,当然写一个可以。
     * 注:若想两个角色同时具有,修改后文的逻辑判断即可。
     * 若需要更复杂的逻辑操作,推荐使用Spring Security框架。
     */
    @GetMapping("admin")
    @AuthToken(role_name = {"admin", "Administrator"})
    public String admin(Integer id, String name, Integer age) {
        System.out.println("admin方法执行:id==>" + id + ",name==>" + name + ",age==>" + age);
        return "hi~ 我需要管理员身份才可以访问";
    }
}

4、新建切片类:

AuthTokenAspect.class,在类上加注解@Aspect表示这是该类是切面。

一个切面类中,可以有多个切点和切点执行的方法

在这里插入图片描述

package com.tzq.aspect.aspect;

import com.tzq.aspect.annotation.AuthToken;
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.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;

/**
 * @Author tangzhiqian
 * @CreateTime 2021/6/8 15:33
 */
@Aspect
@Component
public class AuthTokenAspect {
    /**
     * Spring中使用@Pointcut注解来定义方法切入点
     *
     * @Pointcut 用来定义切点,针对方法。后面的aop增强均是围绕切入点来完成的
     * @Aspect 用来定义切面,针对类。
     * 此处仅配置被我们刚才定义的注解:AuthToken修饰的方法即可
     *
     */
    @Pointcut("@annotation(authToken)")
    public void doAuthToken(AuthToken authToken) {
    }

    /**
     * 此处我使用环绕增强,在方法执行之前或者执行之后均会执行。
     */
    @Around("doAuthToken(authToken)")
    public Object deArrond(ProceedingJoinPoint pjp, AuthToken authToken) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 获取访问该方法所需的role_name信息
        String[] role_name = authToken.role_name();
        if (role_name[0].equals("")){    //role_name没写,默认是“”,长度为1
            // 只需登录,验证是否具有id即可。
            String id = request.getParameter("id");
            /**
             * 此处使用短路与,若id==null直接会执行if体,不会继续判断
             * 若不等于null,则去验证后面的条件,但是也不会出现因为id为null而出现的空指针异常
             * 所以这样写也是安全的。
             */
            if (id != null && !id.equals("")) {
                // 已登录,执行原方法并返回即可。
                return pjp.proceed();
            }
            // 未登录,不执行方法,直接返回错误信息
            return "请登陆后再试!";
        } else {
            // 需要验证身份
            String role = request.getParameter("name");
            for (String str : role_name) {
                /**
                 * 此处str由于是用role_name中取值,则str必定不为空
                 * 而从请求头中获取的role有可能为空,则此处调用str的equals方法
                 * 当然可以直接在获得请求头后进行验证是是否不为空。
                 */
                if (str.equals(role)) {
                    // 身份匹配成功
                    return pjp.proceed();
                }
            }
            return "权限校验失败,不具有指定的身份";
        }
    }

}

到这里,该aop切面编写完成!测试一下:

http://localhost:8077/user
在这里插入图片描述
http://localhost:8077/user?name=admin&id=1
在这里插入图片描述
实现了用户身份认证!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值