Ajax作为WEB中一个重要的异步交互方式,其作用就不需要我在这里强调了,关于它的使用,我在项目中还是遇到了一些问题的,在这里我把它列出来,希望能够帮到大家。
出现的Bug:
1. Ajax无法解析从后台传过来的json数据
2. 后台报错了Ajax依然走了success方法
Bug复现:
Ajax无法解析从后台传过来的json数据
源码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<% String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" +
request.getServerPort() + path + "/";
%>
<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
<title>Insert title here</title>
</head>
<body>
<form action="test/ajaxTest" method="post">
姓名:<input type="text" id="account" name="account"/>
密码:<input type="password" id="passcode" name="passcode"/>
<input type="submit" value="提交"/>
</form>
</body>
<script type="text/javascript">
$(document).ready(function() {
$("form").submit(function() {
var form = $(this);
$.ajax({
type: form.attr('method'),
url: form.attr('action'),
data:{
account: $("input[name=account]").val(),
passcode: $("input[name=passcode]").val()
},
dataType: "json",
success: function (data){
alert("原始json数据:" + data);
eachTest(data);
},
error: function(){
alert("Network Error..." );
}
});
return false;
});
function eachTest(data) {
var json = data;
//var json = eval("(" + data + ")");
alert("获取json属性:json.account:" + json.account);
$.each(json,function(key,value){
alert(key + ": " + value);
});
}
});
</script>
</html>
关键在于最后的一个方法
function eachTest(data) {
var json = data;
//var json = eval("(" + data + ")");
alert("获取json属性:json.account:" + json.account);
$.each(json,function(key,value){
alert(key + ": " + value);
});
}
实际上从后台服务器获取的并不是json格式的数据,而是满足json格式的字符串,因此并不能直接当做
json来使用,直接对其进行解析的话就会解析不出来,需要对其转换
function eachTest(data) {
//var json = data;
var json = eval("(" + data + ")");
alert("获取json属性:json.account:" + json.account);
$.each(json,function(key,value){
alert(key + ": " + value);
});
}
转换之后的效果:
这里简单说明一下Ajax关键方法的意思
$.ajax({
type: //这里填写的是ajax的提交方式,比如:"post","get"
url: //需要提交请求的地址,比如"https://www.google.com",
"user/userAction"
data: //需要提交的数据,注意,是提交给服务器的数据
dataType: //服务器返回的的数据类型,比如"String","json"等
contentType: //ajax的上下文类型,如
"application/x-www-form- urlencoded"(有时候解析不
到json数据也可能是因为页面的cententType和表单/ajax的不
一致导致的,具体可以打开调试 -- network -- 选择页面 --
在Responce Headers这一栏(需要刷新一遍网页才会显示))
success: //表明ajax与后台连接成功后走的方法,可以有从后台返回的数据参数这
里需要注意的是只要ajax与后台建立联系,就会走success方法,即使
没有从后台获取到有用的数据,这里会有逻辑bug,下边有讲
error: //ajax与后台连接失败走的方法,一般会由于网络连接失败,但是也会有其他
原因导致走error这个方法,比如你的url找不到,没有数据data等
});
查看contentType示例:
关于Ajax与后台建立完整连接以上的内容就可以满足
接下来我要讲讲关于使用Ajax编程的程序严谨性问题(在上边的程序片段注释中也提到过)
我们知道Ajax中的success方法是在ajax与后台服务器创建完整连接之后就会走的方法,并且可以返回从后台获取到的反馈数据,但是,这个反馈的数据是不是一定是我们需要的呢?能够获取到后台反馈数据,那是在后台程序执行正常的情况下才能成功,但是后台如果出现bug,那么你的ajax依旧执行了success方法,由于没有得到你需要的参数,所以你的页面是没有任何反馈(或者是动作)的
Bug复现:
后台报错了Ajax依然走了success方法
html>
<head>
<title>Struts Problem Report</title>
<style>
pre {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<h2>Struts Problem Report</h2>
<p>
Struts has detected an unhandled exception:
</p>
<div id="exception-info">
<table>
<tr>
<td><strong>Messages</strong>:</td>
<td>
<ol>
<li>Connection refused: connect</li>
<li>Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.</li>
<li>Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.</li>
</ol>
</td>
</tr>
<tr>
<td><strong>File</strong>:</td>
<td>org/springframework/jdbc/datasource/DataSourceTransactionManager.java</td>
</tr>
<tr>
<td><strong>Line number</strong>:</td>
<td>245</td>
</tr>
</table>
</div>
<div id="stacktraces">
<hr />
<h3>Stacktraces</h3>
<div class="stacktrace" style="padding-left: 0em">
<strong>org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.</strong>
<div>
<pre>
org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:245)
org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:439)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
com.sun.proxy.$Proxy9.queryOneInfo(Unknown Source)
com.cs.action.UserAction.signupCheckAccount(UserAction.java:53)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:892)
ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1537)
ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:117)
com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:108)
ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1613)
ognl.ASTMethod.getValueBody(ASTMethod.java:91)
ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
...... ......
这里是我从浏览器调试模块中截取的部分内容,大致意思是说数据库这一块出问题了,没有连接到数据库(因为我都没开数据库服务),这是我在做项目中偶然遇到的,一般我们的数据库服务器是一直开着的,但是我之前因为出门,就把电脑关了,数据库的服务顺带也关了,后来进行测试的时候,发现之前都没有动的程序怎么突然失灵了,然后在后台也没有看到bug,我以为是需要重启服务(应用程序服务,非数据库服务),但是重启之后还是没有用,程序检查了半天之后感觉没毛病,我就纳闷了,到底是哪里出了问题,我专门有对ajax的连接过程仔细检查了一遍,没毛病,我又专门写了个ajax的测试(没有使用到数据库),也没有毛病,这就尴尬了,这程序之前好好的,怎么现在就不听使唤了?然后我就抱着试试看的心态在浏览器调试中找找看,结果还真是找到了,原来是后台数据库方面除了bug,之前都没有往那边想,也没想去调试,毕竟后台都没有看到报错,其实这也奇怪,后台看不到报错,却能在浏览器中看到,有问题啊,不过总算找到问题来源了,这就好办了
关键来了,在这个过程中我们看到,即使你的ajax程序与后台创建了连接,也就是走了success方法,但是,这也并不能保证你能够从后台获取到你所需要的数据
可能很多人在使用ajax的时候根本就没有考虑到这个问题,以为走了success方法就算与后台创建连接了,也就自然而然的能够获取到自己所需要的信息(我之前也是这么认为的),那么今天看到这个例子,我想对大家编程的严谨性应该有一定的帮助
下边是我的对以上bug进行处理的代码(ajax部分):
$.ajax({
type: "post",
url: "user/signupCheckAccount",
data:account.serialize(),
dateType: "json",
contentType: "application/x-www-form-urlencoded",
cache: false,
success: function(data){
connectSuccess1(data)
},
error: function(){
alert("Network error...");
}
});
function connectSuccess1(data){
console.log(data);
/*判断是否从后台获取到所需要的反馈数据,后台(主要是数据库)出故障仍然走succsee*/
if(data.match("^\{(.+:.+,*){1,}\}$")){
var flag = eval("(" + data + ")");
$.each(flag,function(key,value){
if(key == "SIGNUPCHECKACCOUNT_FLAG" && value == "success"){
... ...
}else{
$('#input-account-msg').html("*该账号已经被注册!请重新输入!");
$('#input-account').focus().select();
}
});
}else{
alert("亲,出了点小问题,请稍后再注册!");
var location = (window.location+'').split('/');
var basePath = location[0]+'//'+location[2]+'/'+location[3];
var url = basePath + '/homepage.jsp';
window.location.href = url;
}
}
以上代码是我在写注册的时候用的,主要是用来从数据库检测用户输入的账号是否已经存在,对于以上出现的问题,我的处理办法(程序已经很明显了,我在啰嗦一遍)是先检查返回的数据是不是自己想要的,如果不是,说明后台肯定哪里是崩了,然后就不需要这么进行下去了,直接跳走,如果是,那就就请继续
以上就是我在ajax方面遇到的问题以及解决方案,希望对大家有帮助!