首页 > 其他分享 >项目笔记

项目笔记

时间:2024-09-15 16:38:22浏览次数:1  
标签:项目 app 笔记 ErrorCode mustRole import 权限 注解

核心业务流程

自定义上传题目流程:

用户答题流程:

AI 创建题目流程:

时序图:

 

架构设计

 在对登录用户的权限进行判断时,不再通过条件判断,编写一大串代码去实现,可以通过写一个Java注解,如

package com.yupi.qidada.annotation;

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

/**
 * 权限校验
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {

    /**
     * 必须有某个角色
     *
     * @return
     */
    String mustRole() default "";

}

这是一个Java注解,用于权限验证。它有两个属性:mustRole和excludeRole。mustRole表示必须有某个角色才能访问该方法,excludeRole表示没有某个角色才能访问该方法。这个注解可以应用于方法上,用于限制访问权限。

实现原理:

  1. 使用@Target和@Retention注解来定义注解的作用范围和生命周期。@Target(ElementType.METHOD)表示这个注解只能应用于方法上,@Retention(RetentionPolicy.RUNTIME)表示这个注解在运行时可用。
  2. 使用@interface关键字定义一个名为AuthCheck的注解,包含两个属性:mustRole和excludeRole。
  3. 在AuthCheck注解中,使用default关键字为mustRole属性设置一个默认值。
  4. 使用ElementType.METHOD表示这个注解只能应用于方法上。
  5. 使用RetentionPolicy.RUNTIME表示这个注解在运行时可用。

用途:
这个注解可以用于权限验证,限制访问权限。例如,在一个方法上添加@AuthCheck(mustRole="admin"),表示只有具有admin角色的用户才能访问该方法。

package com.yupi.qidada.aop;

import com.yupi.qidada.annotation.AuthCheck;
import com.yupi.qidada.common.ErrorCode;
import com.yupi.qidada.exception.BusinessException;
import com.yupi.qidada.model.entity.User;
import com.yupi.qidada.model.enums.UserRoleEnum;
import com.yupi.qidada.service.UserService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * 权限校验 AOP
 *
 */
@Aspect
@Component
public class AuthInterceptor {

    @Resource
    private UserService userService;

    /**
     * 执行拦截
     *
     * @param joinPoint
     * @param authCheck
     * @return
     */
    @Around("@annotation(authCheck)")
    public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
        String mustRole = authCheck.mustRole();
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        // 当前登录用户
        User loginUser = userService.getLoginUser(request);
        UserRoleEnum mustRoleEnum = UserRoleEnum.getEnumByValue(mustRole);
        // 不需要权限,放行
        if (mustRoleEnum == null) {
            return joinPoint.proceed();
        }
        // 必须有该权限才通过
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(loginUser.getUserRole());
        if (userRoleEnum == null) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        // 如果被封号,直接拒绝
        if (UserRoleEnum.BAN.equals(userRoleEnum)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        // 必须有管理员权限
        if (UserRoleEnum.ADMIN.equals(mustRoleEnum)) {
            // 用户没有管理员权限,拒绝
            if (!UserRoleEnum.ADMIN.equals(userRoleEnum)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
        }
        // 通过权限校验,放行
        return joinPoint.proceed();
    }
}

这是一个基于Spring AOP(面向切面编程)的权限校验拦截器。它主要用于在方法执行前,对请求进行权限校验。

1. 首先,定义了一个名为`AuthInterceptor`的类,并使用`@Aspect`和`@Component`注解进行标注,表示这是一个切面类,并且会自动被Spring容器管理。

2. 在`AuthInterceptor`类中,定义了一个名为`doInterceptor`的方法,该方法使用`@Around`注解进行标注,表示这是一个环绕通知,会在目标方法执行前后进行拦截。

3. 在`doInterceptor`方法中,首先获取`AuthCheck`注解中的`mustRole`属性值,然后通过`UserService`获取当前登录用户的信息。

4. 判断`mustRole`属性值是否为空,如果为空,则表示不需要权限,直接放行。

5. 如果`mustRole`属性值不为空,则需要进行权限校验。首先判断当前登录用户的角色是否与`mustRole`属性值相等,如果相等,则表示用户具有该权限,放行。

6. 如果当前登录用户的角色与`mustRole`属性值不相等,则判断用户是否被封号。如果被封号,则抛出`BusinessException`异常。

7. 如果用户没有被封号,则判断用户是否具有管理员权限。如果具有管理员权限,则放行。

8. 如果用户不具有管理员权限,则抛出`BusinessException`异常。

示例:

/**
 * 应用审核
 * @param reviewRequest
 * @param request
 * @return
 */
@PostMapping("/review")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Boolean> doAppReview(@RequestBody ReviewRequest reviewRequest, HttpServletRequest request) {
    ThrowUtils.throwIf(reviewRequest == null, ErrorCode.PARAMS_ERROR);
    Long id = reviewRequest.getId();
    Integer reviewStatus = reviewRequest.getReviewStatus();
    // 校验
    ReviewStatusEnum reviewStatusEnum = ReviewStatusEnum.getEnumByValue(reviewStatus);
    if (id == null || reviewStatusEnum == null) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }
    // 判断是否存在
    App oldApp = appService.getById(id);
    ThrowUtils.throwIf(oldApp == null, ErrorCode.NOT_FOUND_ERROR);
    // 已是该状态
    if (oldApp.getReviewStatus().equals(reviewStatus)) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "请勿重复审核");
    }
    // 更新审核状态
    User loginUser = userService.getLoginUser(request);
    App app = new App();
    app.setId(id);
    app.setReviewStatus(reviewStatus);
    app.setReviewerId(loginUser.getId());
    app.setReviewTime(new Date());
    boolean result = appService.updateById(app);
    ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
    return ResultUtils.success(true);
}

 

全局执行器

为了简化外部调用,需要根据不同的应用类别和评分策略,选择对应的策略执行,因此需要一个全局执行器。

2 种实现方式:

1)编程式,在内部计算选用何种策略:

@Service
@Deprecated
public class ScoringStrategyContext {

    @Resource
    private CustomScoreScoringStrategy customScoreScoringStrategy;

    @Resource
    private CustomTestScoringStrategy customTestScoringStrategy;

    /**
     * 评分
     *
     * @param choiceList
     * @param app
     * @return
     * @throws Exception
     */
    public UserAnswer doScore(List<String> choiceList, App app) throws Exception {
        AppTypeEnum appTypeEnum = AppTypeEnum.getEnumByValue(app.getAppType());
        AppScoringStrategyEnum appScoringStrategyEnum = AppScoringStrategyEnum.getEnumByValue(app.getScoringStrategy());
        if (appTypeEnum == null || appScoringStrategyEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "应用配置有误,未找到匹配的策略");
        }
        // 根据不同的应用类别和评分策略,选择对应的策略执行
        switch (appTypeEnum) {
            case SCORE:
                switch (appScoringStrategyEnum) {
                    case CUSTOM:
                        return customScoreScoringStrategy.doScore(choiceList, app);
                    case AI:
                        break;
                }
                break;
            case TEST:
                switch (appScoringStrategyEnum) {
                    case CUSTOM:
                        return customTestScoringStrategy.doScore(choiceList, app);
                    case AI:
                        break;
                }
                break;
        }
        throw new BusinessException(ErrorCode.SYSTEM_ERROR, "应用配置有误,未找到匹配的策略");
    }
}

优点是直观清晰,缺点是不利于扩展和维护。

2)声明式,在每个策略类中通过接口声明对应的生效条件,适合比较规律的策略选取场景。

接口:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface ScoringStrategyConfig {

    int appType();

    int scoringStrategy();
}

给策略实现类补充注解:

@ScoringStrategyConfig(appType = 0, scoringStrategy = 0)

全局执行器:

@Service
public class ScoringStrategyExecutor {

    // 策略列表
    @Resource
    private List<ScoringStrategy> scoringStrategyList;


    /**
     * 评分
     *
     * @param choiceList
     * @param app
     * @return
     * @throws Exception
     */
    public UserAnswer doScore(List<String> choiceList, App app) throws Exception {
        Integer appType = app.getAppType();
        Integer appScoringStrategy = app.getScoringStrategy();
        if (appType == null || appScoringStrategy == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "应用配置有误,未找到匹配的策略");
        }
        // 根据注解获取策略
        for (ScoringStrategy strategy : scoringStrategyList) {
            if (strategy.getClass().isAnnotationPresent(ScoringStrategyConfig.class)) {
                ScoringStrategyConfig scoringStrategyConfig = strategy.getClass().getAnnotation(ScoringStrategyConfig.class);
                if (scoringStrategyConfig.appType() == appType && scoringStrategyConfig.scoringStrategy() == appScoringStrategy) {
                    return strategy.doScore(choiceList, app);
                }
            }
        }
        throw new BusinessException(ErrorCode.SYSTEM_ERROR, "应用配置有误,未找到匹配的策略");
    }
}

因为用了 ScoringStrategyConfig 注解,所以这个实现类被加上了 component 注解,因此可以被spring 管理扫描到。 然后 @Resoure 注入的时候,会通过 ScoringStrategy 类型找到所有实现 ScoringStrategy 接口的实现类

标签:项目,app,笔记,ErrorCode,mustRole,import,权限,注解
From: https://www.cnblogs.com/qimoxuan/p/18413002

相关文章

  • 个人项目
    作业信息作业属于哪个课程软件工程https://edu.cnblogs.com/campus/gdgy/CSGrade22-12这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-12/homework/13220这个作业的目标准备、创建、开发、管理、测试个人项目1.PSP表格2.题目描述题目:论......
  • 记一次nginx布署spring cloud项目后,jar包运行正常,但访问静态资源报404的问题。
    1、我们知道springcloud,是通过注册中心来注册所有的应用,这里面也包括网关gateway的注册:2、这里面我们运行了consoleapplication应用,这样里面就有一个Instance。3、测试静态资源的访问:4、consoleapplication结构:5、访问单个模块里的资源是正常的,但是上了服务器,nginx布......
  • 项目运行内存异常问题排查
    一:通过命令排查:有的时候在生产环境是无法使用Jprofiler等工具的,我们只能借助jdk提供的相关命令进行排查top:使用Top命令排查CPU消耗很高的进程top-H-ppid:查到进程消耗的CPU很高的情况下我们可以通过以下命令来定位到那个线程消耗的CPU高转换16进制:因为java中查看线程号使用......
  • 学习笔记JVM篇(三)
    一、垃圾回收机制垃圾回收(GarbageCollection)机制,是自动回收无用对象从而释放内存的一种机制。Java之所以相对简单,很大程度是归功于垃圾回收机制。(例如C语言申请内存后要手动的释放)优点:简化了开发难度,同时让内存分配更合理。缺点:屏蔽了底层,同时垃圾回收也会在一定程度上......
  • 高级系统规划与管理师笔记(一)
    目录第一章信息系统综合知识一、信息基本概念二、信息的传输模型三、信息质量的属性(6)四、信息化从“小”到“大”,分层以下5个层次:五、信息化的基本内涵(重点)六、两化融合:主要为工业化和信息化七、电子政务(区分)八、电子商务的概念九、电子商务的类型十、消费者与消......
  • mysql笔记8(多表查询)
    文章目录1.union联合查询可能会用到去重操作2.innerjoin内连接3.leftjoin左连接4.rightjoin右连接5.crossjoin交叉连接6.naturaljoin自然连接naturalleftjoin自然左连接naturalrightjoin自然右连接自然连接的两张表没有同名字段怎么办?7.using......
  • CMake构建学习笔记16-使用VS进行CMake项目的开发D4
    目录*1.概论2.详论2.1创建工程2.2加载工程2.3配置文件:飞数机场2.4工程配置2.5调试执行3.项目案例4.总结1.概论在之前的系列博文中,我们学习了如何构建第三方的依赖库,也学习了如何去组建自己的CMake项目,尤其是学习了CMake的核心配置文件CMakeLists.txt如......
  • 学习笔记——MMSR 自适应多模态融合的序列推荐
    AdaptiveMulti-ModalitiesFusioninSequentialRecommendation Systems前几天当我在阅读这篇论文的时候,在网上找到的相关资料很少,所以当时我读这篇论文的时候特别痛苦,精读了两天半.....所以现在我将自己学习笔记分享出来,给后面需要的小伙伴借鉴借鉴。我目前也是处于学习的......
  • Premake自动部署OpenGL项目
        很多朋友们在构建项目的时候应该都使用过CMake,在github和gitee的很多项目上面都能看到关于CMake的脚本。不过笔者认为,这东西有时候实在是过于繁重了,特别是这个构建的项目足够大的时候。在这里笔者为大家介绍一款轻量轻量化的软件Premake,它可以很方便构建visuals......
  • Cadenza 项目:机器学习如何改善听力受损人士的音乐聆听体验
        音乐,作为全人类共享的文化瑰宝,具有强大的凝聚力,它不仅塑造了我们的社会风貌,更为我们的身心健康带来诸多益处。然而,听力损失却无情地削弱了这份美妙的体验。据世界卫生组织预测,到2050年,全球将有高达25亿人口面临不同程度的听力损失,其中至少7亿人急需治疗。听力受损使......