实习的第二天被要求写一个二级联动,算是测试我水平吧,以前写的都是最简单的那种基于JSP、Servlet的Ajax,今天要求写一个基于框架的,最初的直觉是问题不大,结果···写着写着发现好多问题,总是就是基础决定着上层建筑。废话不多说了,记录一下思路和代码以被后用吧。对于任何一个带有联动效果的表单而言,最开始提交的请求并不是那个注册界面,而是把第一个联动查出来,并跳转到表单界面进行显示。先看一下地区联动的表结构。
效果图:
然后在指定的City类里写处理的代码
在这个类里就完成了对市的查询,同时并以xml的形式把这个信息异步 传递给最开始的最开始的注册表单界面,在表单界面通过获得的xml信息进行提取,并把其中的信息通过dom的形式在表单界面显示,这样就完成了二级联动,值得注意的是在City.java类里要把响应类型改成xml 。即:response.setContentType("text/xml;charset=UTF-8");
也就是dictcode的前两位代表着省,3,、4位代表着市,5、6位代表着市所管辖的区县。通过下面的代码实现初始化表单联动的第一个下拉框,并跳转到表单界面。
public String registerone(){
data =db.getListtolist("from Dict where dictcode like '__0000'");
System.out.println(data.size());
tojsp="addstaff";
return SUCCESS;
}
效果图:
表单下拉框部分源码
<tr>
<td> </td>
<td><font class="left_txt2">城 市:</font>
<select name="sf" id="sf" οnchange="getCity()">
<s:iterator value="data">
<option value="<s:property value="dictcode" />">
<s:property value="dictvalue" />
</option>
</s:iterator>
</select>
<select id="city" name="city" οnchange="getCounty()"></select></td>
<td></td>
</tr>
然后当我们对下拉框的省份进行选择的时候就会触动onchange方法,紧接着就会对数据进行异步处理了
<script type="text/javascript">
var xmlHttp;
function ajaxFunction() {
try {
// Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
} catch (e) {
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("您的浏览器不支持AJAX!");
return false;
}
}
}
}
/**
*获取某个省的城市信息
*/
function getCity() {
var sf = document.getElementById("sf");
ajaxFunction();
xmlHttp.onreadystatechange = function() {
setCity("city");
};
xmlHttp.open("get", "getcity.action?sfcode=" + sf.value, true);
xmlHttp.send(null);
}
function setCity(selectid) {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var root = xmlHttp.responseXML;
// alert(xmlHttp.responseText);
// var root1=eval('('+root+')');
// alert(root);
var data = root.getElementsByTagName("city");
var selectcity = document.getElementById(selectid);
selectcity.length = 0;
for ( var i = 0; i < data.length; i++) {
var option = document.createElement("option");
option.text = data[i].lastChild.firstChild.data;
option.value = data[i].firstChild.firstChild.data;
try {
selectcity.add(option);
} catch (ex) {
selectcity.add(option, null);
}
}
}
}
}
</script>
过程就是通过onchange方法触发getCity()方法,通过dom可以获得选中的省份的值,然后通过使用open方法把这个值传递给对应的处理方法getcity.action (类似于servlet,用来从数据库中检索对应省下的市),之前的这些跟普通的JSP、Servlet处理一样,区别就在于这个二级联动的第二次检索市,首先我们需要得到struts的支持,由于struts2是支持json传递信息的,但是由于我们使用的是最原始的ajax,但是还是要把支持他的包补全,毕竟我们使用的是struts这个路径,笔者使用的struts版本是2.3.8,在它的原始开发包的lib文件夹下找到 struts2-json-plugin-2.3.8.jar 这个jar包,把它引入工程中,然后子啊struts.xml配置处理查询事的action的配置。
<package name="zyx" extends="json-default">
<action name="getcity" class="cn.com.zyx.action.City">
<result name="success" type="json"></result>
</action>
</package>
然后在指定的City类里写处理的代码
package cn.com.zyx.action;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.interceptor.ServletResponseAware;
import cn.com.zyx.dao.DbDao;
import cn.com.zyx.factory.DaoFactory;
import cn.com.zyx.pojo.Dict;
import com.opensymphony.xwork2.ActionSupport;
public class City extends ActionSupport implements ServletResponseAware {
private static final long serialVersionUID = -917771295463799536L;
DbDao db = DaoFactory.getDbDaoBean();
private String tojsp;
private HttpServletResponse response;
private HttpSession session;
private String sfcode;
private PrintWriter out;
public String getcity() throws Throwable {
response.setContentType("text/xml;charset=UTF-8");
response.setCharacterEncoding("UTF-8");// 防止弹出的信息出现乱码
out = response.getWriter();
String sql = "from Dict where dictcode like '" + sfcode.substring(0, 2)
+ "__00'and dictcode!='" + sfcode + "'";
createXML(sql, out);
out.flush();
out.close();
return null;
}
public void createXML(String sql, PrintWriter out) {
List<Object> l = db.getListtolist(sql);
out.print("<root>");
for (int i = 0; i < l.size(); i++) {
Dict d = (Dict) l.get(i);
out.print("<city>");
out.print("<code>" + d.getDictcode() + "</code>");
out.print("<value>" + d.getDictvalue() + "</value>");
out.print("</city>");
}
out.print("</root>");
}
@Override
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public String getTojsp() {
return tojsp;
}
public void setTojsp(String tojsp) {
this.tojsp = tojsp;
}
public HttpServletResponse getResponse() {
return response;
}
public void setResponse(HttpServletResponse response) {
this.response = response;
}
public HttpSession getSession() {
return session;
}
public void setSession(HttpSession session) {
this.session = session;
}
public String getSfcode() {
return sfcode;
}
public void setSfcode(String sfcode) {
this.sfcode = sfcode;
}
}
在这个类里就完成了对市的查询,同时并以xml的形式把这个信息异步 传递给最开始的最开始的注册表单界面,在表单界面通过获得的xml信息进行提取,并把其中的信息通过dom的形式在表单界面显示,这样就完成了二级联动,值得注意的是在City.java类里要把响应类型改成xml 。即:response.setContentType("text/xml;charset=UTF-8");