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、另外,重定向还有一个应用场景:避免在用户重新加载页面时两次调用相同的动作

相关文章
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
9077 132
|
前端开发 Java 测试技术
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
本文介绍了 `@RequestParam` 注解的使用方法及其与 `@PathVariable` 的区别。`@RequestParam` 用于从请求中获取参数值(如 GET 请求的 URL 参数或 POST 请求的表单数据),而 `@PathVariable` 用于从 URL 模板中提取参数。文章通过示例代码详细说明了 `@RequestParam` 的常用属性,如 `required` 和 `defaultValue`,并展示了如何用实体类封装大量表单参数以简化处理流程。最后,结合 Postman 测试工具验证了接口的功能。
1110 0
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestBody
`@RequestBody` 是 Spring 框架中的注解,用于将 HTTP 请求体中的 JSON 数据自动映射为 Java 对象。例如,前端通过 POST 请求发送包含 `username` 和 `password` 的 JSON 数据,后端可通过带有 `@RequestBody` 注解的方法参数接收并处理。此注解适用于传递复杂对象的场景,简化了数据解析过程。与表单提交不同,它主要用于接收 JSON 格式的实体数据。
1761 0
|
前端开发 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@PathVariable
`@PathVariable` 是 Spring Boot 中用于从 URL 中提取参数的注解,支持 RESTful 风格接口开发。例如,通过 `@GetMapping(&quot;/user/{id}&quot;)` 可以将 URL 中的 `{id}` 参数自动映射到方法参数中。若参数名不一致,可通过 `@PathVariable(&quot;自定义名&quot;)` 指定绑定关系。此外,还支持多参数占位符,如 `/user/{id}/{name}`,分别映射到方法中的多个参数。运行项目后,访问指定 URL 即可验证参数是否正确接收。
1142 0
|
NoSQL Java 数据库连接
《深入理解Spring》Spring Data——数据访问的统一抽象与极致简化
Spring Data通过Repository抽象和方法名派生查询,简化数据访问层开发,告别冗余CRUD代码。支持JPA、MongoDB、Redis等多种存储,统一编程模型,提升开发效率与架构灵活性,是Java开发者必备利器。(238字)
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
JSON Java 数据格式
Spring Boot返回Json数据及数据封装
在Spring Boot中,接口间及前后端的数据传输通常使用JSON格式。通过@RestController注解,可轻松实现Controller返回JSON数据。该注解是Spring Boot新增的组合注解,结合了@Controller和@ResponseBody的功能,默认将返回值转换为JSON格式。Spring Boot底层默认采用Jackson作为JSON解析框架,并通过spring-boot-starter-json依赖集成了相关库,包括jackson-databind、jackson-datatype-jdk8等常用模块,简化了开发者对依赖的手动管理。
969 3
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
1018 0
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
487 0
|
JSON 前端开发 Java
第05课:Spring Boot中的MVC支持
第05课:Spring Boot中的MVC支持
539 0

热门文章

最新文章