Spring MVC
作者:mmseoamin日期:2023-12-18

Spring MVC,在这里插入图片描述,第1张

文章目录

  • 一、什么是Spring MVC?
  • 二、Spring MVC创建与连接
  • 三、请求响应
    • 简单参数
    • 实体参数
    • 数组集合参数
    • 日期参数
    • JSON参数
    • 路径参数
    • 获取Cookie/Session/header
    • 四、文件上传
    • 五、返回数据
      • 返回静态页面
      • 请求转发与请求重定向

        一、什么是Spring MVC?

        Spring MVC(Model View Controller)是基于Servlet API构建的原始Web框架,包含在Spring框架中

        Spring MVC,在这里插入图片描述,第2张

        Controller(控制器):应用程序中处理用户交互的部分

        View(视图):应用程序中处理数据显示的部分

        Model(模型):应用程序中处理应用程序数据逻辑的部分

        MVC是一种思想,而Spring MVC是MVC思想的具体实现,并继承了Servlet API的Web框架。也就是当用户在浏览器中输入了url后,我们Spring MVC项目就可以感知到用户的请求

        Spring MVC,在这里插入图片描述,第3张

        我们在创建项目时,需要引入相关依赖

        二、Spring MVC创建与连接

        我们的Spring MVC项目的创建和Spring Boot项目创建方式相同,只不过我们在创建的时候需要引入Spring Web依赖

        Spring MVC,在这里插入图片描述,第4张

        Spring MVC,在这里插入图片描述,第5张

        我们可以发现DispatcherServlet是实现了Servlet接口,于是Tomcat可以识别,我们也称之为核心控制器或者前端控制器

        请求(HttpServletRequest):获取请求数据

        响应(HttpServletResponse):设置响应数据

        BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端

        我们现在来实现一下,在浏览器输出hello SpringMVC

        @Controller //加载类
        @ResponseBody //返回文本信息
        public class UserController {
            
            @RequestMapping("/hello") //路由注册
            public String hello() {
                return "hello SpringMVC";
            }
        }
        

        Spring MVC,在这里插入图片描述,第6张

        @RequestMapping是Spring MVC重要的注解之一,它是用来注册路由映射的,也就是当用户访问某一个url时,会将用户的请求对应到程序中的某个类的某个方法中。

        @RequestMapping既可以修饰类,也可以修饰方法, 我们访问的地址是类 + 方法

        Spring MVC,在这里插入图片描述,第7张

        Spring MVC,在这里插入图片描述,第8张

        那么我们@RequestMapping到底是get请求还是post请求呢?

        我们打开postman测试一下

        Spring MVC,在这里插入图片描述,第9张

        Spring MVC,在这里插入图片描述,第10张

        我们可以发现各种方法都可以访问,但这并不是我们想要的结果,我们只提供一种方法访问,比如我们只想要get请求访问,我们有以下两种方案:

        方法1:设置method属性

        Spring MVC,在这里插入图片描述,第11张

        我们设置我们想要设置的method

        Spring MVC,在这里插入图片描述,第12张

        当我们再去使用post访问时,就会报错

        方法2:GetMapping

        Spring MVC,在这里插入图片描述,第13张

        Spring MVC,在这里插入图片描述,第14张

        Spring MVC,在这里插入图片描述,第15张

        任何方法都遵循以上两种方式,在举一个post方法的写法,其他方法大家可以自行练习。

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

        三、请求响应

        简单参数

        在我们原始的web程序中,我们获取请求参数,需要通过HttpServeletRequest对象手动获取,比如我们要获取一个name和age参数

            @RequestMapping("/simpleParam1")
            public String simpleParam1(HttpServletRequest request) {
                String name = request.getParameter("name");
                String age = request.getParameter("age");
                System.out.println(name +" :" + age);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第16张

        Spring MVC,在这里插入图片描述,第17张

        SpringBoot方式:

        简单参数:参数名与形参变量名相同,定义形参即可接受参数

            @RequestMapping("/simpleParam")
            public String simpleParam(String name,Integer age) {
                System.out.println(name + " :" + age);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第18张

        Spring MVC,在这里插入图片描述,第19张

        如果请求参数名不一致,又会出现什么情况呢?

        Spring MVC,在这里插入图片描述,第20张

        Spring MVC,在这里插入图片描述,第21张

        如果方法形参与请求参数名不匹配时,可以使用@RequestParam注解完成映射

        @RequestMapping("/simpleParam")
            public String simpleParam(@RequestParam(name = "username") String name,Integer age) {
                System.out.println(name + " :" + age);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第22张

        注意:@RequestParam中的required属性默认为true,表示请求中该参数必须传递,如果不传递将报错。如果该参数是可选的,我们需要将该required设置为false

        Spring MVC,在这里插入图片描述,第23张

        Spring MVC,在这里插入图片描述,第24张

        Spring MVC,在这里插入图片描述,第25张

        实体参数

        简单实体对象: 请求参数名与形参对象属性名相同,定义POJO接受即可

        我们前面简单参数可以直接接受即可,如果前端传递的是几十个参数,通过简单参数就比较繁琐,维护比较麻烦,我们就可以通过实体类接受

        定义实体类:

        @Slf4j
        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        public class User {
            private String name;
            private Integer age;
        }
        
        @RequestMapping("/simplePojo")
            public String simplePojo(User user) {
                System.out.println(user);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第26张

        Spring MVC,在这里插入图片描述,第27张

        Spring MVC,在这里插入图片描述,第28张

        复杂实体对象: 请求参数与形参对象属性名相同,按照对象层次结构关系即可接受嵌套的POJO属性参数

        Spring MVC,在这里插入图片描述,第29张

        我们前端在传递参数时,name和age还是正常封装,address是对象,需要一个属性一个属性封装

        Spring MVC,在这里插入图片描述,第30张

        Spring MVC,在这里插入图片描述,第31张

        数组集合参数

        数组集合参数一般使用于前端多选,比如checkbox复选框组件

        数组参数: 请求参数名与形参数组名称相同且请求参数为多个,定义数组参数形参即可接收参数

        Spring MVC,在这里插入图片描述,第32张

        @RequestMapping("arrayParam")
            public String arrayParam(String[] hobby) {
                System.out.println(Arrays.toString(hobby));
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第33张

        Spring MVC,在这里插入图片描述,第34张

        集合参数: 请求参数名与形参集合名称相同且请求参数为多个,@RequestParam绑定参数关系(因为默认参数是封装到数组中)

        @RequestMapping("/listParam")
            public String listParam(@RequestParam List hobby) {
                System.out.println(hobby);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第35张

        日期参数

        日期参数:使用@DateTimeFormat(因为前端传递的时期时间格式多种多样) 注解完成日期参数格式转换

        Spring MVC,在这里插入图片描述,第36张

        @RequestMapping("/dateParam")
            public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime) {
                System.out.println(updateTime);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第37张

        Spring MVC,在这里插入图片描述,第38张

        JSON参数

        JSON参数:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收对象,需要使用RequestBody标识

        Spring MVC,在这里插入图片描述,第39张

        @RequestMapping("/jsonParam")
            public String jsonParam(@RequestBody User user) {
                System.out.println(user);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第40张

        Spring MVC,在这里插入图片描述,第41张

        路径参数

        路径参数:通过请求URL直接传递参数,使用{…}来标识该路径参数,需要使用@PathVariable获取路径参数

        Spring MVC,在这里插入图片描述,第42张

        @RequestMapping("/path/{age}")
            public String pathParam(@PathVariable Integer age) {
                System.out.println(age);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第43张

        上述是我们演示了一个路径参数的传递,那么我们能否进行多个路径参数的传递呢?

        Spring MVC,在这里插入图片描述,第44张

        @RequestMapping("/path2/{age}/{name}")
            public String pathParam2(@PathVariable Integer age,@PathVariable String name) {
                System.out.println(name + " :" + age);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第45张

        简单进行总结一下:

        1. 简单参数: 定义方法形参,请求参数名与形参变量名一致,如果不一致使用@RequestParam手动映射
        2. 实体参数:请求参数名,与实体对象的属性名一致,会自动接收封装
        3. 数组集合参数:数组(请求参数名与数组名一致,直接封装),集合(请求参数名与集合名一致,@RequestParam绑定关系)
        4. 日期参数:@DateTimeFormat
        5. JSON参数:@RequestBody
        6. 路径参数:@PathVariable

        获取Cookie/Session/header

        存储和获取Cookie:

        传统方法

        @RequestMapping("/c1") //设置Cookie
            public String cookie1(HttpServletResponse response) {
                response.addCookie(new Cookie("zd","login"));
                return "OK";
            }
            @RequestMapping("/c2") //获取Cookie
            public String cookie2(HttpServletRequest request) {
                Cookie[] cookies = request.getCookies();
                for (Cookie cookie : cookies) {
                    if(cookie.getName().equals("zd")) {
                        System.out.println("zd" + cookie.getValue());
                    }
                }
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第46张

        使用传统方式获取cookie参数有点太过于繁琐,我们来学习一下简单获取方法。

        简洁获取Cookie 使用@CookieValue注解获取

        @RequestMapping("/c3")
            public String cookie3(@CookieValue(value = "zd",required = false) String zd) {
                System.out.println("zd :" + zd);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第47张

        获取header:

        //传统方式获取User-Agent请求头信息
        @RequestMapping("headerParam1")
            public String headerParam(HttpServletRequest request) {
                System.out.println(request.getHeader("User-Agent"));
                return "OK";
            }
        

        我们抓包看一下请求信息

        Spring MVC,在这里插入图片描述,第48张

        Spring MVC,在这里插入图片描述,第49张

        简洁获取Header方式 使用@RequestHeader

        //使用@RequestHeader获取User-Agent请求头信息
        @RequestMapping("/headerParam2")
            public String headParam2(@RequestHeader("User-Agent") String userAgent) {
                System.out.println(userAgent);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第50张

        存储和获取Session

        //存储Session
        @RequestMapping("/setSess")
            public String setSession(HttpServletRequest request) {
                HttpSession session = request.getSession(true);//如果没有则创建
                if(session != null) {
                    session.setAttribute("zd","login");
                }
                return "OK";
            }
        
        //传统方式获取Session
        @RequestMapping("/getSess")
            public String getSession(HttpServletRequest request) {
                HttpSession session = request.getSession(false);
                String state = "";
                if(session != null && session.getAttribute("zd") != null) {
                    state = (String) session.getAttribute("zd");
                }
                System.out.println("zd :" + state);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第51张

        简洁方式获取Session 使用@SessionAttribute

        //使用SessionAttribute注解获取Session
        @RequestMapping("getSess2")
            public String getSession2(@SessionAttribute(value = "zd",required = false) String state) {
                System.out.println("zd :" + state);
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第52张

        四、文件上传

        文件上传,指的是将本地图片、视频、音频等文件上传到服务器,供其他用户浏览或下载的过程。文件上传在项目中应用十分广泛,我们经常发微博,朋友圈都用到了文件上传功能

        头像:

        Spring MVC,在这里插入图片描述,第53张

        前端三要素:

        1.表单项type = “file”

        2.表单提交方式post

        3.表单的enctype属性 multipart/form-data

        这就是一个最简单的文件上传功能

        Spring MVC,在这里插入图片描述,第54张

        那么我服务器如何接受文件呢?

        Spring MVC,在这里插入图片描述,第55张

        那么服务器接收到的文件如何存储呢?一共有两种方案:

        1.本地存储

        2.OSS

        本地存储:在服务器端,接收到上传上来的文件后,将文件存储到本地服务器磁盘中

        @RequestMapping("/upload")
            public String upload(MultipartFile image) throws IOException {
                String originalFilename = image.getOriginalFilename(); //获取文件原始名
                //将文件存储到指定路径下
                image.transferTo(new File("D://image//" + originalFilename));
                return "OK";
            }
        

        我们使用postman上传一个文件

        Spring MVC,在这里插入图片描述,第56张

        Spring MVC,在这里插入图片描述,第57张

        选择一个文件进行上传

        Spring MVC,在这里插入图片描述,第58张

        当我们点击上传后发现报错了(单个文件大小超出异常)

        在SpringBoot中,文件上传,默认单个文件允许的最大大小为1M,单次请求最大大小为10MB,如果需要上传大文件,可以进行以下配置:

        # 配置单个文件最大上传大小
        spring.servlet.multipart.max-file-size=10MB
        # 配置单次请求最大上传大小(一次请求可以上传多个文件)
        spring.servlet.multipart.max-request-size=100MB
        

        Spring MVC,在这里插入图片描述,第59张

        Spring MVC,在这里插入图片描述,第60张

        当我们上传到本地后,既然服务器重启也会持久化存储的,但是我们根据原始文件名存储是否合理? 当我们上传相同的文件会将之前的文件覆盖,于是我们就需要构建唯一的文件名(不能重复)

        我们这里需要使用 UUID(通用唯一标识码)

        Spring MVC,在这里插入图片描述,第61张

        @RequestMapping("/upload")
            public String upload(MultipartFile image) throws IOException {
                //获取原始文件名
                String originalFilename = image.getOriginalFilename(); //获取文件原始名
                //构建新的文件名
                String newFilename = UUID.randomUUID().toString() + //设置文件名
                        originalFilename.substring(originalFilename.lastIndexOf('.'));//获取文件后缀
                //将文件保存在服务器端 D:\\image\\下
                image.transferTo(new File("D:\\image\\" + newFilename));
                return "OK";
            }
        

        Spring MVC,在这里插入图片描述,第62张

        本地存储有很多缺陷:

        Spring MVC,在这里插入图片描述,第63张

        阿里云OSS:阿里云对象存储OSS(Object Stroage Service),是一款海量、安全、低成本、高可能的云存储服务。使用OSS,可以通过网络随时存储和调用包括文本、图片、音频、视频等文件

        在这里我只介绍大致步骤就不一一演示了:

        1.注册阿里云(实名认证)

        2.充值

        3.开通对象存储服务(OSS)

        4.创建bucket

        5.获取AccessKey(密钥)

        6.参照官方SDK

        7.集成OSS

        五、返回数据

        我们在前面学习会发现,Spring或者SpringBoot默认返回的是视图(xxx.html),但现在基本都是前后端分离,后端只需要返回给前端数据即可,这个时候我们使用@ResponseBody注解即可。

        组合注解:@RestController = @Controller + @ResponseBody

        @ResponseBody返回的值如果是字符会转换为txt/html,如果返回的是对象会转换成application/json返回给前端。@ResponseBody不仅可以用来修饰类,也可以修饰方法。

        返回静态页面

        我们创建前端页面hello.html

        Spring MVC,在这里插入图片描述,第64张

        
        
        
            
            
            
            hello
        
        
            

        Hello SpringMVC

        创建控制器:

        Spring MVC,在这里插入图片描述,第65张

        我们首先需要注释掉@ResponseBody

        @RequestMapping("/helloHtml")
            public String helloHtml() {
                return "/hello.html";
            }
        

        Spring MVC,在这里插入图片描述,第66张

        我们在返回视图是需要加上/的,加了表示绝对路径,不加表示相对路径。在Spring MVC中,使用绝对路径可以避免路径解析错误,确保返回正确的视图

        请求转发与请求重定向

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

        1.forward:请求转发

        2.redirect:请求重定向

        路由转发与请求重定向有以下区别:

        1.定义不同:

        请求转发(forward):发生在服务器内部,服务器接收到客户端请求后,会先将请求转发给目标地址,再将目标地址返回的结果转发给客户端

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

        Spring MVC,在这里插入图片描述,第67张

        Spring MVC,在这里插入图片描述,第68张

        2.请求方不同:

        我们可以看出来:请求转发是服务器端的行为,服务器代替客户端发送请求,并将结果返回给客户端;而请求重定向是客户端的行为

        3.数据共享不同:

        因为请求转发是服务器端完成的,所以客户端只需要发送一次请求,在整个交互过程中使用的都是一个Request请求对象和一个Response响应对象,所以在整个请求过程中,请求和返回的数据是共享的;而请求重定向向客户端发送了两次完全不同的请求,两次请求中数据是不共享的

        4.URL地址不同

        请求转发是服务器代发,再返回客户端,所以整个请求URL是不变的

        Spring MVC,在这里插入图片描述,第69张

        请求重定向是服务器告诉客户端一个临时Location,然后客户端在发送一次请求,所以客户端最终显示的URL是最终跳转到地址,也就是地址发生了变化

        Spring MVC,在这里插入图片描述,第70张

        5.代码层面实现不同:

        //路由转发
        @RequestMapping("/hello2")
            public String hello2() {
                return "forward:/hello.html";
            }
        
        //请求重定向
        @RequestMapping("/hello1")
            public String hello1() {
                return "redirect:/hello.html";
            }