第五章 【若依框架:优化】高级特性与性能优化

目录

一、异步任务管理器

[1. 异步处理优势](#1. 异步处理优势)

[2. 异步管理器实现](#2. 异步管理器实现)

二、操作日志自动化记录

[1. @Log注解使用](#1. @Log注解使用)

[2. AOP切面实现](#2. AOP切面实现)

三、定时任务管理

[1. Quartz核心配置](#1. Quartz核心配置)

[2. 定时任务工具类](#2. 定时任务工具类)

[3. 集群模式配置](#3. 集群模式配置)

四、数据权限控制

[1. 数据权限类型](#1. 数据权限类型)

[2. @DataScope注解使用](#2. @DataScope注解使用)

[3. MyBatis SQL拼接](#3. MyBatis SQL拼接)

[4. 数据权限切面实现](#4. 数据权限切面实现)


本文介绍了企业级应用中的四个核心功能实现方案:

1.异步任务管理器通过线程池实现非阻塞任务处理,提升系统性能;

2.操作日志自动化记录利用AOP切面和自定义注解实现方法级日志采集;

3.定时任务管理基于Quartz框架实现分布式任务调度,支持集群部署;

4.数据权限控制通过注解和SQL拼接实现多维度数据访问控制。这些方案通过注解驱动、AOP切面等技术手段,实现了业务逻辑与技术实现的解耦,提高了系统的可维护性和扩展性。

一、异步任务管理器

1. 异步处理优势
  • 性能提升:将非核心业务异步执行,减少主线程等待时间

  • 故障隔离:异步任务失败不影响主业务事务

  • 提高响应速度:用户无需等待所有任务完成

2. 异步管理器实现
java 复制代码
// 异步管理器单例
public class AsyncManager {
    private static AsyncManager instance = new AsyncManager();
    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
    
    public static AsyncManager me() {
        return instance;
    }
    
    public void execute(TimerTask task) {
        executor.schedule(task, 10, TimeUnit.MILLISECONDS);
    }
}

// 异步工厂
public class AsyncFactory {
    public static TimerTask recordLoginLog(String username, String status, String message) {
        return new TimerTask() {
            @Override
            public void run() {
                // 构建日志对象
                SysLogininfor logininfor = new SysLogininfor();
                logininfor.setUserName(username);
                logininfor.setStatus(status);
                logininfor.setMsg(message);
                logininfor.setLoginTime(new Date());
                
                // 异步保存日志
                SpringUtils.getBean(ISysLogininforService.class)
                    .insertLogininfor(logininfor);
            }
        };
    }
}

// 使用示例
AsyncManager.me().execute(AsyncFactory.recordLoginLog(
    username, 
    Constants.LOGIN_SUCCESS, 
    "登录成功"
));

二、操作日志自动化记录

1. @Log注解使用
java 复制代码
@Log(title = "用户管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SysUser user) {
    return toAjax(userService.insertUser(user));
}

@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SysUser user) {
    return toAjax(userService.updateUser(user));
}

@Log(title = "用户管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{userIds}")
public AjaxResult remove(@PathVariable Long[] userIds) {
    return toAjax(userService.deleteUserByIds(userIds));
}
2. AOP切面实现
java 复制代码
@Aspect
@Component
public class LogAspect {
    
    @Around("@annotation(controllerLog)")
    public Object around(ProceedingJoinPoint joinPoint, Log controllerLog) throws Throwable {
        // 执行前记录开始时间
        long beginTime = System.currentTimeMillis();
        
        // 执行方法
        Object result = joinPoint.proceed();
        
        // 执行后记录日志
        long time = System.currentTimeMillis() - beginTime;
        recordLog(joinPoint, controllerLog, result, time);
        
        return result;
    }
    
    private void recordLog(ProceedingJoinPoint joinPoint, Log log, Object result, long time) {
        // 异步记录操作日志
        AsyncManager.me().execute(AsyncFactory.recordOper(
            log.title(),
            log.businessType(),
            joinPoint.getArgs(),
            result,
            time
        ));
    }
}

三、定时任务管理

1. Quartz核心配置
java 复制代码
@Configuration
public class ScheduleConfig {
    
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setDataSource(dataSource);
        
        Properties prop = new Properties();
        // 集群配置
        prop.put("org.quartz.jobStore.isClustered", "true");
        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
        
        factory.setQuartzProperties(prop);
        factory.setSchedulerName("FrameworkScheduler");
        factory.setStartupDelay(1);
        factory.setOverwriteExistingJobs(true);
        factory.setAutoStartup(true);
        
        return factory;
    }
}
2. 定时任务工具类
java 复制代码
public class ScheduleUtils {
    
    // 创建定时任务
    public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException {
        Class<? extends Job> jobClass = getQuartzJobClass(job);
        
        // 构建JobDetail
        JobDetail jobDetail = JobBuilder.newJob(jobClass)
            .withIdentity(getJobKey(job.getJobId()))
            .build();
        
        // 构建触发器
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
            .cronSchedule(job.getCronExpression());
        CronTrigger trigger = TriggerBuilder.newTrigger()
            .withIdentity(getTriggerKey(job.getJobId()))
            .withSchedule(cronScheduleBuilder)
            .build();
        
        // 将任务参数传入JobDataMap
        jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
        
        scheduler.scheduleJob(jobDetail, trigger);
        
        // 暂停任务
        if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) {
            pauseJob(scheduler, job.getJobId());
        }
    }
}
3. 集群模式配置
  1. 导入Quartz集群表

  2. 修改配置开启集群

  3. 多节点部署实现负载均衡

集群优势

  • 高可用性:单点故障不影响服务

  • 负载均衡:任务分散执行

  • 数据持久化:任务状态不丢失

四、数据权限控制

1. 数据权限类型
java 复制代码
public class DataScopeConstants {
    // 全部数据权限
    public static final String DATA_SCOPE_ALL = "1";
    // 自定义数据权限
    public static final String DATA_SCOPE_CUSTOM = "2";
    // 部门数据权限
    public static final String DATA_SCOPE_DEPT = "3";
    // 部门及以下数据权限
    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
    // 仅本人数据权限
    public static final String DATA_SCOPE_SELF = "5";
}
2. @DataScope注解使用
java 复制代码
@Service
public class SysLogininforServiceImpl implements ISysLogininforService {
    
    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor) {
        return logininforMapper.selectLogininforList(logininfor);
    }
}
3. MyBatis SQL拼接
XML 复制代码
<select id="selectLogininforList" parameterType="SysLogininfor" resultMap="SysLogininforResult">
    select * from sys_logininfor l
    left join sys_dept d on l.dept_id = d.dept_id
    left join sys_user u on l.user_id = u.user_id
    <where>
        <!-- 查询条件 -->
        <if test="userName != null and userName != ''">
            AND l.user_name like concat('%', #{userName}, '%')
        </if>
        <!-- 数据范围过滤 -->
        ${params.dataScope}
    </where>
</select>
4. 数据权限切面实现
java 复制代码
@Aspect
@Component
public class DataScopeAspect {
    
    @Before("@annotation(controllerDataScope)")
    public void doBefore(JoinPoint point, DataScope controllerDataScope) {
        clearDataScope(point);
        handleDataScope(point, controllerDataScope);
    }
    
    protected void handleDataScope(JoinPoint joinPoint, DataScope controllerDataScope) {
        // 获取当前用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser currentUser = loginUser.getUser();
        
        if (!currentUser.isAdmin()) {
            // 构建数据范围SQL
            String dataScopeSql = buildDataScopeSql(currentUser, 
                controllerDataScope.deptAlias(), 
                controllerDataScope.userAlias());
            
            // 设置到参数中
            Object params = joinPoint.getArgs()[0];
            if (params instanceof BaseEntity) {
                ((BaseEntity) params).getParams()
                    .put("dataScope", " AND (" + dataScopeSql + ")");
            }
        }
    }
    
    private String buildDataScopeSql(SysUser user, String deptAlias, String userAlias) {
        StringBuilder sql = new StringBuilder();
        
        for (SysRole role : user.getRoles()) {
            String dataScope = role.getDataScope();
            
            switch (dataScope) {
                case DataScopeConstants.DATA_SCOPE_CUSTOM:
                    sql.append(String.format(
                        " OR %s.dept_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id = %d) ",
                        deptAlias, role.getRoleId()));
                    break;
                case DataScopeConstants.DATA_SCOPE_DEPT:
                    sql.append(String.format(" OR %s.dept_id = %d ", deptAlias, user.getDeptId()));
                    break;
                case DataScopeConstants.DATA_SCOPE_DEPT_AND_CHILD:
                    sql.append(String.format(
                        " OR %s.dept_id IN (SELECT dept_id FROM sys_dept WHERE dept_id = %d or find_in_set(%d, ancestors))",
                        deptAlias, user.getDeptId(), user.getDeptId()));
                    break;
                case DataScopeConstants.DATA_SCOPE_SELF:
                    if (StringUtils.isNotBlank(userAlias)) {
                        sql.append(String.format(" OR %s.user_id = %d ", userAlias, user.getUserId()));
                    }
                    break;
            }
        }
        
        return sql.length() > 0 ? sql.substring(4) : "1=0";
    }
}
相关推荐
一叶之秋14121 小时前
基石之力:掌握 C++ 继承的核心奥秘
开发语言·c++·算法
见牛羊2 小时前
CMakeLists 写法总结3.0
开发语言·c++
大模型玩家七七2 小时前
效果评估:如何判断一个祝福 AI 是否“走心”
android·java·开发语言·网络·人工智能·batch
河码匠2 小时前
设计模式之依赖注入(Dependency Injection)
java·设计模式·log4j
YuTaoShao2 小时前
【LeetCode 每日一题】3721. 最长平衡子数组 II ——(解法二)分块
java·算法·leetcode
m0_528749002 小时前
linux编程----目录流
java·前端·数据库
qq_370773092 小时前
python实现人脸识别
开发语言·python·opencv
spencer_tseng2 小时前
Thumbnail display
java·minio
jay神2 小时前
基于SpringBoot的英语自主学习系统
java·spring boot·后端·学习·毕业设计