1 Controller 类的方法返回值

使用 @Controller 注解的处理器的处理器方法,其返回值常用的有四种类型:
➢ 第一种: ModelAndView
➢ 第二种: String
➢ 第三种:无返回值 void
➢ 第四种:返回自定义类型对象

1.1 返回 ModelAndView

若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好。

mv.setViewName 设置跳转的页面。
mv.addObject map 的形式,传入 key-value。之后在生成页面内容时,根据 key 对应的 value 值填充页面数据。

处理器方法

@RequestMapping(value = "/receiveobject.do")
public ModelAndView receiveParam(Student myStudent){
	System.out.println("receiveParam, name="+myStudent.getName()+"   age="+myStudent.getAge());
	ModelAndView mv  = new ModelAndView();
	mv.addObject("myname",myStudent.getName());
	mv.addObject("myage",myStudent.getAge());
	mv.addObject("mystudent",myStudent);
	mv.setViewName("show");
	return mv;
}

前端页面

<h3>/WEB-INF/view/show.jsp从request作用域获取数据</h3>
<br />
<h3>myname数据:${myname}</h3>
<br />
<h3>myage数据:${myage}</h3>
<h3>student数据:${mystudent}</h3>

1.2 返回 String

处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析。前面很多例子都是返回 String。
注:使用逻辑视图,记得在 Spring MVC 配置文件中配置前后缀。

1.3 返回 Map

Map 作为返回值是数据,能够自动转为 json。

@GetMapping("/map/json")
@ResponseBody public Map getMap(){
  Map<String,Object> map = new HashMap<>();
  map.put("id",1001);
  map.put("address","大兴区");
  map.put("city","北京");
  return map;
}

1.4 void

对于处理器方法返回 void 的应用场景, AJAX 响应。
若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void 。通过 HttpServletResponse 输出数据,响应 AJAX 请求。
使用 JackSon 将对象转换为 Json 格式。

@RequestMapping(value = "/returnVoid-ajax.do")
public void doReturnVoidAjax(HttpServletResponse response, String name, Integer age) throws IOException {
	Student student  = new Student();
	String json = "";
	if(student != null){
		ObjectMapper om  = new ObjectMapper();
		json  = om.writeValueAsString(student);
	}
	response.setContentType("application/json;charset=utf-8");
	PrintWriter pw  = response.getWriter();
	pw.println(json);
	pw.flush();
	pw.close();
}
<head>
  <title>Title</title>
  <script type="text/javascript" src="js/jquery-3.4.1.js"></script>
  <script type="text/javascript">
    $(function () {
      $("button").click(function () {
        $.ajax({
          url: "returnStringData.do",
          data: {
            name: "zhangsan",
            age: 20,
          },
          type: "post",
          dataType: "text", // 收到的数据类型是什么样的
          //dataType:"json",
          success: function (resp) {
            //resp从服务器端返回的是json格式的字符串 {"name":"zhangsan","age":20}
            //jquery会把字符串转为json对象, 赋值给resp形参。
            // [{"name":"李四同学","age":20},{"name":"张三","age":28}]
            /*$.each(resp,function(i,n){
                             alert(n.name+"   "+n.age)
                         })*/
          },
        });
      });
    });
  </script>
</head>
<body>
  <p>处理器方法返回String表示视图完整路径</p>
  <form action="returnString-view2.do" method="post">
    姓名:<input type="text" name="name" /> <br />
    年龄:<input type="text" name="age" /> <br />
    <input type="submit" value="提交参数" />
  </form>
  <button id="btn">发起ajax请求</button>
</body>

1.5 返回自定义类型对象

SpringMVC-3 HttpMessageConverter

处理器方法也可以返回 Object 对象。这个 Object 可以是 Integer,String,自定义对象,Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。返回对象,需要使用 @ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。

具体步骤:

  1. 加入处理 json 的工具库的依赖, springmvc 默认使用的 jackson。

  2. 在 sprigmvc 配置文件之间加入 <mvc: annotation-driven/> 注解驱动。
    相当于

    json = om.writeValueAsString(student);
  3. 在处理器方法的上面加入@ResponseBody 注解
    相当于

    response.setContentType("application/json; charset=utf-8");
    PrintWriter pw  = response.getWriter();
    Pw.println(json);

实现原理:

  1. <mvc:annotation-driven>
    注解驱动实现的功能是完成 java 对象到 json,xml, text,二进制等数据格式的转换。
    <mvc: annotation-driven>在加入到 springmvc 配置文件后,会自动创建 HttpMessageConverter 接口的 7 个实现类对象。

  2. HttpMessageConverter 接口:消息转换器。功能:定义了 java 转为 json,xml 等数据格式的方法。

    boolean canWrite(Class<?> var1, @Nullable MediaType var2);
    void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3)
    1. canWrite() 作用检查处理器方法的返回值,能不能转为 var2 表示的数据格式。例如检查能转为 json,canWrite 返回 true。MediaType:表示数格式的,例如 json, xml 等等。
    2. write() 把处理器方法的返回值对象,调用 jackson 中的 ObjectMapper 转为 json 字符串。相当于 json = om.writeValueAsString(student);
  3. @ResponseBody
    作用:把处理器方法返回对象转为 json 后,通过 HttpServletResponse 输出给浏览器。
    位置:方法的定义上面。和其它注解没有顺序的关系。

1.5.1 返回 POLO 对象

返回对象框架的处理流程:

  1. 框架会把返回 Student 类型,调用框架的中 ArrayList<HttpMessageConverter>中每个类的 canWrite () 方法。检查那个 HttpMessageConverter 接口的实现类能处理 Student 类型的数据—MappingJackson2HttpMessageConverter
  2. 框架会调用实现类的 write(), MappingJackson2HttpMessageConverter 的 write () 方法把李四同学的 student 对象转为 json,调用 Jackson 的 ObjectMapper 实现转为 json / json array /
  3. ContentType: application/json; charset=utf-8
  4. 框架会调用@ResponseBody 把 2 的结果数据输出到浏览器, ajax 请求处理完成
// 返回 Json
@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
}

1.5.2 返回 List 对象

// 返回 Json Array
@RequestMapping(value = "/returnStudentJsonArray.do")
@ResponseBody
public List<Student> doStudentJsonObjectArray(String name, Integer age) {
	List<Student> list = new ArrayList<>();
	Student student = new Student();
	list.add(student);
	list.add(student);
	return list;
}

1.5.3 返回 String 对象

处理器方法返回的是 String , String 表示数据的,不是视图。
默认使用“text/plain; charset=ISO-8859-1”作为 contentType, 导致中文有乱码,
解决方案:给 RequestMapping 增加一个属性 produces, 使用这个属性指定新的 contentType.
返回对象框架的处理流程:

  1. 框架会把返回 String 类型,调用框架的中 ArrayList<HttpMessageConverter>中每个类的 canWrite () 方法. 检查那个 HttpMessageConverter 接口的实现类能处理 String 类型的数据—StringHttpMessageConverter
  2. 框架会调用实现类的 write(), StringHttpMessageConverter 的 write () 方法。把字符按照指定的编码处理 text/plain; charset=ISO-8859-1
  3. 框架会调用@ResponseBody 把 2 的结果数据输出到浏览器, ajax 请求处理完成
@RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
@ResponseBody
public String doStringData(String name,Integer age){
	return "Hello SpringMVC 返回对象,表示数据";
}

1.6 返回 ResponseEntity 对象

ResponseEntity 包含 HttpStatus Code 和应答数据的结合体。因为有 Http Code 能表达标准的语义,200 成功, 404 没有发现等。

@GetMapping("/show/json3")
ResponseEntity<User> getUserInfo(){
  User user = new User();
  user.setName("李四");
  user.setAge(20);
 
  Role role = new Role();
  role.setId(5892);
  role.setRoleName("操作员");
  role.setMemo("基本操作,读取数据,不能修改");
  user.setRole(role);
 
  ResponseEntity<User> response = new ResponseEntity<>(user, HttpStatus.OK);
  return response;
 
}

其他创建 ResponseEntity 的方式

// 200 状态码
ResponseEntity<User> response =  ResponseEntity.ok(user);
 
//HTTP 204 No Content 成功状态响应码,表示该请求已经成功了
ResponseEntity<User> response = ResponseEntity.noContent().build();

ResponseEntity 还用于文件的上传与下载,参考 SpringMVC 文件上传与下载