Springmvc响应Ajax请求(@ResponseBody)

Springmvc响应Ajax请求(@ResponseBody)

创建工程

  • 创建maven project
  • 选择war
  • 自动生成web.xml
  • Target Runtime 选择 Tomcat
  • 添加依赖pom.xml
<dependencies>
​
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>3.2.8.RELEASE</version>
        </dependency>
        
        <!-- Spring-JDBC,要和spring-webmvc的版本一致 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>3.2.8.RELEASE</version>
        </dependency>
​
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
​
        <!-- MyBatis-Spring 整合jar包 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        
        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.28</version>
        </dependency>
​
        <!-- DBCP -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
​
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
​
    </dependencies>
  • 配置前端控制器和解决中乱码的过滤器(web.xml)
<!--配置中文乱码的过滤器-->
<filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
​
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
​
<!--配置前端控制器-->
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--加载spring配置文件-->
            <param-value>classpath:spring-*.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
​
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
  • 配置spring-mvc.xml
    • 要想使用@ResponseBody这个注解来接收Ajax发送过来的请求,必须加上注解驱动<mvc:annotation-driven></mvc:annotation-driven>
    <!-- 组件扫描 -->
    <context:component-scan 
        base-package="cn.tedu.spring.controller" />
    
    <!-- 配置ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/web/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <!-- 配置注解扫描,用于ajax的注解扫描 -->
    <mvc:annotation-driven></mvc:annotation-driven>

编写前端表单

  • 其实并不是使用表单提交的,可以不使用表单
<form action="" method="post">
    姓名: <input type="text" name="name" id="name" onblur="checkName()"><span id="nameSpan"></span><br>
    密码:<input type="password" name="pwd" id="pwd"><span id="pwSpan"></span><br>
    <input type="submit" value="注册">
</form>

效果和实现(@RequestBody)

用户名文本框失去焦点,异步检测用户

  • 用户名文本框失去焦点发生请求处理方法,检测用户名
    • 请求方式POST
    • 返回的值不再是视图的名称,而是处理请求的结果,即使返回给Ajax请求的数据
    @RequestMapping("/checkName.do")
    @ResponseBody   //使用@ResponseBody,表示这个是处理ajax的请求
    public String checkName(@RequestParam("name")String name){
        if ("admin".equals(name)) {
            return "0";  //表示admin这个用户名不能使用,已经存在
        }
        return "1";  //表示此时的用户名不存在,可以使用
    }
  • 前端编写Ajax请求(JQUERY
    • 使用JQuery中的Ajax请求
<!-- 添加jquery文件 -->
<script type="text/javascript" src="<%=request.getContextPath() %>/web/jquery-3.2.1.min.js"></script>
​
<script type="text/javascript">
    
    function checkName(){
        var name=$("#name").val(); //获取用户名
        if(name==""){
            alert("用户名不能为空");
            return;
        }
        var url="<%=request.getContextPath()%>/user/checkName.do";  // 请求的url
        $.post(url,{'name':name},function(responseData,status,xhr){
            //如果状态码正确
            if(status=="success"){
                if(responseData=="0"){
                    //为节点添加提示内容
                    $("#nameSpan").text("用户名已经存在,请重新输入");
                    $("#nameSpan").css("color","red");  //设置颜色为红色
                }else{
                    $("#nameSpan").text("用户名不存在,可以使用");
                    $("#nameSpan").css("color","green"); 
                }
            }
        })
    }`
​
</script>
  • 使用javascript发出Ajax请求
    • GET请求 :xhr.open("GET","<%=request.getContextPath()%>/user/checkName.do?name="+name,true);
    • POST请求需要将数据封装到xhr.send(data)
//使用POST请求
function checkNameFun(){
    var xhr=getXHR();  //获取XHR
    //监听状态改变
    xhr.onreadystatechange=function(){
        if(xhr.readyState==4&&xhr.status==200){
            var text=xhr.responseText;  //获取返回的数据
            if(Text=="0"){
                alert("用户名已经存在,请重新输入");
                
            }else{
                alert("用户名不存在,可以使用");
            }
        }
    }
    
    var name=$("#name").val();  //获取name文本框中的值
    if(name==""){
        alert("用户名不能为空");
        return;
    }
    //编写请求
    xhr.open("POST","<%=request.getContextPath()%>/user/checkName.do",true);
    //在open之后,send之前添加请求头信息
    xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
    //在send之中添加请求信息
    xhr.send("name="+name);  //发送请求
}

@ResponseBody

  • 配置注解驱动支持该注解的使用,直接在spring-mvc.xml中配置即可<mvc:annotation-driven></mvc:annotation-driven>
  • 添加jackson的依赖,处理json数据
    • 我们需要三个jar包,我们只需要添加jackson-databind即可,就会自动的导入其他的两个

    <!-- 添加jackson -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.4</version>
        </dependency>
  • 用于响应Ajax请求
  • 使用@ResponseBody标记的Controller方法的返回值,不再是返回的视图名称,而是返回的给Ajax的请求结果,可以是StringList,Map,单个对象

返回单个值

  • 返回的单个值,比如Stringintboolean
  • 直接使用上面的例子即可
    @RequestMapping("/checkName.do")
    @ResponseBody   //使用@ResponseBody,表示这个是处理ajax的请求
    public String checkName(@RequestParam("name")String name){
        if ("admin".equals(name)) {
            return "0";  //表示admin这个用户名不能使用,已经存在
        }
        return "1";  //表示此时的用户名不存在,可以使用
    }

返回Map

  • 这里我们返回的是一个Map<String,Object>
  • 使用了JackSon,spring会将Map自动转换成JSON对象,那么我们在JSP中就可以用JSON来获取数据即可
  • 编写Controller方法,使用@ResponseBody注解
    @RequestMapping("/testMap.do")
    @ResponseBody   //使用注解
    public Map<String,Object> testMap(@RequestParam("name")String name,@RequestParam("age")Integer age){
        System.out.println(name+"---"+age); //接收请求参数
        Map<String, Object> map=new HashMap<String, Object>();  //新建一个Map
        //新建User对象
        User user1=new User();
        user1.setName("JACK");
        user1.setAge(22);
        
        User user2=new User();
        user2.setAge(33);
        user2.setName("Tom");
        
        //将上面的User对象添加到map中
        map.put("u1",user1);
        map.put("u2",user2);
        return map;
    }
  • jsp页面中添加一个方法,用于发出Ajax请求
    • 使用返回的数据(JSON对象),直接使用data.key的形式即可取出Map中的值
//Ajax请求testMap.do
function testMap(){
    var url="<%=request.getContextPath()%>/user/testMap.do";  // 请求的url
    var d={'name':'陈加兵','age':22};   //需要发出请求的参数
    $.post(url,d,function(responseData,status,xhr){
        //如果状态码正确
        if(status=="success"){
            var user1=responseData.u1;   //取出key为u1的值,是一个user对象
            var user2=responseData.u2;   //取出key为u2的值,是一个user对象
            alert("u1 = "+user1.name+"---"+user1.age);  //打印出u1中的name,age的值
        }
    })
}

返回List

  • 这里的返回值是List<Object>
  • JackSon会自动将List转换成JSON数组,在JSP页面就可以使用JSON的方式来获取数据
  • 比如:[{"name":"JACK","age":22},{"name":"Tom","age":33},10],这个是一个JSON数组的形式,因此我们在js中需要遍历这个数组
  • Controller中方法如下:
    @RequestMapping("/testList.do")
    @ResponseBody
    public List<User> testList(@RequestParam("name") String name,
            @RequestParam("age") Integer age) {
        System.out.println(name + "---" + age); // 接收请求参数
        List<User> list = new ArrayList<User>();
        // 新建User对象
        User user1 = new User();
        user1.setName("JACK");
        user1.setAge(22);
​
        User user2 = new User();
        user2.setAge(33);
        user2.setName("Tom");
        //将数据添加到其中
        list.add(user1);
        list.add(user2);
        return list;
    }
  • jsp中使用发出Ajax请求
    • 此时返回的是数组,因此需要循环遍历
//Ajax请求testList.do
function testList(){
    var url="<%=request.getContextPath()%>/user/testList.do";  // 请求的url
    var d={'name':'陈加兵','age':22};   //需要发出请求的参数
    $.post(url,d,function(responseData,status,xhr){
        //如果状态码正确
        if(status=="success"){
            //此时返回的是一个数组,因此我们需要循环遍历这个数组,但是其中的元素是一个User对象,因此可以使用key-value的形式取出其中的值
            for(var i=0;i<responseData.length;i++){
                //将数据输出到控制台
                console.log(responseData[i].name+"----->" + responseData[i].age);
            }
        }
    })
}

返回单个对象

  • 返回的是一个对象,比如一个User对象,JackSon会将其转换成为JSON对象返回给浏览器
  • 返回的是对象,那么我们在js中可以直接使用key-value的形式取出其中的值
  • Controller中的方法
    @RequestMapping("/testObject.do")
    @ResponseBody
    public User testObject(@RequestParam("name") String name,
            @RequestParam("age") Integer age) {
        System.out.println(name + "---" + age); // 接收请求参数
        User user=new User();
        user.setName("JACK");
        user.setAge(22);
        return user;
    }
  • 发出Ajax请求,并且接收数据
    • 直接使用取值即可
//Ajax请求testObject.do
function testObject(){
    var url="<%=request.getContextPath()%>/user/testObject.do";  // 请求的url
    var d={'name':'陈加兵','age':22};   //需要发出请求的参数
    $.post(url,d,function(responseData,status,xhr){
        //如果状态码正确
        if(status=="success"){
            console.log(responseData.name+"----"+responseData.age);
        }
    })
}

练习

省市二级菜单联动

  • 前端使用下拉菜单<select>实现
    1. 加载页面完成之后,发送一个异步请求,请求所有的省份,在省的下拉菜单中显示出来
    2. 当用户选择了某个省之后,那么发送一个异步请求,获取当前省的所有的信息,并且显示在市的下拉菜单中
    3. 的下拉菜单中需要使用onchange监听选项的改变,只要选项改变了就要发出异步请求,返回对应城市的信息
省:<select name="province" id="province" onchange="getCity()">
    <option value="-1">请选择省</option>
</select>
​
​
市:<select name="city" id="city">
    <option value="-1">请选择市</option>
</select>
​
<!--加载jquery-->
<script type="text/javascript" src="<%=request.getContextPath() %>/web/jquery-3.2.1.min.js"></script>
​
<script type="text/javascript">
    //只要页面加载完成之后就会执行其中的逻辑
    $(function(){
        getProvince();   //页面加载完成就调用这个方法发出异步请求
        
    });
    
    //获取省份的方法
    function getProvince(){
        var url="<%=request.getContextPath()%>/menu/getProvince.do";  //异步请求的url
        var d={};   //没有数据提交
        $.post(url,d,function(data,status,xhr){
            if(status=="success"){
                //循环遍历返回的JSON数组
                for(var i=0;i<data.length;i++){
                    //创建option,用于插入节点
                    var option="<option value=" + data[i].code + ">"+data[i].name+"</option>";
                    //将option插入到下拉列表中
                    $("#province").append(option);
                }
            }
        }); 
    }
    
    
    //根据选择的省份获取市
    function getCity(){
        var province=$("#province").val();  //获取下拉菜单的值,这里返回的是省份的编号
        var url="<%=request.getContextPath()%>/menu/getCity.do";  //异步请求的url
        var d={"province":province};   //将省份的编号传入
        
        //每次都要清空之前的城市
        $("#city").html("<option value='-1'>请选择市</option>");
        
        //如果用户点击了请选择省,那么返回的值就是-1,此时不需要发出异步请求
        if(province==-1){
            return;  
        }
        
        //发出异步请求
        $.post(url,d,function(data,status,xhr){
            if(status=="success"){
                //如果返回的是一个空的,直接返回即可,不需要后续的操作
                if(data.lengt==0){
                    return;
                }
                //循环遍历返回的JSON数组
                for(var i=0;i<data.length;i++){
                    //创建option,用于插入节点
                    var option="<option value=" + data[i].code + ">"+data[i].name+"</option>";
                    //将option插入到下拉列表中
                    $("#city").append(option);
                }
            }
        }); 
    }
</script>
  • Controller编写方法
    1. 展示页面的方法(showMenu.do)
    2. 返回省份信息的方法
    3. 返回城市信息方法
    //显示页面
    @RequestMapping("/showMenu.do")
    public String showMenu() {
        return "menu";
    }
    
    //异步请求返回省份的信息
    @RequestMapping("/getProvince.do")
    @ResponseBody
    public List<Province> getProvince(){
        Province p1=new Province();
        p1.setName("江苏");
        p1.setCode(1001);
        
        Province p2=new Province();
        p2.setName("山东");
        p2.setCode(1002);
        
        List<Province> provinces=new ArrayList<Province>();
        provinces.add(p1);
        provinces.add(p2);
        return provinces;
    }
    
    //异步获取城市信息的方法,这里没有操作数据库,仅仅是模拟,因此只要返回数据即可
    @RequestMapping("/getCity.do")
    @ResponseBody
    public List<City> getCity(@RequestParam("province") Integer code){
        System.out.println(code);
        List<City> cities=new ArrayList<City>();
        
        /**
         * 如果这里涉及到数据库操作
         *      1. 调用service的方法查询,service调用dao的方法查询
         *      2. dao中的查询: 根据code查询出对应的城市即可,当然是联表查询
         *      3. select c.name,c.code from city c join province p on c.provice_id=p.id;
         *      4. mybatis调用第三步的查询语句,直接返回的就是List<City>集合
         */
        
        //这里省略if的判断,主要是看效果
        City c1=new City();
        c1.setName("南京");
        c1.setCode(123);
        
        City c2=new City();
        c2.setName("淮安");
        c2.setCode(1223);
        cities.add(c1);
        cities.add(c2);
         
        return cities;   //返回集合
    }

总结

  • springmvc会通过jackson将返回给ajax请求的对象自动封装成JSON对象,那么在JSP页面我们就可以使用JSON的读取方式获取返回的数据即可

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏极客编程

用Java为Hyperledger Fabric(超级账本)开发区块链智能合约链代码之部署与运行示例代码

您已经定义并启动了本地区块链网络,而且已构建 Java shim 客户端 JAR 并安装到本地 Maven 存储库中,现在已准备好在之前下载的 Hyperled...

30510
来自专栏黑泽君的专栏

day63_SpringMVC学习笔记_01

(1)使用eclipse,创建一个动态的web工程   其中Dynamic web module version版本选择 2.5,这样兼容性好一些;   Def...

10610
来自专栏Golang语言社区

linux 内核同步机制使用

Linux 内核中的同步机制:原子操作、信号量、读写信号量、自旋锁的API、大内核锁、读写锁、大读者锁、RCU和顺序锁。 1、介绍 在现代操作系统里,同一时间...

48250
来自专栏我是攻城师

Java并发之高级自旋锁CLH锁和MCS锁

自旋锁(spin lock)是一个典型的对临界资源的互斥手段,自旋锁是基于CAS原语的,所以它是轻量级的同步操作,它的名称来源于它的特性。自旋锁是指当一个线程尝...

38830
来自专栏Golang语言社区

Golang同步:锁的使用案例详解

互斥锁 互斥锁是传统的并发程序对共享资源进行访问控制的主要手段。它由标准库代码包sync中的Mutex结构体类型代表。只有两个公开方法 Lock Unlock ...

39580
来自专栏Ryan Miao

springmvc学习笔记--json--返回json的日期格式问题

(一)输出json数据 springmvc中使用jackson-mapper-asl即可进行json输出,在配置上有几点: 1.使用mvc:annotation...

504100
来自专栏阿杜的世界

通过EmbeddedServletContainerCustomizer接口调优Tomcat

通过在application.properties设置对应的key-value对,可以配置Spring Boot应用程序的很多特性,例如POST、SSL、MyS...

11710
来自专栏coderhuo

虚拟内存探究 -- 第三篇:一步一步画虚拟内存图

这是虚拟内存系列文章的第三篇。 前面我们提到在进程的虚拟内存中可以找到哪些东西,以及在哪里去找。 本文我们将通过打印程序中不同元素内存地址的方式,一步一步细...

27740
来自专栏代码拾遗

SpringMVC 教程 - Controller

Controller也是一个标准的Spring bean,可以在Servlet的WebApplicationContext中定义。也可以使用@Controlle...

9510
来自专栏IT可乐

Junit 入门使用教程

1、Junit 是什么?   JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的s...

24350

扫码关注云+社区

领取腾讯云代金券