在《Springboot管理系统数据权限过滤(四)——mybatis数据权限插件》中动态实现数据权限控制。
在获取数据权限时分页未处理好,导致添加数据权限后,分页未正常获取数据总条数的问题。
package com.ruoyi.web.core.config;
import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.luo.chengrui.datapermission.interceptor.DataPermissionSqlParserInterceptor;
import com.luo.chengrui.datapermission.rules.DataPermissionRule;
import com.luo.chengrui.datapermission.rules.DefaultDataPermissionRule;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.config.service.ICkStorageService;
import com.ruoyi.framework.datapermissionRule.DeptDatapermissionRule;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.StringValue;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author
* @version 1.0.0
* @description
* @createTime 2023/07/17
*/
@Configuration
public class DefaultDataPermissionConfiguration {
/**
* 初始化部门权限 bean 。
*
* @return
*/
@Bean
public DataPermissionRule deptDataPermissionRule() {
DefaultDataPermissionRule rule = new DefaultDataPermissionRule(() -> {
// 如果是分页,这里需先去掉分页线参数,不然会出线线程污染。待数据权限查询结果完结后,再设置分页参数。
// 当然更好的做法是权限数据从缓存中获取,这样就不需要如此做了。
Page page = PageHelper.getLocalPage();
PageHelper.clearPage();
// 在这里动态获取用户权限;
ICkStorageService ckStorageService = SpringUtils.getBean(ICkStorageService.class);
Set<StringValue> set = null;
//DeptDatapermissionRule是业务自己实现的权限获取方法。
Set<Long> deptIds = DeptDatapermissionRule.getStorageIds();
if (deptIds != null) {
set = new HashSet<>();
if (CollectionUtil.isNotEmpty(deptIds)) {
List<String> storageId = ckStorageService.getSotageIdsByDeptIds(deptIds);
set.addAll(storageId.stream().map(id -> new StringValue(id)).collect(Collectors.toList()));
}
}
if (page != null) {
// 把分页参数设置回线程变量中。
// PageHelper.startPage(page.getPageNum(), page.getPageSize(), page.getOrderBy()).setReasonable(page.getReasonable());
//这里要这么写,因为page中包含了如total的数据,所以不能再startPage。以防分页异常
PageHelper.setLocalPage(page);
}
return set;
});
//当sql中包含以下两个表时,进行数据过滤。
rule.addTableAndColumn("wms_order_info", "storage_id");
rule.addTableAndColumn("wms_sorder_info", "storage_id");
return rule;
}
@Bean
public DataPermissionSqlParserInterceptor dataPermissionSqlParserInterceptor(SqlSessionFactory sqlSessionFactory, List<DataPermissionRule> dataPermissionRuleList) {
DataPermissionSqlParserInterceptor dataPermissionSqlParserInterceptor = new DataPermissionSqlParserInterceptor(dataPermissionRuleList);
if (sqlSessionFactory instanceof SqlSessionFactoryBean) {
((SqlSessionFactoryBean) sqlSessionFactory).setPlugins(dataPermissionSqlParserInterceptor);
}
return dataPermissionSqlParserInterceptor;
}
}
代码块修改一行代码,之前是重新startPage了,导致丢失了count总数。
if (page != null) {
// 把分页参数设置回线程变量中。
// PageHelper.startPage(page.getPageNum(), page.getPageSize(), page.getOrderBy()).setReasonable(page.getReasonable());
//这里要这么写,因为page中包含了如total的数据,所以不能再startPage。以防分页异常
PageHelper.setLocalPage(page);
}
以上,解决PageHelper分页问题,在使用PageHelper的过程中要特别小心,在startPage之后执行的第一个SQL会执行分页(查询总数,再查询结果),第一个执行分页后,会立即clearPage,那么后面执行的SQL将不会再进行分页。