• Spring MVC(建立连接 + 请求)


    一、建立客户端和服务器的连接

    1. 如何建立:@RequestMapping
      • 通过 @RequestMapping 注解建立一个路由映射
      • 由于Spring Boot 内置了Tomcat,Tomcat会帮我们根据这个路由映射,去找到执行的文件
    2. @RequestMapping
      • 修饰对象:类和方法都可以修饰
      • 支持的方法:所以的请求方法都支持
        • 关于指定支持的方法:使用method属性
    @RestController
    @RequestMapping("/test")
    public class HelloController {
        @RequestMapping(value = "/sayhi",method = RequestMethod.GET)
        public String sayHi(){
            return "hello";
        }
    }
    
    1. 注解的属性:如果注解没有写属性名,默认属性名是value,而一旦有多个就需要区分哪个是哪个了

    2. 地址相关问题

      • 访问地址:类的路径/方法路径
      • 路径的写法
        • 层级:可以写多层,如@RequestMapping(“/hello/m1”)
        • 类路径:企业开发商建议写上类路径,因为这既可以减少名字的重复率,降低取名的难度,还可以方便我们查找代码
        • 关于/:理论上可以省略,但实际在企业开发上,建议加上,且是前加后不加 -------> 【/hello/m1】
        • 路径名VS方法名:两者没有什么关系,可以不一样,但是我们通常会取名一样,因为这样可以减少取名频率,且方便我们查找代码

    二、如何构造请求(传参)

    2.1 构造请求方式 + 参数通用注解

    1. 请求构造方式

      • 两种方法:请求的构造主要由前端或工具两种方式构造
      • 为什么我们使用Postman:但由于前后端分离,后端开发人员只需要提供一个接受参数的服务即可,至于怎么传参是前端的事,所以我们一般不用前者,而且为了测试个后端代码,还要写个前端很不值当。所以,我们此处所讲的都是通过postman来构造请求。
    2. 如何构造post请求)

      • 依靠前端:依靠前端的form表单/ajax
      • 依靠工具:使用Postman工具构造
    3. 如何传递JSON对象

      • 依靠前端:依靠前端的ajax传递
      • 依靠工具:使用Postman工具构造
    4. Postman使用的简单介绍:与HTTP格式一一对应

      • 为什么优先使用POST:Postman如果使用GET请求,Spring会默认从查询字符串里拿数据,这是Postman的默认设置,此时如果要传的数据是JSON之类的,就会出bug。所以,我们优先使用POST方法
      • 接口的改名

    在这里插入图片描述

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

    1. 后端参数重命名:@RequestParam注解,注解里面的参数是“前端传的”,后面的则是“后端想用的”
      • 底层逻辑:服务器获取到name对应的值后,将其赋值给username
      • 注意点:使用这个注解后,重命名的参数就变成必传参数了。如果想修改为“非必传”,只需要把required这个属性设置为false即可。
        在这里插入图片描述
    @RestController
    @RequestMapping("/param")
    public class ParamController {
        @RequestMapping("/m4")
        public String m4(@RequestParam("name") String username){
            return username;
        }
    }
    

    2.2 传递单个参数

    1. 底层逻辑
      • 从请求的参数中,获取参数名为name的值,并给name赋值。
      • 相当于封装了Servlet的getPartmer方法,所以后端参数名要求和传的参数名一致。
    @RestController
    @RequestMapping("/param")
    public class ParamController {
        @RequestMapping("/m1")
        public String m1(String name){
            return name;
        }
    }
    

    在这里插入图片描述

    2.3 传递多个参数

    1. 如果设置的值未传怎么办:值为nul
      • 为何推荐使用包装类:因为如果未传值,该参数就会被赋值为null,如果此时数据类型为基本数据类型就会报错。所以企业开发中,我们建立使用包装类。
    2. 参数顺序:传递原理参考【传递单个参数】,所以参数传递顺序是无所谓的
    @RestController
    @RequestMapping("/param")
    public class ParamController {
        @RequestMapping("/m2")
        public String m2(String name, Integer age){
            return "name:" + name + ", age:" + age;
        }
    }
    

    在这里插入图片描述

    2.4 传递数组/集合

    1. 原理:当发送的请求中,同一个参数有多个时,浏览器会默认帮我们给封装成一个数组
    2. 传递数组
      • 两种请求路径
        • 参数间使用&:127.0.0.1:8080/param/m1?name=李四&name=张三&name=王五
        • 参数间使用,:127.0.0.1:8080/param/m1?name=李四,张三,王五
      • 后端代码
    @RestController
    @RequestMapping("/param")
    public class ParamController {
    
        @RequestMapping("/m1")
        public String m1(String[] name){
            //使用lambda表达式进行循环
            Arrays.stream(name).forEach(s -> {
                System.out.print(s + " ");
            });
            return "已经正常接受数组";
        }
    }
    
    1. 传递集合:使用 @RequestParam
      • 为什么要使用注解:因为如果收到多个同参数名的参数,Spring会默认帮我们封装为数组,此时我们是无法用调用集合的方法的。所以我们需要用@RequestParam注解告诉Spring这个参数是个集合。
      • 请求路径:和【传递数组】的传递方法一样
      • 后端代码
    @RestController
    @RequestMapping("/param")
    public class ParamController {
    
        @RequestMapping("/m2")
        public String m2(@RequestParam List<String> name){
            return "接收到的list对象有:" + name.toString();
        }
    }
    

    2.5 传递对象

    1. 原理
      • 前三种方法的弊端
        • 一旦我们需要更改参数,就需要去修改接口定义,并且通知所以调用这个方法的地方,全部改请求参数,这十分繁琐。
        • 一旦前端未传一个后端业务运行所必须的参数,程序就会报错,容错率低
      • 为什么使用对象
        • 如果要修改参数,我们直接在对象内部添加即可
        • 遇到前端未传后端必须的数据时,后端代码里加点逻辑即可
    2. 后端代码
    @RestController
    @RequestMapping("/param")
    public class ParamController {
        @RequestMapping("/m3")
        public String m3(Person person){
            return person.toString();
        }
    }
    
    public class Person {
        private String name;
        private String age;
    }
    
    1. 请求发送:共有两种方法
      • query string:query string里直接把值放进去,Spring 会帮我们进行关系的映射。如【127.0.0.1:8080/param/m3?name=lisi&age=15】
      • JSON:解决了第一种方法query string内容太多的问题

    2.6 传递JSON

    1. 什么是JSON
      • 一种轻量级的数据交互格式
      • 本质是一个字符串,可以和Java对象互相转换
        • 如何互转:使用ObjectMapper类的方法
    2. JSON的泛用性:因为只是数据交互格式,故而实际上面所有的传参都可以通过JSON来传
    3. JSON的格式介绍
      • 键值对
        • 存储地点:数据保存在键值对(Key/Value)中
        • 数据类型:key全部都是字符串,所以要用引号引起来,value则可以是各种类型
        • 分隔问题:键和值使用冒号分隔,数据之间则用逗号分隔
      • 对象和数组表示方法:对象用{}表示,数组用[]表示
    4. 如何传递JSON数据:使用 @RequestBody 注解
      • 为什么要使用该注解
        • 默认情况下,Spring MVC 会将请求参数绑定到方法的参数上,但请求体中的数据并不包含在标准的请求参数中(原本是key-value,传过来直接变成了一整个数据)
        • @RequestBody注解可以让Spring自动把Body里的数据转成对象
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/m1")
        public String m1(@RequestBody Person person){
            return "收到的对象是:" + person.toString();
        }
    }
    

    在这里插入图片描述

    三、相关的其他请求操作

    3.1 获取URL中的参数 @PathVariable

    1. 获取一个URL
      在这里插入图片描述
    2. 可以获取多个URL,但要注意顺序:因为对于URL来说,他并不知道这些值有什么作用,它只会按照顺序放,不会一一对应
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/m2/{userId}/{userName}")
        public String m2(@PathVariable Integer userId, @PathVariable String userName){
            return "接受到的userId为:" + userId + ", userName为:" + userName;
        }
    }
    
    1. 请求格式必须要和后端定义的URL格式,不一致会报错
    2. 关于改名
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/m2/{id}/{userName}")
        public String m2(@PathVariable("id") Integer userId, @PathVariable String userName){
            return "接受到的id为:" + userId + ", userName为:" + userName;
        }
    }
    

    3.2 上传文件 @RequestPart

    1. 如何上传:使用MultipartFile类接收文件 + @RequestPart 注解 + form-data式发送
      • 关于 MultipartFile类:可以接收各种文件,此处我们不用File类
      • 关于 form-data:以表单的形式传输二进制数据,而文件底层就是一大串二进制数据
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/m3")
        public String m3(@RequestPart MultipartFile file) throws IOException {
        	//打印传过来的文件名,此处是【普洱.jpg】
            System.out.println(file.getOriginalFilename());
            //将传过来的文件保存在当前机器上,路径为【D:/apply/+file.getOriginalFilename()】
            file.transferTo(new File("D:/apply/" + file.getOriginalFilename()));
            return "success";
        }
    }
    

    在这里插入图片描述

    3.3 获取和设置 Cookie/Session

    Cookie和Session相关概念

    结合这个理解

    1. 为什么会有Cookie和Session
      • (1)HTTP是无状态的,即没有记忆功能,现在请求和过一会请求,同样的请求参数只会执行同样的处理逻辑。
      • (2)这就意味着,哪怕访问的是一个频繁访问的路径,我们也需要反复登录
      • (3)但有时候,我们需要让我们的服务有记忆功能,Cookie和Session就可以满足这个需求
    2. Cookie可以伪造,Session不行
    3. Cookie 和 Session 都是会话机制
      • 什么是会话机制:会话即对话
        在这里插入图片描述

    获取 + 设置 Cookie

    这是获取

    1. 使用Servlet原生的API获取可以获取到所有的Cookie
      • 为何能使用:因为Spring 是基于Servlet封装的,所以Servlet能用的,他都能用
      • HttpServletRequest和HttpServletResponse:都是Spring的内置对象,可以两个都加上,也可以只放一个,根据需求来
      • 为何要伪造Cookie:如果此时没有Cookie,cookies就会为null,后面更是会空指针异常。所以在没有Cookie的情况下,我们如果要测试该代码,需要伪造Cookie。
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/getCookie")
        public String getCookie(HttpServletRequest request, HttpServletResponse response){
            Cookie[] cookies = request.getCookies();
    
            //使用lambda表达式进行循环
            Arrays.stream(cookies).forEach(cookie -> {
                System.out.println(cookie.getName() + ":" + cookie.getValue());
            });
    
            return "success";
        }
    }
    
    1. 使用@CookieValue注解获取只能获取到指定的Cookie
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/getCookie")
        public String getCookie(@CookieValue String name, @CookieValue Integer age){ 
        	//可以放置多个参数 
            return "Cookie存储的name为" + name;
        }
    }
    

    这是伪造Cookie

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

    获取 + 设置Session

    获取

    1. 使用内置对象 HttpServletRequest
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/getSession")
        public String getSession(HttpServletRequest request){
            HttpSession session = request.getSession(false);  //默认值为true
            if (session != null){
                String username = (String)session.getAttribute("username");
                return "登录用户:" + username;
            }
    
            return "session 为空";
        }
    }
    
    1. 使用内置对象 HttpSession
      • 对 HttpSession session 的理解:相当于第一种方法的【request.getSession(true)】
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/getSession")
        public String getSession(HttpSession session){
            String username = (String)session.getAttribute("username");
            return "username为:" + username;
        }
    }
    
    1. 使用 @SessionAttribute 注解
      • 注意该参数变成了必传的:该注解的内部定义
        在这里插入图片描述
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/getSession")
        public String getSession(@SessionAttribute String username){
            return "session中存储的username为:" + username;
        }
    }
    

    设置

    1. 通过Servlet方法设置:因为Session是服务端的,我们没有办法进行伪造,所以只能通过后端代码创建
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/setSession")
        public String setSession(HttpServletRequest request){
            HttpSession session = request.getSession();
            session.setAttribute("username", "zhangsan");
            return "success";
        }
    }
    

    在这里插入图片描述

    3.4 获取Header

    1. 使用内置对象HttpServletRequest
    @RequestMapping("/param")
    @RestController
    public class ParamController {
        @RequestMapping("/getHeader")
        public String getHeader(HttpServletRequest request){
            //获取Header中某个key的值
            String userAgent = request.getHeader("User-Agent");
            return "userAgent:" + userAgent;
        }
    }
    
    1. 使用@RequestHeader注解
      在这里插入图片描述
  • 相关阅读:
    案例图解:某投资集团企业主数据项目实践分享
    appium2.0+ 单点触控和多点触控新的解决方案
    Vue页面内容未保存时离开页面做弹框提示
    【多目标进化优化】 Pareto 最优解集的构造方法
    nvidia-docker安装指南
    leetcode 36. 有效的数独(模拟题)
    使用FFmpeg合并多个ts视频文件转为mp4格式
    【笔记版】cgroup大摸底
    物联网各类数据如何轻松获取?秘诀就在定制文件推送服务
    千兆光模块和万兆光模块需要注意哪些事项
  • 原文地址:https://blog.csdn.net/wuweixiaoyue/article/details/138672840