转载

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 -->
<beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<propertyname="prefix"value="/web/"/>
	<propertyname="suffix"value=".jsp"/>
</bean>

<!-- 配置注解扫描,用于ajax的注解扫描 -->
<mvc:annotation-driven></mvc:annotation-driven>

编写前端表单

  • 其实并不是使用表单提交的,可以不使用表单
<formaction=""method="post">
	姓名: <inputtype="text"name="name"id="name"onblur="checkName()"><spanid="nameSpan"></span><br>
	密码:<inputtype="password"name="pwd"id="pwd"><spanid="pwSpan"></span><br>
	<inputtype="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文件 -->
<scripttype="text/javascript"src="<%=request.getContextPath() %>/web/jquery-3.2.1.min.js"></script>

<scripttype="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 即可,就会自动的导入其他的两个

    Springmvc响应Ajax请求(@ResponseBody)

<!-- 添加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 监听选项的改变,只要选项改变了就要发出异步请求,返回对应城市的信息
省:<selectname="province"id="province"onchange="getCity()">
	<optionvalue="-1">请选择省</option>
</select>


市:<selectname="city"id="city">
	<optionvalue="-1">请选择市</option>
</select>

<!--加载jquery-->
<scripttype="text/javascript"src="<%=request.getContextPath() %>/web/jquery-3.2.1.min.js"></script>

<scripttype="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;   //返回集合
}
原文  https://chenjiabing666.github.io/2018/05/04/Springmvc响应Ajax请求-ResponseBody/
正文到此结束
Loading...