牛仔裤的夏天

JAVA是蓝色的- online

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  30 随笔 :: 5 文章 :: 15 评论 :: 0 Trackbacks

单位里的查询系统是基于struts的,在结果集显示的处理上都是用 <logic:iterate id=".." indexId="id" name=".." scope="request"> 然后在<bean:write name=".." property=".."> 这样子对付的,后来觉得比较麻烦,就写了一个显示结果集的标签

  • 行记录用HashMap保存
  • 结果集用Vector封装
  • 表格的标题等属性用xml配置
  • dom4j解析xml文件
  • 输出时根据配置合并多行内的相同属性列
  • 求和

表格配置文件table-config.xml保存在/WEB-INF下



用于表格配置的Table.java

package tax.tags;

import java.util.Vector;

public class Table {
 
private String name;
 
private String width;
 
private String title;
 
private String groupby;
 
private Vector<Column> columns;
 
public Table(){
 }

 
public Table(String name){
  
this.name=name;
 }

 
public Vector<Column> getColumns() {
  
return columns;
 }

 
public void setColumns(Vector<Column> columns) {
  
this.columns = columns;
 }

 
public String getName() {
  
return name;
 }

 
public void setName(String name) {
  
this.name = name;
 }

 
public String getTitle() {
  
return title;
 }

 
public void setTitle(String title) {
  
this.title = title;
 }

 
public String getWidth() {
  
return width;
 }

 
public void setWidth(String width) {
  
this.width = width;
 }

 
 
public String getGroupby() {
  
return groupby;
 }

 
public void setGroupby(String groupby) {
  
this.groupby = groupby;
 }

 
public String toString(){
  StringBuffer buf
=new StringBuffer();
  buf.append(
"Name:").append(name).append("\n");
  buf.append(
"Width:").append(width).append("\n");
  buf.append(
"Title:").append(title).append("\n");
  buf.append(
"Groupby:").append(groupby).append("\n");
  
for(int i=0;i<columns.size();i++){
   Column column
=columns.elementAt(i);
   buf.append(
"column name:").append(column.getName()).append("\n");
   buf.append(
"       header:").append(column.getHeader()).append("\n");
   buf.append(
"       width:").append(column.getWidth()).append("\n");
   buf.append(
"       sum:").append(column.isSum()).append("\n");
   buf.append(
"       bind:").append(column.isBind()).append("\n");
  }

  
return buf.toString();
 }

}




class Column{
 
private String name;
 
private String width;
 
private String header;
 
private String map;
 
private boolean sum;
 
private boolean bind;

 
public Column(){
  sum
=false;
  bind
=false;
 }

 
public boolean isBind() {
  
return bind;
 }

 
public void setBind(boolean bind) {
  
this.bind = bind;
 }

 
public String getHeader() {
  
return header;
 }

 
public void setHeader(String header) {
  
this.header = header;
 }

 
public String getName() {
  
return name;
 }

 
public void setName(String name) {
  
this.name = name;
 }

 
public boolean isSum() {
  
return sum;
 }

 
public void setSum(boolean sum) {
  
this.sum = sum;
 }

 
public String getWidth() {
  
return width;
 }

 
public void setWidth(String width) {
  
this.width = width;
 }

 
public String getMap() {
  
return map;
 }

 
public void setMap(String map) {
  
this.map = map;
 }

}


 

用dom4j解析table-config.xml的Dom4jTable.java,因为用到了xpath,所以把jaxen-1.1-beta-6.jar也要拷贝到/web-inf/lib里面去

package tax.tags;

import java.util.List;
import java.util.Vector;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

public class Dom4jTable {
 String tableName;

 
public Dom4jTable() { }

 
public Dom4jTable(String tableName) {
  
this.tableName = tableName;
 }


 
public Document parse(String xmlpath) throws DocumentException {
  SAXReader reader 
= new SAXReader();
  Document doc 
= null;
  doc 
= reader.read(xmlpath);
  
return doc;
 }


 
public Table getTable(Document doc) {
  Table table;
  String xpath 
= "//table[@name='" + tableName + "']";
  Node node 
= doc.selectSingleNode(xpath);
  
if (node == null{
   table 
= null;
  }
 else {
   table 
= new Table(tableName);
   table.setWidth(getValue(node,
"@width"));
   table.setTitle(getValue(node,
"title"));
   table.setGroupby(getValue(node,
"groupby"));
   Vector
<Column> columns = new Vector<Column>();
   Node nodeColumns 
= node.selectSingleNode("columns");
   List list 
= ((Element) nodeColumns).elements();
   
for (int i = 0; i < list.size(); i++{
    Column column 
= new Column();
    Element element 
= (Element) list.get(i);
    column.setName(getValue(element,
"name"));
    column.setHeader(getValue(element,
"header"));
    column.setWidth(getValue(element,
"width"));
    column.setMap(getValue(element,
"map"));
    column.setBind(Boolean.parseBoolean(getValue(element,
"bind")));
    column.setSum(Boolean.parseBoolean(getValue(element,
"sum")));
    columns.add(column);
   }

   table.setColumns(columns);
  }

  
return table;
 }

 
private String getValue(Node node,String name){
  String value
=node.valueOf(name);
  
if(value.equals("")){
   value
=null;
  }

  
return value;
 }

}



自定义标签ShowTableTag.java,写的有点乱,还好能用,本来用sax解析xml的,后来改为dom4j的

package tax.tags;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.Vector;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

public class ShowTableTag extends TagSupport {
 
private static final long serialVersionUID = 1L;

 
private Log log = LogFactory.getLog(this.getClass());

 
private String vectorName;

 
private String tableName;

 
private boolean displaySN = false;

 
private Vector<HashMap> data = null;

 
public int doStartTag() throws JspException {
  
return TagSupport.SKIP_BODY;
 }


 
public int doEndTag() throws JspException {
  String newline 
= "\n";
  
boolean getsum=false;
  JspWriter out 
= pageContext.getOut();
  StringBuffer buf 
= new StringBuffer();
  
if (data == null || data.size() == 0{
   buf.append(
"There is no result available.");
  }
 else {
//   取表格的各项属性设置
   Table table = getTableConfigByDom4j();
//   取表格的各列,然后存入cols数组
   Vector columns = table.getColumns();
   Column[] cols
=new Column[columns.size()];
   BigDecimal[] sum
=new BigDecimal[columns.size()];
   
for(int i=0;i<columns.size();i++){
    cols[i]
=(Column)columns.elementAt(i);
    
if(cols[i].isSum()) getsum=true;
    sum[i]
=new BigDecimal(0);
   }

   
/////////////////////////////////////////////////////////////////////////////////////////
//   如果table没有设置title, 就不打印这部分
   if(table.getTitle()!=null){
    buf.append(
"<DIV id=tag_head><div class=label>").append(newline);
    buf.append(table.getTitle()).append(
"</div></div><div id=tag_body>");
    buf.append(newline);
   }

   
   buf.append(
"<div class=content>").append(newline);
   buf.append(
"<table border=1 cellPadding=0 cellSpacing=0 ");
   buf.append(
"borderColorLight=#000000 borderColorDark=#f8f7f5 width=\"");
   buf.append(table.getWidth()).append("\">").append(newline);
   buf.append("<tr class=tablehead>").append(newline);
   
//   如果标签中的displaySN为true, 则打印序号列
   if (displaySN) {
    buf.append(
"<th>序号</th>").append(newline);
   }


//   打印table的th栏
   for (int i = 0; i < cols.length; i++{
    buf.append(
"<th");
    
if (cols[i].getWidth() != null){
     buf.append(
" width=").append(cols[i].getWidth());
    }

    buf.append(
">").append(cols[i].getHeader()).append("</th>");
    buf.append(newline);
   }

   buf.append(
"</tr>").append(newline);


//   由table的groupby属性产生key_group<Integer,Integer>
//   第一个Integer是行号,从1开始
//   第二个Integer是跨度span,即连续相同的key的数量
   Hashtable key_group = getKeyGroup(table.getGroupby());
   
   
int rowid = 0//行号
   int distid = 0//捆绑相同key行后的行号
   Iterator<HashMap> it = data.iterator();
   
while (it.hasNext()) {
    buf.append(
"<tr class=tablepad>").append(newline);
    
    rowid
++;
    
//    根据行号从key_group中取得pan值, span可能为null  
    Integer span=(key_group==null?null:(Integer)key_group.get(new Integer(rowid)));

//     显示序号
    if (displaySN) {
     
if(key_group==null){
      
//key_group为null表示table中不用合并相同的行
      buf.append("<td>").append(rowid).append("</td>");
     }
else if(span!=null){
      buf.append(
"<td rowspan=").append(span).append(">");
      buf.append(
++distid).append("</td>").append(newline);
     }

    }

//    取得这一行的记录
    HashMap row = (HashMap)it.next();
    
for (int i = 0; i < cols.length; i++{
//     取得td中应该显示的内容
     String td = (String) row.get(cols[i].getName());
     
if(cols[i].isSum()){
      sum[i]
=sum[i].add(new BigDecimal(td));
     }

     
if(cols[i].getMap()!=null){
      TreeMap map 
= (TreeMap) pageContext.getServletContext()
        .getAttribute(cols[i].getMap());
      td
=(String)map.get(td);
     }

     
if (td == null) td = "&nbsp;";
//     区别这个列的bind属性确定是否要合并显示
     if(!cols[i].isBind()||key_group==null){
      buf.append(
"<td>");
      buf.append(td).append(
"</td>").append(newline);
     }
else if(span!=null){
      buf.append(
"<td rowspan=").append(span).append(">");
      buf.append(td).append(
"</td>").append(newline);
     }

    }

    buf.append(
"</tr>").append(newline);
   }

   
//如果需要打印合计数,增加一行
   if(getsum){
    buf.append(
"<tr class=tablepad>");
    
if(displaySN){
     buf.append(
"<td>&nbsp</td>");
    }

    
for(int i=0;i<cols.length;i++){
     
if(cols[i].isSum()){
      buf.append(
"<td>").append(sum[i]).append("</td>").append(newline);
     }
else{
      buf.append(
"<td>&nbsp</td>").append(newline);
     }

    }

    buf.append(
"</tr>").append(newline);
   }

   buf.append(
"</table>").append(newline);
   buf.append(
"</div></div>");
  }

  
try {
   out.println(buf.toString());
  }
 catch (Exception e) {
   log.error(
"e");
   
return TagSupport.SKIP_PAGE;
  }

  
return TagSupport.EVAL_PAGE;
 }



 
private Hashtable getKeyGroup(String key) {
  
if(key==nullreturn null;
//  返回Hashtable, 键-从1开始的行号. 值-从这行开始连续的rowspan值.
  Hashtable<Integer, Integer> ht = new Hashtable<Integer, Integer>();
  Iterator it 
= data.iterator();
  
int count = 0;
  
int start = 0;
  
int current = 0;
  String value 
= "", prevalue = "";

  
while (it.hasNext()) {
   current
++;
   HashMap row 
= (HashMap) it.next();
   value 
= (String) row.get(key);
   
if (value.equals(prevalue))
    count
++;
   
else {
    ht.put(
new Integer(start),new Integer(count));
    prevalue 
= value;
    count 
= 1;
    start
=current;
   }

  }

  ht.put(
new Integer(start),new Integer(count));
  ht.remove(
new Integer(0));
  
return ht;
 }


 
private Table getTableConfigBySax() {
  Table table 
= null;
  SaxTable sax 
= new SaxTable();
  sax.setTableName(tableName);
  String xmlfile 
= pageContext.getServletContext().getRealPath(
    
"WEB-INF/table-config.xml");
  
try {
   XMLReader xdr 
= XMLReaderFactory
     .createXMLReader(
"org.apache.xerces.parsers.SAXParser");
   xdr.setContentHandler(sax);
   xdr.parse(xmlfile);
  }
 catch (Exception e) {
   log.error(e);
  }

  table 
= sax.getTable();
  
return table;
 }


 
private Table getTableConfigByDom4j(){
  Dom4jTable dt 
= new Dom4jTable(tableName);
  Document doc 
= null;
  String xmlPath 
= pageContext.getServletContext().getRealPath(
    
"WEB-INF/table-config.xml");
  
try {
   doc 
= dt.parse(xmlPath);
  }
 catch (DocumentException e) {
   log.error(e);
   
return null;
  }

  Table table 
= dt.getTable(doc);
  
return table;
 }

 
 
public String getTableName() {
  
return this.tableName;
 }


 
public void setTableName(String tableName) {
  
this.tableName = tableName;
 }


 
public String getVectorName() {
  
return this.vectorName;
 }


 
public void setVectorName(String vectorName) {
  
this.vectorName = vectorName;
  Object o 
= pageContext.getRequest().getAttribute(vectorName);
  
if (o != null{
   data 
= (Vector<HashMap>) o;
  }
 else {
   data 
= null;
  }

 }


 
public void setDisplaySN(boolean sn) {
  displaySN 
= sn;
 }


 
public boolean isDisplaySN() {
  
return displaySN;
 }

}




在标签库app.tld中的这一段tag定义

 <tag>
  
<name>showTable</name>
  
<tagclass>tax.tags.ShowTableTag</tagclass>
  
<bodycontent>empty</bodycontent>
  
<info>
   extract the date from a vector and present date in table
  
</info>
  
<attribute>
   
<name>vectorName</name>
   
<required>true</required>
   
<rtexprvalue>true</rtexprvalue>
  
</attribute>
  
<attribute>
   
<name>tableName</name>
   
<required>true</required>
   
<rtexprvalue>true</rtexprvalue>
  
</attribute>
  
<attribute>
   
<name>displaySN</name>
   
<required>false</required>
   
<rtexprvalue>true</rtexprvalue>
  
</attribute>
 
</tag>



最后就可以在jsp文件中使用了,例如:

<app:showTable tableName="jcgl_dzjk" vectorName="data" displaySN="true"/>



还没有在标签里做分页的处理,以后在加工吧

posted on 2006-03-10 13:12 luckyrobbie 阅读(1153) 评论(1)  编辑  收藏 所属分类: Struts & Hibernate

评论

# re: 显示结果集的标签 2006-03-10 13:31 xfan
用display这些标签不就可以了吗,多个配置文件麻烦  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问