在若依框架中看到了一段代码里面
${params.dataScope} 用法是我第一次看到,后面看了后震惊了。不是技术有多难,而是从来没有从这个角度考虑过mybatis可以这么用。非常灵活

where d.del_flag = ‘0’

AND parent_id = #{parentId}

AND dept_name like concat(’%’, #{deptName}, ‘%’)

AND status = #{status}

${params.dataScope}
order by d.parent_id, d.order_num

这里params.dataScope就是单纯的字符串,里面代表了一串sql,通过$拼接到末尾。

然后我们看若依是如何拼接的
这里是注解的标注位置,server层获取部门清单的位置
/** * 查询部门管理数据 * * @param dept 部门信息 * @return 部门信息集合 */ @Override
@DataScope(deptAlias = "d") public List<SysDept> selectDeptList(SysDept dept) {
return deptMapper.selectDeptList(dept); }
下面是重点,通过切面动态拼接params.dataScope参数,从而改变sql查询的范围。
该切面是发生在@DataScope标注的方法执行前进行切入和处理, /** * 数据过滤处理 * * @author sj */ @Aspect
@Component public class DataScopeAspect { /** * 全部数据权限 */ 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"; /** * 数据权限过滤关键字 */ public static final String DATA_SCOPE
= "dataScope"; // 配置织入点
@Pointcut("@annotation(com.sj.common.annotation.DataScope)") public void
dataScopePointCut() { } @Before("dataScopePointCut()") public void
doBefore(JoinPoint point) throws Throwable { handleDataScope(point); }
protected void handleDataScope(final JoinPoint joinPoint) { // 获得注解 DataScope
controllerDataScope = getAnnotationLog(joinPoint); if (controllerDataScope ==
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()) { dataScopeFilter(joinPoint, currentUser,
controllerDataScope.deptAlias(), controllerDataScope.userAlias()); } } } /** *
数据范围过滤 * * @param joinPoint 切点 * @param user 用户 * @param userAlias 别名 */ public
static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String
deptAlias, String userAlias) { StringBuilder sqlString = new StringBuilder();
for (SysRole role : user.getRoles()) { String dataScope = role.getDataScope();
if (DATA_SCOPE_ALL.equals(dataScope)) { sqlString = new StringBuilder(); break;
} else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
sqlString.append(StringUtils.format( " OR {}.dept_id IN ( SELECT dept_id FROM
sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId())); } else if
(DATA_SCOPE_DEPT.equals(dataScope)) { sqlString.append(StringUtils.format(" OR
{}.dept_id = {} ", deptAlias, user.getDeptId())); } else if
(DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
sqlString.append(StringUtils.format( " OR {}.dept_id IN ( SELECT dept_id FROM
sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias,
user.getDeptId(), user.getDeptId())); } else if
(DATA_SCOPE_SELF.equals(dataScope)) { if (StringUtils.isNotBlank(userAlias)) {
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias,
user.getUserId())); } else { // 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(" OR 1=0 "); } } } if
(StringUtils.isNotBlank(sqlString.toString())) { Object params =
joinPoint.getArgs()[0]; if (StringUtils.isNotNull(params) && params instanceof
BaseEntity) { BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) +
")"); } } } /** * 是否存在注解,如果存在就获取 */ private DataScope
getAnnotationLog(JoinPoint joinPoint) { Signature signature =
joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature)
signature; Method method = methodSignature.getMethod(); if (method != null) {
return method.getAnnotation(DataScope.class); } return null; } }
作为前置知识需要了解角色管理页面中,可以配置下面几种数据范围 /** * 全部数据权限 */ public static final String
DATA_SCOPE_ALL = "1"; 不做任何处理 /** * 自定数据权限 */ public static final String
DATA_SCOPE_CUSTOM = "2"; 查询 部门角色对应表中,用户具备的角色可以管理那些部门 OR d.dept_id IN ( SELECT
dept_id FROM sys_role_dept WHERE role_id = {rolelist} ) /** * 部门数据权限 */ public
static final String DATA_SCOPE_DEPT = "3"; 查询部门编号=用户所在部门编号的数据 OR {}.dept_id =
{} /** * 部门及以下数据权限 */ public static final String DATA_SCOPE_DEPT_AND_CHILD =
"4"; 查询部门和子部门的权限 /** * 仅本人数据权限 */ public static final String DATA_SCOPE_SELF =
"5"; if (StringUtils.isNotBlank(userAlias)) {
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias,
user.getUserId())); } else { // 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(" OR 1=0 "); }
总结:

这是利用mybatis语法比较巧妙的地方,目前被用在部门上,利用这种方法在项目中改造一下,可以适配项目具体的数据需求。

技术
©2019-2020 Toolsou All rights reserved,
macOS Big Sur无法完成安装 Big Sur为什么安装不了?Pandas与openpyxl库的超强结合,再见,Excel!2021-06-03一个人不是生来就要被打败的关于linux 命令“iptables -F”,不要轻易执行随机数的生成+猜数字游戏OpenCV python 模板匹配(多匹配)Python 引用cfg类型的配置文件(configparser)(telnetlib的使用方法)navicat运行sql文件时错误JVM老年代垃圾回收Full GCplc和单片机哪个更有前途?为什么本科生都不搞plc?