自定义数据集实现RBP用户资源列表报表需求

用户需求:
列出RBP用户资源列表,目前RBP的功能是提供单个用户的资源列表。用户需要按用户,按机构列出所选用户的资源权限列表。
该需求实现难点在于RBP的权限具有集成关系,目录可以设置继承,下级目录和资源可以继承或不集成该目录的权限。另外用户、机构和角色都可以作为权限的载体,一个用户的最终权限,是由用户本身的权限、用户机构的权限、用户角色的权限三部分组合而成。
介于资源权限逻辑的复杂性,不能通过一个简单的sql就完成逻辑判断得到数据查询结果。

实现思路:
1. 接口开发,遍历RBP的叶子资源,利用系统提供的资源权限判断方法,根据传入的userid和资源id,判断用户是否有资源访问权限,返回该用户有权限的资源列表。
2. 调用接口,完成自定义数据集类开发。调用上面接口,返回数据集结果(用户(多个)的资源列表)。该数据集的结构为resname,url,fatherid,userid。
3. 开发报表,调用自定义数据集生成数据集,在报表中完成分组报表设计。

具体实现:
1. 接口开发:ResPageUtils.java
该接口传入参数userId,返回用户相应资源列表。部分实现代码如下:
public class ResPageUtils {
 public static List getResListbyUser(String userId){
  List<ResInfo> list = new ArrayList<ResInfo>();
  DBAccess dba = null;
  ResultSet rs = null;
  try {
   dba = new DBAccess();
   UserInfo user = “root”.equals(userId) ? null : new UserInfo(userId,dba);
   HashMap pathMap = new HashMap();
   HashMap nameMap = new HashMap();
   rs = dba.executeQuery(“SELECT Res_ID,Res_FatherID,Res_Name FROM T_Res WHERE Res_Type=256 AND Res_IsLeaf=0 AND sys_statu=1″);
   while (rs.next()) {
    int resId = rs.getInt(“Res_ID”);
    int fatherId = rs.getInt(“Res_FatherID”);
    String resName = rs.getString(“Res_Name”);

    pathMap.put(new Integer(resId), new Integer(fatherId));
    nameMap.put(new Integer(resId), resName);
   }
   if (rs != null)
   rs.close();
   //查询出所有的叶子节点资源
   rs = dba.executeQuery(“SELECT Res_ID,Res_Type,Res_Name,Res_Des,Res_FatherID,Res_HasArg,res_path FROM T_Res WHERE Res_ID>10000 AND Res_Type IN (4,8,16,32,64,128,512,10000,10001) AND Res_IsLeaf=1 AND sys_statu=1″);
   ResInfo rif = null;
   //遍历所有的叶子节点资源,判断资源对是否有读取权限,调用了底层基础类的方法Privilege.hasPrivileges,如果有,该资源加入到返回的资源列表中。
   for (int i = 0; rs.next(); i++) {
    rif = new ResInfo();
    int resId = rs.getInt(“Res_ID”);//资源ID
    int resType = rs.getInt(“Res_Type”);//资源类型
    String resName = rs.getString(“Res_Name”);//资源名称
    String resDesc = rs.getString(“Res_Des”);//资源描述
    Integer fatherId = new Integer(rs.getInt(“Res_FatherID”));//资源父id
    int Res_HasArg = rs.getInt(“Res_HasArg”);
    String currResPath = rs.getString(“res_path”);//当前资源路径
    if (!Privilege.hasPrivileges(user, resId, 1, dba))
     continue;
    // 获取资源的路径
    String resPath = “”;
    while (fatherId != null && fatherId.intValue() != -1) {
     resPath = (String) nameMap.get(fatherId) + “>” + resPath;
     fatherId = (Integer) pathMap.get(fatherId);
    }
    while (resPath.endsWith(“>”))
     resPath = resPath.substring(0, resPath.length() – 1);
    
    rif.setResID(resId);
    rif.setResFatherID(fatherId);
    rif.setResType(resType);
    rif.setResDes(resDesc);
    rif.setResName(resName);
    rif.setResPath(resPath);
    list.add(rif);
   }
   if (rs != null)
    rs.close();
  } catch (Exception e) {
//e.printStackTrace();
   list = null;
  //response.sendRedirect(request.getContextPath() + “/mis2/error.jsp”);
  } finally {
   if (dba != null){
    dba.close();
   }
  }
  return list;
 } 
}
2. 自定义数据集类开发
该类继承IDataSetFactory接口,实现接口定义的方法:public DataSet createDataSet(Context ctx, DataSetConfig dsc,boolean retrieve),并返回一个DataSet对象。根据出入的userid列表,循环调用ResPageUtils的getResListbyUser方法,查询多个用户的资源列表并作为数据集返回。部分实现代码:
public class userReslist implements IDataSetFactory{
  public DataSet createDataSet(Context ctx, DataSetConfig dsc, boolean retrieve){
   long time1 = System.currentTimeMillis();
   Map map = ctx.getParamMap(false);
   String[] idlist=null;
   if( map != null ){
       Iterator it = map.keySet().iterator();
         while( it.hasNext() ){
           //分别取得参数
          String key = it.next().toString();
          String value = map.get(key).toString();
          System.out.println(“报表传入的参数”+key+”的值是:”+value);
    //获取报表中的参数userlist,拆分成字符串组
          if(key.equals(“userlist”)&&!value.equals(“”)){
         idlist=value.split(“,”);
          }
          }
         }
   }
//构造一个数据集,添加列名
   DataSet ds = new DataSet(“ds1″);
   ResInfo res=new ResInfo();
   ds.addCol( “resname” );   //列名
   ds.addCol( “url” );  //列名
   ds.addCol( “fatherid” );  //列名
   ds.addCol(“userid”);
   if(idlist!=null){
    for(int j=0;j<idlist.length;j++){
     System.out.println(idlist[j].toString());
     String param=idlist[j].toString();
     List<ResInfo> reslist = new ArrayList<ResInfo>();
     try{
     long time3 = System.currentTimeMillis();
     //调用接口方法getResListbyUser获取用户资源list
     reslist= ResPageUtils.getPageParamsList(idlist[j].toString());
     long time4 = System.currentTimeMillis();
     System.out.println(“计算人员ID为”+idlist[j].toString()+”的资源列表的时间为:>”+(time4-time3)+”ms”);
     System.out.println(“================”);
      }catch (Exception e){
             System.out.println(“自定义异常: 数据不完整”);
             }
    
//根据查询list的数据,设置数据集中的数据
    for( int i = 0; i < reslist.size(); i++ ) {
     //System.out.println( i );
     res=reslist.get(i);
     Row row = ds.addRow();
     row.setData(1, res.getResName());
     row.setData(2, res.getResPath());
     row.setData(3, res.getResFatherID());
     row.setData(4,idlist[j]);
    }
    }
    }
   long time2 = System.currentTimeMillis();
   System.out.println(“数据集创建总时间:>”+(time2-time1)+”ms”);
   return ds;
  }
  
 }
3. 报表模板实现
 1)参数:
 
普通参数:userid 字符串型,orgid字符串组型,这两个参数分别接收参数表单传递过来的用户id和机构id,其中机构id在参数表单中采用可多选的下拉树模式供用户选择。
动态参数:if(userid!=null&&userid!=”",query2(“mis2datasource”,”select user_id from t_user where user_id=?”,userid),orgid!=null&&orgid!=”",query2(“mis2datasource”,”select user_ID from rt_orguser where user_id!=’root’ and org_id in (?)”,orgid))
根据普通参数userid,orgid,动态计算需要查询的用户id列表(多个用户id用,分割)。

2)数据集:
ds1: select a.user_id,a.user_name,b.org_id,e.org_name, c.role_id,d.role_name from t_user a, rt_orguser b, rt_roleuser c, t_role d, t_org e where a.user_id=b.user_id and a.user_id=c.user_id and b.org_id=e.org_id and c.role_id=d.role_id and a.user_id!=’root’ and a.user_id in(?)
参数:split(userlist,”,”)
该数据集可以得到待查询的用户的机构,角色,用户名等用户基本信息。

ds2:采用自定义数据集的方式,此时选择数据集的类型为自定义,然后在编辑界面中输入类名和需要用到的参数。报表运算时,就会自动执行createDataSet()方法来取得报表运算所需要的数据集。
 
3)报表模板设计:
 
A2:设置隐藏行属性,在没有查到用户时,该行显示,否则该行隐藏。
其中A4~C4单元格先按机构分组再按用户id分组,E4单元格:=ds2.Select(resname,false,userid==B4,url+”0″+resname)进行数据集间关联,查出ds2中userid和B4单元格值相等记录,并按照路径和资源名称的升序排列。

实现效果:


热门文章