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>

3.1 普通对象和Map集合

@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);
    }

3.2 数组、List和Set

//测试数组

    @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);
    }

3.3 嵌套形式

@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 Jackson特殊情况的处理

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 有参无参构造
    ...
}

4.2 对象的属性名和JSON字符串中属性名不一致

可以在属性上方添加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"}

4.3 对象回环

一旦对象回环,在解析时会无尽循环解析,直到耗尽JVM内存空间出现异常。出现以下异常信息:

com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)

解决方案:在不需要级联转换的属性上添加JsonIgnore注解

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;

    ...
}

4.4 日期格式

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 实战案例:

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;
    }

5.2 回显信息

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;
    }

5.3 分页查询

同步方式:

 

 

异步方式:

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> \n' +
                " <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> \n" +
                "  <a href='${pageContext.request.contextPath }/student/updateStudent.jsp?studentId="+students[i].studentId+"'>更新</a>\n" +
                "  </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的支持

6.1 $("form").serialize()

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);
        }
    }
});

 

 

 

posted on 2020-10-16 01:32  AlexLiuF  阅读(74)  评论(0编辑  收藏  举报