Java--SpringMVC之处理器方法返回值
Posted MinggeQingchun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java--SpringMVC之处理器方法返回值相关的知识,希望对你有一定的参考价值。
一、处理器方法返回值
使用@Controller注解的处理器方法,返回值会有四种类型:ModelAndView、String、Void、自定义Java对象
1、ModelAndView
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;
2、String
String:表示视图,可以是逻辑名称,也可以是完整视图路径
(1)逻辑视图路径
此时在 springmvc.xml 中需要配置视图解析器
<!-- 声明SpringMVC框架中的视图解析器,设置视图文件的路径:InternalResourceViewResolver
注:处理器方法返回String,表示完整视图路径,此时不能配置视图解析器
-->
<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";
3、void
处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void
处理器方法返回 void 的应用场景,AJAX 响应
由于服务端向浏览器传回的是 JSON 数据,需要使用一个工具类将字符串包装为 JSON 格式,所以需要导入 JSON 的依赖
(1)在 pom.xml 文件中加入处理json工具库的依赖,SpringMVC默认使用jackson
<!--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>
(2)引入jQuery库
由于要使用 jQuery 的 ajax()方法提交 AJAX 请求,所以项目中需要引入 jQuery 的库
(3)index.jsp视图
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<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端页面输出,右键点击【检查】,可以看到请求头以及响应头内容
后台控制台输出如下
4、自定义Java对象
处理器方法也可以返回 Object 对象,这个 Object 可以是 Integer,String,自定义Java对象,Map,List 等。返回的对象不是逻辑视图,而是直接在页面显示的数据
返回对象,需要使用 @ResponseBody 注解,将转换后的 JSON 数据放入到响应体中
(1)在 pom.xml 文件中加入处理json工具库的依赖,SpringMVC默认使用jackson
<!--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>
(2)声明注解驱动
springmvc.xml
<!-- 注解驱动
http://www.springframework.org/schema/mvc
<mvc:annotation-driven> 注解驱动实现的功能:完成Java对象到json,xml,text,二进制等数据格式的转换
-->
<mvc:annotation-driven />
将 Object 数据转化为 JSON 数据,需要由消息转换器 HttpMessageConverter 完成。而消息转换器的开启,需要由 <mvc:annotation-driven/> 来完成
SpringMVC 使用消息转换器实现请求数据和对象,处理器方法返回对象和响应输出之间的自动转换
当 Spring 容器进行初始化过程中,在<mvc:annotation-driven/>处创建注解驱动时,默认创建了八个 HttpMessageConverter 对象
HttpMessageConverter 接口 : HttpMessageConverter<T>是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息
HttpMessageConverter<T>接口定义的方法:
public interface HttpMessageConverter<T>
/**
* 指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为clazz 类型的对
象,同时指定支持MIME类型(text/html,applaiction/json 等)
*/
boolean canRead(Class<?> var1, @Nullable MediaType var2);
/**
* 指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在 MediaType 中定义
*/
boolean canWrite(Class<?> var1, @Nullable MediaType var2);
//该转换器支持的媒体类型
List<MediaType> 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>Title</title>
<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<Student>
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<Student>
/*$.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<HttpMessageConverter>中每个类的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<Student>
* 处理流程如上
*/
@RequestMapping(value = "/returnStudentListJson.do")
@ResponseBody
public List<Student> doStudentListJsonObject(String name, Integer age)
List<Student> 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<HttpMessageConverter>中每个类的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配置文件中加入 <mvc:annotation-driven> 注解驱动
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)<mvc:annotation-driven> 注解驱动
【1】<mvc:annotation-driven> 注解驱动实现的功能:
完成Java对象到json,xml,text,二进制等数据格式的转换 <mvc:annotation-driven>加入到SpringMVC配置文件后,会自动创建HttpMessageConverter接口的8个实现类对象,
包括 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());
......
没有加入注解驱动标签<mvc:annotation-driven /> 时的状态
0 = ByteArrayHttpMessageConverter@5029
1 = StringHttpMessageConverter@5030
2 = SourceHttpMessageConverter@5031
3 = AllEncompassingFormHttpMessageConverter@5032
加入注解驱动标签时<mvc:annotation-driven />的状态
//负责读取二进制格式的数据和写出二进制格式的数据
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
以上是关于Java--SpringMVC之处理器方法返回值的主要内容,如果未能解决你的问题,请参考以下文章
java springMVC之@RequestMapping注解
python lambda 返回值放多个条件的扩展思考(面试题)
linq排序之 根据文本 A-001-002-003 这种类型进行分割排序 空值放于最后