一、场景介绍在开发过程中很多情况下,我们需要根据一定的条件来做数据权限,例如:A组织只能看到A组织的数据及其下属机构,B部门只能看到自己的数据等,这时候如果每次都写SQL校验的话,代码会很臃肿,因为他们要定义一套全局的公共数据权限过滤方法通过他们自己。2.实现思路借助Spring的拦截器或过滤器,当请求进入Controller时,将用户的数据权限信息存储在数据权限上下文中,在MyBatis执行SQL之前进行动态拼接。MyBatis-Plus给我们提供了一个DataPermissionHandler接口,用于数据权限控制。它的核心调用逻辑位于DataPermissionInterceptor中,所以我们需要定义一个DataPermissionHandler实现类,注入到MybatisPlusInterceptor中。3、实现步骤定义数据权限配置对象@DatapublicclassDataAuthConfig{privateMapparams;privateDataAuthConfig(){}/***构建实例**@returncom.minportal.platform.common.mybatis.core.DataPermissionContextHolder*@author郭帅*@date2022/7/25*@since1.0**/publicstaticDataAuthConfigcreate(){DataAuthConfigconfig=newDataAuthConfig();config.setParams(newConcurrentHashMap<>(4));返回配置;}/***添加参数**@paramkeysql字段名*@paramvalue值*@returnjava.util.Map*@author郭帅*@date2022/7/25*@since1.0**/publicDataAuthConfigwithParam(Stringkey,Objectvalue){//设置参数params.put(key,价值);//添加参数returnthis;}}定义数据权限上下文publicclassDataAuthContextHolder{privatestaticfinalThreadLocalCONTEXT=newThreadLocal<>();/***获取配置**@returnjava.util.Map*@author郭帅*@date2022/7/25*@since1.0**/publicstaticDataAuthConfiggetContext(){if(Objects.isNull(CONTEXT.get())){synchronized(DataAuthContextHolder.class){//判断是否为空if(Objects.isNull(CONTEXT.get())){CONTEXT.set(DataAuthConfig.create());}}}//返回返回CONTEXT.get();}/***清除数据**@author郭帅*@date2022/7/25*@since1.0**/publicstaticvoidclean(){CONTEXT.remove();}}implementationDataPermissionHandlerinterface/***GlobalDataAuthorityHandler**@author郭帅*@version1.0*@date2022/7/25*/publicclassGlobalDataAuthHandlerimplementsDataPermissionHandler{@OverridepublicExexpressiongetSqlSegment(Expressionwhere,StringmappedStatementId){//从数据权限上下文中获取数据权限参数列表DataAuthConfigconfig=DataAuthContextHolder.getContext();//判断是否为空if(config==null||CollUtil.isEmpty(config.getParams())){returnwhere;}else{returndataScopeFilter(where,config.getParams());}}/***构建过滤条件**@paramwhere条件对象*@paramconditions条件列表*@returnnet.sf.jsqlparser.expression.Expression*@author郭帅*@date2022/7/25*@since1.0**/publicstaticExpressiondataScopeFilter(Expressionwhere,Mapconditions){//定义条件AtomicReferencewhereAtomic=newAtomicReference<>(where);//循环构造条件conditions.forEach((key,value)->{//判断value的类型(collection特殊处理)if(valueinstanceofCollection){Collection>collection=(Collection>)value;InExpression表达式=新在表达式();expression.setLeftExpression(newColumn(key));//获取条件ItemsListitemsList=newExpressionList(collection.stream().map(String::valueOf).map(StringValue::new).collect(Collectors.toList()));expression.setRightItemsList(itemsList);//拼接条件whereAtomic.set(newAndExpression(whereAtomic.get(),expression));}else{whereAtomic.set(newAndExpression(whereAtomic.get(),newEqualsTo(newColumn(key),newStringValue(String.valueOf(value)))));}});返回whereAtomic.get();}}将实现的拦截器注入MybatisPlusInterceptor@ConfigurationpublicclassMybatisPlusConfig{/***分页插件和数据权限插件*/@BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptor=newMybatisPlusInterceptor();//数据权限拦截器.addInnerInterceptor(newDataPermissionInterceptor(newGlobalDataAuthHandler()));返回外挂;}}定义Spring拦截器处理数据权限上下文参数@ComponentpublicclassDataAuthInterceptorimplementsHandlerInterceptor{@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{//设置数据权限信息//ExampleAdepartmentonly你可以查看自己的数据及其子部门A1的数据DataAuthContextHolder.getContext().withParam("organId",Lists.newArrayList("A","A1"));返回HandlerInterceptor.super.preHandle(请求,响应,处理程序);}@OverridepublicvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)throwsException{HandlerInterceptor.super.postHandle(request,response,handler,modelAndView);}@OverridepublicvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex)throwsException{DataAuthContextHolder.clean();}}4.总结大部分的数据权限过滤对于SQL结构不是特别复杂的应该是可以的。这里的数据类型只区分集合和其他类型,如果你的业务有如有其他需求可修改扩充