POST请求必须设置ContentType请求头的值为application/x-www.form-encoded。表单的enctype默认值就是为application/x-www.form-encoded,因为是默认值,大家可能会忽略。当设置了<form>的enctype=” application/x-www.form-encoded”时,等同与设置了Cotnent-Type请求头。
但在使用AJAX发送请求时,就没有默认值了,这需要我们自己来设置请求头:
<span style="font-size:18px;"> xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");</span>
当没有设置Content-Type请求头为application/x-www-form-urlencoded时,Web容器会忽略请求体的内容。所以,在使用AJAX发送POST请求时,需要设置这一请求头,然后使用send()方法来设置请求体内容。
<span style="font-size:18px;"> xmlHttp.send("b=B");</span>
这时Servlet就可以获取到这个参数:
<span style="font-size:18px;">AServlet: public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { System.out.println(request.getParameter("b")); System.out.println("Hello AJAX!"); response.getWriter().print("Hello AJAX!"); }</span>
<span style="font-size:18px;">ajax2.jsp: <script type="text/javascript"> function createXMLHttpRequest() { try { return new XMLHttpRequest();//大多数浏览器 } catch (e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { return new ActiveXObject("Microsoft.XMLHTTP"); } } } function send() { var xmlHttp = createXMLHttpRequest(); xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { var div = document.getElementById("div1"); //获取节点 div.innerHTML = xmlHttp.responseText; //添加内容 } }; xmlHttp.open("POST", "/ajaxdemo1/AServlet?a=A", true); //打开连接 xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //设置请求头 xmlHttp.send("b=B"); } </script> <h1>AJAX2</h1> <button onclick="send()">测试</button> <div id="div1"></div></span>
在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回true或false,返回true表示这个用户名已经被注册过,返回false表示没有注册过。
客户端得到服务器返回的结果后,确定是否在用户名文本框后显示“用户名已被注册”的错误信息!
● regist.jsp页面中给出注册表单;
● 在username表单字段中添加onblur事件,调用send()方法;
● send()方法获取username表单字段的内容,向服务器发送异步请求,参数为username;
● RegistServlet:获取username参数,判断是否为“fightfaith”,如果是响应true,否则响应false;
regist.jsp:
<span style="font-size:18px;"><script type="text/javascript"> function createXMLHttpRequest() { try { return new XMLHttpRequest(); } catch (e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { return new ActiveXObject("Microsoft.XMLHTTP"); } } } function send() { var xmlHttp = createXMLHttpRequest(); xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { if(xmlHttp.responseText == "true") { document.getElementById("error").innerHTML = "用户名已被注册!"; } else { document.getElementById("error").innerHTML = ""; } } }; xmlHttp.open("POST", "/ajaxdemo1/BServlet", true); xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); var username = document.getElementById("username").value; xmlHttp.send("username=" + username); } </script> <h1>注册</h1> <form action="" method="post"> 用户名:<input id="username" type="text" name="username" onblur="send()"/><span id="error"></span><br/> 密 码:<input type="text" name="password"/><br/> <input type="submit" value="注册"/> </form></span>
RegistServlet.java:
<span style="font-size:18px;"> public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); String username = request.getParameter("username"); if("fightfaith".equals(username)) { response.getWriter().print(true); } else { response.getWriter().print(false); } }</span>
select.jsp:
<span style="font-size:18px;"><h1>省市联动</h1> 省: <select name="province" id="province"> <option>===请选择===</option> </select> 市: <select name="city" id="city"> <option>===请选择===</option> </select></span>
当select.jsp页面打开时,向服务器发送异步请求,得到所有省份的名称(文本数据)。然后使用每个省份名称创建<option>,添加到<select name=”province”>中。
为<select name=”province”>元素添加onchange事件监听。当选择的省份发生变化时,再向服务器发送异常请求,得到当前选中的省份下所有城市(XML数据)。然后客户端解析XML文档,使用每个城市名称创建<option>,添加到<select name=”city”>元素中。
服务器端:使用china.xml保存所有省份和城市名称:
<span style="font-size:18px;">china.xml <?xml version="1.0" encoding="utf-8"?> <china> <province name="北京"> <city>东城区</city> <city>西城区</city> …… </province> <province name="天津"> <city>和平区</city> <city>河东区</city> …… </province> <province name="河北"> <city>保定</city> <city>衡水</city> …… </province> …… </china></span>
● ProvinceServlet:负责把所有省份名称响应给客户端,这需要使用dom4j解析china.xml,得到所有<province>元素的name属性值,连接成一个字符串发送给客户端;
● CityServlet:负责得到某个省份元素,然后以字符串形式发送给客户端;
ProvinceServlet.java:
<span style="font-size:18px;">public class ProvinceServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { // 注意设置编码 response.setContentType("text/html;charset=utf-8"); // 使用DOM4J解析xml文档 InputStream input = this.getClass().getClassLoader().getResourceAsStream("china.xml"); SAXReader reader = new SAXReader(); try { Document doc = reader.read(input); // xpath查询所有province元素的name属性 List<Attribute> provinceNameAttributeList = doc.selectNodes("//province/@name"); // 用来装载所有name属性值 List<String> provinceNames = new ArrayList<String>(); // 遍历每个属性,获取属性名称,添加到list中 for(Attribute proAttr : provinceNameAttributeList) { provinceNames.add(proAttr.getValue()); } // System.out.println(provinceNames); // 把list转换成字符串 String str = provinceNames.toString(); // 把字符串前后中的[]去除发送给客户端 response.getWriter().print(str.substring(1, str.length()-1)); } catch (DocumentException e) { throw new RuntimeException(e); } } }</span>
CityServlet.java:
<span style="font-size:18px;">public class CityServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { request.setCharacterEncoding("utf-8"); // 注意,这里内容类型必须是text/xml,不然客户端得到的就不是xml文档对象,而是字符串了。 response.setContentType("text/xml;charset=utf-8"); // 获取省份参数 String provinceName = request.getParameter("provinceName"); InputStream input = this.getClass().getClassLoader().getResourceAsStream("china.xml"); SAXReader reader = new SAXReader(); try { Document doc = reader.read(input); // 查询指定省份名称的<province>元素 Element provinceElement = (Element)doc.selectSingleNode("//province[@name='" + provinceName + "']"); // System.out.println(provinceElement.asXML()); // 把元素转换成字符串发送给客户端 response.getWriter().print(provinceElement.asXML()); } catch (Exception e) { throw new RuntimeException(e); } } }</span>
客户端(解释放在注释中):
● 在打开select.jsp页面时就向服务器请求所有省份的名称,添加到<select name=”province”>元素中。
● 给<select name=”province”>元素添加onchange事件监听,内容为向服务器发送请求,得到XML文档:<province>元素,然后解析它,添加到<select name=”city”>中。
<span style="font-size:18px;">// 文档加载完成后 // 加载所有省份名称 window.onload = function() { //请求服务器,加载所有省名称到<select>中 //1. ajax四步 var xmlHttp = createXMLHttpRequest(); xmlHttp.onreadystatechange = callback;//服务器响应完成后执行callback函数 xmlHttp.open("GET", "/ajaxdemo1/ProvinceServlet", true);//向服务器发送GET请求 xmlHttp.send(null);//发送请求 }; // 本方法获取服务器响应的所有省份的名称 function callback() { if(this.readyState == 4 && this.status == 200) { // 把服务器响应的省份名称,使用逗号分割成字符串数组 var provinceNameArray = this.responseText.split(", "); // 遍历每个省份名称,使用每个省份名称创建<option>元素,添加到province的<select>中 for(var i = 0; i < provinceNameArray.length; i++) { addProvinceOption(provinceNameArray[i]); } // 为province的<select>元素添加onchange事件监听 document.getElementById("province").onchange = loadCities; } } // 本函数在province的<select>元素发送变化时执行! // 本函数会使用当前选中的省份名称为参数,向服务器发送请求,获取当前省份下的所有城市! function loadCities() { var proName = this.value;//获取<select>选择的省份名称 /* AJAX4步 */ var xmlHttp = createXMLHttpRequest();//创建异常对象 // 指定回调函数 xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { // 得到服务器响应的xml文档对象 var doc = xmlHttp.responseXML;//注意,这里使用的是resopnseXML属性,不是resopnseText // 获取文档中所有city元素 var cityElementList = doc.getElementsByTagName("city"); // 获取html元素:city的<select> var citySelect = document.getElementById("city"); // 删除city的<select>元素的所有子元素 removeChildNodes(citySelect); // 创建<option>元素,指定文本内容为“请选择” var qxzOption = document.createElement("option"); var textNode = document.createTextNode("===请选择==="); qxzOption.appendChild(textNode); // 把"请选择"这个<option>添加到<select>元素中 citySelect.appendChild(qxzOption); // 循环遍历每个服务器端响应的每个<city>元素 for(var i = 0; i < cityElementList.length; i++) { var cityEle = cityElementList[i]; var cityName = null; // 获取<city>元素的文本内容!处理浏览器差异! if(window.addEventListener) { cityName = cityEle.textContent; } else { cityName = cityEle.text; } // 使用城市名称创建<option>,并添加到<select>元素中 addCityOption(cityName); } } }; xmlHttp.open("POST", "/ajaxdemo1/CityServlet", true);//打开与服务器的连接 // 因为是POST请求,所以要设置Content-Type请求头 xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // 参数为当前选中的省份名称 xmlHttp.send("provinceName=" + proName); } // 使用proName创建<option>元素添加到<select>元素中 function addProvinceOption(proName) { var option = document.createElement("option");//创建<option>元素 var textNode = document.createTextNode(proName);//使用省份名称创建文本节点 option.appendChild(textNode);//把省份名称的文本节点添加到<option>元素中 option.setAttribute("value", proName);//使用省份名称来设置<option>元素的value属性 document.getElementById("province").appendChild(option);//把<option>元素添加到<select>元素中 } // 本函数用来创建城市的<option>,并添加到<select>元素中 function addCityOption(cityName) { var citySelect = document.getElementById("city");//获取id为city的<select> var cityOption = document.createElement("option");//创建<option>元素 var textNode = document.createTextNode(cityName);//使用城市名称创建文本节点 cityOption.appendChild(textNode);//把文本节点添加到<option>元素中 cityOption.setAttribute("value", cityName);//设置<option>元素的value属性为城市名称 citySelect.appendChild(cityOption);//把<option>元素添加到<select>元素中 } //删除指定元素的所有子元素 function removeChildNodes(ele) { var nodes = ele.childNodes;//获取当前元素的所有子元素集合 while(nodes.length > 0) {//遍历所有子元素 ele.removeChild(nodes[0]);//删除子元素 } }</span>
分享:关于XPATH的使用讲解链接(请点这里),其中的几张图非常好。