4.3.构造生成xml的servlet
这一步的主要实现是从数据表中提取符合要求的记录生成嵌套的xml,servlet的源码是xmlservlet.java,选用oracle作数据库服务器。
对数据库记录处理的过程基本上类似于xsl模版的处理:
先查找layer的值为0的记录,对该记录进行分析,分析是否具有下级节点,这是通过该记录的href是否为空来进行分支处理的,href为空时,通过id的输入参数进行递归查找,请参见xmlservlet.java源码。
/*rowset是resultset的增强类,具有可序列化的特点,所以代替resultset来作为可以放入sessionbean的结果集类型*/
import javax.sql.rowset;
/*com.sitechasia.ejb.*包含需要的sessionbean的远程接口类*/
import com.sitechasia.ejb.*;
public class xmlservlet extends httpservlet {
printwriter out;
private static resultedit re;
private object ref;
boolean flag=true;
private handle handle=null;
private static string hostip = null;
private static string hostport = null;
private static final string content_typex = "text/xml";
private static final string content_typeh = "text/html";
/*不同的显示页面使用的xsl模版不一样,在这里先定义调用的xsl模版名称*/
private static final string content_xslt = "<?xml-stylesheet type=\"text/xsl\" href=\"/xsl/treefunc.xsl\"?>";
private static final string content_xslc = "<?xml-stylesheet type=\"text/xsl\" href=\"xmltreexsl.xsl\"?>";
public void service(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {
try{
/*获得客户端的session,判断该session里面是否含有sessionbean的句柄和其他相关内容,依据判断结果进行分支处理*/
httpsession session=request.getsession();
if ( session.getattribute("resultedithandle")==null) {
flag=false;
}
else {
flag=true;
/*获得保存在session中sessionbean的句柄*/
handle=(handle)session.getattribute("resultedithandle");
/*从获得的句柄得到sessionbean的ejb实例*/
re =(resultedit)handle.getejbobject();
}
/*session中含有sessionbean的分支处理*/
if (flag){
/*从sessionbean的实例中得到可序列化的结果集rowset*/
rowset rs = re.getrowset();
response.setcontenttype(content_typex);
out = response.getwriter();
out.println("<?xml version=\"1.0\" encoding=\"gb2312\" ?>");
/*通过判断servlet是否带有request参数,来判断使用哪种模版*/
if (request.getparametervalues("clickid")==null){
out.println(content_xslt);
}
else {
out.println(content_xslc);
}
out.println("<project>");
/**使用递归算法按层次把结果集中的记录排列,这里没有使用结果集的各个字段名称来指定数据的取值,而是通过结果集的字段序号来取得相应的数据值的,所以需要把提交表单中查询语句按照这里规定的字段序号来书写,这样可以使有不同字段名称的不同的结果集按照一定顺序书写后,都可以用来生成xml树,在这里规定了字段序号的相对应的名称,在4.2.的数据表的结构定义中有详细描述,下面指出代码中指定的序号对应的模版字段名称:
id 1 表示序号,是节点的唯一标识;
layer 2 层,顶层是从0开始计算,依此类推;
name 3 节点的名称,也可以是节点的唯一识别标识;
value 4 节点在浏览器中显示的名称,为用户提供一个快速查看
father 5 父节点的id值,除开layer为0的节点该值为0;
herf 6 链接对象,当一个节点是树叶时,存在相应的链接,树杈节点该值为空
target 7 链接对象显示的目标窗口,树杈节点该值亦为空
*/
while(rs.next()){
if (rs.getstring(2).equals("0")){
if(rs.getstring("herf")==null){
out.println("<node>");
out.println("<id>"+rs.getstring(1)+"</id>");
out.println("<layer>"+rs.getstring(2)+"</layer>");
out.println("<name>"+rs.getstring(3)+"</name>");
out.println("<value>"+(rs.getstring(4))+"</value>");
out.println("<father>"+rs.getstring(5)+"</father>");
out.println("<href></href>");
out.println("<target></target>");
childnode(rs.getstring(1));
out.println("</node>");
}
else {
out.println("<node>");
out.println("<id>"+rs.getstring(1)+"</id>");
…
}
}
}
out.println("</project>");
rs.close();
}
else {
response.setcontenttype(content_typeh);
out = response.getwriter();
out.println("<html><head><title>no ejb message</title><meta http-equiv=refresh content=2;url=/refreshpost.html/></head>");
out.println("<body>");
out.println("<p><p><p><center>refresh…… return refreshpost.html</center></p></p></p></body></html>");
}
}
catch(exception e){
system.out.println("errror:"+e.getmessage());
e.printstacktrace();
}
}
/**clean up resources
*/
public void destroy() {
}
/**方法childnode(string father)是一个递归调用的方法,用来生成带有树层次关系的xml*/
public void childnode(string father){
try{
rowset rs = re.getrowset();
while(rs.next()){
if (rs.getstring(5).equals(father)){
if(rs.getstring("herf")==null){
out.println("<node>");
out.println("<id>"+rs.getstring(1)+"</id>");
…
childnode(rs.getstring(1));
out.println("</node>");
}
else{
out.println("<node>");
…
out.println("</node>");
}
}
}
rs.close();
}
catch(exception e){
system.out.println(e.getmessage());
e.printstacktrace();
}
}
}
