??xml version="1.0" encoding="utf-8" standalone="yes"?>
AJAX是今q初才问世的新技术,是Asynchronous JavaScript and XML的羃写。它是一l开发Web应用E序的技术,它ɋ览器可以ؓ用户提供更ؓ自然的浏览体验。每当需要更新时Q客LWeb面的修Ҏ异步的和逐步增加的。这PAJAX在提交Web面内容时大大提高了用户界面的速度。在ZAJAX的应用程序中没有必要长时间等待整个页面的h。页面中需要更新的那部分才q行更改Q如果可能的话,更新是在本地完成的,q且是异步的?br />
J2ee是一U用来开发分布式pȝ的体pȝ构。它主要是用Javacd发业务实体。通过JSP来连接应用服务器?br />
本文开发一个组l机构管理小pȝQ通过q个实例来介l如何用Ajax开发WEB应用E序。本pȝh增加、修攏V删除组l机构的功能。同时给机构分配人员Q能增加、修攏V删除h员?br />
二?界面设计
树结构是大多软gpȝ中常采用的结构Ş式。由于树型结构层ơ分明、上下关系清楚、且展开收羃表达信息方便、界面也较美观,所以是大家热衷于用此结构。组l机构管理是一般Y件基本具有的。组l机构是指公司的l织l构。集团公司可包括分公子公司,公司下面又有U室。员工归属于所在的公司。系l运行后的界面如下:
树结构区1 | l织~码? |
人员理? |
Q?TABLE border="1" width="100%" height="100%"Q?br /> QTRQ?br /> QTD rowspan="2"Q<FONT face="宋体"Q</FONTQ</TDQ?br /> QTDQ</TDQ?br /> Q?TRQ?br /> QTRQ?br /> QTDQ</TDQ?br /> Q?TRQ?br /> Q?TABLEQ?/td> |
Qdiv id="divTree" style="width:100%; height:100%;background-color:#f5f5f5;border :1px solid Silver;overflow:auto;"Q?br /> Q?divQ?/td> |
Qdiv id="divContent" style="height:100%; overflow-y:auto;" width="100%"Q?br /> Qtable id="tbList" border="1" width="100%"Q?br /> Qtr seqNo="1"Q<tdQ?br /> Qtable border="1" width="100%"Q?br /> QtrQ?br /> Qtd width="5%"Q<input type="checkbox" value="on"Q</inputQ?Q?tdQ?br /> Qtd width="0%" style="display:none"Q?Qinput type="text" size="20"Q</inputQ</tdQ?br /> Qtd width="40%"Q<input type="text" size="20"Q</inputQ</tdQ?br /> Qtd width="25%"Q?br /> Qselect size="1" name="D1"Q?br /> Qoption value="0"Q男Q?optionQ?br /> Qoption selected="true" value="1"Q女Q?optionQ?br /> Q?selectQ?br /> Q?tdQ?br /> Q?trQ?br /> Q?tableQ? Q?tdQ</trQ?br /> Q?tableQ?br /> Q?divQ? |
三?前端面的主要编?br />
1. 树的实现
在WEB上实现树l构Q同h们是通过Ajax来实现的。树上可以显C定义的图标,可以插入、删除、结炏Vƈ且结点可LUd。这里我们不重点讲树的实现技术,我们已经装好了Q你只要按要求去改动是了?
1) 键接树型文g
在<headQ与Q?headQ之间键接我们的与树有关的文? 代码如下Q?br />
Qlink rel="STYLESHEET" type="text/css" href="css/dhtmlXTree.css"Q?br /> Qscript src="js/dhtmlXCommon.js"Q</scriptQ?br /> Qscript src="js/dhtmlXTree.js"Q</scriptQ? |
Qbody onload="preLoadImages();doOnLoad();"Q?/td> |
//doOnLoad实现装蝲q显C树。设|树属性等?br /> function doOnLoad(){ OrgTree=new dhtmlXTreeObject(document.getElementById('divTree'),"100%","100%",0); //dhtmlXTreeObject是树对象Q通过新徏对象Q指定树昄的DIV可定义树?br /> OrgTree.setImagePath("imgs/");//讄树的囄所在位|?br /> OrgTree.setDragHandler();//讄树结Ҏ?br /> OrgTree.enableDragAndDrop(true) //讄树结Ҏ否可拖动 OrgTree.setDragHandler(myDragHandler); //讄树结Ҏ动时所执行的方?br /> OrgTree.setOnClickHandler(mySelectHandler); //讄树单L所执行的方?br /> //OrgTree.setXMLAutoLoading("Org.jsp");//装蝲树结Ҏ据。数据来源如Org.jsp所q回的XML格式的字W串Q数据是动态装载,且当展开时才装蝲?br /> OrgTree.loadXML("root.xml?0");//装蝲树结Ҏ据。数据来源root.xml文gQƈ且从xml文g的ID号ؓ0处读取数据?br /> //OrgTree.loadXML("Org.jsp");//装蝲树结Ҏ据。数据来源如Org.jsp所q回的XML格式的字W串,q且是一ơ性全部装载数据? } //preLoadImagesҎ实现树控件的图标定义 function preLoadImages(){ var imSrcAr = new Array("line1.gif","line2.gif","line3.gif","line4.gif","minus2.gif","minus3.gif", "minus4.gif","plus2.gif","plus3.gif","plus4.gif","book.gif","books_open.gif","books_close.gif", "magazine_open.gif","magazine_close.gif","tombs.gif","tombs_mag.gif","book_titel.gif") var imAr = new Array(0); for(var i=0;iQimSrcAr.length;i++){ imAr[imAr.length] = new Image(); imAr[imAr.length-1].src = "imgs/"+imSrcAr[i] } } |
l织理的实?br />
l织可以增加、删除、编辑。同时当选择树结Ҏ应该把组l显C出来供~辑Q查看。ؓ了实现这些功能,你只要按要求L动就是了?br />
1) 全局变量的定?br />
许多地方我们要用C些公共变量,我们在<scriptQ与Q?scriptQ之间定义全局变量, 代码如下Q?br />
var OrgTree = null; //l织树Dom var nextSeq = 0;//人员理的顺序号Q流水号Q?br /> var personDom;//人员Dom var CurrNodeId;//当前l点Id |
2) 初始?br />
当页面打开时我们要控g好那部分该显C,那部分要隐藏。且对全局变量的赋值等,l织cd装蝲。在面的文档打开时装载自定义ҎinitQ), initҎ实现初始化?br />
Qbody onload="init();"Q?/td> |
initҎ实现如下Q?br />
function init(){ //定义personDomZ个XMLDOM'对象 personDom= new ActiveXObject('Microsoft.XMLDOM'); personDom.async = false; //定义stylesheetZ个XMLDOM'对象Q且stylesheet为personDom定昄风格 stylesheet = new ActiveXObject('Microsoft.XMLDOM'); stylesheet.async = false; stylesheet.load("addOrgPerson.xsl"); //装蝲stylesheet的风格定义文?br /> //装蝲l织cd数据 var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.open("POST","Org.jsp?mode=GetOrgType", false); xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlhttp.send(); retXml=xmlhttp.responseText; // alert(retXml); //把组l类型插入下拉列表控件中 var OrgDoc = new ActiveXObject('Microsoft.XMLDOM'); OrgDoc.async = false; OrgDoc.loadXML(retXml); var root = OrgDoc.documentElement; oNodeList = root.childNodes; txtType.options.length =oNodeList.length; for (var i=0; iQoNodeList.length; i++) { Item = oNodeList.item(i); var OrgTypeId=Item.childNodes(0).text; var OrgTypeName=Item.childNodes(1).text; txtType.options[i].value=OrgTypeId; txtType.options[i].text=OrgTypeName; // txtType.options[0]. } } |
3) ~写树拖动及选择l点的方?br />
// myDragHandler实现树结Ҏ动时重新指定父子关系?br /> function myDragHandler(idFrom,idTo){ var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.open("POST","Org.jsp?mode=moveOrg&orgId=" + idFrom + "&newparentOrgId=" + idTo, false); xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlhttp.send(); retXml=xmlhttp.OrgponseText; return true; } // mySelectHandler实现选择树结点对pȝ的控Ӟ同时昄l织信息及该l织下的人员?br /> function mySelectHandler(id){ tbOrg.style.display="block"; divOrgMemo.style.display="none"; divOrgInfo.style.display="none"; if(id==1) { divOrgMemo.style.display="block"; div1.style.display="none"; div2.style.display="none"; div3.style.display="none"; divContent.style.display="none"; div5.style.display="none"; } else { divOrgInfo.style.display="block"; div1.style.display="block"; div2.style.display="block"; div3.style.display="block"; divContent.style.display="block"; div5.style.display="block"; } CurrNodeId=id; //装蝲l织信息q显C在~码和名U的文本控g上? loadOrg(id); //装蝲某组l下人员信息 var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.open("POST","Org.jsp?mode=GetPerson&orgId=" + id, false); xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlhttp.send(); retXml=xmlhttp.responseText; personDom.loadXML (retXml); //lh员信息的每行加上序号 for(var i=0; iQpersonDom.documentElement.childNodes.length; i++){ personDom.documentElement.childNodes[i].setAttribute("seqNo", nextSeq); nextSeq++; } //人员信息昄在divContent上面 divContent.innerHTML = personDom.transformNode(stylesheet); }; //装蝲l织信息q显C在~码和名U的文本控g上?br /> function loadOrg(OrgId){ if(OrgId == null){ OrgId = OrgTree.getSelectedItemId(); } if(OrgId == ""){ tbOrg.style.display = "none"; return; } var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.open("POST","Org.jsp?mode=loadOrg&OrgId=" + OrgId, false); xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlhttp.send(); retXml=xmlhttp.responseText; var OrgDoc = new ActiveXObject('Microsoft.XMLDOM'); OrgDoc.async = false; OrgDoc.loadXML(retXml); if(OrgId != 1){ txtCode.value = OrgDoc.selectSingleNode("http://OrgCode").text; txtName.value = OrgDoc.selectSingleNode("http://OrgName").text; } tbOrg.style.display = "block"; } |
4) 建立l织
l织建立主要是通过调用XMLHTTP对象来实现。我们主要学会如何调用XMLHTTP。组l徏立应该在后台实现Q把l织信息插入数据库中。这里我们通过JSP来实现。我们的Org.jsp 文g中有个createOrgҎQ该Ҏ传递一个父ID?br />
function createOrg(parentOrgId){ var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.open("POST","Org.jsp?mode=createOrg&parentOrgId=" + parentOrgId, false); xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlhttp.send(); retXml=xmlhttp.responseText; var orgId = (new Number(retXml)).toString(); return orgId; } |
5) 删除l织
l织删除同样是调用Org.jsp 文g中的deleteOrgҎ来实玎ͼ该方法传递所删除的结点ID?br />function deleteOrg(){
var OrgId = OrgTree.getSelectedItemId();
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("POST","Org.jsp?mode=deleteOrg&OrgId=" + OrgId, false);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send();
}
6) ~辑l织
l织修改是调用Org.jsp 文g中的modifyOrgҎ来实玎ͼ该方法传递所修改的结点ID。同时修改的数据通过自定义的XML格式的字W串传?q时通过send字符串来实现。修改前数据一律要验证其合法性,q提C错误信息?br />
3. 人员理的实?br />function modifyOrg(){
if(OrgTree.getSelectedItemId() == ""){
return "N";
}
if(txtCode.value == ""){
alert("误入编码!");
return "N";
}
if(txtName.value == ""){
alert("误入名Uͼ");
return"N";
}
var OrgId = OrgTree.getSelectedItemId();
var OrgKind;
//alert(txtType.options[txtType.selectedIndex].value)
var strModify = "Q?xml version='1.0' encoding='gb2312'?Q? +
"QdataQ? +
"QOrgCodeQ<![CDATA[" + txtCode.value + "]]Q</OrgCodeQ? +
"QOrgNameQ<![CDATA[" + txtName.value + "]]Q</OrgNameQ? +
"QOrgKindQ<![CDATA[" + txtType.options[txtType.selectedIndex].value+ "]]Q</OrgKindQ? +
"Q?dataQ?;
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("POST","Org.jsp?mode=modifyOrg&OrgId=" + OrgId, false);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send(strModify);
OrgTree.setItemText(OrgTree.getSelectedItemId(),txtName.value);
}
人员可以增加、删除、编辑。同时当选择树结Ҏ应该把h员显C出来供~辑、查?.....
1) 增加人员
人员增加实现的原理是在personDom中加入结点peorsoneQ该l点相当于表的一行,讄属性。同时在peorsone中不l地加入其它l点Q代表数据库的字D,且必MXLT文g的标号同名。这些结点相当该行的列。最后在表中插入一行,行上插入一列,q显CZ?br />function addPerson(){
var seqNo = nextSeq;
nextSeq++;
var peorsonNode = personDom.createNode("1", "peorsone","");
peorsonNode.setAttribute("isNew", "Y");
peorsonNode.setAttribute("isDelete", "N");
peorsonNode.setAttribute("seqNo", seqNo);
personDom.documentElement.appendChild(peorsonNode);
var PersonId= personDom.createNode("1", "personId", "");
peorsonNode.appendChild(PersonId);
var personCode= personDom.createNode("1", "personCode", "");
peorsonNode.appendChild(personCode);
var PersonName= personDom.createNode("1", "personName", "");
peorsonNode.appendChild(PersonName);
var Sex= personDom.createNode("1", "sex", "");
peorsonNode.appendChild(Sex);
var tr = tbList.insertRow(tbList.rows.length);
tr.setAttribute("seqNo", seqNo);
var td = tr.insertCell(0);
td.innerHTML = peorsonNode.transformNode(stylesheet);
}
2) 删除人员
人员删除同样是调用Org.jsp 文g中的deletePersonҎ来实玎ͼ该方法传递所删除的h员ID。如何确定h员ID是通过d隐藏的IDQƈ扫描整个表,看那些被选中。这里我们要注意是提供多w择的?br />function deletePerson(){
for(var i=0; iQtbList.rows.length; i++){
var row=tbList.rows[i].cells[0].children[0].rows[0];
if(row.cells[0].children[0].checked)
{
var personId=row.cells[1].children[0].value;
if(personIdQ?)
{
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("POST","Org.jsp?mode=deletePerson&personId=" + personId, false);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send();
}
tbList.deleteRow(i);
i--;
}
}
}
3) ~辑人员
人员修改我们要判定哪些行被修改了。刚增加但没保存的行应该是新增而不是修改的?br />function save(){
if( modifyOrg()=="N")
{
return;
}
for(var i=0; iQtbList.rows.length; i++)
{
var row=tbList.rows[i].cells[0].children[0].rows[0];
var personId=row.cells[1].children[0].value;
var seqNo = tbList.rows[i].getAttribute("seqNo");
var staffNode = personDom.selectSingleNode("http://peorsone[@seqNo='" + seqNo + "']");
var personCode=row.cells[2].children[0].value;
var personName=row.cells[3].children[0].value;
var sex=row.cells[4].children[0].value; //alert(staffN;ode );
if(staffNode.getAttribute("isNew") == "Y")
{
createPerson(CurrNodeId,personCode,personName,sex);
}
else
{
var strXML = "Q?xml version='1.0' encoding='gb2312'?Q? +
"QdataQ? +
"QpersonCodeQ<![CDATA[" + personCode+ "]]Q</personCodeQ? +
"QpersonNameQ<![CDATA[" + personName + "]]Q</personNameQ? +
"QsexQ<![CDATA[" + sex+ "]]Q</sexQ? +
"QpersonIdQ<![CDATA[" + personId+ "]]Q</personIdQ? +
"Q?dataQ?;
//alert(strXML );
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("POST","Org.jsp?mode=modifyPerson", false);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send(strXML );
}
}
}
四?XML与XSL文g设计
XML是种可扩展的标记语言Q它h开攄、可扩展的、可自描q的语言l构Q它已经成ؓ|上数据和文档传输的标准。XSLT的目的是信息内容与 Web 昄分离QHTML 通过按抽象概念(如段落、重点和~号列表Q定义显C来实现讑֤独立性。XSLT用来具体昄控gQ设|控仉根{?br />
Ajax主要使用XML和XSLTq行数据交换与处理?br />
1. 树信息的XML文g(见root.xml文g)
XML是标记语aQ元素必L对出现。树l构中以tree为根l点Q以item为结点体Q属性text指出l点所昄的文本,id指出唯一的所标识受?br />
Q?xml version='1.0' encoding='gb2312'?Q?br /> Qtree id="0"Q?br /> Qitem child="1" text="l织" id="1" Q?br /> Q?itemQ? Q?treeQ?/td> |
Q?xml version="1.0" encoding="gb2312"?Q?br /> //q是定义xml文g的首行。用来指明版本及字符?br /> Qxsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" language="JavaScript"Q?br /> //q里定义了stylesheet 元素。ƈ指出其国际命名的l织及语a? Qxsl:template match="/"Q?br /> Qxsl:apply-templates select="peorsones"/Q?br /> Q?xsl:templateQ?br /> //上面是匹配的规则?/"表示从根l开始去匚w。匹配到下面的peorsones标记。这是正则表辑ּ有关的学问。我们只要理解就可以?br /> Qxsl:template match="peorsones"Q?br /> //当匹配上peorsones时所要做的事情?br /> Qtable id="tbList" border="1" width="100%"Q?br /> //定义一个id?tbList的表根{此表格是显C在WEB上的 Qxsl:for-each select="peorsone"Q?br /> //循环匚wpeorsone QtrQ?br /> //定义tbList表格的一行,q在行上增加一个叫seqNo的属性名Qgؓ匚w到的seqNoQ序P Qxsl:attribute name="seqNo"Q<xsl:value-of select="@seqNo"/Q</xsl:attributeQ?br /> QtdQ?br /> //定义行上的一列,列又d?br /> Qxsl:apply-templates select="."/Q?br /> Q?tdQ?br /> Q?trQ?br /> Q?xsl:for-eachQ? Q?tableQ?br /> Q?xsl:templateQ?br /> Qxsl:template match="peorsone"Q?br /> Qtable border="1" width="100%"Q?br /> QtrQ?br /> //定义宽ؓ5%的一列,在该列上插入一个checkbox控g Qtd width="5%"Q?br /> Qinput type="checkbox" value="on" size="10"Q</inputQ?br /> Q?tdQ?br /> //定义一个不昄的列Q在该列上插入一个text控gQtext的gؓ匚w到的personIdQh员IdQ?br /> Qtd style="display:none"Q?br /> Qinput type="text" size="25"Q?br /> Qxsl:attribute name="value"Q<xsl:value-of select="personId"/Q</xsl:attributeQ?br /> Q?inputQ? Q?tdQ?br /> Qtd width="30%"Q? Qinput type="text" size="20"Q? Qxsl:attribute name="value"Q<xsl:value-of select="personCode"/Q</xsl:attributeQ? Q?inputQ? Q?tdQ? Qtd width="40%"Q? Qinput type="text" size="40"Q?br /> Qxsl:attributename="value"Q<xsl:value-of select="personName"/Q</xsl:attributeQ? Q?inputQ?br /> Q?tdQ?br /> //定义一个width?8%的列Q在该列上插入一个下拉列表select 控gQselect的值如果匹配到?时则??Q?时则?? Qtd width="28%"Q?br /> Qselect size="1"Q?br /> Qoption value="0"Q?br /> Qxsl:if test=".[sex=0]"Q?br /> Qxsl:attribute name="selected"QtrueQ?xsl:attributeQ?br /> Q?xsl:ifQ?br /> ?br /> Q?optionQ?br /> Qoption value="1"Q?br /> Qxsl:if test=".[sex=1]"Q?br /> Qxsl:attribute name="selected"QtrueQ?xsl:attributeQ?br /> Q?xsl:ifQ? 奻I/optionQ?br /> Q?selectQ?br /> Q?tdQ?br /> //定义一列,在该列上插入一个button控gQonclick 事g定义的方法,该方法传递当前单ȝ按纽 Qtd width="*"Q? Qbutton onclick="openPersonRolePage(this)" style="width: 36; height: 21"Q角Ԍ/buttonQ?br /> Q?tdQ?br /> Q?trQ?br /> Q?tableQ?br /> Q?xsl:templateQ?br /> Q?xsl:stylesheetQ?/td> |
五?数据接口的实?/strong>Q见Org.jpg文gQ?br />
Org.JSP文g用来在服务器上运行Java的类与前台web之间架起一座桥。取C间g的接口作用?br />
q里分析部分代码Q?br />
Q?@ page contentType="text/html; charset=GBK" %Q?br /> Q?@ page import="java.sql.*" %Q?br /> Q?@ page import="javax.naming.*" %Q?br /> Q?@ page import="javax.sql.*" %Q?br /> Q?@ page import="tool.*" %Q?br /> Q?@ page import="orgNew.*" %Q?br /> Q?@ page import="org.w3c.dom.*" %Q?br /> //上面主要是引用一些javac?br /> Q? try{ //request.setCharacterEncoding("GBK"); Document doc = XmlTool.createDocumentFromRequest(request); //建立web面文档请求的文档对象 Connection conn = ConnTool.getConnectionFromPool(); //获取h的方法名 String mode=request.getParameter("mode"); //out.println("ccc"); //如果Ҏ中没有其它参数则dl织树数?br /> if(mode == null){ /* int OrgId = Integer.parseInt(request.getParameter("id")); String str = orgManager.getChildOrg(OrgId, conn); out.println(str); */ String str = orgManager.getTree(conn); //out.println(str); out.println(str); }else if(mode.equals("createOrg")){ //如果是createOrgҎ则徏立一个组l?br /> int parentOrgId = Integer.parseInt(request.getParameter("parentOrgId")); //取出传递来的第一个参数parentOrgId int OrgId = orgManager.createOrg(parentOrgId, conn); //调用orgManager cȝcreateOrgҎ来徏立一个组l?br /> out.println(OrgId); //q回l果 } conn.close(); } catch(Exception e){ e.printStackTrace(); } %Q?/td> |
六?后台数据的实?/b>
1. 数据l构的定?br />
q里Q我们主要有三个表。一个是l织l构表,一个是人员表personQ一个组lh员关联表orgPerson。组l结构表有OrgCodeQ组l代码)、OrgNameQ组l名Uͼ、orgIdQ组lIdQ? parentOrgIdQ父IdQ。h员表有personCodeQh员代码)、personNameQh员名Uͼ, sexQ性别Q、personIdQh员IdQ。orgPerson表有orgId, personId?br />
2. 数据库的q接
WEB应用E序常用MySQL作后台数据库Q这是因为MySQL单、高效。这里我们也用MySQL作ؓ数据库。Java中用jdbcq接数据库。下面是q接数据库的CODEQ?br />
public static Connection getConnectionFromPool() throws Exception { Context ctx = new InitialContext(); DataSource ds = (DataSource) ctx.lookup("java:/erpds"); return ds.getConnection(); } /** * 取数据库链接对象 * @return Connection 数据库链接对?br /> * @throws Exception */ /* public static Connection getDirectConnection() throws Exception { Class.forName("com.sybase.jdbc2.jdbc.SybDriver"); String url = "jdbc:sybase:Tds:19.64.13.16:4100/wydb?charset=iso_1"; String user = "sa"; String password = "2860008"; Connection conn = DriverManager.getConnection(url, user, password); return conn; } */ |
. 业务逻辑层的实现
后台开发我们用JavacL实现。这里我们开发了一个orgNew包,cd为orgManager。此cd装了与数据库操作有关的方法。通过main可调试程序的正确性?br />
q里l出了新增加一个组l的全部代码和通过XML取得树结构信息的代码Q树l构通过递归实现?br />
package orgNew;// JavacL打的?br /> import tool.*; import java.sql.*; import java.util.*; // 引用Javacȝ public class orgManager { public orgManager() { } public static void main(String[] args) throws Exception { Connection conn = tool.ConnTool.getDirectConnection();// 引用数据讉Kc?br /> conn.setAutoCommit(false); orgManager orgManager1 = new orgManager(); orgManager1.createOrg(0, conn); //试建立l织是否正确 } //建立一个组l?br /> public static int createOrg(int parentOrgId, Connection conn) throws Exception { String sql = "insert into Org (OrgName, parentOrgId) values('新组l?, ?)"; PreparedStatement pstat = conn.prepareStatement(sql); pstat.setInt(1, parentOrgId); pstat.executeUpdate(); pstat.close(); Statement stat = conn.createStatement(); String sql2 = "select max(OrgId) from Org"; ResultSet rs = stat.executeQuery(sql2); rs.next(); int OrgId = rs.getInt(1); rs.close(); stat.close(); System.out.println(OrgId); return OrgId; } } //通过递归得到l织信息的XML格式的数?br /> public static String getTree(Connection conn) throws Exception { StringBuffer ret = new StringBuffer();//定义可缓冲的字符?br /> ret.append("Q?xml version='1.0' encoding='gb2312'?Q<tree id='0'Q?);//定义XML格式的头信息 ret.append(" Qitem child='1' text='l织' id='1' Q?);//插入l点体。注树结点以item为标? ret.append(getChildTree(1, conn)); ret.append("Q?itemQ?);//l点体结束标?br /> ret.append("Q?treeQ?);//树结束标?br /> return ret.toString();//q回字符?br /> } public static String getChildTree(int OrgId, Connection conn) throws Exception { StringBuffer ret = new StringBuffer(); String sql = "select a.OrgId, a.OrgName, a.OrgCode,count(b.parentOrgId) from Org a " + "left join Org b on a.OrgId = b.parentOrgId " + "where a.parentOrgId = ? " + "group by a.OrgId, a.OrgName"; PreparedStatement pstat = conn.prepareStatement(sql); pstat.setInt(1, OrgId); ResultSet rs = pstat.executeQuery(); while (rs.next()) { int childOrgId = rs.getInt(1); String childOrgName = rs.getString(2); String childOrgCode = rs.getString(3); if (childOrgCode == null) { childOrgCode = " "; } if (childOrgName == null) { childOrgName = "新组l?; } int childCount = rs.getInt(3); if (childCount Q?0) { childCount = 1; } ret.append("Qitem child='" + childCount + "' text='" + childOrgName + "' id='" +childOrgId + "' code='"+childOrgCode+"'Q?); ret.append(getChildTree(childOrgId, conn)); ret.append("Q?itemQ?); } rs.close(); pstat.close(); return ret.toString(); } |
其它代码见orgManager.java文g?br />
七?ȝ
本文仉过一个实例全面介l了Ajax开发的各个l节。通过与J2ee的结合来实现三层分布式开发的层次划分Q后C前端的调用。数据的d、访问及展现?
通过q个实例Q我们可见,Ajax使WEB中的界面与应用分R数据与呈现分离的分,有利于分工合作、减非技术h员对面的修攚w成的WEB应用E序错误、提高效率、也更加适用于现在的发布pȝ。也可以把以前的一些服务器负担的工作{嫁到客户端,利于客户端闲|的处理能力来处理?br />
Ajax是传lWEB应用E序的一个{变。以前是服务器每ơ生成HTML面q返回给客户端(览器)。Ajax理念的出玎ͼ揭开了无h更新面时代的序q,q有代替传统web开发中采用form(表单)递交方式更新web面的趋势,可以是一个里E碑?br />
MQAjax适用于交互较多,频繁L据,数据分类良好的WEB应用?/p>
|
|
因ؓ幅的关pȝ略了MediaAssetcȝ详细代码Q但应用模式依然是清晰的。MediaAssetc遍历文档的节点Q?br />当它到不同的子节点Ӟ它用子节点的内容填充自己的成员数据?br />如果它发C一个嵌套的子资源节点,它只需要创Z个新的MediaAsset对象Q?br />然后子资源节点的数据填充到新对象的成员数据中?br />实现上述处理的方法数不胜数。我们还可以使用其他的解析器或解析器架构Q?br />如Java API for XML Parsing (JAXP)?br />除了使用DOM模型外,事g驱动的SAX模型也可用于解析XML?br />cM的程序也可用来生XML数据——前提是允许产生新的数据对象Q在本例中是MediaAssetQ,它可其相应的XML实体插入到DOM中,
然后DOM输出C个流中(诸如一个文Ӟ一个SocketQ或者一个HTTPq接...Q?br />q有其他更高层次的标准,可将XML映射到Java对象的过E进一步自动化Q或化)?br />例如Q用XML概要QSchemaQ和XMLl定处理引擎Q您可以半自动地满x个XML概要的XML数据转变成Java数据对象?br />代表性的引擎是CastorQ是由ExoLab组理的一个开放源代码目的物?br />上述使用Xerces DOM的简单例子仅仅是演示了这一处理q程的底层模型?br />上述CZ表明Q在Java环境中解析或产生XML是非常方便的Q这与J2EE没有必然兌?br />格式化ؓXML的数据可以从应用E序的Q何层ơ流入或输出Q这使得与外部系l的集成性无可限量?br />但我们能否以一U更为直接的方式XML数据源集成到J2EE架构中去呢?
N消息
J2EE架构包含了对JMSQJava消息服务QAPI的访问,以实现面向消息的通信QJ2EE 1.2.1版只需JMS
API卛_Q在J2EE 1.3版中JMS基本定型Q此时必ȝ某个兼容J2EEq_的服务器提供一个JMS API ProviderQ?br />q一cȝ异步交互Q与之相对的是:本地或远E方法调用所代表的同步交互)被证明在某些应用环境中是非常有用的?br />某些时候,交互只需要通过间接的请求或回答来实玎ͼ卻I在某些情况下Q发出消息后不可能立x到答复,
但我们仍希望当消息发重新在U时Q确保他能收到答复信息?br />面向消息pȝ的实际应用之一是企业之间的松散集成。类gEDIQ电子文档交换)时代的文档交换,
两个企业׃业务的需要而交换消息,此时通常不能Z使用RPC或者RMI、CORBA、DCOM之类的远E方法交互而在两者之间进行紧密集成?br />象JMS APIq样的消息系l允许双方交换基于JMS API的消息蝲P
前提是双方在会话的时候均能提供兼容的JMS API服务?br />当前仍然存在的困难是Q双Ҏ否能从相同的格式或协议?br />q正是XML大显w手的时候。XML明确地被设计来解xcL据交换问?br />——灵丹妙药就是“面向消息的概要表”(Message-Oriented Communication SchemeQ,
实质是Z一个双方认同的DTD或schemaQ用XML格式来交换消息蝲荗?br />JMS API支持好几U消息,其中的TextMessage代表文本消息载荷?br />一个简单而有效的XML消息交换Ҏ是,在一端将我们的XML文档插入TextMessageQ然后在另一端用自制的XML解析E序Q如前面的MediaParserQ解开数据qӞ可选地Q将其{换成Java对象?br />q得我们既可以用JMS API支持的公开预订的消息模型,也可以用JMS API支持的点对点的消息模型来发送XML消息?br />上述Ҏ有一些局限,因ؓ对于JMSq行时处理而言QXML的内容基本上是不透明的?br />例如QJMS API允许使用Z特定消息头的路由。这很容易理解,其当我们希望XML消息Ҏ其内定w取不同走向时?br />例如在我们的MediaAsset例子中,我们希望公开讲内容Q但只想把特定的内容传送给那些预订了课E的人,或传送给那些表明可以接受某些媒体格式Q如视频)的h?br />Z发挥JMS API的h|以便实现上述Z内容的消息\由,我们有必要从XML数据中解析出关键信息Q?br />然后在构造标准JMS API消息头时插入q些信息。这是可行的Q但要实现XML信息我们得额外地写很多代码Q交换消息的双方均如此)?br />Z在XML和JMS API之间架v桥梁Q一些厂商提供了自定义的JMS扩展Q以便直接支持XML消息机制?br />例如QBEApȝ公司ZJ2EE的WebLogic应用服务器特别ؓTextMessage提供了XMLMessage子类Q允许用XPath表达式来qoXML消息?br />不过q是一U专有的扩展Q这要求交换消息的双方必都能处理这cL息?br />为此QSun公司目前正在开发用于XML消息的Java APIQJAXMQ。其目标是提供一个高U别的标准服务,以实现基于ebXML的消息的合成与传送?br />一个JAXM服务提供E序可以这cL息映到适当的物理消息系l(诸如JMS APIQ中厅R?br />让XML看得?/strong>
XML同Webpȝ的用L面进行集成显然是一U有益的试。绝大多数的界面E序Q无论是Zq是不基于WebQ都是将数据q行转换Q然后用易读的格式展现给用户?br />用诸如XMLq种“易消化”的格式存放数据简化上q工作,同时它还大大提高了内容的可管理性,接下来我们就可看到这一炏V?br />不过首先要大书一W的是,XML在Web界面层的应用得益于JSP技术的发展?br />一直以来大安希望能清晰地区分Web应用E序的表C层与底层对象模型,JSP框架诞生于这些努力之中(包括早期JHTML试Q?br />JSP框架允许Java代码嵌入到HTML内容中,q样既可以实现动态内容,又不必经怿改Java Servlets的代码?br />在页面中包含Java技术的途径是通过JSP标记QJSP TagsQ,q些标记以XML风格出现。在JSP中,
JavaE序以代码片Dc服务器端JavaBeanslg、在服务器端触发特定操作的不透明标记Q标准的或自定义的){Ş式存在?br />当某个用户通过览器请求JSP面Ӟ一个Java应用服务器解析该JSP面Q将其编译成一个Java ServletQ然后执行该Servlet以生答复页面?br />一U直接将XML数据源集成到JSP的界面中ȝҎ是,XML加蝲到JavaBeanslg中(如同我们在MediaAsset例子中所做的Q,然后在JSP中直接引用这些JavaBeanslg?br />下面是一个嵌入Java代码片断的例子:Media Assets for Lecture 14:
Iterator iter = assets.iterator();
%>]]> %>]]>Name Type URN ]]>
上述E序q有一U更z的写法Q那是使用自定义JSP面标记。这h们就可以从JSP面中剔Z码段Q只使用JavaBeanslg和自定义的JSP标记卛_。比如说Qؓ了去掉创析器、加载资源数据到集合中的那段代码Q我们可创徏一个自q标记Q由它在q后完成q些工作?