方案1:传统方案 提交表单,服务器端处理,错误后跳转到注册页面,同时显示错误信息。返回客户端的使用整个注册页面。 缺点:较大的网络流量,用户体验不好 方案2:使用Ajax方案。 用户名的确认和用户书写其他表单项可以同时进行;返回客户端的至少错误信息; 优点:较小的网络流量,用户体验好
就是一个技术
Ajax的最大特点:异步访问(快),局部刷新(用户体验高),就是页面数据会变化,但是整个页面没有刷新
ajax是运行在浏览器上面的代码,所以在不同的浏览器上面,创建ajax对象的方式是不一样的,比如火狐,谷歌,IE浏览器,他们就不一样,我们写的ajax代码,要想实现在某一个浏览器上面运行,就需要创建对应的ajax对象。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<base href="<%=request.getContextPath()+"/"%>">
<title>注册页面</title>
<script type="text/javascript">
var xhr;
function checkNC() {
var nc = document.getElementById("nc").value;
if(nc==null||nc==''){
document.getElementById("nc_span").innerText="用户名不能为空";
}else {
//发送ajax请求
//[1]创建XMLHttpRequest对象
xhr=new XMLHttpRequest();
//[2]和服务器建立连接
//xhr.open(method,url,acy,username,passward);
xhr.open("get","RegisterServlet?nc="+nc,true);
//[3]执行回调函数
xhr.onreadystatechange=process;
//[4]发送请求数据
xhr.send(null);
}
}
function process() {
//接受ajax 的响应内容
var text= xhr.responseText;
//把响应回的内容放到span中
document.getElementById("nc_span").innerText=text;
}
</script>
</head>
<body>
<h3>用户注册</h3>
<form>
<p>
昵称:<input type="text" name="nc" id="nc" onblur="checkNC()"/>
<span id="nc_span"></span>
</p>
<p>
真是姓名:<input type="text" name="uname"/>
</p>
<p>
密码:<input type="text" name="pwd"/>
</p>
<p>
描述:<input type="text" name="desc"/>
</p>
<p>
<input type="submit" value="注册"/>
</p>
</form>
</body>
</html>
不同浏览器创建方式不同 可以提取为方法供调用
function createXMLHttpRequest(){
if(window.ActiveXObject){//IE
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}else{ //其他浏览器
xhr = new XMLHttpRequest();
}
}
xmlHttp.open("GET",“exmp1.jsp",true);
xmlHttp.open(“POST,“exmp1.jsp");
xmlHttp.open("GET", "examp1.jsp?"+new Date().getTime(),true);
使用 XMLHttpRequest 对象的 open() 方法来建立请求。参数如下:
request-type:发送请求的类型。典型的值是 GET 或 POST。
url:要连接的 URL
asynch:如果希望使用异步连接则为 true,否则为 false。默认为 true。
username:如果需要身份验证,则可以在此指定用户名。
password:如果需要身份验证,则可以在此指定口令。
通常使用其中的前三个参数或前两个参数即可。
Ajax响应回来后自动调用函数 不同的Ajax请求基本步骤相同,差别和难易主要在回调函数
function process(){
if(xhr.readyState == 4){//200 404 500
if(xhr.status == 200){
//得到返回的结果
var result = xhr.responseText;
//写到指定位置
document.getElementById("namemsg").innerHTML=result;
}else{
alert("Ajax请求错误");
}
}
}
表示请求的状态或情形。在Ajax应用程序中需要了解五种就绪状态,但通常只使用状态4:
0:请求没有发出(在调用 open() 之前)
1:请求已经建立但还没有发出(调用 send() 之前)
2:请求已经发出正在处理之中(这里通常可以从响应得到内容头部)
3:请求已经处理,响应中有部分数据可用,但是服务器还没有完成响应
4:响应已完成,可以访问服务器响应并使用它
状态码status 200 404 返回结果数据 responseText responseXML
xmlHttp.send(null); //get
xmlHttp.send(queryString); //post
如果是get请求,参数已经附加在url中,采用send(null)即可。 如果是post请求,需要通过send()来传递参数。 如果是post请求,要在send之前添加如下语句指定http header: xmlHttp.setRequestHeader("Content-Type“,“application/x-www-form-urlencoded”);
第一个下拉框选择一个省,第二个下拉框就会出现对应省下面的市。要实现的就是这种情况,一个下拉框的变化,导致另一个下拉框里面的内容实现变化
我们首先在jsp页面写两个下拉框
以上的下拉框,第一个下拉框有3个值,第二个下拉框里面什么都没有。现在我们写ajax代码,让选择了第一个下拉框之后,第二个下拉框出现不同的内容。
也就是在第一个下拉框上写一个改变的事件,当选择的东西变了,就会触发这个事件,这个事件里面的内容就是根据这个选择的东西,从后端获取对应的数据之后,放到第二个下拉框里面。
<script type="text/javascript">
var xhr;
function change(val) {
// 创建xhr对象
xhr = new XMLHttpRequest();
// 和服务器建立连接
xhr.open("get","ajaxServlet02?val="+val,true);
// 执行回调函数
xhr.onreadystatechange=process;
// 发送请求
xhr.send(null);
}
function process() {
if(xhr.status==200&&xhr.readyState==4){
}
var text = xhr.responseText;
var list2=text.substring(1,text.length-1);
//分割完成的字符串的数组
var list3 = list2.split(",");
//获得下拉框的对象
var sel = document.getElementById("sel");
sel.innerHTML="<option>--请选择--</option>";
for (var i in list3) {
sel.innerHTML +="<option>"+list3[i]+"</option>"
}
}
</script>
@WebServlet("/ajaxServlet02")
public class ajaxServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
String val = req.getParameter("val");
List<String> list = new ArrayList<>();
list.add("足球");
list.add("篮球");
List<String> list2 = new ArrayList<>();
list2.add("腾讯");
list2.add("爱奇艺");
List<String> list3 = new ArrayList<>();
list3.add("火锅");
list3.add("香锅");
Map<String,List<String>> map = new HashMap<>();
map.put("1",list);
map.put("2",list2);
map.put("3",list3);
List<String> li = map.get(val);
resp.getWriter().print(li);
}
}
后端的数据是以什么格式返回给前段的,我们需要知道,二级联动里面,后端是以字符串的形式返回给前段,前段获取后还得自己截取,变为数组,最后获取数据,所以这种很不友好。
out.print("Ajax响应内容"); 二级联动例子里面就是以这种返回数据,以这种方式返回的数据是一个list集合
前段的ajax就是以这种进行获取
var text= xhr.responseText; 这样获取后端传到前段的list集合其实是一个字符串,具体写法是
'[YY直播, 腾讯课堂, 斗鱼直播]'
以上ajax获取之后,就是一个字符串。
前段需要分割这个字符串,变为list集合,之后再使用这个数据,很麻烦的
var list2=text.substring(1,text.length-1);
//分割完成的字符串的数组
var list3 = list2.split(",");
最后前段 使用这个list3 集合
Student stu=new Student(1,"张三","男"); 创建的这个对象要返回给前段
out.print(stu); 响应给前段是一个对象的toString ()方法
eval("var json="+text); eval() 这个方法就可以将张的像json的字符串转为json格式
响应给前段的是这个
我们前段需要把这个对象,变为json格式:
更改toString方法
String json="{sid:"+stu.getSid()+", sname:'"+stu.getSname()+"', sex:'"+stu.getSex()+"'}";
eval("var json="+text);
后端返回给前段的数据格式是一个json格式就可以,我们可以使用这个工具进行转化就可以
Gson gson=new Gson();
String json = gson.toJson(list);
也可以转成对应的JSON格式 需要注意:字符串的key必须使用引号引出 {‘key1’:value,‘key2’:value2…} var json2 = JSON.parse(text);
resp.setContentType("text/xml;charset=utf-8");
out.print("<users> " +
"<user1>" +
"<age>18</age>" +
"<name>zs</name>" +
" </user1> " +
"<user2>" +
"<age>20</age>" +
"<name>lisi</name>" +
" </user2> " +
"</users>");
var doc= xhr.responseXML;
var name= doc.getElementsByTagName("name")[0].innerHTML; 获取到xml里面name属性的值