Spring MVC【返回数据与请求转发和重定向】

简介: Spring MVC【返回数据与请求转发和重定向】

我们知道,默认请求下⽆论是 Spring MVC 或者是 Spring Boot 都是由控制器(Controller)返回的是视图(View)(xxx.html),⽽现在都是前后端分离的,后端只需要返给给前端数据即可,这个时候我们就需要使⽤@ResponseBody 注解了


🍎一. 返回数据


🍒1.1 返回静态页面


我们先创建一个前端输出的文字的页面,最后来通过Controller来进行访问

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>hello,spring mvc</title>
    <script src="index.js"></script>
</head>
<body>
    <h1>Hello,Spring MVC.</h1>
</body>
</html>
 //访问静态页面
    @RequestMapping("/sayhi")
    public String sayHi(){
        return  "/hello.html";
    }

edf235c1fb57455a9b1f6ab4e4745fbf.png

🍒1.2 返回一个非静态页面


@ResponseBody是修饰类或方法的注解,作用是返回当前类中或方法中的非静态页面

 //访问非静态页面
    @ResponseBody
    @RequestMapping("/sayhi")
    public String sayHi(){
        return  "/hello.html";
    }

de111fc8697243229c6cd55d12666e1e.png

🍒1.3 返回text/html类型页面

这个和返回静态页面的区别就是,需要用@ResponseBody,并且需要使用


前端标题符

  @RequestMapping("/m7")
    @ResponseBody
    public String method_7() {
        return "<h1>Hello,HTML~</h1>";
    }


c0a867c0bccb45cc846f3daedc529957.png


🍒1.4 返回JSON对象

 @RequestMapping("/m8")
    @ResponseBody
    public HashMap<String, String> method_8() {
        HashMap<String, String> map = new HashMap<>();
        map.put("Java", "Java Value");
        map.put("MySQL", "MySQL Value");
        map.put("Redis", "Redis Value");
        return map;
    }

9cf31da687b54e969d88ee0dead9e2d0.png


🍒1.5 实现计算器功能


可使⽤ postman 传递参数,或使⽤ form 表单的⽅式提交参数


前端⻚⾯:


<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>计算器示例</title>
</head>
<body>
<form action="http://localhost:8080/calc">
    <h1>计算器</h1>
    数字1:<input name="num1" type="text"><br>
    数字2:<input name="num2" type="text"><br>
    <input type="submit" value=" 点击相加 ">
</form>
</body>
</html>

后端页面:

@RestController
public class CalcController {
    @RequestMapping("/calc")
    public String calc(Integer num1,Integer num2){
        if (num1 == null || num2==null) {
            if (num1 == null || num2 == null) return "<h1>参数错误!</h1><a href='javascript:history.go(-1);'>返回</a>";
        }
        return "<h1>结果:" + (num1+num2) +"</h1>";
    }
}

19a23aadd776458ab9545e9d92ff2bc2.pngf75c06a8154a4e5bbb852af19f66b20b.png


🍒1.6 使用ajax方式实现登陆功能


前端代码:


<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="js/jquery-1.9.1.min.js"></script>
    <title>Document</title>
    <script>
       // ajax 提交
        function mysub(){
            // 1.判空
            var username = jQuery("#username");
            var password = jQuery("#password");
            if(jQuery.trim(username.val())==""){
                alert("请先输入用户名!");
                username.focus(); // 光标重制到此元素
                return;
            }
            if(jQuery.trim(password.val())==""){
                alert("请先输入密码!");
                password.focus(); // 光标重制到此元素
                return;
            }
            jQuery.ajax({
                url:"/user/login3",
                type:"POST",
                contentType:"application/json",
                data:JSON.stringify({"username":username.val(),
            "password":password.val()}),
                success:function(result){
                    alert(JSON.stringify(result));
                }
            });
        }
    </script>
</head>
<body>
<div style="text-align: center;">
    <h1>登录</h1>
    用户:<input id="username">
    <br>
    密码:<input id="password" type="password">
    <br>
    <input type="button" value=" 提交 " οnclick="mysub()" style="margin-top: 20px;margin-left: 50px;">
</div>
</body>
</html>


后端代码:

 @RequestMapping("/login3")
    public HashMap<String,Object> login2(String username, String password){
        HashMap<String,Object> result = new HashMap<>();
        int state = 200; //状态码
        int data = -1;   //等于1,登陆成功,否则登陆失败
        String msg = "未知错误";
        //使用Spring提供的方法tringUtils.hasLength方法就可以同时判断username是否是"空"和null了
        if (StringUtils.hasLength(username) && StringUtils.hasLength(password) && username.equals("admin") && password.equals("admin") ){
           if ( username.equals("admin") && password.equals("admin")) {
               data = 1;
               msg = "";
           }else {
               msg = "用户名或密码错误";
           }
        }else {
            // 参数为空
            msg = "非法参数";
        }
        result.put("state",state);
        result.put("data",data);
        result.put("msg",msg);
        return result;
    }

415f8953e4b849368b46dc870c366c78.png





🍎二.请求转发与请求重定向


return 不但可以返回⼀个视图,还可以实现跳转,跳转的⽅式有两种:

forward 是请求转发

redirect:请求重定向


forward(请求转发)和 redirect(请求重定向)的区别,举例来说,例如:

你告诉你妈妈,你想吃辣条,如果你妈妈,说好,我帮你去买,这就是 forward 请求转发;

如果你妈妈让你⾃⼰去买,那么就是请求 redirect 重定向


🍒2.1 请求转发(forward)


代码示例:

// [请求转发]
    // 实现方法(1)
    @RequestMapping("/fw")
    public String myForward(){
        return "forward:/hello.html";
    }
    // 实现方法(2)
    @RequestMapping("/fw2")
    public void myFoward2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/hello.html").forward(request,response);
    }

2aa0058ce20c4864907eab943df00fd0.png

我们可以使用fiddler来进行抓包验证,我们可以发现请求转发客户端只是访问了一次,而转发的过程中是由服务器内部进行访问静态页面后返回数据给服务端的


cf8a61539ffe4466a7ba1063bcf88339.png


df709de4474147f78038f7ff0a9889d5.png


🍒2.2 请求重定向(redirect)


代码示例:


  // [请求重定向]
    // 实现方法(1)
    @RequestMapping("/rd")
    public String myRedirect(){
        return "redirect:/hello.html";
    }
    // 实现方法(2)
    @RequestMapping("/rd2")
    public void myRedirect(HttpServletResponse response) throws IOException {
        response.sendRedirect("/hello.html");
    }

b57a8c15393e420ba8ae12d26b69f95c.png



我们可以使用fiddler来进行抓包验证,我们可以发现请求1转发客户端是先访问服务器,而服务器内部会响应客户端的请求1,之后客户端会进行请求2,服务器进行进行访问静态页面后返回数据给客户端的,我们看到页面就了解了,重定向会将页面地址最后跳转到我们需要访问的静态页面地址



ec9810492c7341688daecd6b2be5ea9b.png



238664c16f034e38aa53da491f8de445.png


🍎三.请求转发和请求重定向有什么区别


请求转发和请求重定向主要区别,包含以下 5 点:


● 定义不同

● 跳转方不同

● 数据共享不同

● 最终 URL 地址不同

● 代码实现不同


🍒3.1 定义不同


请求转发(Forward):发生在服务端程序内部,当服务器端收到一个客户端的请求之后,会先将请求,转发给目标地址,再将目标地址返回的结果转发给客户端


请求重定向(Redirect):请求重定向指的是服务器端接收到客户端的请求之后,会给客户端返回了一个临时响应头,这个临时响应头中记录了,客户端需要再次发送请求(重定向)的 URL 地址,客户端再收到了地址之后,会将请求发送到新的地址上,这就是请求重定向


🍒3.2 跳转方不同


请求转发是服务器端的行为,服务器端代替客户端发送请求,并将结果返回给客户端;

而请求重定向是客户端的行为,它们的交互流程

如下图所示:



3b8de9741b074200a07e371eaa035a3f.png

a9d8e4f73a2e437a9080b549151ede4e.png


🍒3.3 数据共享不同


请求转发是服务器端实现的,所以整个执行流程中,客户端(浏览器端)只需要发送一次请求,因此整个交互过程中使用的都是同一个 Request 请求对象和一个 Response 响应对象,所以整个请求过程中,请求和返回的数据是共享的;而请求重定向客户端发送两次完全不同的请求,所以两次请求中的数据是不同的


🍒3.4 最终 URL 地址不同


请求转发是服务器端实现的,所以整个执行流程中,客户端(浏览器端)只需要发送一次请求,因此整个交互过程中使用的都是同一个 Request 请求对象和一个 Response 响应对象,所以整个请求过程中,请求和返回的数据是共享的;而请求重定向客户端发送两次完全不同的请求,所以两次请求中的数据是不同的


请求转发:



6e73a05f6d6b4b07b531bd5b476288e8.png


请求重定向:


d2a88e718023422fa93a6895957d65cd.png



🍒3.5 代码实现不同

// [请求转发]
    // 实现方法(1)
    @RequestMapping("/fw")
    public String myForward(){
        return "forward:/hello.html";
    }
    // 实现方法(2)
    @RequestMapping("/fw2")
    public void myFoward2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/hello.html").forward(request,response);
    }
    // [请求重定向]
    // 实现方法(1)
    @RequestMapping("/rd")
    public String myRedirect(){
        return "redirect:/hello.html";
    }
    // 实现方法(2)
    @RequestMapping("/rd2")
    public void myRedirect(HttpServletResponse response) throws IOException {
        response.sendRedirect("/hello.html");
    }

🍒3.6 转发和重定向的选择


1、重定向的速度比转发慢,因为浏览器还得发出一个新的请求,如果在使用转发和重定向都无所谓的时候建议使用转发


2、因为转发只能访问当前web的应用程序,所以不同web应用程序之间的访问,特别是要访问到另外一个web站点上的资源的情况,这个时候就只能使用重定向了


3、另外,重定向还有一个应用场景:避免在用户重新加载页面时两次调用相同的动作

相关文章
|
12天前
|
设计模式 前端开发 Java
步步深入SpringMvc DispatcherServlet源码掌握springmvc全流程原理
通过对 `DispatcherServlet`源码的深入剖析,我们了解了SpringMVC请求处理的全流程。`DispatcherServlet`作为前端控制器,负责请求的接收和分发,处理器映射和适配负责将请求分派到具体的处理器方法,视图解析器负责生成和渲染视图。理解这些核心组件及其交互原理,有助于开发者更好地使用和扩展SpringMVC框架。
24 4
|
1月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
113 2
|
2月前
|
设计模式 前端开发 Java
Spring MVC——项目创建和建立请求连接
MVC是一种软件架构设计模式,将应用分为模型、视图和控制器三部分。Spring MVC是基于MVC模式的Web框架,通过`@RequestMapping`等注解实现URL路由映射,支持GET和POST请求,并可传递参数。创建Spring MVC项目与Spring Boot类似,使用`@RestController`注解标记控制器类。
51 1
Spring MVC——项目创建和建立请求连接
|
2月前
|
存储 Java API
如何使用 Java 记录简化 Spring Data 中的数据实体
如何使用 Java 记录简化 Spring Data 中的数据实体
44 9
|
2月前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
2月前
|
前端开发 Java Spring
【Spring】“请求“ 之后端传参重命名,传递数组、集合,@PathVariable,@RequestPart
【Spring】“请求“ 之后端传参重命名,传递数组、集合,@PathVariable,@RequestPart
42 2
|
2月前
|
JSON 前端开发 Java
【Spring】“请求“ 之传递 JSON 数据
【Spring】“请求“ 之传递 JSON 数据
100 2
|
2月前
|
前端开发 Java Spring
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
145 2
|
2月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
65 2
|
2月前
|
前端开发 Java 数据库
springBoot:template engine&自定义一个mvc&后端给前端传数据&增删改查 (三)
本文介绍了如何自定义一个 MVC 框架,包括后端向前端传递数据、前后端代理配置、实现增删改查功能以及分页查询。详细展示了代码示例,从配置文件到控制器、服务层和数据访问层的实现,帮助开发者快速理解和应用。