当前位置 : 主页 > 编程语言 > java >

java配置化快速生成报表查询和excel导出功能。

来源:互联网 收集:自由互联 发布时间:2021-06-28
对Bean添加自定义的两个注释 @Table(tableName="BLACK_INFO",expFileName="黑名单类型",orderBy="id")public class UiBlackInfo {@TableColumn(dbColumn="id")private String id;@TableColumn(dbColumn="reason",excelHeader="理由")privat
对Bean添加自定义的两个注释
@Table(tableName="BLACK_INFO",expFileName="黑名单类型",orderBy="id")
public class UiBlackInfo {
	@TableColumn(dbColumn="id")
	private String id;
	@TableColumn(dbColumn="reason",excelHeader="理由")
	private String reason; // 理由
	@TableColumn(dbColumn="remarks",excelHeader="备注")
	private String remarks;    // 备注
	//@TableColumn(dbColumn="create_by",excelHeader="创建者")
	private String createBy;    // 创建者
	@TableColumn(dbColumn="create_date",excelHeader="创建日期",dbFunc="to_char(create_date,'yyyyMMdd')")
	private String createDate;    // 创建日期
	@TableColumn(dbColumn="update_by",excelHeader="更新者")
	private String updateBy;    // 更新者
	@TableColumn(dbColumn="update_date",excelHeader="更新日期",dbFunc="to_char(update_date,'yyyyMMdd')")
	private String updateDate;    // 更新日期
    getter and setter ....

}
controller中快速生成报表分页查询结果以及excel导出的方法
/**
	 * 通用的查询方法。 通过Bean上的Table table和 TableColumn col 注释拼凑成SQL执行。
	 * select col.dbFunc col.dbColumn,... from table.tableName 
	 * where 1=1 and [col.dbFunc|col.dbColumn]= request.getParameter(field)
	 * order by tale.orderBy;
	 * 然后根据col.excelHeader()组织成展示报表或者excel导出。
	 * 目前把所有字段都作为String来处理。 不是String的,通过dbFunc转成String.
	 * 2017年10月26日 不是String貌似也没有问题,需要测试下。
	 * where后面的条件比对,暂时只支持 = 操作。 其他操作等以后代码跑稳定了再扩展把。。
	 * @param request
	 * @return
	 * @throws Exception
	 */
	protected PageBean
 
   queryData(HttpServletRequest request,PageBean
  
    pageBean) throws Exception{ logger.info(">>>开始通用报表数据查询"); ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass(); // JdbcTemplate appJdbcTemplate = SpringContextUtil.getBean("appJdbcTemplate", JdbcTemplate.class); //得到t的实现类型 Class
   
     repoClass = (Class
    
     )type.getActualTypeArguments()[0]; StringBuilder sql = new StringBuilder("select ");//要执行的SQL //把request里的参数插入到查询对象中。 Field[] fields = repoClass.getDeclaredFields(); StringBuilder sqlCols = new StringBuilder();//sql的字段名 StringBuilder sqlCond = new StringBuilder(" where 1=1 ");//sql的查询条件 List
      paras = new ArrayList();//sql的执行参数 List
       
         tableHeaders = new ArrayList
        
         (); // for(Field field:fields){ for(int i = 0 ; i < fields.length; i ++){ Field field = fields[i]; TableColumn col = field.getAnnotation(TableColumn.class); if(null != col){ //把所有配置了TabelColumn注释的列全部都查出来 String dbFunc = col.dbFunc(); String dbColumn = col.dbColumn(); sqlCols.append(dbFunc + " "+ dbColumn+","); //只有TableColumn里配置了excelHeader属性的列才会最终展示出来。 if(StringUtils.isNotEmpty(col.excelHeader())){ tableHeaders.add(col.excelHeader()); String fieldName = field.getName();//.toLowerCase() if(StringUtils.isNotEmpty(request.getParameter(fieldName))){ String para = request.getParameter(fieldName); if(para.indexOf("%")>=0){ para = URLDecoder.decode(para,"UTF-8"); } //有dbFunc就用dbFunc作为查询条件。如果没有,就用dbColumn sqlCond.append(" and ").append(StringUtils.isEmpty(dbFunc)?dbColumn:dbFunc).append("=?"); paras.add(para); } } }else{ //没有配置col的暂时就不管了。 } } if(StringUtils.isEmpty(sqlCols)){ throw new Exception(repoClass.getSimpleName()+"的TableColumns注释配置不正确"); } //根据bean的注释配置SQL Table table = repoClass.getAnnotation(Table.class); if(null == table){ throw new Exception(repoClass.getSimpleName()+"未配置 Table 注释"); } sql.append(sqlCols.substring(0,sqlCols.length()-1)).append(" from ").append(table.tableName()).append(sqlCond); if(StringUtils.isNotEmpty(table.orderBy())){ sql.append(" order by "+table.orderBy()); } logger.info(">>>封装查询 sql=>"+sql+";paras =>"+paras.toArray()); //封装分页SQL String pagedSQL = "";//分页查询数据SQL String countSQL = "";//获取总记录数SQL int startKey = (pageBean.getCurrPage()-1) * pageBean.getPageSize(); int endKey = startKey + pageBean.getPageSize(); if("oracle".equals(this.getDbType().trim())){ countSQL = "select count(*) COUNT from ("+sql+")"; pagedSQL = "select * from (select rownum rn,t.* from ("+sql.toString()+") t) p where p.rn>"+startKey+" and p.rn<="+endKey; }else if("mysql".equals(this.getDbType().trim())){ countSQL = "select count(*) COUNT from ("+sql+")"; pagedSQL = "select * from ("+sql.toString()+") limit "+startKey+","+pageBean.getPageSize(); }else{ throw new Exception("暂不支持的数据库类型 => "+this.getDbType()); } int totalCount = Integer.parseInt(appJdbcTemplate.queryForMap(countSQL, paras.toArray()).get("COUNT").toString()); pageBean.setTotalCount(totalCount); //查询SQL logger.info(">>>准备执行分页查询 sql=>"+pagedSQL+";paras =>"+paras.toArray()); //查询的结果包含了所有配置了tableColumn注释的field。 List
         
          > queryRes = appJdbcTemplate.queryForList(pagedSQL,paras.toArray()); List
          
            pageT = new ArrayList<>(); for(Map
           
             res:queryRes){ //Oracle分页查询时多出了个rn字段用来分页,结果中要把他去掉。 if("oracle".equals(this.getDbType().trim())){ if(res.containsKey("rn")){ res.remove("rn"); } } //结果过滤 T t = repoClass.newInstance(); for(Field field:fields){ TableColumn col = field.getAnnotation(TableColumn.class); if (null != col) { //将结果拼装成Bean if (res.containsKey(col.dbColumn().toUpperCase())) { String fieldName = field.getName(); String setterName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); Method setter = t.getClass().getMethod(setterName, field.getType()); setter.invoke(t, res.get(col.dbColumn().toUpperCase())); } //为了通用模板前台展示不需要过滤,将tableColumn里excelHeader为空的列从结果Map里去掉。 if (StringUtils.isEmpty(col.excelHeader())) { res.remove(col.dbColumn().toUpperCase()); } } } pageT.add(t); } //将结果全部封装到pageBean里 pageBean.setTableHeaders(tableHeaders.toArray()); pageBean.setPage(queryRes); pageBean.setPageT(pageT); logger.info(">>>通用报表分页查询成功。"); return pageBean; } protected Object exportData(HttpServletRequest request,HttpServletResponse response) throws Exception{ logger.info(">>>开始通用报表导出"); ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass(); //得到t的实现类型 Class
            
              repoClass = (Class
             
              )type.getActualTypeArguments()[0]; StringBuilder sql = new StringBuilder("select ");//要执行的SQL //把request里的参数插入到查询对象中。 Field[] fields = repoClass.getDeclaredFields(); StringBuilder sqlCols = new StringBuilder();//sql的字段名 StringBuilder sqlCond = new StringBuilder(" where 1=1 ");//sql的查询条件 List
               paras = new ArrayList();//sql的执行参数 List
                
                  colNames = new ArrayList<>();//excel导出的列头 List
                 
                   expFields = new ArrayList<>();//excel导出的属性 for(int i = 0 ; i < fields.length;i++){ Field field = fields[i]; String fieldName = field.getName();//.toLowerCase(); TableColumn col = field.getAnnotation(TableColumn.class); if(null != col){ String excelHeader = col.excelHeader(); String dbFunc = col.dbFunc(); String dbColumn = col.dbColumn(); //按excelHeader属性来组织需要导出的列 没有的列会是默认值null if(StringUtils.isNotEmpty(excelHeader)){ colNames.add(excelHeader); expFields.add(dbColumn); sqlCols.append(dbFunc + " "+dbColumn+","); } if(StringUtils.isNotEmpty(request.getParameter(fieldName))){ String para = request.getParameter(fieldName); if(para.indexOf("%")>=0){ para = URLDecoder.decode(para,"UTF-8"); } sqlCond.append(" and ").append(StringUtils.isEmpty(dbFunc)?dbColumn:dbFunc).append("=?"); paras.add(para); } } } if(StringUtils.isEmpty(sqlCols)){ throw new Exception(repoClass.getSimpleName()+"的TableColumns参数配置不正确"); } //根据bean的注释配置SQL Table table = repoClass.getAnnotation(Table.class); if(null == table){ throw new Exception(repoClass.getSimpleName()+"未配置 Table 注释"); } sql.append(sqlCols.substring(0,sqlCols.length()-1)).append(" from ").append(table.tableName()).append(sqlCond); logger.info(">>>准备执行导出数据查询 sql=>"+sql+";paras =>"+paras.toArray()); //查询SQL // JdbcTemplate appJdbcTemplate = SpringContextUtil.getBean("appJdbcTemplate", JdbcTemplate.class); List
                  
                   > queryRes = appJdbcTemplate.queryForList(sql.toString(),paras.toArray()); //将查询结果按照导出的需要组织数据。只有配置了excelHeader属性的的TableColumn列才会导出 List
                   
                     infoList = new ArrayList
                    
                     (); queryRes.stream().forEach(res->{ List
                     
                       rowInfo = new ArrayList<>(); for(int i = 0 ; i < expFields.size();i++){ String expField = expFields.get(i); if(StringUtils.isNotEmpty(expField)){ expField = expField.trim().toUpperCase(); //过滤掉查出结果为空的情况res.get(expField) 为null rowInfo.add(res.containsKey(expField)?(null == res.get(expField))?"":res.get(expField).toString():""); } } infoList.add(CommonUtils.listString2Array(rowInfo)); }); //结果导出 Excelexport excelExport=new Excelexport(request, response,table.expFileName()); excelExport.export(table.expFileName(), infoList,CommonUtils.listString2Array(colNames)); return "EXCEL EXPORTED"; } 
                      
                       pageBean的结构
                       
                      
public class PageBean 
                       
                         implements Serializable{
	private static final long serialVersionUID = 1L;
	/**
	 * 当前页
	 */
	private int currPage;
	/**
	 * 总记录数
	 */
	private int totalCount;
	/**
	 * 总页数
	 */
	private int totalPageCount;
	/**
	 * 每页的记录条数
	 */
	private int pageSize=30;
	/**
	 * 显示的统计标题
	 */
	private String pageTitle = "";
	/**
	 * 当前页的记录
	 */
	private List
                        
                          pageT;; /** * Map形式 保存数据库查出来的结果。 * 通用模版展现时,可以不用过滤 */ private List
                         
                          > page; /** * 通用报表表头列 */ private Object[] tableHeaders; /** * 搜索条件 */ private Map
                          
                            conditions; /** * 下一页的开始行 */ // public String startRowKey; /** * 上一页的开始字段 * */ // public String backStartRowKey; /** * 开始时间 */ // public String starttime; /** * 结束时间 */ // public String endtime; /** * 开始行 */ // public String startRow; /** * 结束行 */ // public String stopRow; /** * 查询方向--向上分页(left)或向下分页(right) */ private String pagingType; getter and setter ... }
                          
                         
                        
                       
网友评论