使用@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 中需要配置视图解析器
- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
-
- <property name="prefix" value="/WEB-INF/view/" />
-
- <property name="suffix" value=".jsp" />
- bean>
@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
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-coreartifactId>
- <version>2.9.0version>
- dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-databindartifactId>
- <version>2.9.0version>
- dependency>
(2)引入jQuery库
由于要使用 jQuery 的 ajax()方法提交 AJAX 请求,所以项目中需要引入 jQuery 的库

(3)index.jsp视图
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
-
- <head>
- <title>Titletitle>
-
- <script type="text/javascript" src="js/jquery-3.4.1.js">script>
- <script type="text/javascript">
- $(function (){
- $("button").click(function (){
- //alert("button click");
- $.ajax({
- url:"returnVoid-ajax.do", //处理器返回void,响应Ajax请求
- data:{
- name:"zhangsan",
- age:18
- },
- type:"post",
- dataType:"json",
- success:function (resp){
- //resp从服务器端返回的是json的字符串 {"name":"zhangsan","age":18}
- //jQuery会将字符串转为json对象,赋值给resp形参
- alert(resp.name + " "+resp.age);
- }
- })
- })
- })
- script>
- head>
-
- <body>
- <p>SpringMVC项目p>
-
- <button id="btn"> 发起Ajax请求 button>
-
- body>
- html>
(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
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-coreartifactId>
- <version>2.9.0version>
- dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-databindartifactId>
- <version>2.9.0version>
- dependency>
(2)声明注解驱动
springmvc.xml
- <mvc:annotation-driven />
将 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" %>
- <html>
-
- <head>
- <title>Titletitle>
-
- <script type="text/javascript" src="js/jquery-3.4.1.js">script>
- <script type="text/javascript">
- $(function (){
- $("button").click(function (){
- //alert("button click");
- $.ajax({
- //url:"returnVoid-ajax.do", //处理器返回void,响应Ajax请求
- //url:"returnStudentJson.do", //处理器方法返回Java对象Student
- //url:"returnStudentListJson.do", //处理器方法返回集合List
- url:"returnStringData.do", //有@ResponseBody注解,处理器方法返回的是String,String表示数据
- data:{
- name:"zhangsan",
- age:18
- },
- type:"post",
- //dataType:"json",
- dataType:"text",
- success:function (resp){
- //resp从服务器端返回的是json的字符串 {"name":"zhangsan","age":18}
- //jQuery会将字符串转为json对象,赋值给resp形参
- //alert(resp.name + " "+resp.age);
-
- //处理器方法返回集合List
- /*$.each(resp,function (i,n){
- alert(n.name+" "+n.age)
- })*/
-
- alert("返回的是文本数据:"+resp);
- }
- })
- })
- })
- script>
- head>
-
- <body>
- <p>SpringMVC项目p>
-
- <button id="btn"> 发起Ajax请求 button>
-
- body>
- html>
(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}
