SSM之SpringMVC系列(三)---- 响应数据和结果视图

上篇文章我们讲了SpringMVC 的请求参数的绑定和常用的注解,现在来讲SpringMVC中响应数据和结果视图

响应数据和结果视图

对于控制器(Controller)中方法的返回值,可以为以下其中一种:

  • String 字符串类型
  • void 无返回值
  • ModelAndView SpringMVC 为我们提供的一种可以包含数据和视图的对象
  • JavaBean 对象 (通过json数据响应)

返回值为 String

  • 当控制器返回值为String类型的时候,默认情况是返回逻辑视图名,然后被视图解析器解析为物理视图地址,最终底层通过请求转发将请求转发到对应页面。

  • 前面的环境搭建大家可以去看看我之前的这篇文章 传送门

  • response.jsp代码:

<a href="user/testString">testString</a>
  • 控制器代码
@Controller
@RequestMapping("/user")
public class UserController {
    
    

    /**
     * 返回值为 String ,结合 model 对象保存数据
     * @param model
     * @return
     */
    @RequestMapping("/testString")
    public String testString(Model model){
    
    
        System.out.println("testString执行了。。。");
        // 模拟从数据库中查询出User对象
        User user = new User();
        user.setUsername("老王");
        user.setPassword("123");
        user.setAge(30);
        // model对象
        model.addAttribute("user",user);
        return "success";
    }
}

返回值为 void

  • 当使用void作为控制器方法的返回值时,方法执行结束后默认转发的路径为当前方法绑定的路径,也就是@RequestMapping 中的值。但是实际上这个返回值也会被视图解析器解析,所以一般都会报 404 错误。譬如,此时有一个控制器方法为:
@RequestMapping("/testVoid")
    public void testVoid(Model model){
    
    
        System.out.println("testString执行了。。。");
    }

在这里插入图片描述

  • 如果既想使用 void返回值,同时又想对请求做出响应,譬如请求转发或者重定向,那么我们就可以利用Servlet提供的原生 API 作为控制器方法的参数
  • 请求转发
@RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response)throws Exception{
    
    
        System.out.println("testString执行了。。。");
        // 转发是一次请求,无需加项目虚拟目录,但是因为直接通过原生api进行转发,不会经过视图解析器,所以应该写具体路径
        request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
        // 转发或重定向后,如果还有代码,会继续执行,此时可以使用 return; 结束
        return;
    }
  • 重定向
 @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response)throws Exception{
    
    
        System.out.println("testString执行了。。。");
        // 重定向,需要项目虚拟目录
        response.sendRedirect(request.getContextPath()+"/index.jsp");
        return;
    }
  • 直接像客户端生成响应,譬如响应 json 数据
@RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response)throws Exception{
    
    
        System.out.println("testString执行了。。。");
        // 解决中文乱码
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        // 直接会进行响应
        response.getWriter().print("你好");
        return;
    }

当方法的参数中含有 HttpServletResponse时,即使方法体中不做任何处理,方法结束后也不会跳转到别的页面。关于这点,查阅官方文档,是因为此时 SpringMVC 会认为对请求已经作出了响应,所以不会再帮我们跳转到别的页面。

返回值为 ModelAndView

  • 当控制器方法返回值为 ModelAndView 的时候,其实就相当于第一种方式的返回值为 String 加上参数为 Model,因为 ModelAndView 也可以传入数据(在页面上直接使用 EL 表达式获取:${attributeName}),同时还可以设置将要跳转的逻辑视图名称。

  • success.jsp代码:

<body>
    <h3>执行成功</h3>
    ${requestScope.user}
</body>
  • 控制器方法
    /**
     * 返回ModelAndView
     * @return
     */
    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView(){
    
    
        // 创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        System.out.println("testModelAndView方法执行了...");
        // 模拟从数据库中查询出User对象
        User user = new User();
        user.setUsername("小王");
        user.setPassword("456");
        user.setAge(20);
        // 把user对象存储到mv对象中,也会把user对象存入到request对象
        mv.addObject("user",user);

        // 跳转到哪个页面
        mv.setViewName("success");
        return mv;
    }

请求转发和重定向

  • 当控制器方法的返回值为 String的时候,默认就是请求转发,我们也可以像上面的例子一样,使用 Servlet 原生的 API 来完成请求转发或者重定向。不过,SpringMVC 还为我们提供了另一种方式,那就是使用forward:redirect:关键字。
    /**
     * 使用关键字的方式进行转发或者重定向
     * @return
     */
    @RequestMapping("/testForwardOrRedirect")
    public String testForwardOrRedirect(){
    
    
        System.out.println("testForwardOrRedirect方法执行了...");

        // 请求的转发 forward: 关键字转发,不会使用视图解析器
        // return "forward:/WEB-INF/pages/success.jsp";

        // redirect: 关键字重定向,不用加项目路径
        return "redirect:/index.jsp";
    }
  • 对于forward: 关键字,根据官方文档,底层也是使用 Servlet 原生 API 进行转发,也就是RequestDispatcher.forward(),所以不会经过视图解析器,因此转发路径需要具体路径。

在这里插入图片描述
需要注意的是,如果用了formward:则路径必须写成实际视图url,不能写逻辑视图。
它相当于“request.getRequestDispatcher("url").forward(request,response)”。使用请求转发,既可以转发到 jsp,也可以转发到其他的控制器方法。

  • 对于response:关键字,根据官方文档,SpringMVC 会根据当前 Servlet 的上下文进行重定向,因此不需要写项目路径。
    在这里插入图片描述
    它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 页面,则 jsp 页面不能写在WEB-INF目录中,否则无法找到

使用 @RequestBody 和 @ResponseBody 进行 json 交互

  • 在开发中,很多时候都是客户端提交 json数据,服务器接收 json 数据并解析,然后生成json 响应给客户端。这个时候我们就可以使用 @RequestBody@ResponseBody 来完成json数据的交互。
  • response.jsp代码:
<%--
  Created by IntelliJ IDEA.
  User: 15728
  Date: 2021/2/19
  Time: 20:49
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="js/jquery.min.js"></script>
    <script>
        // 页面加载,绑定单击事件
        $(function(){
    
    
           $("#btn").click(function () {
    
    
              //alert("你好");
               // 发送ajax请求
               $.ajax({
    
    
                   //编写json格式,设置属性和值
                   url:"user/testAjax",
                   contentType:"application/json;charset=UTF-8",
                   data:'{"username":"一个Java小白","password":"123","age":18}',
                   dataType:"json",
                   type:"post",
                   success:function (data) {
    
    
                       // data服务器端响应的json的数据,进行解析
                       alert(data);
                       alert(data.username);
                       alert(data.password);
                       alert(data.age);
                   }
               });
           });
        });

    </script>
</head>
<body>
    <button id="btn">发送ajax的请求</button>
</body>
</html>

因为我们配置了前端控制器 DispatcherServlet,因此对于所有的请求都会进行拦截,包括静态资源。为了使引入的jquery.js不被拦截,我们需要在配置文件springmvc.xml 中配置不拦截静态资源

  <!--前端控制器,哪些静态资源不拦截-->
  <mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 -->
  <mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 -->
  <mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript --> 
  • location属性 : 指定webapp目录下的包
  • mapping属性 : 表示以 /static 开头的所有请求路径
  • 控制器代码
 /**
     * 模拟异步请求响应
     */
    @RequestMapping("/testAjax")
    public @ResponseBody User testAjax(@RequestBody User user){
    
    
        System.out.println("testAjax方法执行了...");
        // 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
        System.out.println(user);
        // 做响应,模拟查询数据库
        user.setUsername("一个Java小白2");
        user.setAge(20);
        // 做响应
        return user;
    }
  • 客户端发送了一个json串,服务器使用@RequestBody获取请求体内容,并使用 jacksonjson串封装到 User 对象中;服务器使用@ResponseBody生成响应,通过 jackson 将 User 对象转成 json 串。
  • SpringMVC 默认使用MappingJacksonHttpMessageConverter 进行转换,因此需要导入jackson 的依赖
	<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
    <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-annotations</artifactId>
      <version>2.9.0</version>
    </dependency>

导入出错的,老样子。传送门

  • 使用 jackson 进行 json 和 JavaBean 对象的自动转换时,需要保证 json 串的与 JavaBean 的属性名称一一对应

猜你喜欢

转载自blog.csdn.net/weixin_43844418/article/details/113871281
今日推荐