1. 使用@Controller 注解的处理器的处理器方法,其返回值常用的有四种类型: 22
➢ 第一种:ModelAndView
➢ 第二种:String
➢ 第三种:无返回值 void
➢ 第四种:返回自定义类型对象
根据不同的情况,使用不同的返回值。
2. 返回 ModelAndView 22
若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时
处理器方法返回 ModelAndView 比较好。当然,若要返回 ModelAndView,则处理器方法中
需要定义 ModelAndView 对象。
在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何
资源跳转(如对页面的 Ajax 异步响应),此时若返回 ModelAndView,则将总是有一部分多
余:要么 Model 多余,要么 View 多余。即此时返回 ModelAndView 将不合适。
3. 返回 String表示视图 23
处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址
3.1 返回内部资源逻辑视图名 23
若要跳转的资源为内部资源,则视图解析器可以使用 InternalResourceViewResolver 内部
资源视图解析器。此时处理器方法返回的字符串就是要跳转页面的文件名去掉文件扩展名后
的部分。这个字符串与视图解析器中的 prefix、suffix 相结合,即可形成要访问的 URI。
3.1.1 例如 23
直接修改处理器类 MyController
/**
* 处理器方法返回String--表示逻辑视图名称,需要配置视图解析器 23
*/
@RequestMapping(value = "/returnString-view.do")
public String doReturnView(HttpServletRequest request,String name, Integer age){
System.out.println("doReturnView, name="+name+" age="+age);
//可以自己手工添加数据到request作用域
request.setAttribute("myname",name);
request.setAttribute("myage",age);
// show : 逻辑视图名称,项目中配置了视图解析器
// 框架对视图执行forward转发操作
return "show";
}
index.jsp
<%--index.jsp页面的编写 23--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>处理器方法返回String表示视图名称</p>
<form action="returnString-view.do" method="get">
姓名:<input type="text" name="name"> <br/>
年龄:<input type="text" name="age"> <br/>
<input type="submit" value="提交参数">
</form>
</body>
</html>
当然,也可以直接返回资源的物理视图名。不过,此时就不需要再在视图解析器中再配
置前辍与后辍了。
//处理器方法返回String,表示完整视图路径, 此时不能配置视图解析器 23
@RequestMapping(value = "/returnString-view2.do")
public String doReturnView2(HttpServletRequest request,String name, Integer age){
System.out.println("===doReturnView2====, name="+name+" age="+age);
//可以自己手工添加数据到request作用域
request.setAttribute("myname",name);
request.setAttribute("myage",age);
// 完整视图路径,项目中不能配置视图解析器
// 框架对视图执行forward转发操作
// 使用视图解析器后的路径 /WEB-INF/view//WEB-INF/view/show.jsp.jsp
//我们要是用完整路径访问,就不能需要视图解析器,所以注释掉springmvc.xml文件中的视图解析器 23
return "/WEB-INF/view/show.jsp";
}
4. 返回 void(了解) 24
void: 不能表示数据,也不能表示视图。
若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。
在处理ajax的时候,可以使用void返回值。 通过HttpServletResponse输出数据。响应ajax请求。ajax请求服务器端返回的就是数据, 和视图无关。
4.1 例如,对于 AJAX 的异步请求的响应。 24
4.1.1 Step1:maven 加入 jackson 依赖
由于本项目中服务端向浏览器传回的是 JSON 数据,需要使用一个工具类将字符串包装
为 JSON 格式,所以需要导入 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>
4.1.2 Step2:引入 jQuery 库
由于本项目要使用 jQuery 的 ajax()方法提交 AJAX 请求,所以项目中需要引入 jQuery 的
库。在 WebRoot 下新建一个 Folder(文件夹),命名为 js,并将 jquery-1.11.1.js 文件放入其
中。
当然,该 jQuery 库文件,需要在使用 ajax()方法的 index 页面中引入。
4.1.3 Step3:定义 index 页面
index 页面由两部分内容构成:一个是<button/>,用于提交 AJAX 请求;一个是<script/>,
用于处理 AJAX 请求。
index.jsp
<%-- 引入jQuery库文件 24--%>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function (){
//$("button")是标签选择器
// $("#btn")是类选择器
// $(".class样式名)是类选择器
$("button").click(function (){
//alert("单击按钮了")
$.ajax({
url:"returnVoid-ajax.do",
data:{
name:"zhangsan",
age:22
},
type:"post",
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>
<br/>
<button id="btn">发起ajax请求</button>
4.1.4 Step4: 定义对象 Student
Student
package com.bjpowernode.vo;
//保存请求参数值的一个普通类 21
public class Student {
// 属性名和请求中参数名一样
private String name;
private Integer age;
public Student() {
System.out.println("===Student的无参数构造方法===");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("setName"+name);
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
System.out.println("setAge"+age);
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
4.1.5 Step5:修改处理器类 MyController
处理器对于 AJAX 请求中所提交的参数,可以使用逐个接收的方式,也可以以对象的方
式整体接收。只要保证 AJAX 请求参数与接收的对象类型属性同名。
4.1.5.1 以逐个方式接收参数:
MyController
//处理器方法返回void, 响应ajax请求 24
//手工实现ajax,json数据: 代码有重复的 1. java对象转为json; 25
// 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表示处理结果
Student student = new Student();
student.setName(name);
student.setAge(age);
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();
}
5. 返回对象是object 25-26
处理器方法也可以返回 Object 对象。 例如String , Integer , Map,List, Student等等都是对象,但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。对象有属性, 属性就是数据。 所以返回Object表示数据, 和视图无关。
返回对象,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。
Object:
5.1 可以使用对象表示的数据,响应ajax请求。返回对象是student 26
5.1.1 pom.xml 26
由于返回 Object 数据,一般都是将数据转化为了 JSON 对象后传递给浏览器页面的。而
这个由 Object 转换为 JSON,是由 Jackson 工具完成的。所以需要导入 Jackson 的相关 Jar 包。
依赖:
<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>
5.1.2 声明注解驱动 26,27,28
将 Object 数据转化为 JSON 数据,需要由消息转换器 HttpMessageConverter 完成。而转
换器的开启,需要由来完成。
SpringMVC 使用消息转换器实现请求数据和对象,处理器方法返回对象和响应输出之间
的自动转换
当 Spring 容器进行初始化过程中,在处创建注解驱动时,默认
创建了七个 HttpMessageConverter 对象。也就是说,我们注册,就
是为了让容器为我们创建 HttpMessageConverter 对象。
springmvc.xml
<!-- 添加注解驱动 28-->
<mvc:annotation-driven/>
5.1.2.1 springmvc处理器方法返回Object, 可以转为json输出到浏览器,响应ajax的内部原理 26-27-28
注解驱动。
注解驱动实现的功能是 完成java对象到json,xml, text,二进制等数据格式的转换。
在加入到springmvc配置文件后, 会自动创建HttpMessageConverter接口的7个实现类对象, 包括 MappingJackson2HttpMessageConverter (使用jackson工具库中的ObjectMapper实现java对象转为json字符串)
HttpMessageConverter接口:消息转换器。
功能:定义了java转为json,xml等数据格式的方法。 这个接口有很多的实现类。
这些实现类完成 java对象到json, java对象到xml,java对象到二进制数据的转换
下面的两个方法是控制器类把结果输出给浏览器时使用的:
boolean canWrite(Class var1, @Nullable MediaType var2);
void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3)
1)canWrite作用检查处理器方法的返回值,能不能转为var2表示的数据格式。
检查 student(lisi,20) 能不能转为var2表示的数据格式。如果检查能转为json,canWrite返回true
MediaType:表示数格式的, 例如json, xml等等
例如处理器方法
@RequestMapping(value = "/returnString.do")
public Student doReturnView2(HttpServletRequest request,String name, Integer age){
Student student = new Student();
student.setName("lisi");
student.setAge(20);
return student;
}
2)write:把处理器方法的返回值对象,调用jackson中的ObjectMapper转为json字符串。
例如 json = om.writeValueAsString(student);
总结:说白了canWrite就是判断能不能转,write是真正干活转换的
5.1.3 在处理器方法的上面加入@ResponseBody注解 28
5.1.3.1 @ResponseBody注解 28
作用:把处理器方法返回对象转为json后,通过HttpServletResponse输出给浏览器。响应ajax请求的。
位置:方法的定义上面。 和其它注解没有顺序的关系。
例如代替我们完成以下代码
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(json);
MyController
@RequestMapping(value = "/returnStudentJson.do")
@ResponseBody
public Student doStudentJsonObject(String name, Integer age) {
//调用service,获取请求结果数据 , Student对象表示结果数据
Student student = new Student();
student.setName("李四同学");
student.setAge(20);
return student; // 会被框架转为json
}
发送的ajax请求,index.jsp
<%-- 引入jQuery库文件 24--%>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function (){
//$("button")是标签选择器
// $("#btn")是类选择器
// $(".class样式名)是类选择器
$("button").click(function (){
//alert("单击按钮了")
$.ajax({
url:"returnStudentJson.do",
data:{
name:"zhangsan",
age:22
},
type:"post",
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)
}
})
})
})
</script>
<br/>
<br/>
<button id="btn">发起ajax请求</button>
5.1.3.2 返回对象框架的处理流程: 29
1. 框架会把返回Student类型,调用框架的中ArrayList中每个类的canWrite()方法检查那个HttpMessageConverter接口的实现类能处理Student类型的数据---->MappingJackson2HttpMessageConverter
2.框架会调用实现类的write(), MappingJackson2HttpMessageConverter的write()方法
把李四同学的student对象转为json, 调用Jackson的ObjectMapper实现转为json
contentType: application/json;charset=utf-8
3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成
5.2 返回的对象的List集合 30
修改处理器 MyController
/**
* 处理器方法返回List 30
* 返回对象框架的处理流程:
* 1. 框架会把返回List类型,调用框架的中ArrayList中每个类的canWrite()方法
* 检查那个HttpMessageConverter接口的实现类能处理Student类型的数据--MappingJackson2HttpMessageConverter
*
* 2.框架会调用实现类的write(), MappingJackson2HttpMessageConverter的write()方法
* 把李四同学的student对象转为json, 调用Jackson的ObjectMapper实现转为json array
* contentType: application/json;charset=utf-8
*
* 3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成
*/
@RequestMapping(value = "/returnStudentJsonArray.do")
@ResponseBody
public List doStudentJsonObjectArray(String name, Integer age) {
List list = new ArrayList<>();
//调用service,获取请求结果数据 , Student对象表示结果数据
Student student = new Student();
student.setName("李四同学");
student.setAge(20);
list.add(student);
student = new Student();
student.setName("张三");
student.setAge(28);
list.add(student);
return list;//会被框架转为json格式的数组
}
修改 index 页面
<%-- 引入jQuery库文件 24--%>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function (){
//$("button")是标签选择器
// $("#btn")是类选择器
// $(".class样式名)是类选择器
$("button").click(function (){
//alert("单击按钮了")
$.ajax({
url:"returnStudentJsonArray.do",
data:{
name:"zhangsan",
age:22
},
type:"post",
dataType:"json",
success:function (resp){
//resp从服务器端返回的是json格式的字符串 {"name":"zhangsan","age":20}
//jquery会把字符串转为json对象, 赋值给resp形参。
//alert(resp.name+","+resp.age)
// [{"name":"李四同学","age":20},{"name":"张三","age":28}]
//这是jQuery中的循环数组函数 30
$.each(resp,function(i,n){
alert(n.name+" "+n.age)
})
// alert(resp);
}
})
})
})
</script>
<br/>
<br/>
<button id="btn">发起ajax请求</button>
5.2.1 返回对象框架的处理流程:30
1. 框架会把返回List类型,调用框架的中ArrayList中每个类的canWrite()方法 检查那个HttpMessageConverter接口的实现类能处理Student类型的数据--MappingJackson2HttpMessageConverter
2.框架会调用实现类的write(), MappingJackson2HttpMessageConverter的write()方法
把李四同学的student对象转为json, 调用Jackson的ObjectMapper实现转为json array
contentType: application/json;charset=utf-8
3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成
5.3 返回值是String字符串表示数据 31
若要返回非中文字符串,将前面返回数值型数据的返回值直接修改为字符串即可。但若
返 回 的 字 符 串 中 带 有 中 文 字 符 , 则 接 收 方 页 面 将 会 出 现 乱 码 。 此 时 需 要 使 用@RequestMapping 的 produces 属性指定字符集。produces,产品,结果,即该属性用于设置输出结果类型。
MyController
@RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
@ResponseBody
public String doStringData(String name,Integer age){
return "Hello SpringMVC 返回对象,表示数据";
}
index.jsp
<%-- 引入jQuery库文件 24--%>
<script type="text/javascript" src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
$(function (){
//$("button")是标签选择器
// $("#btn")是类选择器
// $(".class样式名)是类选择器
$("button").click(function (){
//alert("单击按钮了")
$.ajax({
url:"returnStringData.do",
data:{
name:"zhangsan",
age:22
},
type:"post",
//dataType:"json",
dataType:"text",
success:function (resp){
//resp从服务器端返回的是json格式的字符串 {"name":"zhangsan","age":20}
//jquery会把字符串转为json对象, 赋值给resp形参。
//alert(resp.name+","+resp.age)
// [{"name":"李四同学","age":20},{"name":"张三","age":28}]
//输出 返回的String 表示数据 31
alert("返回的是文本数据="+resp);
}
})
})
})
</script>
<br/>
<br/>
<button id="btn">发起ajax请求</button>
5.3.1 返回对象框架的处理流程: 31
1. 框架会把返回String类型,调用框架的中ArrayList中每个类的canWrite()方法检查那个HttpMessageConverter接口的实现类能处理String类型的数据--StringHttpMessageConverter
2.框架会调用实现类的write(), StringHttpMessageConverter的write()方法
把字符按照指定的编码处理 text/plain;charset=ISO-8859-1
3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成