• Java--SpringMVC之处理器方法返回值


    一、处理器方法返回值

    使用@Controller注解的处理器方法,返回值会有四种类型:ModelAndView、String、Void、自定义Java对象

    1、ModelAndView

    ModelAndView:有数据和视图

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

    若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的 Ajax 异步响应),此时返回 ModelAndView 将不适合

    1. @RequestMapping(value = "/receiveproperty.do")
    2. public ModelAndView doSome(String name,Integer age){
    3. System.out.println("doSome, name="+name+" age="+age);
    4. //处理 some.do请求,相当于service调用处理完成
    5. ModelAndView mdv = new ModelAndView();
    6. mdv.addObject("myname",name);
    7. mdv.addObject("myage",Integer.valueOf(age));
    8. mdv.setViewName("show");
    9. return mdv;
    10. }

    2、String

    String:表示视图,可以是逻辑名称,也可以是完整视图路径

    (1)逻辑视图路径

    此时在 springmvc.xml 中需要配置视图解析器

    1. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    2. <property name="prefix" value="/WEB-INF/view/" />
    3. <property name="suffix" value=".jsp" />
    4. bean>

    @Controller注解处理器 

    1. /**
    2. * 1、处理器方法返回String
    3. * (1)表示逻辑视图名称,需要配置视图解析器
    4. * (2)表示完整视图路径,不能配置视图解析器
    5. */
    6. @RequestMapping(value = "/returnString-view.do")
    7. public String doReturnStringView(HttpServletRequest request,String name,Integer age){
    8. System.out.println("doReturnStringView, name="+name+" age="+age);
    9. request.setAttribute("myname",name);
    10. request.setAttribute("myage",age);
    11. // show : 逻辑视图名称,项目中配置了视图解析器
    12. // 框架对视图执行forward转发操作
    13. return "show";
    14. }

    (2)完整视图路径

    返回完整视图路径时,不需要设置视图解析器,不然会报错

    1. HTTP状态 404 - 未找到
    2. 文件 [/WEB-INF/view/WEB-INF/view/show.jsp.jsp] 未找到

    1. //处理器方法返回String,表示完整视图路径,此时不能配置视图解析器
    2. @RequestMapping(value = "/returnString-view1.do")
    3. public String doReturnStringView1(HttpServletRequest request,String name,Integer age){
    4. System.out.println("doReturnStringView1, name="+name+" age="+age);
    5. request.setAttribute("myname",name);
    6. request.setAttribute("myage",age);
    7. // 完整视图路径,项目中不能配置视图解析器
    8. // 框架对视图执行forward转发操作,如果配置了视图解析器会出现如下结果
    9. // HTTP状态 404 - 未找到 文件 [/WEB-INF/view/WEB-INF/view/show.jsp.jsp] 未找到
    10. return "/WEB-INF/view/show.jsp";
    11. }

    3、void

    处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void

    处理器方法返回 void 的应用场景,AJAX 响应

    由于服务端向浏览器传回的是 JSON 数据,需要使用一个工具类将字符串包装为 JSON 格式,所以需要导入 JSON 的依赖

    (1)在 pom.xml 文件中加入处理json工具库的依赖,SpringMVC默认使用jackson

    1. <dependency>
    2. <groupId>com.fasterxml.jackson.coregroupId>
    3. <artifactId>jackson-coreartifactId>
    4. <version>2.9.0version>
    5. dependency>
    6. <dependency>
    7. <groupId>com.fasterxml.jackson.coregroupId>
    8. <artifactId>jackson-databindartifactId>
    9. <version>2.9.0version>
    10. dependency>

    (2)引入jQuery库 

    由于要使用 jQuery 的 ajax()方法提交 AJAX 请求,所以项目中需要引入 jQuery 的库

    (3)index.jsp视图

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>Titletitle>
    5. <script type="text/javascript" src="js/jquery-3.4.1.js">script>
    6. <script type="text/javascript">
    7. $(function (){
    8. $("button").click(function (){
    9. //alert("button click");
    10. $.ajax({
    11. url:"returnVoid-ajax.do", //处理器返回void,响应Ajax请求
    12. data:{
    13. name:"zhangsan",
    14. age:18
    15. },
    16. type:"post",
    17. dataType:"json",
    18. success:function (resp){
    19. //resp从服务器端返回的是json的字符串 {"name":"zhangsan","age":18}
    20. //jQuery会将字符串转为json对象,赋值给resp形参
    21. alert(resp.name + " "+resp.age);
    22. }
    23. })
    24. })
    25. })
    26. script>
    27. head>
    28. <body>
    29. <p>SpringMVC项目p>
    30. <button id="btn"> 发起Ajax请求 button>
    31. body>
    32. html>

    (4)创建Java对象Student类

    1. package com.mycompany.domain;
    2. public class Student {
    3. // 属性名和请求中参数名一样
    4. private String name;
    5. private Integer age;
    6. public Student() {
    7. System.out.println("===Student的无参数构造方法===");
    8. }
    9. public String getName() {
    10. return name;
    11. }
    12. public void setName(String name) {
    13. System.out.println("setName"+name);
    14. this.name = name;
    15. }
    16. public Integer getAge() {
    17. return age;
    18. }
    19. public void setAge(Integer age) {
    20. System.out.println("setAge"+age);
    21. this.age = age;
    22. }
    23. @Override
    24. public String toString() {
    25. return "Student{" +
    26. "name='" + name + '\'' +
    27. ", age=" + age +
    28. '}';
    29. }
    30. }

    (5) 处理器类MyController

    1. /**
    2. * 处理器返回void,响应Ajax请求
    3. * 实现Ajax,json数据:代码重复:1、Java对象转为json;2、通过HttpServletResponse输出json数据
    4. */
    5. @RequestMapping(value = "/returnVoid-ajax.do")
    6. public void doReturnVoidAjax(HttpServletResponse response,String name,Integer age) throws IOException {
    7. System.out.println("===doReturnVoidAjax====, name="+name+" age="+age);
    8. //处理Ajax,使用json做数据格式
    9. Student student = new Student();
    10. student.setName("张三");
    11. student.setAge(18);
    12. String json = "";
    13. //将结果对象转为json格式数据
    14. if (student != null){
    15. ObjectMapper objectMapper = new ObjectMapper();
    16. json = objectMapper.writeValueAsString(student);
    17. System.out.println("student转换的json===="+json);
    18. }
    19. //输出数据,响应Ajax请求
    20. response.setContentType("application/json;charset=utf-8");
    21. PrintWriter pw = response.getWriter();
    22. pw.println(json);
    23. pw.flush();
    24. pw.close();
    25. }

    点击按钮,发起请求,可以看到web端页面输出,右键点击【检查】,可以看到请求头以及响应头内容

     后台控制台输出如下

    4、自定义Java对象

    处理器方法也可以返回 Object 对象,这个 Object 可以是 Integer,String,自定义Java对象,Map,List 等。返回的对象不是逻辑视图,而是直接在页面显示的数据

    返回对象,需要使用 @ResponseBody 注解,将转换后的 JSON 数据放入到响应体中

    (1)在 pom.xml 文件中加入处理json工具库的依赖,SpringMVC默认使用jackson

    1. <dependency>
    2. <groupId>com.fasterxml.jackson.coregroupId>
    3. <artifactId>jackson-coreartifactId>
    4. <version>2.9.0version>
    5. dependency>
    6. <dependency>
    7. <groupId>com.fasterxml.jackson.coregroupId>
    8. <artifactId>jackson-databindartifactId>
    9. <version>2.9.0version>
    10. dependency>

    (2)声明注解驱动 

    springmvc.xml

    1. <mvc:annotation-driven />

     将 Object 数据转化为 JSON 数据,需要由消息转换器 HttpMessageConverter 完成。而消息转换器的开启,需要由 来完成

    SpringMVC 使用消息转换器实现请求数据和对象,处理器方法返回对象和响应输出之间的自动转换

    当 Spring 容器进行初始化过程中,在处创建注解驱动时,默认创建了八个 HttpMessageConverter 对象

    HttpMessageConverter 接口 : HttpMessageConverter是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息

    HttpMessageConverter接口定义的方法:

    1. public interface HttpMessageConverter {
    2. /**
    3. * 指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为clazz 类型的对
    4. 象,同时指定支持MIME类型(text/html,applaiction/json 等)
    5. */
    6. boolean canRead(Class var1, @Nullable MediaType var2);
    7. /**
    8. * 指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在 MediaType 中定义
    9. */
    10. boolean canWrite(Class var1, @Nullable MediaType var2);
    11. //该转换器支持的媒体类型
    12. List getSupportedMediaTypes();
    13. //将请求信息流转换为 T 类型的对象
    14. T read(Class var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;
    15. //将 T 类型的对象写到响应流中,同时指定相应的媒体类型为 contentType
    16. void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
    17. }

    (3)在处理器方法上加入@ResponseBody注解

    index.jsp视图

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>Titletitle>
    5. <script type="text/javascript" src="js/jquery-3.4.1.js">script>
    6. <script type="text/javascript">
    7. $(function (){
    8. $("button").click(function (){
    9. //alert("button click");
    10. $.ajax({
    11. //url:"returnVoid-ajax.do", //处理器返回void,响应Ajax请求
    12. //url:"returnStudentJson.do", //处理器方法返回Java对象Student
    13. //url:"returnStudentListJson.do", //处理器方法返回集合List
    14. url:"returnStringData.do", //有@ResponseBody注解,处理器方法返回的是String,String表示数据
    15. data:{
    16. name:"zhangsan",
    17. age:18
    18. },
    19. type:"post",
    20. //dataType:"json",
    21. dataType:"text",
    22. success:function (resp){
    23. //resp从服务器端返回的是json的字符串 {"name":"zhangsan","age":18}
    24. //jQuery会将字符串转为json对象,赋值给resp形参
    25. //alert(resp.name + " "+resp.age);
    26. //处理器方法返回集合List
    27. /*$.each(resp,function (i,n){
    28. alert(n.name+" "+n.age)
    29. })*/
    30. alert("返回的是文本数据:"+resp);
    31. }
    32. })
    33. })
    34. })
    35. script>
    36. head>
    37. <body>
    38. <p>SpringMVC项目p>
    39. <button id="btn"> 发起Ajax请求 button>
    40. body>
    41. html>

    (1)Java对象

    1. /**
    2. * 处理器方法返回Java对象Student,通过SpringMVC框架转为json,响应Ajax请求
    3. * @ResponseBody
    4. * 作用:将处理器方法返回对象转为json后,通过HttpServletResponse输出给浏览器
    5. * 位置:方法定义上面,和其他注解没有上下顺序关系
    6. *
    7. * SpringMVC返回Java对象处理流程:
    8. * 1、SpringMVC框架返回Java对象Student类型,是调用框架ArrayList中每个类的canWrite()方法
    9. * 检查哪个HttpMessageConverter接口的实现类能处理Student类型的数据--MappingJackson2HttpMessageConverter
    10. *
    11. * 2、SpringMVC框架会调用实现类的write()方法,MappingJackson2HttpMessageConverter的write()方法
    12. * 将student对象转为json,调用Jackson的ObjectMapper实现转为json
    13. * contentType:application/json;charset=utf-8
    14. *
    15. * 3、SpringMVC框架会调用@ResponseBody注解将结果数据输出到浏览器,Ajax请求处理完成
    16. */
    17. @RequestMapping(value = "returnStudentJson.do")
    18. @ResponseBody
    19. public Student doStudentJsonObject(String name,Integer age){
    20. Student student = new Student();
    21. student.setName("李四");
    22. student.setAge(18);
    23. return student; // 会被框架转为json
    24. }

    (2)List集合

    1. /**
    2. * 处理器方法返回集合List
    3. * 处理流程如上
    4. */
    5. @RequestMapping(value = "/returnStudentListJson.do")
    6. @ResponseBody
    7. public List doStudentListJsonObject(String name, Integer age){
    8. List list = new ArrayList<>();
    9. //调用service,获取请求结果数据 , Student对象表示结果数据
    10. Student student = new Student();
    11. student.setName("李四");
    12. student.setAge(20);
    13. list.add(student);
    14. student = new Student();
    15. student.setName("张三");
    16. student.setAge(18);
    17. list.add(student);
    18. return list;
    19. }

    (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")

     

    1. /**
    2. * 处理器方法返回String(此处String表示数据,不是视图路径)
    3. * 区分String是视图路径还是数据,关键就看是否有@ResponseBody注解;有@ResponseBody注解,返回String就是数据,反之就是视图路径
    4. *
    5. * 默认响应头Response Headers中Content-Type: text/plain;charset=ISO-8859-1,导致中文有乱码
    6. * 解决方案
    7. * 给@RequestMapping增加一个属性 produces,使用此属性指定Content-Type
    8. *
    9. * 处理器方法返回String数据处理流程
    10. * 1、SpringMVC框架调用框架中中ArrayList中每个类的canWrite()方法
    11. * 检查哪个HttpMessageConverter接口的实现类能处理String类型的数据--StringHttpMessageConverter
    12. * 2、SpringMVC框架会调用实现类的write()方法,StringHttpMessageConverter的write()方法
    13. * 将字符按照指定的编码处理 ,如:text/plain;charset=ISO-8859-1
    14. * 3、SpringMVC框架会调用@ResponseBody注解将结果数据输出到浏览器,Ajax请求处理完成
    15. */
    16. @RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")
    17. @ResponseBody
    18. public String doStringData(String name,Integer age){
    19. return "Hello SpringMVC 返回对象,表示数据";
    20. }

    总结:

    1、Ajax使用,主要使用json的数据,实现步骤如下:

    (1)加入处理json工具库的依赖,SpringMVC默认使用jackson

    (2)在SpringMVC配置文件中加入 注解驱动

    json = ObjectMapper.writeValueAsString(student);

    (3)在处理器方法上加入@ResponseBody注解 

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

    2、SpringMVC处理器方法返回object,可以转为json输出到浏览器,响应Ajax内部原理

    (1) 注解驱动

    【1】 注解驱动实现的功能:

    完成Java对象到json,xml,text,二进制等数据格式的转换 加入到SpringMVC配置文件后,会自动创建HttpMessageConverter接口的8个实现类对象,

    包括 MappingJackson2HttpMessageConverter (使用jackson工具库中的ObjectMapper实现java对象转为json字符串)

    【2】HttpMessageConverter接口:消息转换器

    功能:定义了Java转json,xml等数据格式的方法,这个接口有很多实现类 这些实现类完成 java对象到json, java对象到xml,java对象到二进制数据的转换 两个方法是控制器类把结果输出给浏览器时使用:

    1. boolean canWrite(Class var1, @Nullable MediaType var2)
    2. void write(T va1, @Nullable MediaType va2, HttpOutputMessage var3)

    如处理器方法

    1. @RequestMapping(value = "/returnString.do")
    2. public Student doReturnView2(HttpServletRequest request,String name, Integer age){
    3. Student student = new Student();
    4. student.setName("lisi");
    5. student.setAge(20);
    6. return student;
    7. }

    【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请求

    1. PrintWriter pw = response.getWriter();
    2. pw.println(json);
    3. pw.flush();
    4. pw.close();

    DispatcherServlet 类中此处加入断点

    1. public class DispatcherServlet extends FrameworkServlet {
    2. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    3. ......
    4. HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
    5. ......
    6. }
    7. }

    没有加入注解驱动标签 时的状态

    1. 0 = {ByteArrayHttpMessageConverter@5029}
    2. 1 = {StringHttpMessageConverter@5030}
    3. 2 = {SourceHttpMessageConverter@5031}
    4. 3 = {AllEncompassingFormHttpMessageConverter@5032}

    加入注解驱动标签时的状态

    1. //负责读取二进制格式的数据和写出二进制格式的数据
    2. 0 = {ByteArrayHttpMessageConverter
    3. //负责读取字符串格式的数据和写出字符串格式的数据
    4. 1 = {StringHttpMessageConverter@5161}
    5. //负责读取资源文件和写出资源文件数据
    6. 2 = {ResourceHttpMessageConverter@5162}
    7. //
    8. 3 = {ResourceRegionHttpMessageConverter@5163}
    9. //能够读 / 写 来 自 HTTP 的 请 求 与 响 应 的
    10. javax.xml.transform.Source ,支持 DOMSource,
    11. SAXSource, 和 StreamSource 的 XML 格式
    12. 4 = {SourceHttpMessageConverter@5164}
    13. //负责处理表单(form)数据
    14. 5 = {AllEncompassingFormHttpMessageConverter@5165}
    15. //使用 JAXB 负责读取和写入 xml 标签格式的数据
    16. 6 = {Jaxb2RootElementHttpMessageConverter@5166}
    17. //负责读取和写入 json 格式的数据。利用Jackson 的 ObjectMapper 读写 json 数据,操作Object 类型据,可读取 application/json,响应媒体类型为 application/json
    18. 7 = {MappingJackson2HttpMessageConverter@5167}

  • 相关阅读:
    可堆叠的残差注意力模块用于图像分类(Residual Attention Network for Image Classification——代码复现与解读)
    java计算机毕业设计基于安卓Android/微信小程序的校园报修管理APP
    Linux:基础IO(二.缓冲区、模拟一下缓冲区、详细讲解文件系统)
    Mybatis 中 ResultHandler 的用法(获取大结果集,实现结果流式输出)
    希尔排序算法(思路分析) [数据结构][Java]
    用 Java 实现阻塞队列
    【AN基础工具—动画人物绘制】
    文件管理工具“三剑客” #Everything #SpaceSniffer #Clover
    10.3使用Servlet写一个表白墙网站
    各种手型都合适,功能高度可定制,雷柏VT9PRO mini和VT9PRO游戏鼠标上手
  • 原文地址:https://blog.csdn.net/MinggeQingchun/article/details/123679135