1 JSON
AJAX是一种异步请求,在Client和Server端之间建立连接,交换数据。
异步请求下,Server端响应回Client不是一个完整的页面,而是字符串数据。当服务端响应的结果比较复杂时(对象、数组、集合),简单格式的字符串不能满足需求。
在传递复杂的数据时,不能使用简单格式的字符串,而是使用JSON格式的字符串。
JSON(JavaScript Object Notation)JS对象字符串表示形式,定义了对象等复杂数据的特定字符串格式。独立于各个编程语言,是一种轻量级的数据交换格式。
2 JSON语法
2.1 普通对象和Map
json格式:
普通对象:{"属性名1":属性值1,"属性名2":属性值2,...}
Map集合:{"key1":value1,"key2":value2,...}
2.2 数组、List、Set
json格式:
[元素1,元素2,...]
3 Jackson的使用
在pom.xml引入依赖
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.3</version> </dependency>
@Test public void testObject() throws JsonProcessingException { Student s = new Student(1,"xiaohei",false,100.0,new Date()); //使用jackson转换普通对象 ObjectMapper mapper = new ObjectMapper(); String objectJson = mapper.writeValueAsString(s); System.out.println("objectJson = " + objectJson); } //测试Map集合 @Test public void testMap() throws JsonProcessingException { Map<String, Object> map = new HashMap<>(); map.put("id",1); map.put("name","xiaohei"); map.put("sex",false); map.put("age",18); map.put("score",100.0); map.put("birthday",new Date()); //使用jackson转换map集合 ObjectMapper mapper = new ObjectMapper(); String mapJson = mapper.writeValueAsString(map); System.out.println("mapJson = " + mapJson); }
//测试数组 @Test public void testArray() throws JsonProcessingException { Object[] os = {1,"xiaohei",false,new Student(1,"xiaohei",false,100.0,new Date()),new Date()}; //使用jackson转换map ObjectMapper mapper = new ObjectMapper(); String arrayJson = mapper.writeValueAsString(os); System.out.println("arrayJson = " + arrayJson); } //测试List @Test public void testList() throws JsonProcessingException { List<String> list = new ArrayList<>(); list.add("xiaohei"); list.add("xiaobai"); list.add("xiaohong"); list.add("xiaolv"); ObjectMapper mapper = new ObjectMapper(); String listJson = mapper.writeValueAsString(list); System.out.println("listJson = " + listJson); } //测试Set @Test public void testSet() throws JsonProcessingException { Set<String> set = new HashSet<>(); set.add("xiaohei"); set.add("xiaobai"); set.add("xiaohong"); set.add("xiaolv"); ObjectMapper mapper = new ObjectMapper(); String setJson = mapper.writeValueAsString(set); System.out.println("setJson = " + setJson); }
@Test public void testNest() throws JsonProcessingException { Address address = new Address("郑州", "文化路硅谷广场"); List<String> favorites = new ArrayList<>(); favorites.add("吃"); favorites.add("喝"); favorites.add("睡"); Map<String, Double> scores = new HashMap<>(); scores.put("语文", 89.0); scores.put("数学", 99.0); scores.put("英语", 90.0); User user = new User(1, "xiaohei", address, favorites, scores); //使用jackson转换嵌套的对象 ObjectMapper mapper = new ObjectMapper(); String str = mapper.writeValueAsString(user); System.out.println("str = " + str); }
4.1 null的处理
jackson默认会转换属性值为null的属性,可以在属性所在的类型上添加注解,不再转换null属性。
@JsonInclude(JsonInclude.Include.NON_NULL) public class Student implements Serializable { private Integer studentId; private String studentName; private Boolean sex; private Double score; private Date birthday; // get set 有参无参构造 ... }
可以在属性上方添加JsonProperty注解,自定义转换后的属性名。
public class Student implements Serializable { @JsonProperty("id") private Integer studentId; @JsonProperty("name") private String studentName; private Boolean sex; private Double score; private Date birthday; // get set 有参无参构造 ... } //转换结果示例:{"sex":false,"score":100.0,"id":1,"name":"xiaohei"}
一旦对象回环,在解析时会无尽循环解析,直到耗尽JVM内存空间出现异常。出现以下异常信息:
com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)
public class People implements Serializable { private Integer peopleId; private String peopleName; private Passport passport; ... } public class Passport implements Serializable { private Integer passportId; private String serial; //不再级联转换people @JsonIgnore private People people; ... }
jackson默认将日期数据转换为ms数,需要自定义转换格式,可以使用JsonFormat注解。
public class Student implements Serializable { private Integer studentId; private String studentName; private Boolean sex; private Double score; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date birthday; ... }
5.1 登录
login.jsp
<!-- 引入jquery.js和自定义的js文件--> <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/myajax.js"></script> <script type="text/javascript"> $(function(){ $("input:button").click(function(){ //发起ajax请求 var url = "${pageContext.request.contextPath }/login"; var usernameVal = $("input[name='username']").val(); var pwdVal = $("input[name='pwd1']").val(); var validateCodeVal = $("input[name='validateCode']").val(); var data = "username="+usernameVal+"&pwd1="+pwdVal+"&validateCode="+validateCodeVal; myAJax(url,data,"post",function(result){ console.log(result); console.log(typeof result); var o = JSON.parse(result);// json字符串 ==> JS对象 console.log(o); console.log(typeof o); console.log(o.status); console.log(o.msg); if(o.status == "success"){ //跳转 location.href = "${pageContext.request.contextPath}/student/showPageStudents"; }else{ //回显错误信息 $("#msg").html(o.msg); } }) }); }) </script>
UserAction.java
public String login() throws IOException { // 1 收参 // 进行验证码判断 // 从session中获取真实的验证码 HttpServletRequest req = ServletActionContext.getRequest(); HttpSession session = req.getSession(); String realCode = (String) session.getAttribute("realCode"); //获取流 HttpServletResponse resp = ServletActionContext.getResponse(); //设置编解码集 resp.setCharacterEncoding("utf-8"); PrintWriter pw = resp.getWriter(); Map<String, String> map = new HashMap<>(); if (!validateCode.equalsIgnoreCase(realCode)) { map.put("status","failed"); map.put("msg","验证码不正确"); }else { // 2 调用业务层方法 UserService service = new UserServiceImpl(); boolean flag = service.login(username, pwd1); // 3 跳转 if (flag) { session.setAttribute("login", true); map.put("status", "success"); } else { map.put("status", "failed"); map.put("msg", "用户名或密码错误"); } } //将map转换为json字符串,通过流响应输出 ObjectMapper mapper = new ObjectMapper(); String mapJson = mapper.writeValueAsString(map); pw.print(mapJson); pw.flush(); return null; }
updateStudent.jsp
<html> <head> <title>添加商品</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <!-- 在web项目中 css的路径要替换为 css文件的uri 也就是 /项目名/css/style.css --> <link rel="stylesheet" type="text/css" href="../css/style.css" /> </head> <body> <div id="wrap"> <div id="top_content"> <div id="header"> <div id="rightheader"> </div> <div id="topheader"> <h1 id="title"> <a href="#">口碑管理</a> </h1> </div> <div id="navigation"> </div> </div> <div id="content"> <p id="whereami"> </p> <h1> 添加口碑: </h1> <form action="${pageContext.request.contextPath }/student/updateStudent" method="post"> <input type="hidden" name="s.studentId" value=''/> <table cellpadding="0" cellspacing="0" border="0" class="form_table"> <tr> <td valign="middle" align="right"> 口碑名: </td> <td valign="middle" align="left"> <input type="text" class="inputgri" name="s.studentName" value=''/> </td> </tr> <tr> <td valign="middle" align="right"> 年龄: </td> <td valign="middle" align="left"> <input type="text" class="inputgri" name="s.age" value='' /> </td> </tr> <tr> <td valign="middle" align="right"> 性别: </td> <td valign="middle" align="left"> 男<input type="radio" name="s.sex" value="男" /> 女<input type="radio" name="s.sex" value="女" /> </td> </tr> <tr> <td valign="middle" align="right"> 电话: </td> <td valign="middle" align="left"> <input type="text" class="inputgri" name="s.mobile" value=''/> </td> </tr> <tr> <td valign="middle" align="right"> 报备老师: </td> <td valign="middle" align="left"> <select name="s.teacherName"> <option value="元哥">元哥</option> <option value="双元老师">双元老师</option> <option value="超哥">超哥</option> </select> </td> </tr> <tr> <td valign="middle" align="right"> 奖励金额: </td> <td valign="middle" align="left"> <input type="text" class="inputgri" name="s.money" value=''/>(¥) </td> </tr> </table> <p> <input type="submit" class="button" value="确认" /> </p> </form> </div> </div> <div id="footer"> <div id="footer_bg"> www.zparkhr.com.cn </div> </div> </div> </body> <!-- 引入jquery.js 和自定义的js文件--> <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/myajax.js"></script> <script type="text/javascript"> //页面一旦加载完毕,立刻发起请求 $(function(){ var url="${pageContext.request.contextPath}/student/showOneStudent"; var data="studentId=${param.studentId}"; var type="get"; myAJax(url,data,type,function(result){ console.log(result); var s = JSON.parse(result); $("input[name='s.studentId']").val(s.studentId); $("input[name='s.studentName']").val(s.studentName); $("input[name='s.age']").val(s.age); if(s.sex == "男"){ $("input:radio:first").prop("checked",true); }else{ $("input:radio:last").prop("checked",true); } $("input[name='s.mobile']").val(s.mobile); $("select>option").each(function(index,dom){ console.log(dom.innerHTML); if(dom.innerHTML == s.teacherName){ dom.selected = true; } }); $("input[name='s.money']").val(s.money); }); }); </script> </html>
StudentAction.java
public String showOneStudent() throws IOException { // 1 收参 // 2 调用业务层方法 StudentService service = new StudentServiceImpl(); student = service.showOneStudent(studentId); // 3 通过流输出student对象的数据 HttpServletResponse resp = ServletActionContext.getResponse(); resp.setCharacterEncoding("utf-8"); PrintWriter pw = resp.getWriter(); ObjectMapper mapper = new ObjectMapper(); String studentJson = mapper.writeValueAsString(student); pw.print(studentJson); pw.flush(); return null; }
同步方式:
异步方式:
selectPageStudents.jsp
<!-- 引入jQuery和自定义外部js文件--> <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.1.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/myajax.js"></script> <script type="text/javascript"> //抽取处理ajax结果的代码 function handleResult(result){ console.log(result); var page = JSON.parse(result); //遍历page.students 向表格体中添加内容 var students = page.students; var tbody = $("tbody"); tbody.empty();//tbody.html(""); for(var i = 0; i <students.length; i++){ //将students[i] 转换为一行 var html = '<tr class="row1"><td><input type="checkbox" name="ids" value="'+ students[i].studentId +'"/></td> ' + " <td>"+students[i].studentName+"</td> " + " <td>"+students[i].age+"</td> " + " <td>"+students[i].sex+"</td> " + " <td>"+students[i].mobile+"</td> " + " <td>"+students[i].teacherName+"</td> " + " <td>"+students[i].money+"</td> " + " <td> " + " <a href='${pageContext.request.contextPath }/student/removeStudent?studentId="+students[i].studentId+"'>删除</a> " + " <a href='${pageContext.request.contextPath }/student/updateStudent.jsp?studentId="+students[i].studentId+"'>更新</a> " + " </td> " + "</tr>"; var tr = $(html); tbody.append(tr); } var p = $("#a"); //先清空p标签内部内容 p.empty();//p.html(""); //生成首页 var first = $("<a href='javascript:void(0)' onclick='handleAClick(1,2)'>首页</a>") p.append(first); //根据page.totalPage 生成超链接 for(var i = 1; i <= page.totalPage ;i++){ var a = $("<a href='javascript:void(0)' onclick='handleAClick("+i+",2)'>"+i+"</a>"); p.append(a); } //生成尾页 var last = $("<a href='javascript:void(0)' onclick='handleAClick("+page.totalPage+",2)'>尾页</a>") p.append(last); } //禁用超链接的默认跳转,并给其绑定单击事件,触发ajax function handleAClick(pageNum,pageSize){ var url ="${pageContext.request.contextPath }/student/showPageStudents"; var data="pageNum="+pageNum+"&pageSize="+pageSize; var type="get"; console.log(data); myAJax(url,data,type,handleResult); } //页面一旦加载完毕,立刻发起查询请求 $(function(){ //发起ajax请求,获取首页数据 var url="${pageContext.request.contextPath }/student/showPageStudents"; var data="pageNum=1&pageSize=2"; var type="get"; myAJax(url,data,type,handleResult); }) </script>
6 jQuery对AJAX的支持
ajax发起请求,传递数据的格式:key1=value1&key2=value2...
通过serialize()方法,快速将表单中所有的input输入框的值转换为请求格式的数据。
6.2 $.ajax()
$.ajax()封装ajax请求,参数类型是Object参数。
语法:
$.ajax({
url: 请求路径,
data: 键值对的数据|对象形式的数据,
type: "get"|"post",
success: function(result){
//处理结果的函数
},
dataType:"json"
});
data是对象,会将对象自动转换为 属性名1=属性值1&属性名2=属性值2...
dataType:"json" 自动将响应结果转换为js对象
示例
$.ajax({
url:"${pageContext.request.contextPath }/login",
data:$("form").serialize(),
type:"post",
dataType:"json",
success:function(result){
console.log(result);
console.log(typeof result);
if(result.status == "success"){
//跳转
location.href = "${pageContext.request.contextPath}/student/showPageStudents.jsp";
}else{
//回显错误信息
$("#msg").html(result.msg);
}
}
});