处理器方法的返回值
处理器方法的返回值
返回 ModelAndView
若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好。
当然,若要返回 ModelAndView,则处理器方法中需要定义 ModelAndView 对象。
在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的 Ajax 异步响应),此时若返回 ModelAndView,则将总是有一部分多余:要么 Model 多余,要么 View 多余。即此时返回 ModelAndView 将不合适。
@Controller
public class UserController {
// 处理登录的控制器
@RequestMapping(value = "islogin", method = RequestMethod.POST)
public ModelAndView checkLogin(Users users) {
ModelAndView mav = new ModelAndView();
if (users.getLoginname().equals("lisi")
&& users.getLoginpwd().equals("123")) {
users.setRealname("李四");
// 返回的数据
mav.addObject("users", users);
// 跳转的页面 配合视图解析器
mav.setViewName("show");
} else {
mav.addObject("msg", "用户名或者密码错误");
// 跳转的页面
mav.setViewName("login");
}
return mav;
}
}
ModelAndView 也可以当作方法参数传入, 不用自己创建, Model 可以单独使用.
@Controller
public class UserController {
// 处理登录的控制器
@RequestMapping(value = "islogin", method = RequestMethod.POST)
public ModelAndView checkLogin(ModelAndView mav, Users users) {
Model m = new Model();
if (users.getLoginname().equals("lisi")
&& users.getLoginpwd().equals("123")) {
users.setRealname("李四");
// 返回的数据
mav.addObject("users", users);
// 跳转的页面 配合视图解析器
mav.setViewName("show");
} else {
mav.addObject("msg", "用户名或者密码错误");
// 跳转的页面
mav.setViewName("login");
}
return mav;
}
}
返回 String
String: 表示视图,可以是逻辑名称,也可以是完整视图路径
逻辑名称:
/** 处理器方法返回String--表示逻辑视图名称,需要配置视图解析器 */
@RequestMapping(value = "/receiveproperty.do")
public String doSome(String name, Integer age) {
System.out.println("doSome, name=" + name + " age=" + age);
// show : 逻辑视图名称,项目中配置了视图解析器
// 框架对视图执行forward转发操作
return "show";
}
手动添加数据:
/** 处理器方法返回String--表示逻辑视图名称,需要配置视图解析器 */
@RequestMapping(value = "/receiveproperty.do")
public String doSome(String name, Integer age) {
System.out.println("doSome, name=" + name + " age=" + age);
//可以自己手动添加数据到request作用域
request.setAttribute("myname",name);
request.setAttribute("myage",age);
// show : 逻辑视图名称,项目中配置了视图解析器
// 框架对视图执行forward转发操作
return "show";
}
完整视图路径:
//处理器方法返回String,表示完整视图路径, 此时不能配置视图解析器
@RequestMapping(value = "/receiveproperty.do")
public String doSome(String name, Integer age) {
System.out.println("doSome, name=" + name + " age=" + age);
request.setAttribute("myname",name);
request.setAttribute("myage",age);
// 完整视图路径,项目中不能配置视图解析器
// 框架对视图执行forward转发操作
return "/WEB-INF/view/show.jsp";
// 如果使用了视图解析器, 那路径就会变成
// /WEB-INF/view/WEB-INF/view/show.jsp.jsp
}
返回 void
void: 不能表示数据,也不能表示视图。
在处理 ajax 的时候,可以使用 void 返回值。 通过 HttpServletResponse 输出数据。响应 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做数据的格式
//使用Student表示处理结果
Student student = new Student();
student.setName("张飞同学");
student.setAge(28);
String json = "";
//把结果的对象转为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();
}
ajax 请求:
$(function () {
$("button").click(function () {
$.ajax({
url: "returnVoid-ajax.do",
data: {
name: "zhangsan",
age: 20,
},
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);
},
});
});
});
返回对象 Object
Object:例如 String, Integer, Map, List, Student 等等都是对象
对象有属性, 属性就是数据。 所以返回 Object 表示数据, 和视图无关。
可以使用对象表示的数据,响应 ajax 请求。
现在做 ajax, 主要使用 json 的数据格式
实现步骤:
加入处理 json 的工具库的依赖, springmvc 默认使用的 jackson。
在 sprigmvc 配置文件之间加入
<mvc:annotation-driven>
注解驱动;对应的功能
json = om.writeValueAsString(student);
在处理器方法的上面加入
@ResponseBody
注解
对应的功能:
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(json);
springmvc 处理器方法返回 Object, 可以转为 json 输出到浏览器,响应 ajax 的内部原理
mvc:annotation-driven
注解
mvc:annotation-driven
注解驱动实现的功能是完成 java 对象到 json,xml, text,二进制等数据格式的转换。
mvc:annotation-driven
在加入到 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)`
例如下面程序
@RequestMapping(value = "/returnString.do")
@ResponseBody
public Student doReturnView2(HttpServletRequest request,String name, Integer age){
Student student = new Student();
student.setName("lisi");
student.setAge(20);
return student;
}
HttpMessageConverter
接口的 canWrite 方法作用是检查处理器方法的返回值能不能转为 var2 表示的数据格式。
检查 student (lisi,20) 能不能转为 var2 表示的数据格式。如果检查能转为 json,canWrite 返回 true
参数 MediaType:表示数据格式, 例如 json, xml 等等
write 方法:把处理器方法的返回值对象,调用 jackson 中的 ObjectMapper 转为 json 字符串。
json = om.writeValueAsString(student);
- @ResponseBody 注解
放在处理器方法的上面, 通过 HttpServletResponse 输出数据,响应 ajax 请求。
PrintWriter pw = response.getWriter();
pw.println(json);
pw.flush();
pw.close();
没有加入注解驱动标签 <mvc:annotation-driven />
时的状态:
org.springframework.http.converter.ByteArrayHttpMessageConverter
org.springframework.http.converter.StringHttpMessageConverter
org.springframework.http.converter.xml.SourceHttpMessageConverter
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
加入注解驱动标签时 <mvc:annotation-driven />
的状态:
org.springframework.http.converter.ByteArrayHttpMessageConverter
org.springframework.http.converter.StringHttpMessageConverter
org.springframework.http.converter.ResourceHttpMessageConverter
org.springframework.http.converter.ResourceRegionHttpMessageConverter
org.springframework.http.converter.xml.SourceHttpMessageConverter
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
处理器方法返回一个 Student:
通过框架转为 json,响应 ajax 请求
@ResponseBody:
作用:
把处理器方法返回对象转为 json 后,通过 HttpServletResponse 输出给浏览器。
位置:
方法的定义上面。 和其它注解没有顺序的关系。
返回对象框架的处理流程:
框架会把返回 Student 类型,调用框架的中
ArrayList<HttpMessageConverter>
中每个类的 canWrite () 方法检查那个 HttpMessageConverter 接口的实现类能处理 Student 类型的数据 --MappingJackson2HttpMessageConverter框架会调用实现类的 write (),MappingJackson2HttpMessageConverter 的 write () 方法把李四同学的 student 对象转为 json,调用 Jackson 的 ObjectMapper 实现转为 json
contentType: application/json;charset=utf-8
框架会调用 @ResponseBody 把 2 的结果数据输出到浏览器, ajax 请求处理完成
@RequestMapping(value = "/returnStudentJson.do")
@ResponseBody
public Student doStudentJsonObject(String name, Integer age) {
//Student对象表示结果数据
Student student = new Student();
student.setName("李四同学");
student.setAge(20);
return student; // 会被框架转为json
}
处理器方法返回 List<Student>
:
返回对象框架的处理流程:
框架会返回
List<Student>
类型,调用框架的中ArrayList<HttpMessageConverter>
中每个类的 canWrite () 方法检查那个 HttpMessageConverter 接口的实现类能处理 Student 类型的数据 --MappingJackson2HttpMessageConverter
框架会调用实现类的 write(), MappingJackson2HttpMessageConverter 的 write () 方法
把李四同学的 student 对象转为 json, 调用 Jackson 的 ObjectMapper 实现转为 json array
contentType: application/json;charset=utf-8
框架会调用 @ResponseBody 把 2 的结果数据输出到浏览器, ajax 请求处理完成
@RequestMapping(value = "/returnStudentJsonArray.do")
@ResponseBody
public List<Student> doStudentJsonObjectArray(String name, Integer age) {
List<Student> list = new ArrayList<>();
// 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;
}
ajax 接收:
$(function () {
$("button").click(function () {
$.ajax({
url: "returnStudentJsonArray.do",
data: {
name: "zhangsan",
age: 20,
},
type: "post",
dataType: "json",
success: function (resp) {
// list集合在前端会显示为一个数组
// [{"name":"李四同学","age":20},{"name":"张三","age":28}]
// 循环遍历
$.each(resp, function (i, n) {
alert(n.name + " " + n.age);
});
},
});
});
});
处理器方法返回 String:
处理器方法返回的是 String , String 表示数据的,不是视图。
区分返回值 String 是数据,还是视图,看有没有 @ResponseBody 注解
如果有 @ResponseBody 注解,返回 String 就是数据,反之就是视图
默认使用 “text/plain;charset=ISO-8859-1” 作为 contentType, 导致中文有乱码
解决方案:给 RequestMapping 增加一个属性 produces, 使用这个属性指定新的 contentType.
返回对象框架的处理流程:
框架会把返回 String 类型,调用框架的中
ArrayList<HttpMessageConverter>
中每个类的 canWrite () 方法检查那个 HttpMessageConverter 接口的实现类能处理 String 类型的数据 --StringHttpMessageConverter
框架会调用实现类的 write(), StringHttpMessageConverter 的 write () 方法
把字符按照指定的编码处理 text/plain;charset=ISO-8859-1
框架会调用 @ResponseBody 把 2 的结果数据输出到浏览器, ajax 请求处理完成
@RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
@ResponseBody
public String doStringData(String name,Integer age){
return "Hello SpringMVC 返回对象,表示数据";
}
ajax 接收:
$(function () {
$("button").click(function () {
//alert("button click");
$.ajax({
url: "returnStringData.do",
data: {
name: "zhangsan",
age: 20,
},
type: "post",
dataType: "text",
success: function (resp) {
alert("返回的是文本数据:" + resp);
},
});
});
});