使用@Controller注解的处理器方法,返回值会有四种类型:ModelAndView、String、Void、自定义Java对象
ModelAndView:有数据和视图
若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时 处理器方法返回 ModelAndView 比较好。
若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的 Ajax 异步响应),此时返回 ModelAndView 将不适合
@RequestMapping(value = "/receiveproperty.do")
public ModelAndView doSome(String name,Integer age){
System.out.println("doSome, name="+name+" age="+age);
//处理 some.do请求,相当于service调用处理完成
ModelAndView mdv = new ModelAndView();
mdv.addObject("myname",name);
mdv.addObject("myage",Integer.valueOf(age));
mdv.setViewName("show");
return mdv;
}
String:表示视图,可以是逻辑名称,也可以是完整视图路径
(1)逻辑视图路径
此时在 springmvc.xml 中需要配置视图解析器
@Controller注解处理器
/**
* 1、处理器方法返回String
* (1)表示逻辑视图名称,需要配置视图解析器
* (2)表示完整视图路径,不能配置视图解析器
*/
@RequestMapping(value = "/returnString-view.do")
public String doReturnStringView(HttpServletRequest request,String name,Integer age){
System.out.println("doReturnStringView, name="+name+" age="+age);
request.setAttribute("myname",name);
request.setAttribute("myage",age);
// show : 逻辑视图名称,项目中配置了视图解析器
// 框架对视图执行forward转发操作
return "show";
}
(2)完整视图路径
返回完整视图路径时,不需要设置视图解析器,不然会报错
HTTP状态 404 - 未找到
文件 [/WEB-INF/view/WEB-INF/view/show.jsp.jsp] 未找到
//处理器方法返回String,表示完整视图路径,此时不能配置视图解析器
@RequestMapping(value = "/returnString-view1.do")
public String doReturnStringView1(HttpServletRequest request,String name,Integer age){
System.out.println("doReturnStringView1, name="+name+" age="+age);
request.setAttribute("myname",name);
request.setAttribute("myage",age);
// 完整视图路径,项目中不能配置视图解析器
// 框架对视图执行forward转发操作,如果配置了视图解析器会出现如下结果
// HTTP状态 404 - 未找到 文件 [/WEB-INF/view/WEB-INF/view/show.jsp.jsp] 未找到
return "/WEB-INF/view/show.jsp";
}
处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void
处理器方法返回 void 的应用场景,AJAX 响应
由于服务端向浏览器传回的是 JSON 数据,需要使用一个工具类将字符串包装为 JSON 格式,所以需要导入 JSON 的依赖
(1)在 pom.xml 文件中加入处理json工具库的依赖,SpringMVC默认使用jackson
com.fasterxml.jackson.core
jackson-core
2.9.0
com.fasterxml.jackson.core
jackson-databind
2.9.0
(2)引入jQuery库
由于要使用 jQuery 的 ajax()方法提交 AJAX 请求,所以项目中需要引入 jQuery 的库
(3)index.jsp视图
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
SpringMVC项目
(4)创建Java对象Student类
package com.mycompany.domain;
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 +
'}';
}
}
(5) 处理器类MyController
/**
* 处理器返回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 = new Student();
student.setName("张三");
student.setAge(18);
String json = "";
//将结果对象转为json格式数据
if (student != null){
ObjectMapper objectMapper = new ObjectMapper();
json = objectMapper.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();
}
点击按钮,发起请求,可以看到web端页面输出,右键点击【检查】,可以看到请求头以及响应头内容
后台控制台输出如下
处理器方法也可以返回 Object 对象,这个 Object 可以是 Integer,String,自定义Java对象,Map,List 等。返回的对象不是逻辑视图,而是直接在页面显示的数据
返回对象,需要使用 @ResponseBody 注解,将转换后的 JSON 数据放入到响应体中
(1)在 pom.xml 文件中加入处理json工具库的依赖,SpringMVC默认使用jackson
com.fasterxml.jackson.core
jackson-core
2.9.0
com.fasterxml.jackson.core
jackson-databind
2.9.0
(2)声明注解驱动
springmvc.xml
将 Object 数据转化为 JSON 数据,需要由消息转换器 HttpMessageConverter 完成。而消息转换器的开启,需要由
SpringMVC 使用消息转换器实现请求数据和对象,处理器方法返回对象和响应输出之间的自动转换
当 Spring 容器进行初始化过程中,在
HttpMessageConverter 接口 : HttpMessageConverter
HttpMessageConverter
public interface HttpMessageConverter {
/**
* 指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为clazz 类型的对
象,同时指定支持MIME类型(text/html,applaiction/json 等)
*/
boolean canRead(Class> var1, @Nullable MediaType var2);
/**
* 指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在 MediaType 中定义
*/
boolean canWrite(Class> var1, @Nullable MediaType var2);
//该转换器支持的媒体类型
List getSupportedMediaTypes();
//将请求信息流转换为 T 类型的对象
T read(Class extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;
//将 T 类型的对象写到响应流中,同时指定相应的媒体类型为 contentType
void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}
(3)在处理器方法上加入@ResponseBody注解
index.jsp视图
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
SpringMVC项目
(1)Java对象
/**
* 处理器方法返回Java对象Student,通过SpringMVC框架转为json,响应Ajax请求
* @ResponseBody:
* 作用:将处理器方法返回对象转为json后,通过HttpServletResponse输出给浏览器
* 位置:方法定义上面,和其他注解没有上下顺序关系
*
* SpringMVC返回Java对象处理流程:
* 1、SpringMVC框架返回Java对象Student类型,是调用框架ArrayList中每个类的canWrite()方法
* 检查哪个HttpMessageConverter接口的实现类能处理Student类型的数据--MappingJackson2HttpMessageConverter
*
* 2、SpringMVC框架会调用实现类的write()方法,MappingJackson2HttpMessageConverter的write()方法
* 将student对象转为json,调用Jackson的ObjectMapper实现转为json
* contentType:application/json;charset=utf-8
*
* 3、SpringMVC框架会调用@ResponseBody注解将结果数据输出到浏览器,Ajax请求处理完成
*/
@RequestMapping(value = "returnStudentJson.do")
@ResponseBody
public Student doStudentJsonObject(String name,Integer age){
Student student = new Student();
student.setName("李四");
student.setAge(18);
return student; // 会被框架转为json
}
(2)List集合
/**
* 处理器方法返回集合List
* 处理流程如上
*/
@RequestMapping(value = "/returnStudentListJson.do")
@ResponseBody
public List doStudentListJsonObject(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(18);
list.add(student);
return list;
}
(3)String数据
处理器方法返回String(此处String表示数据,不是视图路径)
区分String是视图路径还是数据,关键就看是否有@ResponseBody注解;有@ResponseBody注解,返回String就是数据,反之就是视图路径
默认响应头Response Headers中Content-Type: text/plain;charset=ISO-8859-1,导致中文有乱码
给@RequestMapping增加一个属性 produces,使用此属性指定Content-Type;
@RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
/**
* 处理器方法返回String(此处String表示数据,不是视图路径)
* 区分String是视图路径还是数据,关键就看是否有@ResponseBody注解;有@ResponseBody注解,返回String就是数据,反之就是视图路径
*
* 默认响应头Response Headers中Content-Type: text/plain;charset=ISO-8859-1,导致中文有乱码
* 解决方案
* 给@RequestMapping增加一个属性 produces,使用此属性指定Content-Type
*
* 处理器方法返回String数据处理流程
* 1、SpringMVC框架调用框架中中ArrayList中每个类的canWrite()方法
* 检查哪个HttpMessageConverter接口的实现类能处理String类型的数据--StringHttpMessageConverter
* 2、SpringMVC框架会调用实现类的write()方法,StringHttpMessageConverter的write()方法
* 将字符按照指定的编码处理 ,如:text/plain;charset=ISO-8859-1
* 3、SpringMVC框架会调用@ResponseBody注解将结果数据输出到浏览器,Ajax请求处理完成
*/
@RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
@ResponseBody
public String doStringData(String name,Integer age){
return "Hello SpringMVC 返回对象,表示数据";
}
总结:
1、Ajax使用,主要使用json的数据,实现步骤如下:
(1)加入处理json工具库的依赖,SpringMVC默认使用jackson
(2)在SpringMVC配置文件中加入
json = ObjectMapper.writeValueAsString(student);
(3)在处理器方法上加入@ResponseBody注解
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.println(json);
2、SpringMVC处理器方法返回object,可以转为json输出到浏览器,响应Ajax内部原理
(1)
【1】
完成Java对象到json,xml,text,二进制等数据格式的转换
包括 MappingJackson2HttpMessageConverter (使用jackson工具库中的ObjectMapper实现java对象转为json字符串)
【2】HttpMessageConverter接口:消息转换器
功能:定义了Java转json,xml等数据格式的方法,这个接口有很多实现类 这些实现类完成 java对象到json, java对象到xml,java对象到二进制数据的转换 两个方法是控制器类把结果输出给浏览器时使用:
boolean canWrite(Class> var1, @Nullable MediaType var2)
void write(T va1, @Nullable MediaType va2, HttpOutputMessage var3)
如处理器方法
@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;
}
【1】canWrite:检查处理器方法的返回值,能不能作为var2表示的数据格式 检查student(lisi,18)能不能转为var2表示的数据格式;如果检查能转为json,canWrite返回true MediaType:表示数据格式的,如json,xml等
【2】write:将处理器方法的返回值对象,调用jackson中的ObjectMapper转为json字符串
json = objectMapper.writeValueAsString(student);
(2)@ResponseBody注解 放在处理器方法的上面,通过HttpServletResponse输出数据,响应ajax请求
PrintWriter pw = response.getWriter();
pw.println(json);
pw.flush();
pw.close();
在 DispatcherServlet 类中此处加入断点
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
......
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
......
}
}
没有加入注解驱动标签
0 = {ByteArrayHttpMessageConverter@5029}
1 = {StringHttpMessageConverter@5030}
2 = {SourceHttpMessageConverter@5031}
3 = {AllEncompassingFormHttpMessageConverter@5032}
加入注解驱动标签时
//负责读取二进制格式的数据和写出二进制格式的数据
0 = {ByteArrayHttpMessageConverter
//负责读取字符串格式的数据和写出字符串格式的数据
1 = {StringHttpMessageConverter@5161}
//负责读取资源文件和写出资源文件数据
2 = {ResourceHttpMessageConverter@5162}
//
3 = {ResourceRegionHttpMessageConverter@5163}
//能够读 / 写 来 自 HTTP 的 请 求 与 响 应 的
javax.xml.transform.Source ,支持 DOMSource,
SAXSource, 和 StreamSource 的 XML 格式
4 = {SourceHttpMessageConverter@5164}
//负责处理表单(form)数据
5 = {AllEncompassingFormHttpMessageConverter@5165}
//使用 JAXB 负责读取和写入 xml 标签格式的数据
6 = {Jaxb2RootElementHttpMessageConverter@5166}
//负责读取和写入 json 格式的数据。利用Jackson 的 ObjectMapper 读写 json 数据,操作Object 类型据,可读取 application/json,响应媒体类型为 application/json
7 = {MappingJackson2HttpMessageConverter@5167}