• SpringMVC 程序开发


    1. 什么是 SpringMVC

    官方描述:https://docs.spring.io/springframework/docs/current/reference/html/web.html#spring-web

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

    1.1 什么是 MVC

    Model View Controller(模型,视图,控制器),他是一种设计模式,这种设计模式将软件(项目)分为三部分: 模型,视图,控制器
    在这里插入图片描述

    Model(模型) 是应用程序中用于处理应用程序的数据逻辑的部分.通常模型对象负责在数据库中存取数据

    View(视图) 是应用程序中处理数据显示的部分.通常视图是依据模型数据创建的.

    Controller(控制器) 是应用程序中处理用户交互的部分.通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据…

    1.2 MVC 和 SpringMVC 什么关系

    MVC 是一种设计思想,而 SpringMVC 是一个 具体的实现框架.

    SpringMVC 是一个 基于 MVC 设计模式 和 Servlet API 实现的 Web 框架,同时 SpringMVC 又是 Spring 框架中的一个 WEB 模块,他是随着 Spring 的诞生而存在的一个框架.
    Spring 和 SpringMVC 诞生历史比较久远,在他们之后才有了 Spring boot.

    2. Spring MVC 项目创建

    我们只要基于 Spring Boot 框架添加一个 Spring Web(它使用的就是 Spring MVC)依赖,此时的项目就变成了Spring MVC项目.
    在这里插入图片描述

    我们学习SpringMVC主要学习:

    1. 实现用户和程序的映射(在浏览器输入 URL 地址之后,能够在程序中匹配到相应方法)
    2. 服务端要得到用户的请求参数
    3. 服务器要将结果返回给用户

    2.1 使用用户和程序的映射

    2.1.1 方法一: 使用@RequestMapping(“/xxx”)

    创一个 UserController 类,实现用户到 Spring 程序的互联互通:

    在这里插入图片描述

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    @ResponseBody // 表示的是返回一个非静态页面的数据
    @RequestMapping("/user") //类上面的 RequestMapping 可以省略
    public class UserController {
    
        @RequestMapping("/sayhi")
        public String sayHi(){
            return "Hello World!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    启动之后:在浏览器输入:http://localhost:8080/user/sayhi
    在这里插入图片描述

    tip:
    在这里插入图片描述

    @RequestMapping 特征:

    1. 既能修饰类(可选)也能修饰方法
    2. 默认情况下,既支持 POST 请求方式,也支持 GET 请求方式

    可以用 Postman验证一下:
    Postman下载方法:https://blog.csdn.net/chenbaifan/article/details/124850501?spm=1001.2014.3001.5501

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

    @RequestMapping 参数扩展(只支持某种类型的请求方式,比如 POST 类型的请求方式):

    @RequestMapping(method = RequestMethod.POST,value = "/sayhi")

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

    只支持 GET:
    在这里插入图片描述

    @RequestMapping(method = RequestMethod.GET,value = "/sayhi")

    2.1.2 方法二: 使用@PostMapping(“/xxx”)

    只支持 POST 请求方式
    @PostMapping("/sayhi2")
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    2.1.3 方法三: 使用 @GetMapping(“/xxx”)

    只支持 GET 请求方式
    @GetMapping("/sayhi3")
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    小总结:@RequestMapping既支持 GET 也支持 POST,但他也可以设置指定 GET 或 POST
    @GetMapping只支持 GET 请求,PostMapping只支持 POST 请求

    2.2 获取用户请求参数

    2.2.1 获取单个参数

    对象:
    在这里插入图片描述

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

    2.2.2 获取多个参数

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

    2.2.3 获取对象

    在这里插入图片描述

    在这里插入图片描述

    2.2.4 参数重命名(@RequesParam 注解)

    某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不致,如前端传递了个name 给后端,后端是有 username 字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使 @RequestParam 来重命名前后端的参数值.
    在这里插入图片描述在这里插入图片描述

    错误的:
    在这里插入图片描述

    在这里插入图片描述

    使用 @RequestParam 注解注意事项:
    如果在参数中添加 @RequestParam 注解,那么前端一定要传递此参数,否则就会报错,如果想要解决此问题,可以给 @RequestParam 里面添加 required = false

    报错的:
    在这里插入图片描述
    在这里插入图片描述

    修改的:
    在这里插入图片描述在这里插入图片描述

    2.2.5 获取 JSON 格式的数据(@RequestBody)

    要使用 @RequestBody 这个注解:
    在这里插入图片描述

    接着再用 Postman 模拟发送 JSON 数据给服务器:

    在这里插入图片描述

    2.2.6 从 URL 地址中获取参数 (@PathVariable)

    注意:我说的不是从 URL 地址中的参数部分获取参数
    在这里插入图片描述在这里插入图片描述

    2.2.7 上传文件

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

    这样有个不好的一点,就是存储的地方写死了在本机,如果我要存到服务器,其他平台就不好办了,所以我们可以这样做:

    # 开发环境的配置文件
    
    # 图片保存的路径
    img:
      path: D:/Training/
    
    
    # 生产环境的配置文件
    
    # 图片保存的路径
    img:
      path: /root/img/
    
    
    
    # 设置配置文件的运行平台
    spring:
      profiles:
        active: dev
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在不同运行平台配置文件设置:

    1. 新建不同的配置文件:
      在这里插入图片描述在这里插入图片描述在这里插入图片描述
      在不同的平台配置文件的命名规则: application-平台.yml(properits),必须得这样命名,
    1. 在主配置文件中设置运行的配置文件:
      在这里插入图片描述
      这样操作之后,我们只需要修改active 对应的环境就可以随意存储了,不需要频繁的修改.

    在这里插入图片描述

    // 从配置文件中读取图片的保存路径
        @Value("${img.path}")
        private String imgPath;
    
        @RequestMapping("/upimg")
        public boolean upImg(Integer uid, @RequestPart("img") MultipartFile file) {
            boolean result = false;
            String fileName = file.getOriginalFilename(); // 得到原图片的名称(xxx.png)
            fileName = fileName.substring(fileName.lastIndexOf(".")); // 得到图片后缀(png)
            fileName = UUID.randomUUID().toString() + fileName;
            // 保存图片到本地目录
            try {
                file.transferTo(new File(imgPath + fileName));
                result = true;
            } catch (IOException e) {
                log.error("上传图片失败:" + e.getMessage());
            }
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    在这里插入图片描述

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

    2.2.8 获取 Cookie

    ① servlet 获取 Cookie 的方法

    @RequestMapping("/cookie")
        public void getCookie(HttpServletRequest request) {
            // 得到全部的 Cookie
            Cookie[] cookies = request.getCookies();
            for (Cookie item : cookies) {
                log.info("Cookie Name:" + item.getName() +
                        " | Cookie Value:" + item.getValue());
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    返回结果:
    在这里插入图片描述在这里插入图片描述

    这样的缺点就是一次都把所有的 cookie 都给读出来了

    ② 使用 @CookieValue 注解实现 Cookie 的读取

     @RequestMapping("/cookie2")
        public String getCookie2(@CookieValue("456") String cookie) {
            return "Cookie Value:" + cookie;
        }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    2.2.9 获取 Header (请求头) 里面的信息

    ① Servlet 方式

     @RequestMapping("/getua")
        public String getHead(HttpServletRequest request) {
            return "header:" + request.getHeader("User-Agent");
        }
    
    • 1
    • 2
    • 3
    • 4

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

    ② 使用注解 @RequestHeader 的方式

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

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

    2.2.10 存储 Session

    设置(存储)Session 之前:
    在这里插入图片描述

    存储 Session 之后:

    @RequestMapping("/setsess")
        public boolean setSession(HttpServletRequest request) {
            boolean result = false;
            // 1.得到 HttpSession
            HttpSession session = request.getSession(true); // true=如果没有会话,那么创建一个会话
            // 2.使用 setAtt 设置值
            session.setAttribute("userinfo", "张三");
            result = true;
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    在这里插入图片描述

    保存了SessionId 就传给服务器获取

    2.2.11 获取 Session

    ① Servlet 方式

    @RequestMapping("/getsess")
        public String getSession(HttpServletRequest request) {
            String result = null;
            // 1.得到 HttpSession 对象
            HttpSession session = request.getSession(false); // false=如果有会话,使用会话,如果没有,那么不会新创建会话
            // 2.getAtt 得到 Session 信息
            if (session != null && session.getAttribute("userinfo") != null) {
                result = (String) session.getAttribute("userinfo");
            }
            return "会话: "+result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    先存才取:
    在这里插入图片描述

    ② 使用注解 @SessionAttribute 的方式

    @RequestMapping("/getsess2")
        public String getSession2(@SessionAttribute(value = "userinfo",
                required = false) String userinfo) {
            return "会话:" + userinfo;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    2.3 返回数据

    2.3.1 返回静态页面

    创建一个前端页面:
    在这里插入图片描述
    在这里插入图片描述

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

    注意: 我没加 @ResponseBody 注解,加了就不是返回静态页面了:

    2.3.2 返回一个非静态页面

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

    2.3.3 练习: 实现计算器功能

    前端代码
    在这里插入图片描述

    后端代码
    在这里插入图片描述

    结果

    在这里插入图片描述

    在这里插入图片描述

    2.3.4 模拟实现登录功能

    前端代码: 发送 JSON

    
    
    
        
        
        
        
        Document
        
    
    
    

    登录

    用户:
    密码:
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    在这里插入图片描述

    后端代码: 接收 JSON

     /**
         * 获取前端的 json 数据
         *
         * @param userInfo
         * @return
         */
        @RequestMapping("/login")
        public HashMap login(@RequestBody UserInfo userInfo) {
            HashMap result = new HashMap();
            int state = 200;
            int data = -1; // 等于 1,登录成功,否则登录失败
            String msg = "未知错误";
            if (StringUtils.hasLength(userInfo.getUsername()) && StringUtils.hasLength(userInfo.getPassword())) {
                if (userInfo.getUsername().equals("admin") && userInfo.getPassword().equals("admin")) {
                    data = 1;
                    msg = "";
                } else {
                    msg = "用户名或密码失败!";
                }
            } else { // 参数为空
                msg = "非法参数";
            }
            result.put("state", state);
            result.put("data", data);
            result.put("msg", msg);
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

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

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

    在这里插入图片描述

    在这里插入图片描述

    2.3.5 请求重定向和请求转发

    ① 请求转发 Forward

    请求转发是服务器端帮用户实现的

    方式一:
    在这里插入图片描述注解要改成@Controller

    方式二:
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    ② 请求重定向 Redirect

    重定向的请求发生在客户端(浏览器端),服务器端对不同用户进行请求操作

    方式一:
    在这里插入图片描述注解要用@Controller

    方式二:
    在这里插入图片描述
    在这里插入图片描述

    3. 小结

    3.1 组合注解 @RestController

    @RestController = @Controller + @ResponseBody
    自动识别是返回静态页面还是非静态页面
    在这里插入图片描述

    3.2 请求转发(Forward)和请求重定向(Redirect)区别

    我们在 Java 中,实现跳转的方式有两种:请求转发和重定向, 二者是有区别的:

    1. 定义不同
    2. 跳转方不同
    3. 数据共享不同
    4. 最终 URL 地址不同
    5. 代码实现不同

    1. 定义不同
    请求转发: 发生在服务端程序内部,当服务器收到一个客户的请求之后,会先将请求转发给目标地址,在将目标地址返回的结果转发给客户端.(张三(客户端)李四(服务器端)借钱,然而李四却并没有那么多钱,于是李四就去找王五借钱,在把钱给张三,这个过程张三就相当于只找李四借了钱)
    请求重定向: 请求重定向指服务器端接收到客户端请求后,给客户端一个临时响应头,这里就包含了再次请求的地址(张三(客户端)李四(服务器端)借钱,李四没有,他就告诉张三:“你去找王五借吧,我现在没钱”,于是张三就去找王五借钱了)

    2. 跳转方式不同
    请求转发是服务器端的行为 ,服务器端代替客户端发送请求,并将结果返回给客户端;
    请求重定向是客户端的行为
    在这里插入图片描述

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

    4. 最终 URL 地址不同
    请求转发 是服务器代为请求,再将结果返回给客户端,所以在整个请求过程中 URL 地址是不变的;
    请求重定向 是告诉客户端到另一个地址去访问,要再发一次请求,所以地址是要跳转的

    5. 代码实现不同
    请求转发
    在这里插入图片描述
    请求重定向
    在这里插入图片描述要用@Controller注解

    3.3 IDEA 热部署(热加载)

    这个就是让我们在修改代码的过程中,他会自动检测到代码已经修改,并重启 spring boot 项目,就不用我们每修改一次想要查看效果就必须重启项目
    1. 添加 spring boot 开发者框架支持
    在这里插入图片描述

    2. 开启 IDEA 的自动编译
    在这里插入图片描述
    在这里插入图片描述

    3. 开启运行中的热部署
    这个是 IDEA 版本 2021.2 之前的版本配置方式
    在这里插入图片描述

    搜索:compiler.automake.allow.when.app.running
    在这里插入图片描述

    IDEA 2021.2 之后的版本
    在这里插入图片描述

    4. 启动项目使用 debug,而不是 run 运行
    可能有些点击run也行

    在这里插入图片描述

    这样设置之后,修改代码了就不用自己频繁启动了,他自己检测到代码变动了自己就重启项目了

    3.4 查看更多注解

    官方 API: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-requestmapping

  • 相关阅读:
    云计算项目七:jump-server安装部署
    关于面向对象的几大特性所能够解决的编程问题
    MySQL执行计划分析
    Java代码审计——WebGoat XML外部实体注入(XXE)
    Android 8.1 隐藏设置中的WLAN菜单
    ssm+vue+java微信小程序的英语学习激励系统#毕业设计
    一个在线下载地图XYZ瓦片的网站实现
    React中的受控组件(controlled component)和非受控组件(uncontrolled component)
    SpringCloud Sleuth 分布式请求链路跟踪
    基于istio实现单集群地域故障转移
  • 原文地址:https://blog.csdn.net/web13985085406/article/details/126041671