javaEE高阶---Spring MVC

news2024/11/26 14:56:11

一 : 什么是Spring MVC ?

1.1 概述

Spring MVC全称Spring Web MVC,又称为Spring Web,它是一个原始的基于Servlet API 的 web 框架.

Q : 经典问题 : Spring/Spring Boot/Spring MVC 有什么区别 ?

A : Spring,一般指代的是Spring Framework,它是一个开源的应用程序框架,提供了一个简易的开发方式,通过这种开发方式,将避免那些可能致使代码变得繁杂混乱的大量的业务/工具对象,说的更通俗一点就是由框架来帮你管理这些对象,包括它的创建,销毁等,比如基于Spring的项目里经常能看到的Bean,它代表的就是由Spring管辖的对象。
Spring MVC是Spring的一部分,Spring 出来以后,大家觉得很好用,于是按照这种模式设计了一个 MVC框架(一些用Spring 解耦的组件),主要用于开发WEB应用和网络接口,它是Spring的一个模块 .
Spring Boot 是所有基于 Spring 开发的项目的起点 . Spring Boot是在Spring的基础上面搭设的框架,目的是为了简化Spring项目的搭设和开发过程 .

在这里插入图片描述

在这里插入图片描述

1.2 MVC

MVC 是 Model View Controller 的缩写,它是软件工程中的一种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分.

在这里插入图片描述

1.3 MVC和Spring MVC的区别与联系

MVC 是一种思想,Spring MVC 是对 MVC 思想的具体实现.

总结来说,Spring MVC 是一个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架 . 既然是 Web 框架,那么当用户在浏览器中输入了 url 之后,我们的 Spring MVC 项目就可以感知到用户的请求 .

1.4 学习重点

在这里插入图片描述

二 : Spring MVC项目的创建

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三 : 连接的功能

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller //控制器,在Spring启动的时候加载并注册
@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    //当使用“/web”+“/hi”可以访问到当前方法
    @RequestMapping("/hi")
    @ResponseBody //将java对象转为json格式的数据
    public Object say() {
        return "Hi,Spring MVC!";
    }
}

运行结果 :
在这里插入图片描述

细说注解

在这里插入图片描述

@Controller

在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在SpringMVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。

@RequestMapping

@RequestMapping 既可修饰类,也可以修饰方法,当修饰类和方法时,访问的地址是类 + 方法 .

@RequestMapping也可以只修饰方法 :

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller //控制器,在Spring启动的时候加载并注册
public class WebController {

    @RequestMapping("/hi")
    @ResponseBody
    public Object say() {
        return "Hi,Spring MVC!";
    }
}

运行结果 :

在这里插入图片描述
@RequestMapping 是 post 还是 get 请求?

使用Postman进行测试 :

先发送GET请求 :

在这里插入图片描述

再发送POST请求 :

在这里插入图片描述

经过测试 , 发现两种请求都可以正常发送 .

同时 , @RequestMapping 也可以指定发送的请求类型 :

指定GET请求
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller //控制器,在Spring启动的时候加载并注册
public class WebController {

    @RequestMapping(value = "/hi",method = RequestMethod.GET)
    @ResponseBody
    public Object say() {
        return "Hi,Spring MVC!";
    }
}

当我们指定请求类型时 , 需要添加method参数 , 此时前面的路径/hi也被添加了value注释 , 这说明当只有一个参数时 , 默认类型为value ; 当有多个参数时 , 需要显式指定参数的类型 .

使用Postman进行测试 :

在这里插入图片描述
在这里插入图片描述

同理可指定请求类型为POST .

关于请求的指定 , 还可以使用专门的注解 :

@GetMapping 和 PostMapping , 在此不做过多演示 , 使用方法和@RequestMapping类似 .

总结 :

在这里插入图片描述

@ResponseBody

@ResponseBody的作用其实是将java对象转为json格式的数据 .

  1. 如果一个方法上没有加入ResponseBody注解,则Spring会将方法的返回值封装为一个ModelAndView对象返回 .
  2. 如果一个方法上加入了ResponseBody注解时,当返回值是字符串时,则返回字符串至客户端 ; 如果返回值是一个对象时,则将对象转换为json串,返回到客户端 .
  3. 如果将ResponseBody注解加在类前面 , 其效果等同于将该注解加在该类的所有方法上 !!!

文章推荐 : @ResponseBody详解

四 : 获取参数的功能

4.1 获取单个参数

在 Spring MVC 中可以直接用方法中的参数来实现传参.
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller //控制器,在Spring启动的时候加载并注册
@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping(value = "/say")
    @ResponseBody
    public Object say(String name) {
        return "I am" + name;
    }
}

在这里插入图片描述
在这里插入图片描述

某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不一致,比如前端传递了一个name后端,而后端又是有user字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用 @RequestParam 来重命名前后端的参数值 .

package com.example.demo;

import com.example.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller //控制器,在Spring启动的时候加载并注册
@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping(value = "/hi")
    @ResponseBody
    public Object say(@RequestParam("name") String user) {
        return "hi" + user;
    }
}

在这里插入图片描述

运行结果 :

在这里插入图片描述

4.2 获取多个参数

直接在单个参数后进行追加.
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller //控制器,在Spring启动的时候加载并注册
@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping(value = "/say")
    @ResponseBody
    public Object say(String name,Integer age) {
        return "I am" + name + " age : " + age;
    }
}

在这里插入图片描述

注意 : 参数传递的顺序不影响最终的解析 , 获取结果只和参数的名称有关 .

4.3 获取对象

就和普通的方法获取对象一样.
package com.example.demo;

import com.example.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller //控制器,在Spring启动的时候加载并注册
@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping(value = "/say")
    @ResponseBody
    public Object say(String name,Integer age) {
        return "I am" + name + " age : " + age;
    }

    @RequestMapping(value = "/stu")
    @ResponseBody
    public Object func(Student student) {
        return student.toString();
    }
}

package com.example.model;

import lombok.Data;

@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
    private String classId;
}

运行结果 :

在这里插入图片描述

注意 : 参数的传递大小写敏感 .

4.4 获取表单参数

在这里插入图片描述

4.4.1 Form表单传参

package com.example.demo;

import com.example.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller //控制器,在Spring启动的时候加载并注册
@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping("/login")
    @ResponseBody
    public String login(String user,String password) {
        return "用户名: " + user + "密码: " + password;
    }
}

运行结果 :

在这里插入图片描述
上面这种方法是通过Postman构造前端请求 , 也可以通过写代码构造前端请求 , 演示如下 :

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>注册</title>
</head>
<body>
    <form action="login" method="get">
    <div>
        <h1>用户登录</h1>
            用户:<input name="user"><br>
            密码:<input name="password"><br>
            <input type="submit" value="提交">
    </div>
    </form>

</body>
</html>
package com.example.demo.controller;

import com.example.demo.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller //控制器,在Spring启动的时候加载并注册

public class WebController {
    @RequestMapping("/login")
    @ResponseBody
    public String login(String user,String password) {
        return "用户名: " + user + "密码: " + password;
    }
}

运行结果 :

在这里插入图片描述

点击提交按钮 :

在这里插入图片描述
在这里插入图片描述

4.4.2 Ajax传参

第一步 : 引入jquery .

在这里插入图片描述

第二步 : 在前端构造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">
    <title>Document</title>
    <script src="js/jquery.min.js"></script>
</head>
<body>
<div>
    <h1> 登录 </h1>
    用户:<input id="name" name="name"><br>
    密码:<input id="password" name="password"><br>
    <input type="button" onclick="func()" value=" 提 交 ">
</div>
<script>
    function func(){
        jQuery.ajax({
            url:"login1",
            type:"POST",
            data:{"name":jQuery("#name").val(),"password":jQuery("#password").val()},
            success:function(result){
               alert(result);
               console.dir(result);
            }
        });
    }
</script>
</body>
</html>

第三步:Ajax传参

新建User对象(普通对象) ;

package com.example.demo.model;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String name;
    private String password;
    private Integer age;
    private String sex;
    private String classId;
    // ....
}
package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;


@ResponseBody
@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping("/login1")
    public String login1(String name,String password) {
        return "用户名: " + name + "密码: " + password;
    }
}

运行结果 :

在这里插入图片描述

注意 : 这里传递的并不是一个json对象 , 而是一个普通对象 !!! 我们使用Fiddler抓包来查看结果 :

在这里插入图片描述

4.5 接收JSON对象

首先 , 我们仍然使用前面的代码 , 并使用Postman构造一个json对象 , 查看结果 :

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;



@ResponseBody
@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping("/login1")
    public String login1(String name,String password) {
        return "用户名: " + name + "密码: " + password;
    }
}

在这里插入图片描述
此时你会发现 , 用户名和密码都为null , 说明后端没拿到数据 , 是否是因为我的参数不是一个对象 , 而导致拿不到数据呢 ? 基于此猜想 , 我们写出第二种代码 :

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;


@ResponseBody
@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping("/login2")
    public String login2(User user) {
        String name = user.getName();
        String password = user.getPassword();
        return "用户名: " + name + "密码: " + password;
    }
}

在这里插入图片描述

此时后端依然没有拿到数据 . 正确做法是 , 使用**@RequestBody** , 这个注解就是

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@ResponseBody
@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping("/login3")
    public String login3(@RequestBody User user) {
        String name = user.getName();
        String password = user.getPassword();
        return "用户名: " + name + "密码: " + password;
    }
}

在这里插入图片描述

注意 : @RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交 .

注意区分 , 表单提交和json对象提交的区别 , 只有在json对象提交时才需要添加 @RequestBody注解 :

在这里插入图片描述
在这里插入图片描述

4.6 上传文件@RequestPart

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@ResponseBody
@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
public class WebController {

    @RequestMapping("upload")
    public String upload(@RequestPart("myfile")MultipartFile file) throws IOException {
        file.transferTo(new File("C:\\java-projrct\\javaEE\\SpringMVC1\\img.jpg"));
        return "success";
    }
}

使用Postman构造请求 :

在这里插入图片描述
运行结果 :

在这里插入图片描述
在这里插入图片描述

4.7 获取Cookie/Session/Header

1. 获取cookie

方法一:传统方式,获取 Request 和 Response 对象
package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;

@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
@ResponseBody
public class WebController {

    @RequestMapping("/cookie")
    public String getCookies(HttpServletResponse response, HttpServletRequest request) {
        String name = request.getParameter("name");
        // 获取所有 cookie 信息
        Cookie[] cookies = request.getCookies();
        return name + " 你好.";
    }
}

运行结果 :

在这里插入图片描述
方法二:简便方法,使用@CookieValue.

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;

@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
@ResponseBody
public class WebController {

    @RequestMapping("/getcookie")
    public String getCookie(@CookieValue("name") String name,
                            @CookieValue("talent") String talent) {
        return "name:" + name + " |talent:" + talent;
    }
}

运行结果 :

在这里插入图片描述
在这里插入图片描述

注意 , 每次访问该网页 , 都会把当前浏览器的所有cookie返回给后端 , 不管后端需要不需要用到 . 示例如下 :

在这里插入图片描述
在这里插入图片描述

浏览器会默认将当前网站的所有cookie返回给后端 , 原因是http协议是无状态的 . 所谓无状态 , 就是指当用户访问浏览器时 , 浏览器不会记住当前用户是张三 , 还是李四 , 还是王五 , 这就会出现一个问题 . 比如当我在某网站刷题时候 , 我每一次操作网页 , 都需要进行登录 , 这显然是很疯狂的 . 比如我每次选择一个选项 , 要做下一题时 , 一点 , 直接触发重新登录 , 这谁顶得住啊 . 一般情况下 , 登录一段时间后是无需继续操作的 , 比如登录后 , 30min之内无需再次进行登录操作 .

解决方法就是在url上动手脚 , 在url上加一个身份标识, 每次后端在拿请求时 , 先从url里拿到身份标识 , 一看 , 诶 , 这不我张三哥吗 . 但是这种方式是有风险的 . 其一 , 直接将身份标识加在url里 , 有暴露的风险 . 其二 , 我是通过url进行验证的 , 但是url是极容易伪造的 .

所谓"兵来将挡水来土掩" , 我们将身份标识存到浏览器这边 , 即把身份标识加到cookie里 . 当然这种加到cooki里的方式也可以被伪造 , 比如我们前面就使用开发者工具伪造了一系列的cookie . 我们需要记住一句话 :

所有的加密操作 , 不是完全地解决安全问题 , 而是增加了破解的成本 !!!

相比于直接在url中添加参数 , 操作网站的cookie显然要复杂一些 .

此时身份信息已经存到cookie里了 , 但是我也不知道后端什么时候需要这个身份信息 , 什么时候不需要这个身份信息 , 索性认将当前网站的所有cookie返回给后端 !!!

cookie在客户端工作 , session则工作在服务器端 . 服务器端有一个会话表 , 这个会话表里有两部分的数据 . 一部分是session id , 是随机生成的 , 同一个用户 , 在某次登陆时session id也各不同 . 而另外一部分 , 则是这个session id 所对应的用户的信息 . 服务器会把session id给cookie , 相当于在客户端只存储了session id , 没有具体信息 , 所以关键信息并没有泄露 ; 在前端向后端返回数据时 , 服务器拿到cookie中的session id 后 , 判断此session id是否有效 , 如果有效 , 那我就知道 , 诶 , 这不我张三哥吗 .

所以 , cookie和session通常是配合使用的 . cookie是可以伪造的 , 但是session是不能伪造的 .

在这里插入图片描述

2. 获取session

先设置 , 后获取 .

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;

@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
@ResponseBody
public class WebController {

    @RequestMapping("/setsession")
    @ResponseBody
    public String setSession(HttpServletRequest request) {
// 获取 HttpSession 对象,参数设置为 true 表示如果没有 session 对象就创建一个session
        HttpSession session = request.getSession(true);
        if(session!=null){
            session.setAttribute("username","pilihuo");
        }
        return "session 存储成功";
    }

    @RequestMapping("/getsession")
    @ResponseBody
    public String getSession(@SessionAttribute(value = "username",required = false)
                                String username) {
        return "username:"+ username;
    }
}

在这里插入图片描述

直接获取session (不设置session)
在这里插入图片描述

先调用setsession , 后调用getsession :在这里插入图片描述

成功 !!!

2. 获取Header

@RequestHeader
package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;

@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
@ResponseBody
public class WebController {


    @RequestMapping("/getheader")
    public String getHeader(@RequestHeader("User-Agent") String userAgent) {
        return "userAgent" + userAgent;
    }
}

运行结果 :

在这里插入图片描述

抓包结果 :
在这里插入图片描述

4.8 特殊的URL和获取参数的方式

@PathVariable

什么是特殊的URL ?

在这里插入图片描述

如何获取特殊的URL传递的参数呢 ?

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;

@Controller //控制器,在Spring启动的时候加载并注册
//@RequestMapping("/web") //当使用"/web"可以访问到当前类
@ResponseBody
public class WebController {

@RequestMapping("parameter/{name}{password}")
	    public String parameter(@PathVariable("name") String username,
	                            @PathVariable("password") String password){
	    return "name = " + username + "password = " + password;
	}
}

运行结果 :

在这里插入图片描述

五 : 输出数据的功能

默认请求下无论是 Spring MVC 或者是 Spring Boot 返回的是视图(xx.html),而现在都是前后端分离的,后端只需要返给给前端数据即可,此时需要使用@ResponseBody注解 , 然后直接return即可 .

请求转发或请求重定向

forward VS redirect

return还可以实现跳转,跳转的方式有两种:

forward 是请求转发;

redirect:请求重定向 .

在这里插入图片描述

举例 :

转发:某人去了甲局,甲局看了之后,直到护照应该由乙局来管,但甲局的工作人员并没有赶走某人,而是让某人等着,自己在办公室后面联系了乙局的工作人员,乙局护照办好后送到了甲局,然后甲局的工作人员将护照交给了某人;

重定向:某人去了甲局后,甲局的工作人员说护照不归他们关,应该去乙局。然后某人自己去了乙局,办了护照 .

演示 :

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TestController {
    //请求转发
    @RequestMapping("/hello")
    public String hello() {
        return "forward:/login.html";
    }

    //请求重定向
    @RequestMapping("/hello1")
    public String hello1() {
        return "redirect:/login.html";
    }
}

在这里插入图片描述

本文内容到此结束 !!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/51980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

业务数据分析-常见业务指标

目录 1、什么是指标&#xff1f; 2、以互联网电商数据为例分析常用的指标 3、如何选择指标 4、电商指标体系详细介绍 1、什么是指标&#xff1f; 我们说过分析的最终目的就是为了通过客观的数据去发现公司业务存在的问题&#xff0c;那怎么通过什么数据呢&#xff1f;业务…

连接MySQL问题的错题小集

目录 一. 连接不上数据库 踩坑 解决过程 二. Can‘t connect to MySQL server on ‘localhost:3306‘ (10061) 排查1&#xff1a;数据库没有启动 排查2&#xff1a;判断数据库是否存在 排查3&#xff1a;数据库没有启动 ​编辑 过程&#xff1a; 报错了&#xff0c;排…

12.Java 技术栈中间件优雅停机方案设计与实现全景图

Java 技术栈中间件优雅停机方案设计与实现全景图 本系列 Netty 源码解析文章基于 4.1.56.Final 版本 本文概要 在上篇文章 中笔者为大家详细介绍了 Netty 在处理连接关闭时的完整过程&#xff0c;并详细介绍了 Netty 如何应对 TCP 连接在关闭时会遇到的各种场景。 在连接关闭…

软件压力测试有哪些测试流程?软件测试报告收费情况

软件压力测试是一种基本的质量保证行为&#xff0c;它是每个重要软件测试工作的一部分。通过给软件系统不断施压&#xff0c;强制其在极限条件下运行&#xff0c;以观察软件系统可运行到哪种程度&#xff0c;从而发现系统性能缺陷。测试人员根据测试过程进行总结和分析&#xf…

[附源码]Python计算机毕业设计Django个性化产品服务管理系统论文

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

电脑重装系统后序列号怎么查

最近很多网友都在问怎么看桌面操作系统序列号&#xff0c;我们安装系统的时候是需要知道&#xff0c;其实想要知道自己电脑的序列号非常简单的&#xff0c;网友们看看下面操作就知道了。 工具/原料&#xff1a; 系统版本&#xff1a;win10 型号&#xff1a;联想小新Air 13 Pro…

【矩阵论】4. 矩阵运算——广义逆——减号逆

4.5 减号逆 若 AAmnAA_{m\times n}AAmn​ 与 XXnmXX_{n\times m}XXnm​ &#xff0c;有 AXAAAXAAAXAA &#xff0c;则称 XXnmXX_{n\times m}XXnm​ 为A的减号逆(一号逆)&#xff0c;记为 XA−A(1)XA^{-}A^{(1)}XA−A(1) 全体 A−A^{-}A− 的集合记为 A{1}{X∣AXAA}A^{\{1\}}\…

【自然语言处理概述】百度百科数据爬取

【自然语言处理概述】百度百科数据爬取 作者简介&#xff1a;在校大学生一枚&#xff0c;华为云享专家&#xff0c;阿里云专家博主&#xff0c;腾云先锋&#xff08;TDP&#xff09;成员&#xff0c;云曦智划项目总负责人&#xff0c;全国高等学校计算机教学与产业实践资源建设…

氮化镓(GaN)功率半导体之预测

前言 氮化镓&#xff08;GaN&#xff09;是一种非常坚硬且在机械方面非常稳定的宽带隙半导体材料。由于具有更高的击穿强度、更快的开关速度&#xff0c;更高的热导率和更低的导通电阻&#xff0c;氮化镓基功率器件明显比硅基器件更优越。 氮化镓晶体可以在各种衬底上生长&…

充分利用自动化测试的 10 个最佳实践

你试过吃带壳的坚果吗&#xff1f;如果是&#xff0c;我想这不是一次非常成功的经历。 虽然大家都知道坚果是非常健康和有营养的。矛盾的是&#xff0c;许多公司在实施测试自动化时没有考虑细微差别。每个人都知道它对身体有好处&#xff08;就像吃坚果对我们健康有益一样&…

线上环境不要使用console.log,会导致页面卡顿,内存泄漏的原因

在我的这篇文章中分享了一个经验&#xff0c;就是vite打包之后会自动屏蔽所有的console.log打印的日志。 那么&#xff0c;在线上环境中不要使用 console.log 打印日志&#xff0c;已经成为共识&#xff0c;你知道是为什么么&#xff1f; 原因当然在于这个罪魁祸首 console 方…

深拷贝、浅拷贝的方法

目录 浅拷贝 深拷贝 与浅拷贝概念&#xff1a; 深浅拷贝出现的前提&#xff1a; 应用类型的数据&#xff08;对象和数组&#xff09; 深拷贝就是把目标对象里面的数据一个一个都复制下来&#xff0c;创建出一个一模一样的&#xff0c;存放地 址不一样&#xff0c;互不影响。…

【白嫖】如何底价续费服务器

目录 背景 问题 缓解方案 背景 现在各大云服务商的学生价服务器都已经关闭了&#xff0c;华为云、阿里云、百度云&#xff0c;以前都有学生价服务器&#xff0c;一年只要99。现在我找半天都没找到入口&#xff0c;而原价的一年得500块起步。。。 但是&#xff01;&#xff0…

MySQL事务详解

目录 引例 什么是事务 一个完整事务所具有的四大属性 为什么会出现事务 事务常见操作方式 事务隔离级别 为什么要存在隔离级别 一致性 引例 如下图&#xff0c;是一个火车售票系统&#xff0c;当客户端A发现还有一张票时&#xff0c;将票卖掉&#xff0c;还没执行更新…

C++实现UDP可靠传输(二)

声明&#xff1a;禁止以任何形式转载本文章。本文章仅供个人学习记录与交流探讨&#xff0c;文章中提供的思路只是一种解决方案&#xff0c;代码也并非完整代码&#xff0c;如有需要&#xff0c;请自行设计协议并完成编程任务。 食用本文章之前&#xff0c;推荐阅读&#xff…

RKMEDIA--VENC/VDEC使用

前面两篇已经介绍了VI和VO的使用&#xff0c;本章节来介绍rkmedia且也是瑞芯微平台重点部分&#xff1a;编解码。 目录 一、简介 二、编解码能力 三、编码 编码初始化&#xff1a; 在初始化VENC时需要注意几点&#xff1a; venc编码帧率控制&#xff1a; 编码添加osd位图…

软件设计师考试重点1 计算机组成与体系结构

软件设计师考试重点1 计算机组成与体系结构一、 数据的表示1. 进制转换2. 原码/反码/补码/移码3. 数值表示范围4. 浮点数的运算二、运算器与控制器1. 计算机结构2. 计算机五大组成部分&#xff1a;3. CPU组成部分&#xff1a;4. 控制器组成部分&#xff1a;5. 运算器组成部分&a…

如何构建一个自动化油田注水站监控系统?

一、应用背景 目前&#xff0c;在大部分的钻井平台中&#xff0c;维护油田注水站的工作状态主要通过人工方式进行&#xff0c;这种方式不仅作业效率低且对工人的经验有着较高要求。此外&#xff0c;油田注水站的工作环境恶劣&#xff0c;为了能够有效地掌握各个设备的工作状态…

【测试沉思录】20. 如何做好测试需求分析?

作者&#xff1a;刘亚茹 编辑&#xff1a;毕小烦 我们都知道测试用例是软件测试中保障质量的必要手段&#xff0c;而测试需求作为用例编写的主要依据却往往被很多人忽视。到底什么是测试需求&#xff1f;又如何做好测试需求分析呢&#xff1f;本文带你了解一下。 1. 测试需求到…

Java项目如何导出数据为 PDF 文件?

文章目录Java项目如何导出数据为 PDF 文件&#xff1f;一、代码结构如下二、代码说明1、添加依赖 pom.xml3、添加字体4、PDF 导出工具类三、效果图结语Java项目如何导出数据为 PDF 文件&#xff1f; 一个小需求&#xff0c;需要将页面上的数据导出为PDF&#xff0c;正常情况下…