一、 处理器方法的返回值
使用@Controller 注解的处理器的处理器方法,其返回值常用的有四种类型:
➢ 第一种:ModelAndView
➢ 第二种:String
➢ 第三种:无返回值 void
➢ 第四种:返回自定义类型对象
根据不同的情况,使用不同的返回值。
1.1返回ModelAndView
若处理器方法执行完后,需求是进行资源跳转和传递数据,那么使用ModelAndView合适,但是如果是只需要进行其中一项,那么返回ModelAndView是多余的
1.2返回String类型
这个是进行资源跳转所需要的。
返回的是逻辑视图名称或者完整视图路径。
1.3返回void
对于处理器方法返回 void 的应用场景,AJAX 响应.
若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。
添加jackson依赖
因为服务器向浏览器传的数据类型是JSON数据,故需要一个工具类将字符串包装为JSON格式。
<!--Jackson依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
1.3.3 在index.jsp中点击按钮发送ajax请求
<%@ page contentType ="text/html;charset=UTF-8" language="java" %>
<html>
<script type="text/javascript" src="js/jquery.js"></script>
<body>
<button id="btn">发起ajax请求</button>
</form>
</body>
</html>
1.3.4 编写ajax请求的jquery代码
分析:使用ajax函数发送ajax请求的时候,需要程序员给我们传过来什么?
* 请求的方式(type):GET/POST
* 请求的URL(url):url
* 请求时提交的数据(data):data
* 请求时发送异步请求还是同步请求(async):true表示异步,false表示同步。
<script type="text/javascript">
$(function(){
$("button").click(function(){
//alert("button click");
$.ajax({
//url:"returnVoid-ajax.do",
//url:"returnStudentJsonArray.do",
url:"returnStringData.do",
data:{
name:"zhangsan",
age:20
},
type:"post",
dataType:"text",
//dataType:"json",
success:function(resp){
//resp从服务器端返回的是json格式的字符串 {"name":"zhangsan","age":20}
//jquery会把字符串转为json对象, 赋值给resp形参。
// [{"name":"李四同学","age":20},{"name":"张三","age":28}]
//alert(resp.name + " "+resp.age);
/*$.each(resp,function(i,n){
alert(n.name+" "+n.age)
})*/
alert("返回的是文本数据:"+resp);
}
})
})
})
</script>
1.3.5 定义Student对象
public class Student {
// 属性名和请求中参数名一样
private String name;
private Integer age;
1.3.6 修改处理器类MyController
处理器对于 AJAX 请求中所提交的参数,可以使用逐个接收的方式,也可以以对象的方式整体接收。只要保证 AJAX 请求参数与接收的对象类型属性同名。
以逐个方式接收参数
//处理器方法返回void, 响应ajax请求
//手工实现ajax,json数据: 代码有重复的 1. java对象转为json; 2. 通过HttpServletResponse输出json数据
@RequestMapping(value = "/returnVoid-ajax.do")
public void doReturnVoidAjax(HttpServletResponse response, String name, Integer age) throws IOException {
System.out.println("===doReturnVoidAjax====, name="+name+" age="+age);
//处理ajax, 使用json做数据的格式
//service调用完成了, 使用Student表示处理结果,因为json数据对应的是java对象
Student student = new Student();
student.setName("张飞同学");
student.setAge(28);
String json = "";
//把结果的对象转为json格式的数据
if( student != null){
ObjectMapper om = new ObjectMapper();
json = om.writeValueAsString(student);
System.out.println("student转换的json===="+json);
}
//输出数据,响应ajax的请求
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(json);
pw.flush();
pw.close();
}
使用ObjectMapper的writeVlueAsString()来返回Ajax想要返回的数据类型
1.3.7
1.4返回对象Object
基于以上的程序进行改善,框架来做将对象转换为json字符串,框架来做响应json数据到浏览器上面。
处理器方法返回对象,实际上是返回数据。 因为对象有属性,属性就是数据。 也就是说我们返回的这个数据是直接在页面上显示的。
改善:
现在做ajax,主要使用json的数据格式。
a. 实现步骤
1、加入处理json的工具库依赖,使对象数据转换为json数据,springmvc默认使用的jackson。
2、在springmvc配置文件加入 <mvn:annotation-driven>
注解驱动
实现以下代码
json=om.writeValueAsString(student)
3、在处理器方法上面加入@ResourcesBody注解
response.setContentType("application/json;charset=utf-8");
PrintWriter ps = response.getWriter();
pw.println(json);
b.响应ajax内部原理
springmvc处理器方法返回Object类,springmvc可以将其转为json数据输出到浏览器,其响应ajax的内部原理是:
1、<mvn:annotation-driver>
注解驱动
完成java对象到json,xml,text,二进制等数据格式的转换
涉及到HttpMessageConverter接口:消息转换器
他定义了java对象转为json,xml,text等数据格式的方法。这个接口有很多的实现类。这些实现类完成java对象到json,xml,text数据格式的转换。
①HttpMessageConverter接口内的方法
public interface HttpMessageConverter<T> {
boolean canRead(Class<?> var1, @Nullable MediaType var2);
boolean canWrite(Class<?> var1, @Nullable MediaType var2);
List<MediaType> getSupportedMediaTypes();
T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;
void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}
这四个方法两两一对。
如下:下面两个方法是控制器类把结果输出到浏览器中
boolean canWrite(Class<?> var1, @Nullable MediaType var2);
void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
1)canWrite方法是检查处理器方法的返回值,能否转为var2的数据格式(MediaType)。
MediaType:是数据格式,该类中有json,xml,text等数据格式
框架会试着把数据转成json,xml等,首要是json,如果可以转换,其他的就不检查了。
2)wirte方法:把处理器的返回值对象转换为var2的数据格式,此时会调用jackson中的ObjectMapper转化数据格式。
json = om.writeValueAsString(返回值对象)
②HttpMessageConverter的实现类
当使用了注解驱动后,注解驱动会自动创建HttpMessageConverter的7个实现类,包括MappingJackson2HttpMessageConverter(使用jackson工具库中的objectMapper实现java对象转为json字符串的实现类)。
当没有加入、
解驱动时,HttpMessageConverter只有4个实现类。
c.@ResourceBody注解
放在处理器方法的上面,通过HttpServletResponse输出数据,响应ajax请求。
并且自动设置响应数据格式
response.setContentType(“text/html”),响应格式是根据ajax请求中的dataType设置的。
PrintWriter pw = response.getWriter();
pw.println(json);
pw.flush();
pw.close();
实现步骤
1.4.1添加依赖
只有声明了这个依赖才能转换对象为json对象
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
1.4.2声明注解驱动
<mvn:annotation-driven>
1.4.3 在控制器中写控制类
@Controller
public class MyController {
@RequestMapping("/returnStudent.do")
@ResponseBody
public Student returnStudent(String name,Integer age){
Student stu = new Student(name,age);
return stu;
}
}
1.5处理器方法返回的是一个List<>集合
当有多个对象的时候,需要返回一个List集合
最终返回的是一个JSON数组
测试:直接在浏览器上输入目标地址->返回的是一个数组
数组用Jquery的循环数组来输出集合中的数组元素
1.6利用String返回文本数据
如果处理器方法上面有@ResponseBody注解那String返回的就是文本数据,否则是视图。
测试程序出现的问题:
a.当处理器方法返回数据和ajax请求的dataType不同时,会在页面出错synax error
b.当改变ajax的dataType为text时,会出现中文乱码。
当设置dataType是text时,响应头的文本格式ContentType默认是text/plain;charset=ISO-8859-1。这个编码方法是给浏览器看的,浏览器根据这个ContentType的编译方式去编译服务器返回的数据。
已知在前面我们定义了过滤器,过滤器中配置的过滤数据是将请求的数据和相应的数据的数据格式都转变为utf-8,而当我们使用了dataType为text,底层的HttpMessageConverter走的是StringHttpMessageConverter实现类,他的底层是response.setContentType("text/pain charset=iso-8859-1)会覆盖配置的过滤器
解决方案是给@RequestMapping增加一个属性produces,改变响应头的编码格式。