请上传宽度大于 1200px,高度大于 164px 的封面图片
    调整图片尺寸与位置
    滚轮可以放大缩小图片尺寸,按住图片拖动可调整位置,多余的会自动被裁剪掉
取消
liqc(uid:89199)
职业资格认证:尚未取得认证
MongoDB程序数据源+报表设计探路
程序数据源之所以要用到程序数据源,是因为组内的项目使用的数据库是MongoDB,而帆软的mongodb插件支持的查询深度还不够,所以采用程序数据源的方式来处理。 帆软报表控件程序数据源的写法说白了比较简单,就是实现AbstractTableData这个抽象类,然后实现其中的4个抽象方法即可。 但是使用起来不是很顺畅,原因在于: - 首先要在在IDE中写程序数据源的代码; - 然后编译对应的代码生成class文件; - 将class文件拷贝到帆软报表设计器对应的classes目录下; - 打开报表设计器选择程序数据源(class文件)进行报表设计; - 设计完成的报表拷贝到项目的reportlets目录下; 可以看到,需要不停地在IDE和报表设计器之间切换,还需要在资源管理器中移动文件。可能这是目前嵌入式部署不得不面对的问题,如果是独立部署的话,可能就仅仅需要将classes文件拷贝到帆软报表设计器对应目录下即可。 测试程序数据源可行性在项目中写了一个数据源,如下:public class TestDemo extends AbstractTableData { private String columnNames; private Object rowData; public TestDemo() { String columnNames = {"Name", "Score"}; Object datas = {{"Alex", new Integer(15)}, {"Helly", new Integer(22)}, {"Bobby", new Integer(99)}}; this.columnNames = columnNames; this.rowData = datas; } @Override public int getColumnCount() throws TableDataException { return columnNames.length; } @Override public String getColumnName(int columnIndex) throws TableDataException { return columnNames; } @Override public int getRowCount() throws TableDataException { return rowData.length; } @Override public Object getValueAt(int rowIndex, int columnIndex) { return rowData; }} 不涉及业务,不涉及mongodb数据库,仅仅测试一下可行性。 按照上面的步骤设计完报表之后,将报表拷贝回项目reportlets目录,运行: http://img.blog.csdn.net/20170807094355603?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWNoYW5nMDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast 可以看到,程序运行OK,报表也能正常显示。 MongoDB程序数据源由于写了程序数据源之后,是要放到报表设计器目录下进行报表设计才能看到结果的,这样给调试带来了一些难度。 解决办法就是: - main方法进行跟踪调试; - 单元测试; // 数据源一共有多少列(多少个字段) public abstract int getColumnCount() throws TableDataException; // 对应index的那一列的列名(字段名)是什么 public abstract String getColumnName(int index) throws TableDataException; // 数据源一共有多少行(多少条记录) public abstract int getRowCount() throws TableDataException; // 对应rowIndex的那一行的第columnIndex列的数值 public abstract Object getValueAt(int rowIndex, int columnIndex); 从抽象类接口可以看出,四个抽象方法意义很明确,使用main方法或者单元测试来进行验证的话,跟踪调试查看的数据没有问题,那么报表中的数据应该就没有问题。关于数据库连接的问题按照从前的思维,希望能够使用数据库连接池,复用数据库连接。 然后发现MongoDB的MongoClient和关系型数据库的连接还是有一些区别的,可能开销没有那么大。因此在数据源中直接new新的MongoClient来使用。 再后来仔细想想,我们的程序数据源不是运行在我们的Web容器中,不是使用spring进行管理,而是编译成为class文件之后拷贝到帆软的设计器目录下使用的,那个时候,怎么使用数据库连接池中的连接资源呢? 所以,目前还是在每个数据源中直接new连接的方式来操作,有没有更好的办法抽空问问帆软的技术支持。数据源Demo按照业务,从我们自己的mongo数据库中获取数据,写了如下一个数据源:public class BQItemDataSource extends AbstractTableData { private enum Field_Name { CODE("code"), DESCRIPTION("description"), SPEC("spec"), UNIT("unit"), JLGZ("jlgz"), TYPE("type"), QUANTITY("quantity"); private String fieldName; private Field_Name(String fieldName) { this.fieldName = fieldName; } @Override public String toString() { return fieldName; } } private String columnNames; private ArrayList> rowData; public BQItemDataSource() {// setDefaultParameters(new Parameter {new Parameter("ObjectId")}); columnNames = new String; int i = 0; for (Field_Name fieldName : Field_Name.values()) { columnNames = fieldName.toString(); } } @Override public int getColumnCount() throws TableDataException { return columnNames.length; } @Override public String getColumnName(int columnIndex) throws TableDataException { return columnNames; } @Override public int getRowCount() throws TableDataException { init(); return rowData.size(); } @Override public Object getValueAt(int rowIndex, int columnIndex) { init(); if (columnIndex >= columnNames.length) { return null; } if (rowIndex >= rowData.size()) { return null; } return rowData.get(rowIndex).get(columnNames); } public void init() { if (rowData != null) { return; } rowData = new ArrayList>();// String objectId = parameters.getValue().toString(); String objectId = "5959b01b9107541bbc5cb98b"; JSONArray dataArray = getMongoTableData(); for (int i = 0; i row = new LinkedHashMap(); if (dataObj.containsKey(Field_Name.CODE.toString())) { row.put(Field_Name.CODE.toString(), dataObj.getString(Field_Name.CODE.toString())); } else { row.put(Field_Name.CODE.toString(), null); } if (dataObj.containsKey(Field_Name.DESCRIPTION.toString())) { row.put(Field_Name.DESCRIPTION.toString(), dataObj.getString(Field_Name.DESCRIPTION.toString())); } else { row.put(Field_Name.DESCRIPTION.toString(), null); } if (dataObj.containsKey(Field_Name.SPEC.toString())) { row.put(Field_Name.SPEC.toString(), dataObj.getString(Field_Name.SPEC.toString())); } else { row.put(Field_Name.SPEC.toString(), null); } if (dataObj.containsKey(Field_Name.UNIT.toString())) { row.put(Field_Name.UNIT.toString(), dataObj.getString(Field_Name.UNIT.toString())); } else { row.put(Field_Name.UNIT.toString(), null); } if (dataObj.containsKey(Field_Name.JLGZ.toString())) { row.put(Field_Name.JLGZ.toString(), dataObj.getString(Field_Name.JLGZ.toString())); } else { row.put(Field_Name.JLGZ.toString(), null); } if (dataObj.containsKey(Field_Name.TYPE.toString())) { row.put(Field_Name.TYPE.toString(), dataObj.getString(Field_Name.TYPE.toString())); } else { row.put(Field_Name.TYPE.toString(), null); } if (dataObj.containsKey(Field_Name.QUANTITY.toString())) { row.put(Field_Name.QUANTITY.toString(), dataObj.getDouble(Field_Name.QUANTITY.toString())); } else { row.put(Field_Name.QUANTITY.toString(), null); } rowData.add(row); } } private JSONArray getMongoTableData() { MongoClient mongoClient=new MongoClient( "localhost" , 27017 ); MongoDatabase db = mongoClient.getDatabase("gbq"); MongoCollection collection = db.getCollection("project"); Document doc= collection.find(eq("_id", new ObjectId("5959b01b9107541bbc5cb98b"))).first(); if(doc!=null){ JSONObject data = JSONObject.fromObject(doc.get("data")); return data.getJSONArray("bqItem"); }else{ return new JSONArray(); } } public void release() throws Exception { super.release(); this.rowData = null; }// public static void main(String args) {// BQItemDataSource dataSource = new BQItemDataSource();// dataSource.init();// try {// System.out.println(dataSource.getColumnCount());// for (int i = 0; i < dataSource.getColumnCount(); i++) {// System.out.println(dataSource.getColumnName(i));// }// for (int i = 0; i < dataSource.getRowCount(); i++) {// for (int j = 0; j < dataSource.getColumnCount(); j++) {// System.out.print(dataSource.getValueAt(i, j) + "@");// }// System.out.println();// }// } catch (Exception e) {// e.printStackTrace();// }// }} 如上的数据源中,没有使用传参方式,而是直接在代码中把参数写死了。实际上可以采用传参的方式,在帆软报表设计器中可以设定参数。 但是,上面的数据源class拷贝到帆软设计器目录下的时候,字段是可以获取到的,但是数据是获取不到的。 http://img.blog.csdn.net/20170807100310671?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWNoYW5nMDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast 预览报表的时候页面是空的。依赖的问题想了很久,没有得到答案。周末的时候突然灵光一闪,想到一个可能的原因: - 我们的程序数据源中使用了JSON和MongoClient,这两个东西是依赖于某些jar包的; - 程序数据源的class文件拷贝到帆软目录下,在帆软的内置服务器中运行,而这个内置服务器未必引用了对应的jar包; - 那为什么这个class数据源还是可以引用,并且能看到字段呢?因为帆软中引用的是class文件,而不是源代码,用到字段的时候调用getColumnCount和getColumnName这两个方法,是不受影响的;而显示数据的时候,调用getRowCount和getValueAt两个方法,内部使用了JSON和MongoClient相关的接口,可能内部已经报异常了。 解决办法: - 查看程序数据源的jar包依赖(使用IDEA的Maven插件查看依赖关系图): http://img.blog.csdn.net/20170807101154005?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWNoYW5nMDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast - 将所依赖的jar包拷贝到帆软的lib目录下: 从上图可以看出,直接依赖的包有json-lib和mongodb-driver; 因mongdodb而间接依赖的包有mongodb-driver-core和bson; 因json而间接依赖的包有commons-beanutils、commons-logging、commons-lang、commons-collections、ezmorph。 完成以上步骤之后,在帆软报表设计器中设计完报表点击预览,可以看到报表的内容: http://img.blog.csdn.net/20170807101449650?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWNoYW5nMDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast 至此,程序数据源的路已经走通,可以尽情发挥业务编程能力,编写数据源了!
Maven项目嵌入式部署帆软报表控件
官方嵌入式部署流程嵌入式部署流程拷贝文件 简单粗暴式的话,直接将相关目录全部拷贝到自己项目的WEB-INF目录下;看了一下,差不多有两三百兆的样子; 精细化操作的话,选择性拷贝; 拷贝的jar包包括6个fr的jar包,1个fr的plugin的jar包;(与官方文档有不相符的地方); 拷贝的目录包括plugins目录(报表控件的插件目录),reportlets目录(将来存放报表的目录),resources目录(资源文件目录); web.xml配置在项目的web.xml中配置报表控件的servlet及servlet-mapping。部署过程遇到的问题 组内的项目是Maven项目,是通过pom.xml管理项目的jar包依赖的,也就是没有在项目目录下保留lib目录;这样就导致报表控件所需的jar包无法直接拷贝到程序目录下,而创建lib的话与maven项目会有所冲突; 目录拷贝的选择性;帆软官方文档让把reportlets、resources、plugins目录完整拷贝到项目目录下。查看了一下对应目录,reportlets目录下有很多的演示报表cpt文件,plugins是安装的插件文件,resources下面有很多配置文件以及地图文件…… 项目使用SpringMVC,直接使用前置的Dispatcher进行所有请求的分发;这样的话,报表控件的servlet就会被忽略掉; …… 部署问题处理 关于项目依赖jar包的处理,采用的方式是搭建maven私服,使用的是nexus;这样仅需要在组内项目中配置maven仓库地址即可,对项目的冲击最小。(在Nexus中进行第三方jar包的管理); 从报表控件要拷贝的目录中删除项目不需要的文件,reportlets下的示例报表全部清理掉,plugins下目前仅保留与web页面自适应相关的插件,resources目录下把地图相关的资源全部清理掉,别的配置文件目前没有深究暂且保留; 在web.xml中目前先把报表控件的ReportServer的servlet前置,后面再研究相关的处理吧;
个人成就
内容被浏览6,648
加入社区6年283天
返回顶部