• SpringMVC 框架详解


    1.什么是 Spring MVC

    官方对于 Spring MVC 的描述是这样的:

    Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从一开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来自其源模块的名称(Spring-webmvc),但它通常被称为“SpringMVC”。

    从上述定义我们可以得出两个关键信息:

    1. Spring MVC 是⼀个 Web 框架。
    2. Spring MVC 是基于 Servlet API 构建的。

    然而要真正的理解什么是 Spring MVC?我们首先要搞清楚什么是 MVC?

    1.1 什么是MVC

    MVCModel View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。

    • Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
    • View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
    • Controller(控制器)是应用程序中处理⽤户交互的部分。通常控制器负责从视图读取数据,控制用户输⼊,并向模型发送数据。

    1.2 MVC 和 Spring MVC 的关系

    MVC 是一种思想,而 Spring MVC 是对 MVC 思想的具体实现。总的来说,Spring MVC 是一个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架。

    2.第一个SpringMVC程序

    (1) 创建SpringMVC项目
    Spring MVC 可以基于 Spring Boot 创建,也就是创建一个 Spring Boot 项目,勾选上 Spring Web 模块即可,详情请参考:SpringBoot项目创建及运行

    (2) 创建一个 UserController 类,实现用户到 Spring 程序的互联互通,具体实现代码如下:

    @Controller
    @ResponseBody
    @RequestMapping("/user")    // 路由映射
    public class UserController {
    
        @RequestMapping("/hi")
        public String sayHi() {
            return "

    hi, SpringMVC

    "; } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (3) 这样实现之后,启动项目,当访问地址:http://localhost:8080/user/hi 时就能打印“hi,SpringMVC”的信息了。

    2.1 @RequestMapping 注解

    @RequestMapping 是 Spring Web 应用程序中最常被用到的注解之⼀,它是用来注册接口的路由映射的。

    路由映射:所谓的路由映射指的是,当用户访问⼀个 url 时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射。

    2.2 @ResponseBody 注解

    @ResponseBody 返回的值如果是字符会转换成 text/html,如果返回的是对象会转换成 application/json 返回给前端。
    @ResponseBody 可以用来修饰方法或者是修饰类,修饰类表示类中的所有方法都会返回 html 或者 json,而不是视图

    2.3 get 和 post

    @RequestMapping 默认是 get 方式的请求,如果想接收POST请求,我们可以显示的指定 @RequestMapping 来接收 post

    @RequestMapping(value = "/hi",method= RequestMethod.POST)
    
    • 1

    get 请求的 3 种写法:

    // 写法1
    @RequestMapping("/index") 
    // 写法2
    @RequestMapping(value = "/index",method = RequestMethod.GET) 
    // 写法3
    @GetMapping("/index")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    post 请求的 2 种写法:

    // 写法1
    @RequestMapping(value = "/index",method = RequestMethod.POST) 
    // 写法2
    @PostMapping("/index")
    
    • 1
    • 2
    • 3
    • 4

    3.获取参数

    3.1 传递单个参数

    在 Spring MVC 中可以直接用方法中的参数来实现传参,比如以下代码:

        @RequestMapping("/showname")
        public String showName(String name) {
            return "姓名:" + name;
        }
    
    • 1
    • 2
    • 3
    • 4

    在 postman 中模拟传参:
    在这里插入图片描述

    3.2 传递对象

    Spring MVC 可以自动实现参数对象的赋值,比如 Person 对象:
    创建Person类:

    @Data
    public class Person {
        private int id;
        private String name;
        private String password;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    传递对象代码实现:

        @RequestMapping("/person")
        public Object getPerson(Person person) {
            return person;
        }
    
    • 1
    • 2
    • 3
    • 4

    通过url访问并传递参数:
    在这里插入图片描述

    3.3 表单参数传递/传递多个参数(非对象)

    @RequestMapping("/login")
        public String login(String username, String password) {
            return "用户名:" + username + " 密码:" + password;
        }
    
    • 1
    • 2
    • 3
    • 4

    通过url访问并传递参数:
    在这里插入图片描述

    3.4 后端参数重命名(后端参数映射)

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

        @RequestMapping("/time")
        public String getTime(@RequestParam("time") String createtime) {
            return createtime;
        }
    
    • 1
    • 2
    • 3
    • 4

    输入url传递参数:
    在这里插入图片描述

    3.5 设置参数非必传

    拿上面的例子,不给time传参数:
    在这里插入图片描述

    就会报400,为什么会这样呢?
    看下@RequestParam源码:
    在这里插入图片描述
    发现默认情况下参数是必传的,如果不传参数则会报错,我们可以通过设置 @RequestParam 中的 required=false 来设置参数为非必传,具体实现如下:

        @RequestMapping("/time2")
        public String getTime2(@RequestParam(value = "time", required = false) String createtime) {
            return createtime;
        }
    
    • 1
    • 2
    • 3
    • 4

    通过url访问并不设置参数:
    在这里插入图片描述

    发现并没有报错,说明设置是有效的。

    3.6 接收JSON对象

        @RequestMapping(value = "getjson", method = RequestMethod.POST)
        public Object getJson(@RequestBody Person person) {
            return person;
        }
    
    • 1
    • 2
    • 3
    • 4

    通过postman传递一个json字符串:
    在这里插入图片描述

    成功接收。

    3.7 获取URL中参数

        @RequestMapping("/geturl/{name}/{password}")
        public String getUrl(@PathVariable String name, @PathVariable String password) {
            return "名称:" + name + " 密码:" + password;
        }
    
    • 1
    • 2
    • 3
    • 4

    通过url获取参数:
    在这里插入图片描述

    3.8 上传文件

    创建 application.yml 配置文件,配置文件保存路径:

    # 图片保存路径
    myfile:
      path: E:/Data/
    
    • 1
    • 2
    • 3

    后端实现代码:

        @Value("${myfile.path}")
        private String filePath;    // 从配置文件中获取文件上传路径
    
        @RequestMapping("/upfile")
        public boolean upFile(String name, @RequestPart("myfile") MultipartFile file) {
            boolean result = false;
            try {
                // 得到原文件的名称和后缀
                String fileType = file.getOriginalFilename();
                if (fileType != null) {
                    fileType = fileType.substring(fileType.lastIndexOf("."));
                }
                // 文件保存的名称
                String fileName = UUID.randomUUID().toString() + fileType;
                file.transferTo(new File(filePath + fileName));
                result = true;
                log.info(name + ":图片上传成功!");
            } catch (IOException e) {
                log.error(name + ":图片上传失败!");
            }
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    注意:这里用到了log,要给类上加上@Slf4j注解。

    用postman上传文件:
    在这里插入图片描述
    文件成功保存到路径下:
    在这里插入图片描述
    在这里插入图片描述

    控制台也打印成功日志:
    在这里插入图片描述

    3.9 获取Cookie/Session/header

    获取 Cookie 方法1:

        @RequestMapping("/getck")
        public void getCookie(HttpServletRequest request) {
            Cookie[] cookies = request.getCookies();
            Arrays.stream(cookies).forEach(cookie -> {
                log.info(cookie.getName() + ":" + cookie.getValue());
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    方法2:

        @RequestMapping("/getck2")
        public String getCookie2(@CookieValue("bite") String bite) {
            return bite;
        }
    
    • 1
    • 2
    • 3
    • 4

    获取Header:

        @RequestMapping("/header")
        public String getHeader(@RequestHeader("User-Agent") String userAgent) {
            return userAgent;
        }
    
    • 1
    • 2
    • 3
    • 4

    获取session方法1:

        @RequestMapping("/getsess")
        public String getSession(HttpServletRequest request) {
            String result = "";
            HttpSession session = request.getSession(false);
            if (session != null && session.getAttribute("SESSION_KEY") != null) {
                result = (String) session.getAttribute("SESSION_KEY");
            }
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    方法2:

        @RequestMapping("/getsess2")
        public String getSession2(@SessionAttribute(required = false, name = "SESSION_KEY") String data) {
            return data;
        }
    
    • 1
    • 2
    • 3
    • 4

    设置session:

        @RequestMapping("/setsess")
        public boolean setSession(HttpServletRequest request) {
            boolean result = false;
            try {
                HttpSession session = request.getSession(true);
                session.setAttribute("SESSION_KEY", "java");
                result = true;
            } catch (Exception e) {
                log.error("出现异常:" + e.getMessage());
            }
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.返回数据

    4.1 返回静态页面

    创建前端页面 index.html:
    在这里插入图片描述

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
        <h1 style="color: blue">hello, SpringMVCh1>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    创建控制器 Controller:

    @Controller
    public class IndexController {
        @RequestMapping("/index")
        public Object index() {
            return "/index.html";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在浏览器输入url:
    在这里插入图片描述

    4.2 返回JSON对象

        @RequestMapping("/map")
        @ResponseBody
        public HashMap<String, String> mapJson() {
            HashMap<String, String> map = new HashMap<>();
            map.put("Java", "Java Value");
            map.put("MySQL", "MySQL Value");
            map.put("Redis", "Redis Value");
            return map;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    4.3 请求转发或请求重定向

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

    • forward:请求转发;
    • redirect:请求重定向。

    请求转发和重定向的使用对比:

    // 请求重定向
    @RequestMapping("/index1")
    public String index(){
    return "redirect:/index.html"; 
    }
    // 请求转发
    @RequestMapping("/index2") 
    public String index2(){
    return "forward:/index.html"; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    举例说明 forward 和 redirect
    例如,你告诉你男/女朋友你想吃雪糕,如果他/她说好,我给你买,这就是forward请求转发,如果他/她说自己买去,那么就是redirect重定向

    forward 和 redirect 具体区别如下:

    • 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
    • 请求重定向地址发⽣变化,请求转发地址不发生变化。
    • 请求重定向与直接访问新地址效果⼀致,不存在原来的外部资源不能访问;请求转发服务器端转发,有可能造成原外部资源不能访问。
  • 相关阅读:
    【Apache Flink 介绍与学习】
    开源模型应用落地-qwen2-7b-instruct-LoRA微调-LLaMA-Factory(五)
    1.5-16:买房子
    从头学前端-HTML简介
    SpringBoot整合RabbitMQ实现六种工作模式
    深度学习入门(三十五)计算性能 编译器和解释器
    【踩坑系列】pyhton request 访问 url 时遇到 HTTP Error 503: Service Temporarily Unavailable
    【黑马云盘 Debug】ASSERT: “i >= 0 && i < size()“
    机器人力控制构架
    es6过滤对象里面指定的不要的值filter过滤
  • 原文地址:https://blog.csdn.net/m0_59140023/article/details/125799039