一、MyBatisPlusConfig配置:
package com.ruoyi.framework.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.ruoyi.framework.datascope.DataScopeInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * Mybatis Plus 配置 * * @author ruoyi */ @EnableTransactionManagement(proxyTargetClass = true) @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 數據權限 interceptor.addInnerInterceptor(dataScopeInterceptor()); // 分頁插件 interceptor.addInnerInterceptor(paginationInnerInterceptor()); // 樂觀鎖插件 interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor()); return interceptor; } /** * 分頁插件,自動識別數據庫類型 */ public PaginationInnerInterceptor paginationInnerInterceptor() { PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); // 設置數據庫類型為mysql paginationInnerInterceptor.setDbType(DbType.MYSQL); // 設置最大單頁限制數量,默認 500 條,-1 不受限制 paginationInnerInterceptor.setMaxLimit(-1L); return paginationInnerInterceptor; } /** * 樂觀鎖插件 */ public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() { return new OptimisticLockerInnerInterceptor(); } /** * 數據權限插件 * * @return DataScopeInterceptor */ public DataScopeInterceptor dataScopeInterceptor() { return new DataScopeInterceptor(); } }
二、DataScopeInnerInterceptor數據權限攔截器配置
package com.ruoyi.framework.datascope; import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.toolkit.PluginUtils; import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; import com.ruoyi.common.Enum.DataScopeTypeEnum; import com.ruoyi.common.core.data.DataScope; import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.framework.web.service.TokenService; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import java.util.List; import java.util.Map; /** * 數據權限 * * @author: Fred * @email 453086@qq.com * @create: 2021-05-25 11:12 */ public class DataScopeInterceptor implements InnerInterceptor { @Override public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql); String originalSql = boundSql.getSql(); Object parameterObject = boundSql.getParameterObject(); // 查找參數中包含DataScope類型的參數 DataScope dataScope = findDataScopeObject(parameterObject); if (dataScope == null) { return; } LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest()); if (StringUtils.isNotNull(loginUser)) { SysUser currentUser = loginUser.getUser(); // 如果是超級管理員,則不過濾數據 if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) { String scopeName = dataScope.getScopeName(); List<String> deptIds = dataScope.getDeptIds(); dataScopeFilter(currentUser, deptIds); if (deptIds.isEmpty()) { originalSql = String.format("SELECT %s FROM (%s) temp_data_scope WHERE 1 = 2", dataScope.getFunc().getType(), originalSql); } else { String join = CollectionUtil.join(deptIds, ","); originalSql = String.format("SELECT %s FROM (%s) temp_data_scope WHERE temp_data_scope.%s IN (%s)", dataScope.getFunc().getType(), originalSql, scopeName, join); } } } mpBs.sql(originalSql); } /** * 查找參數是否包括DataScope對象 * * @param parameterObj 參數列表 * @return DataScope */ private DataScope findDataScopeObject(Object parameterObj) { if (parameterObj instanceof DataScope) { return (DataScope) parameterObj; } else if (parameterObj instanceof Map) { for (Object val : ((Map<?, ?>) parameterObj).values()) { if (val instanceof DataScope) { return (DataScope) val; } } } return null; } /** * 數據范圍 * * @return */ private void dataScopeFilter(SysUser user, List<String> deptList) { for (SysRole role : user.getRoles()) { String roleScope = role.getDataScope(); if (DataScopeTypeEnum.ALL.getType().equals(roleScope)) { return; } if (DataScopeTypeEnum.CUSTOM.getType().equals(roleScope)) { // 獲取自定義 } if (DataScopeTypeEnum.OWN_CHILD_LEVEL.getType().equals(roleScope)) { // 獲取子集 } if (DataScopeTypeEnum.OWN_LEVEL.getType().equals(roleScope)) { deptList.add(user.getDeptId().toString()); } } } }
/* * Copyright (c) 2018-2025, lengleng All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the pig4cloud.com developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: lengleng (wangiegie@gmail.com) */ package com.ruoyi.common.core.data; import com.ruoyi.common.Enum.DataScopeFuncEnum; import lombok.Data; import lombok.EqualsAndHashCode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * @author lengleng * @date 2018/8/30 * 數據權限查詢參數 */ @Data @EqualsAndHashCode(callSuper = true) public class DataScope extends HashMap { /** * 限制范圍的字段名稱 */ private String scopeName = "dept_id"; /** * 具體的數據范圍 */ private List<String> deptIds = new ArrayList<>(); /** * 是否只查詢本部門 */ private Boolean isOnly = false; /** * 函數名稱,默認 SELECT * ; * * <ul> * <li>COUNT(1)</li> * </ul> */ private DataScopeFuncEnum func = DataScopeFuncEnum.ALL; }
/* * Copyright (c) 2018-2025, lengleng All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the pig4cloud.com developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: lengleng (wangiegie@gmail.com) */ package com.ruoyi.common.Enum; import lombok.AllArgsConstructor; import lombok.Getter; /** * 數據權限函數類型 * * @author lengleng * @date 2020-06-17 */ @Getter @AllArgsConstructor public enum DataScopeFuncEnum { /** * 查詢全部數據 SELECT * FROM (originSql) temp_data_scope WHERE temp_data_scope.dept_id IN * (1) */ ALL("*", "全部"), /** * 查詢函數COUNT SELECT COUNT(1) FROM (originSql) temp_data_scope WHERE * temp_data_scope.dept_id IN (1) */ COUNT("COUNT(1)", "自定義"); /** * 類型 */ private final String type; /** * 描述 */ private final String description; }
