A-A+

基于Nutz.Dao的数据权限管理的实现2

2016年05月31日 技术 暂无评论 阅读 3,303 次

索引请点击这里

上篇文章说到简单的实现了数据权限的管理,但是从代码清晰度、条理性上来看,还是十分粗糙的,只能凑合着使用。要么说干这行纯粹就是跟自己作对呢,要么说程序员大都是完美主义者呢,所以我用我仅有的Java编程经验,绞尽脑汁的又改了一版出来,我觉的对于我来说没准就算到头了。

这次改进主要关注以下几个点:

1. 当前登录的人员不再由调用方传入,所以减少了一个参数。我觉的就应该是这样的,调用方不需要传输无用的参数,不管调用方怎么调用,该做数据过滤的时候是一定要做的,这个其实应该由底层去强制控制,越底层越好。

2. 不要普通的工程师在开发Dao内的函数时显式调用工具类生成SQL,应该直接指定SQL,然后由底层去格式化。这样的话,一般的工程师不需要管数据权限是怎么实现的,只需要按照规则去写代码即可,便于项目组中的成员高低搭配。但是我做不到或者不想做成在JDBC层直接拦截的,因为我觉的分析原生SQL是一件很麻烦的事情,没有时间去开发、调试、改进。所以我还是定下了SQL书写的规则,通过模板引擎来间接实现控制,这样折中的办法对于我来说性价比较高。

以下就是实现的过程(贴代码):

1. 自定义Nutz.Dao的FileSqlManager

  1. import com.xnck.common.util.BeanUtil;
  2. import org.nutz.dao.SqlNotFoundException;
  3. import org.nutz.dao.Sqls;
  4. import org.nutz.dao.impl.NutDao;
  5. import org.nutz.dao.sql.Sql;
  6. /**
  7.  * 重写nutz.dao的FileSqlManager类
  8.  * 使用SQL文件创建Sql对象时,如果包含指定的关键字,则使用权限控制
  9.  */
  10. public class FileSqlManager extends org.nutz.dao.impl.FileSqlManager {
  11.     private String ruleKeyword = "ByRule";
  12.     private volatile static NutDao dao;
  13.     public FileSqlManager(String... paths){
  14.         super(paths);
  15.     }
  16.     public String getRuleKeyword() {
  17.         return ruleKeyword;
  18.     }
  19.     public void setRuleKeyword(String ruleKeyword) {
  20.         this.ruleKeyword = ruleKeyword;
  21.     }
  22.     public Sql create(String key) throws SqlNotFoundException {
  23.         String sql = get(key);
  24.         if (key.toLowerCase().contains(ruleKeyword.toLowerCase())){
  25.             NutDao dao = getDao();
  26.             sql = SqlRuleTool.injectSearchSql(dao, key, sql);
  27.         }
  28.         return Sqls.create(sql);
  29.     }
  30.     private static NutDao getDao() {
  31.         if (null == dao) {
  32.             synchronized (FileSqlManager.class){
  33.                 if (null == dao){
  34.                     dao = BeanUtil.getBean("dao", NutDao.class);
  35.                 }
  36.             }
  37.         }
  38.         return dao;
  39.     }
  40. }

2. 修改Spring配置文件

  1. <bean id="daoRunner" class="com.xnck.sysbase.dao.helper.SpringDaoRunner" />
  2. <bean id="sqlManager" class="com.xnck.sysbase.dao.helper.FileSqlManager">
  3.     <constructor-arg name="paths" value="all.sqls" />
  4. </bean>
  5. <bean id="dao" class="org.nutz.dao.impl.NutDao">
  6.     <property name="dataSource" ref="dataSource"/>
  7.     <property name="runner" ref="daoRunner"/>
  8.     <property name="sqlManager" ref="sqlManager"/>
  9. </bean>

然后就没了,上文中的SqlRuleTool可以参见上一篇文章,调用的时候会更加简洁,比如:

  1. public List<UserInfo> getUsersByRule(String byUserId, Condition cnd){
  2.         //Sql sql = SqlTool.injectSearchSql(this.dao, "userDao.getUsersByRule", byUserId);
  3.         Sql sql = this.dao.sqls().create("userDao.getUsersByRule");
  4.         sql.setParam("byuserid", byUserId);
  5.         sql.setCondition(cnd);
  6.         return this.search(sql);
  7.     }

如果确定不需要传入byUserId的话,可以将原始SQL语句的@byUserId作为保留字,在自定义的FileSqlManager 内判断处理后的SQL是否包含这个保留字,如果包含的话直接用sql.setParam给参数赋值,就能够让代码更加简洁一些。

这里要注意的是SqlRuleTool或得当前登录人是通过一个封装类来完成的。我前几年一直在微软平台下工作,当时.NET有一个全局的封装类可以获得当前的登录人,在使用Java时我还苦恼为什么没有这么一个类,直到前些日子我才偶然发现这个类其实是需要自己封装的,所以才能让我豁然开朗了一小下。

至此,我觉的我已经尽了全力进行封装,除非哪天再豁然开朗一下了。同时推荐读一下《聊聊数据权限那些事》,是通过JDBC层来进行数据权限管理,更加底层更加灵活更加完善,当然要熟悉和使用或者自行仿制一个也更耗费时间,不过借鉴一下,将某些东西植入到自己的东西里面,也是一件不错的事情。

给我留言

Copyright © 字痕随行 保留所有权利.   Theme  Ality

用户登录

分享到: