SpringBoot使用AOP进行用户权限判断,已处理完成!!!

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。

本次完成了使用IDE进行SpringBoot进行AOP的用户全向判断。

本次项目整体结构:

引入依赖:

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <!--<exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>-->
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>

        <!--引入AOP依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>

    </dependencies>

用户信息实体类:

package com.wen.entity;

import lombok.Data;

/**
 * 作者: WENHENG
 * 时间: 2020/10/19 10:30
 * 说明: 用于对用户进行描述
 */

@Data
public class Users {

    private String name;

    private String role;

    public Users() {

    }

    public Users(String name, String role) {
        this.name = name;
        this.role = role;
    }
}
自定义权限注解:
package com.wen.service;

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

/**
 * 作者: WENHENG
 * 时间: 2020/10/15 19:30
 * 说明: 权限注解
 */

//注解的作用目标:方法
@Target(ElementType.METHOD)
//注解传递存活时间,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
public @interface RoleInfo{
    //角色的名字
    String role() default "";
}

编译自定义的注解的解析器(用于完成对注解的方法的权限判断处理):

package com.wen.service;

import com.wen.entity.Users;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;

import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
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 javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import static jdk.nashorn.internal.objects.NativeMath.log;

/**
 * 作者: WENHENG
 * 时间: 2020/10/19 10:46
 * 说明:
 */
@Aspect
@Component
@Slf4j
public class RolesAspect {

    @Pointcut("@annotation(com.wen.service.RoleInfo)")
    private void checkCut(){

    }
    // 前置通知
    @Before("checkCut()")
    public void myBefore(JoinPoint joinPoint) {
        System.out.print("前置通知,目标:");
        System.out.print(joinPoint.getTarget() + "方法名称:");
        System.out.println(joinPoint.getSignature().getName());
    }

    // 前置通知
    @After("checkCut()")
    public void myAfter(JoinPoint joinPoint) {
        System.out.print("hou置通知,目标:");
        System.out.print(joinPoint.getTarget() + "方法名称:");
        System.out.println(joinPoint.getSignature().getName());
    }

    @Around("checkCut()")
    public void parse(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕开始");

        Class targetClassName = joinPoint.getTarget().getClass();
        String methodName = joinPoint.getSignature().getName();

        // 获取目标方法
//        Method method = targetClassName.getMethod(methodName);
        Signature signature = joinPoint.getSignature();

        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        String methAccess = "";

        // 判断注解中是否存在@RoleInfo注解
        if(method.isAnnotationPresent(RoleInfo.class)){
            RoleInfo roleInfo = method.getAnnotation(RoleInfo.class);
            // 获取到注解中的name值
            methAccess = roleInfo.role();
            System.out.println(methAccess);

            Object[] parm = joinPoint.getArgs();

            if (parm[0].equals(methAccess)){
                System.out.println("获取到该权限");
                joinPoint.proceed();
            } else {
                System.out.println("没有执行权限");
            }

            System.out.println("环绕结束");
        }
    }
}

Service接口:

package com.wen.service;

import com.wen.entity.Users;

/**
 * 作者: WENHENG
 * 时间: 2020/10/19 10:54
 * 说明: 用户业务接口
 */

public interface UserService {

    public void save(Users user);

    public void update(String root, Users user);

    public void get(Users user);
}

ServiceImpl接口实现类:

package com.wen.service.serviceImpl;

import com.wen.entity.Users;
import com.wen.service.RoleInfo;
import com.wen.service.UserService;
import org.springframework.context.annotation.Role;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

/**
 * 作者: WENHENG
 * 时间: 2020/10/19 11:30
 * 说明:
 */
@Service
@Repository("UserService")
public class UserServiceImpl implements UserService {

    @Override
    @RoleInfo(role = "admin")
    public void save(Users user) {
        System.out.println("save()方法");
    }

    @Override
    @RoleInfo(role = "admin")
    public void update(String root, Users user) {
        System.out.println("update()方法");
    }

    @Override
    @RoleInfo(role = "admin")
    public void get(Users user) {
        System.out.println("get()方法");
    }
}

测试类:

package com.wen;

import com.wen.entity.Users;
import com.wen.service.RoleInfo;
import com.wen.service.UserService;
import org.apache.catalina.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@SpringBootTest
class Exp1ApplicationTests {

    @Qualifier("UserService")
    @Autowired(required = false)
    private UserService userService;

    @Test
    void contextLoads() {
    }

    @Test
    public void actionLogAnno() throws Exception {
        Users users = new Users();

        users.setName("admin");
        users.setRole("admin");


        userService.update("admin",users);
    }



}

注意:在Users实体类中使用的@Data注解需要使用到Lombok插件,请自行到IDE的插件库进行下载安装,并导入LomBok依赖或者jar包。

AOP通知的优先级:环绕通知 > 前置通知 > 后置通知。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot是一个用于构建独立的、生产级别的Spring应用程序的框架,它提供了丰富的功能和特性,方便开发人员快速搭建和开发项目。 在Spring Boot中使用AOP(面向切面编程)可以实现将一些公共的功能逻辑代码从业务逻辑代码中解耦出来,提高代码的复用性和可维护性。通过AOP可以在方法的前后注入一些通用的逻辑,例如日志记录、异常处理、权限校验等。 其中,使用AOP进行结果的统一封装是很常见的需求。通过AOP可以在方法执行后对返回的结果进行封装,统一处理返回结果的格式,并可以对结果进行一些统一的处理操作,例如添加统一的返回码、返回信息、返回时间等。 在Spring Boot中使用AOP进行结果的统一封装可以按照以下步骤进行: 1. 创建一个切面(Aspect),通过在切面类上加上@Aspect注解标识该类是一个切面类。 2. 在切面类中定义一个切点(Pointcut),通过定义一个方法并添加@Pointcut注解来指定切入点。 3. 在切面类中定义一个通知(Advice),通过@Before、@After、@Around等注解来指定通知类型,并在通知方法中编写需要执行的逻辑。 4. 在通知方法中获取方法的返回结果,并进行相应的封装和处理。 5. 在Spring Boot的配置类中添加@EnableAspectJAutoProxy注解来启用AOP使用以上步骤可以实现对方法返回结果的统一封装,使得返回结果具有统一的格式和处理逻辑。这样可以提高代码的重用性和可维护性,并且可以在一处对结果进行集中处理,减少了代码的重复性,提高了开发效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WEN丶HENG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值