Spring Web MVC入门(2)——请求

news2025/1/16 20:16:32

目录

一、传递单个参数

基础类型和包装类型的区别

1、基础类型

(1)不传参

(2)传字符串

2、包装类型

(1)不传参

(2)传字符串

3、小结

二、传递多个参数

三、传递对象

四、后端参数重命名(后端参数映射)

五、传递数组

六、传递集合

不加注解@RequestParam

加注解@RequestParam

七、传递JSON数据

1、JSON概念

JSON于JavaScript的关系:

2、JSON语法

(1)JSON的语法:

(2)JSON的两种结构:

3、JSON字符串和Java对象互转

4、JSON优点

5、传递JSON对象

八、获取URL中参数@PathVariable

九、上传文件@RequestPart

十、获取Cookie / Session

1、回顾Cookie

2、理解Session

3、Cookie 和 Session 的区别(面试常考)

4、获取Cookie

(1)传统获取Cookie

(2)简洁获取Cookie

5、获取Session

(1)Session 存储

(2)传统获取Session

(3)简洁获取 Session(1)

(4)简洁获取 Session(2)

下面讨论一下Spring从传统获取Session到简洁获取Session:

十一、获取Header

1、传统获取Header

2、简洁获取Header


        访问不同的路径,就是发送不同的请求在发送请求时,可能会带一些参数,所以学习Spring的请求,主要是学习如何传递参数到后端,以及后端如何接收

        传递参数,这里主要使用Postman来模拟,浏览器也可以,但是Postman会更方便。

后端开发人员无需过度关注如何传递参数,了解即可,实际开发中以Postman测试为主。比如餐厅里的厨师,不需要关注用户是在店里下单还是外卖平台下单,只需要知道如何接收订单,根据订单做出对应的菜肴即可。

一、传递单个参数

        接收单个参数,在Spring MVC中直接使用方法中的参数就可以了,比如以下代码:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/Demo1")
public class Demo1 {
    @RequestMapping("/test")
    public String test(String name) {
        return "接收到的参数name:" + name;
    }
}

        Postman观察返回的请求:

        查询字符串名称必须和方法里的参数名称一样,如图:

        现在把name改成name1,结果如下:

        因为URL已经指定要访问test方法了,但是方法没有name1这个参数,就只能返回一个null了。

基础类型和包装类型的区别

1、基础类型

        基础类型现在正常传参,代码如下:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/Demo1")
public class Demo1 {
    @RequestMapping("/test")
    public String test(int age) {
        return "接收到的参数age:" + age;
    }
}

        Postman:

        

        是没有任何问题的。下面看看如果不传参,会怎么样

(1)不传参

        Postman:

        错误码是500,说明是服务器这边出问题了,观察程序日志:

        上面说int类型的参数age,虽然为可选的,但由于被声明为基本类型,而不能转换为空值,考虑将其声明为对应基本类型的包装类型。按照错误信息解决错误即可初学者也应该养成看错误日志的习惯

(2)传字符串

        传字符串,Postman:

        错误码是400,说明是客户端这边出问题了,error提示:Bad Request,说明请求有问题,再看服务器这边,也出现了警告日志:

        如果实在看不懂,可以去有道云进行翻译,如图:

        说明基本类型int不能转换为字符串

2、包装类型

        代码如下:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/Demo1")
public class Demo1 {
    @RequestMapping("/test")
    public String test(Integer age) {
        return "接收到的参数age:" + age;
    }
}

        正常传参,观察结果:

        没有问题。

(1)不传参

        当不传参时,Postman结果如下:

        和基本类型不同,并没有报错,而是显示出null。

        对于包装类型,如果不传对应参数,Spring接收到的数据则为null,所以企业开发中,对于参数可能为空的数据,建议使用包装类型

(2)传字符串

        传字符串,Postman结果:

        报错和基本类型一样,日志如下:

3、小结

        对于方法里参数可能为null的数据,建议使用包装类型而对于传递对象时(后面会讲到),对象(类)里面可以不使用包装类型如果无法进行区分,那就都使用包装类型好了


二、传递多个参数

        和接收单个参数一样,无非就是多加几个参数而已,代码如下:

    @RequestMapping("/test2")
    public String test2(String name, Integer age) {
        return "接收到的参数name:" + name + "  接收到的参数age:" + age;
    }
}

        Postman观察结果如下:

        这里传参的时候,填入query string 的参数位置顺序可以任意的,结果不受这个顺序影响

        但是如果要传很多个,3个,4个,5个.....,这样进行传参代码就会显得很丑,所以,就可以引入对象,下面的内容介绍传对象。


三、传递对象

        现在有Student类,代码如下:

public class Student {
    private String name;
    private int age;
    private int id;

    public String getName() {return name;}
    public int getAge() {return age;}
    public int getId() {return id;}
    public void setName(String name) {this.name = name;}
    public void setAge(int age) {this.age = age;}
    public void setId(int id) {this.id = id;}

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", id=" + id +
                '}';
    }
}

        传递对象的代码:

    @RequestMapping("test3")
    public Object test3(Student student) {
        return student.toString();
    }

        Postman发送请求,结果如下:

        如果不传参数呢?这里不会吧报错?试一下就知道了,如图:

        

        可以看到,并不会报错原因就是在对象(类)中,成员属性会自动初始化使用基础类型,也会进行初始化,如果没有传递这个参数,不会报错但如果直接在接口方法中声明,使用int类型,没传参就会报错,就像上面介绍基础类型报错的例子。


四、后端参数重命名(后端参数映射)

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

        代码如下:

@RequestMapping("d1")
@RestController
public class Demo1 {
    @RequestMapping("r1")
    public String method_1(@RequestParam(value = "time") String newTime) {
        return "接收到的参数newTime:" + newTime;
    }
}

        postman页面如下:

        

        可以看到,Spring可以正确的把浏览器传递的参数time绑定到后端参数newTime上。

        我们试试传参的参数改成newTime,看看有没有问题,postman页面如下:

        

        错误码400,说明客户端这边的请求有问题,看看报错日志:

        请求参数“time”不存在,说明访问这个方法,必须要有参数,而我们传的newtTime参数,在这里没有,所以就报错了,我们也可以设置参数不是必须的,代码如下:

@RequestMapping("d1")
@RestController
public class Demo1 {
    @RequestMapping("r1")
    public String method_1(@RequestParam(value = "time",required = false) String newTime) {
        return "接收到的参数newTime:" + newTime;
    }
}

        这样如果我们没有传参,也不会报错了,如图:

        

        或者传其他参数名,也不会报错

        

 在这里可以得出结论:

1、注解:@RequestParam 进行参数重命名时,请求参数只有和@RequestParam声明的名称一致,才能进行参数绑定和赋值。

2、注解:@RequestParam 默认访问此方法是必须要带参数的,也可以设置不再参数。


五、传递数组

        传递数组时,Spring MVC可以自动绑定数组参数的赋值,代码如下:

    @RequestMapping("r2")
    public String method2(String[] str) {
        return Arrays.toString(str);
    }

        postman页面如下:

        

        浏览器可以使用以下URL:

http://127.0.0.1:8080/d1/r2?str=zhangsan&str=lisi&str=wangwu
http://127.0.0.1:8080/d1/r2?str=zhangsan%2clisi%2cwangwu
http://127.0.0.1:8080/d1/r2?str=zhangsan,lisi,wangwu


六、传递集合

        集合参数,和数组类似,同一个请求参数名有多个,且需要使用@RequestParam注解绑定参数关系。

        默认情况下,请求中参数名相同的多个值,是封装到数组。如果要封装到集合,要使用@RequestParam绑定参数关系。

不加注解@RequestParam

        不加注解@RequestParam的代码:

    @RequestMapping("r3")
    public String method3(List<String> list) {
        return "size:" + list.size() + ",list:" + list;
    }

        postman页面:

        

        可以看到,服务器这边报错了,看看日志:

        说明传参的时候,出问题了,因为没有加注解@RequestParam,所以默认传的参数是数组,但接收的确实集合List,所以服务器这边代码就会报错。

加注解@RequestParam

        加注解@RequestParam的代码:

    @RequestMapping("r3")
    public String method3(@RequestParam List<String> list) {
        return "size:" + list.size() + ",list:" + list;
    }

        postman页面:

        

        可以看到,这时候就没出错了,因为加了注解@RequestParam后,客户端这边传的参数就不是数组了,而是List。


七、传递JSON数据

1、JSON概念

        JSON:JavaScript Object Notation【JavaScript 对象表示法】。

        JSON是一种轻量级的数据交互格式。它基于ECMAScript(欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式,来存储和表示数据。——百度百科

        简单来说:JSON就是一种数据格式,有自己的格式和语法,使用文本表示一个对象或数组的信息,因此JSON本质是字符串。主要负责在不同的语言中进行数据传递和交换。

        类似于:国际通用语言:英语。或者是中国56个民族不同地区的通用语言:普通话。有自己的语法,但其他语言也认识。

JSON于JavaScript的关系:

        没有关系,只是语法相似,js开发者能更快的上手而已,但是他的语法本身比较简单,所以也很好学。

2、JSON语法

        JSON是一个字符串,它的格式非常类似JavaScript对象字棉量的格式,如下是一段JSON数据:

{
    "squadName": "Super hero squad",
    "homeTown": "Metro City",
    "formed": 2016,
    "secretBase": "Super tower",
    "active": true,
    "members": [
        {
            "name": "Molecule Man",
            "age": 29,
            "secretIdentity": "Dan Jukes",
            "powers": [
                "Radiation resistance",
                "Turning tiny",
                "Radiationblast"
            ]
        },
        {
            "name": "Madame Uppercut",
            "age": 39,
            "secretIdentity": "Jane Wilson",
            "powers": [
                "Million tonne punch",
                "Damage resistance",
                "Superhumanreflexes"
            ]
        },
        {
            "name": "Eternal Flame",
            "age": 1000000,
            "secretIdentity": "Unknown",
            "powers": [
                "Immortality",
                "Heat Immunity",
                "Inferno",
                "Teleportation",
                "Interdimensional travel"
            ]
        }
    ]
}

        也可以进行压缩:

{"squadName":"Super hero squad","homeTown":"Metro City","formed":2016,"secretBase":"Super tower","active":true,"members":[{"name":"Molecule Man","age":29,"secretIdentity":"Dan Jukes","powers":["Radiation resistance","Turning tiny","Radiationblast"]},{"name":"Madame Uppercut","age":39,"secretIdentity":"Jane Wilson","powers":["Million tonne punch","Damage resistance","Superhumanreflexes"]},{"name":"Eternal Flame","age":1000000,"secretIdentity":"Unknown","powers":["Immortality","Heat Immunity","Inferno","Teleportation","Interdimensional travel"]}]}

        压缩后和没压缩之前的数据是一样的,只不过没压缩的进行了格式化,更易读。

(1)JSON的语法:

1、数据在 键值对(Key / Value)中。

2、数据由逗号 " , " 分割。

3、对象用 " { } " 表示。

4、数组用 " [ ] " 表示。

5、值可以为对象,也可以为数组,数组中可以包含多个对象。

(2)JSON的两种结构:

1、对象:大括号 " { } " 保存的对象是一个无序的 键值对 集合。一个对象以左括号 " { " 开始,右括号 " } " 结束。每个 "键" 后跟一个冒号 " : ",键值对使用逗号 " , " 分隔。

2、数组:中括号 " [ ] " 保存的数组是值(Value)的有序集合。一个数组以左中括号 " [ " 开始,右中括号 " ] ",值之间使用逗号 " , " 分隔。

所以,以下都是合法的JSON数据:

{"name":"admin","age":18}
["hello", 3.1415, "json"]
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三","age":20}]

        可以使用在线JSON格式化工具来进行校验和书写:在线JSON校验格式化工具(Be JSON)

3、JSON字符串和Java对象互转

        JSON本质上是一个字符串,通过文本来存储和描述数据。

        Spring MVC框架也集成了JSON的转换工具,我们可以直接使用,来完成JSON字符串和Java对象的互转。

        本质上是 Jackson-databind 提供的功能,Spring MVC框架中已经把该工具包引入了进来,咱们直接使用即可,如果脱离SPring MVC使用,需要引入相关依赖:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.5</version>
</dependency>

        Person类如下:

public class Person {
    private int id;
    private String name;
    private String password;
    public Person(){ };
    public Person(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    };
    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
    public int getId() {return id;}
    public String getName() {return name;}
    public String getPassword() {return password;}
    public void setId(int id) {this.id = id;}
    public void setName(String name) {this.name = name;}
    public void setPassword(String password) {this.password = password;}
}

        互转的代码如下:

public class JSONUtils {
    private static ObjectMapper objectMapper = new ObjectMapper();

    public static void main(String[] args) throws JsonProcessingException {
        Person person = new Person(10, "zhangsan", "123456");
        //对象转为JSON字符串
        String jsonStr = objectMapper.writeValueAsString(person);
        System.out.println("JSON字符串为:" + jsonStr);
        //JSON字符串转为对象
        Person p = objectMapper.readValue(jsonStr, Person.class);
        System.out.println("转换的对象为:" + person.toString());
    }
}

        运行结果如下:

4、JSON优点

1、简单易用:语法简单,易于理解和编写,可以快速地进行数据转换。

2、跨平台支持:JSON可以被多种编程语言解析和生成,可以在不同的平台和语言之间进行数据交换和传输。

3、轻量级:相较于XML格式,JSON数据格式更加轻量级,传输数据时占用的带宽较小,可以提高传输速度。

4、易于扩展:JSON的数据结构灵活,支持嵌套对象和数组等复杂的数据结构,便于扩展和使用。

5、安全性:JSON数据格式是一种纯文本格式,不包含可执行代码,不会执行恶意代码,因此具有较高的安全性。

        基于以上特点,JSON在Web应用程序中被广泛使用,如前后端数据交互、API接口数据传输等。

5、传递JSON对象

        接收JSON对象,需要使用@RequestBody注解。

RequestBody:请求正文,意思是这个注解作用在请求正文的数据绑定,请求参数必须写在请求正文中。

        后端代码如下:

@RestController
@RequestMapping("/d1")
public class Demo {
    @RequestMapping("/m1")
    public Object method1(@RequestBody Person person) {
        return person.toString();
    }
}

        使用postman发送json请求参数:

        可以看到,后端正确接收到了,下面通过fiddler观察一下请求参数:

        

        可以看到,请求类型是json。那如果后端代码去掉注解@RequestBody呢?代码如下:

@RestController
@RequestMapping("/d1")
public class Demo {
    @RequestMapping("/m1")
    public Object method1( Person person) {
        return person.toString();
    }
}

        继续使用Postman传递json,看看响应结果:

        可以看到,并没有给person赋值成功。


八、获取URL中参数@PathVariable

        path variable路径变量

        和字面表达的意思一样,这个注解主要作用在请求URL路径上的数据绑定(默认传递参数写在URL上,Spring MVC就可以获取到)

        后端代码:

    @RequestMapping("/m2/{id}/{name}")
    public String method2(@PathVariable Integer id, @PathVariable("name") String userName) {
        return "解析参数id:" + id + ",name:" + userName;
    }

        使用浏览器,访问:http://127.0.0.1:8080/d1/m2/5/zhangsan  ,页面如下:

        

        使用Postman页面如下:

        

        可以看到,后端接收到了URL的参数,下图是参数对应关系:

如果方法参数名称和需要绑定的URL的变量名称一致时,可以简写,不用给@PathVariable的属性赋值,例如上述例子中的id变量。

如果方法参数名称和需要绑定的URL的变量名称不一致时,需要给@PathVariable的属性赋值,如上述例子中的userName变量。


九、上传文件@RequestPart

        使用注解RequestPart

        后端代码实现:

    @RequestMapping("m3")
    public String getFile(@RequestPart("file") MultipartFile file) throws IOException {
        //获取文件名称
        String fileName = file.getOriginalFilename();
        //文件上传到指定路径
        file.transferTo(new File("D:/desktop/file/javaEE/temp" + file.getOriginalFilename()));
        return "接收到的文件名称为: " + fileName;
    }

        Postman页面如下:

        查看电脑 D:/desktop/file/javaEE/temp/ 路径下是否有cat.jpg文件:


十、获取Cookie / Session

        HTTP协议自身是属于 “无状态” 协议“无状态” :默认情况下,HTTP协议的客户端和服务器的这次通信,和下次通信之间没有直接的联系(也可以理解成 “无记忆”)

        在计算机领域,我们认为 “无状态” 是好的,相反,“有状态” 就不好

        但是实际开发中,很多时候是需要知道请求之间有关联的关系,例如我登录第三方网站,第一次登录成功后,后续的访问就不用继续输入账户密码,可以直接登录成功,所以这时候服务器就需要知道我之前是登录过了的。

1、回顾Cookie

        下面简单介绍一下Cookie,详细介绍可以看我之前写的博客:网络原理 - HTTP / HTTPS(2)

        Cookie本质是浏览器这边,本地化永久存储数据的机制,是一个身份标识,相当于令牌

        客户端和服务器之间的登录请求交互,大概流程图如下:

        

        Cookie就像就诊卡去医院看病,第一次去陌生的医院看病,进行挂号,一般都是要买个就诊卡的,医生给你看病时,第一句也不是问你病情,而是像你要就诊卡,这个就诊卡就记录着你之前的病史、开过的药、生病的日期,都会记录着,如果是第一次去这个医院,当然也就没有之前的病史了,但你这次的就诊也会记录在这上面。大概流程图如下:

        

        Cookie就简单介绍到这。

        客户端这边有了Cookie这个 “令牌”,那服务器这边也就需要记录 这个 “令牌” 的信息;因为一个网站,会有很多客户,大型网站无时无刻都有很多请求访问过来,那么就会带有非常多的Cookie,这也就意味着,服务器这边也要对 这些 “令牌” 进行管理,这些工作也就是下面要介绍的 Session 来负责了。

2、理解Session

        了解Session之前,我们先谈谈会话(会话:对话的意思),现实中的会话如下图:

        

        在计算机领域中,会话是一个客户端与服务器的不中断的请求响应。对于服务器来说,客户端发来的请求,服务器能识别出请求来自同一个客户端当一个未知的客户端向Web应用程序发送第一个请求,此时就开始了一个会话。当客户明确结束会话或者服务器在一个时限(时间阈值,Session默认的超时时间是30min,但这也是可以进行设置)没有接收到客户端发来的任何请求,此时会话就结束了

有点像打电话咨询客服,每次打一个电话,就会有客服和我们进行沟通,此时会话就建立了,当我们挂断电话,此时会话就会结束,或者较长时间没有回客服,没有新的请求,此时会话也会结束。

        服务器同一时刻会收到很多请求,服务器也需要清楚的区分每个请求是从属于哪个用户,也就是会有不同的会话要进行区分这些会话,就需要在服务器这边记录每个会话以及与用户信息的对应关系,服务器为了保存用户信息创建了一个特殊的对象:Session。大概流程图如下:

        Session的本质就是一个 “哈希表”,存储了一些键值对结构。Key就是SessionID,Value就是用户信息(用户信息可以根据需求灵活设计)。结构大概如下图:

        SessionId 是由服务器生成的一个 “唯一性字符串”,从Session机制的角度来看,这个唯一性字符串称为 “SessionId”。但是站在整个登录流程中看待,也可以把这个唯一性字符串称为:“token”。

        上述例子中的令牌ID,就可以看做是SessionId,只不过令牌除了 ID 之外,还会带一些其他信息,比如时间、签名等。

    举个账户余额的例子,如图:

        Cookie和Session搭配一起使用,大概流程如下:

1、当用户登录的时候,服务器在Session会新增一个新记录,并把SessionID,返回给客户端(通过HTTP响应中是Set-Cookie字段返回)

2、客户端后续再给服务器发送请求的时候,需要在请求中带上SessionId(通过HTTP请求中的Cookie字段带上)

3、服务器接收到请求后,根据请求中的SessionId,找到对应的Session中,获取到对应的用户信息,再进行后续的操作。如果找不到,就重新创建Session,再把SessionId返回给客户端

注意Session默认是保存在内存中的,如果重启服务器,Session数据就像消失

3、Cookie 和 Session 的区别(面试常考)

(1)Cookie是客户端保存用户信息的一种机制,Session是服务器保存用户信息的一种机制

(2)Cookie和Session之间是通过SessionId关联起来的(并没有什么直接关系),SessionId是Cookie和Session之间的桥梁

(3)Cookie和Session经常会搭配在一起使用,但不是必须搭配的

        a、完全可以用Cookie保存一些数据在客户端;这些数据并不一定是用户身份信息(SessionId)

        b、Session的SessionId也不是非得通过Cookie / Set-Cookie传递,也有其他方式,比如通过URL传递

4、获取Cookie

(1)传统获取Cookie

        代码如下:

@RestController
@RequestMapping("/d1")
public class Demo1 {
    @RequestMapping("/getC1")
    public String getCookie(HttpServletRequest request, HttpServletResponse response) {
        //获取参数
        //String name = request.getParameter("name");
        //获取所有参数
        Cookie[] cookies = request.getCookies();

        //1、不使用lambda表达式
        StringBuilder stringBuilder = new StringBuilder();
        if(cookies != null) {
            for(Cookie ck : cookies) {
                stringBuilder.append(ck.getName() + ":" + ck.getValue());
            }
        }
        //return "获取Cookie信息:" + stringBuilder;
        
        //2、使用lambda表达式
        if(cookies != null) {
            Arrays.stream(cookies).forEach(ck -> System.out.println(ck.getName() + ":" + ck.getValue()));
        }
        return "获取Cookie";
    }
}

        使用浏览器访问:http:127.0.0.1:8080/d1/getC1,页面如下:

        

        因为没有设置Cookie,现在Cookie是null,控制台也不会打印Cookie,如图:

        现在在浏览器手动设置一些Cookie,如图:

         这个称为:host domain

        也可以使用Postman设置Cookie,如图:

        刷新一下页面,再看看控制台,打印了hahaha:666,说明后端接收到了浏览器发来的Cookie,如图:

        从这个例子也能看出来,Cookie是可以伪造的,也就是不安全的,所以使用Cookie时,后端也需要进行Cookie的校验。

1、Spring MVC是基于Servlet API构建的原始Web框架,也是在Servlet的基础上实现的,HttpServletRequest、HttpServletResponse 是Servlet提供的两个类,是Spring MVC方法的内置对象。需要时直接在方法中添加声明即可(例如注解@CookieValue,下面会介绍)

2、HttpServletRequest 对象代表客户端的请求。当客户端通过HTTP协议访问服务器时,HTTP请求头的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获取到客户端请求的所有信息

3、HttpServletResponse 对象代表服务器的响应。HTTP响应的信息都在这个对象中,比如向客户端发送的数据、响应头、状态码等等。通过这个对象提供的方法,可以获得服务器响应的所有内容

        Spring MVC在这两个对象的基础上进行了封装,给我们提供了更简单的使用方法(使用注解)。下面介绍简洁获取Cookie的使用方法。

(2)简洁获取Cookie

        后端代码如下:

    @RequestMapping("/getC2")
    public String getCookie2(@CookieValue("name") String newName) {
        return "从Cookie中获取值,name:" + newName;
    }

        Cookie如下:

        浏览器访问:http:127.0.0.1:8080/d1/getC2 ,页面如下:

        

5、获取Session

(1)Session 存储

        因为Session是服务器这边存储的信息,所以要获取到到Session前要先有它。

        Session也是基于HttpServletRequest来存储和获取的,下面是存储Session的后端代码:

    @RequestMapping("/setSess")
    public String setSess(HttpServletRequest request) {
        //从Cookie中获取到SessionId,根据SessionId获取Session对象,如果没有,就会创建一个
        HttpSession session = request.getSession();
        session.setAttribute("name", "zhangsan");
        return "设置Session成功";
    }

        这个代码中虽然看不到SessionId这样的概念,但是getSession操作内部会提取到请求中的Cookie的SessionId,然后根据SessionId获取到对应的Session对象,Session对象用HttpSession来描述。如图:

        运行代码后浏览器页面如下:

        可以看到Cookie多了一个,就是我们刚才设置的,再看看Postman页面:

        也是多了一个,和浏览器一样的Cookie。

        通过fiddler抓包观察,如图:

(2)传统获取Session

        获取Session有两种方式,getSession的不同参数有两种情况,如下两种:

HttpSession getSession(boolean create);
HttpSession getSession();

HttpSession getSession(boolean create),参数如果为true,则当不存在会话是,会新建会话;参数如果不为false,则当不存在会话时,返回null,不新建会话。

        后端代码如下:

    @RequestMapping("getSess1")
    public String getsSess(HttpServletRequest request) {
        //从cookie中获取到了sessionID, 根据sessionID获取Session对象取Session对象,如果session不存在,不会自动创建
        HttpSession session = request.getSession(false);
        String userName = (String) session.getAttribute("name");
        return "name: " + userName;
    }

        Object getAttribute(String name):返回该session会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null。

        前面我们已经存储了Session:session.setAttribute("name", "zhangsan");   

        现在获取一下session,浏览器访问:http:127.0.0.1:8080/d1/getSess1 ,页面如下:

        

        Postman页面如下:

        

        通过fiddler抓包进行观察,如图:

        

        可以看到,客户端发送HTTP请求时,SessionId通过Cookie传递给了服务器。

        这里如果我们修改一下Cookie的值,就会拿不到了,如图:

        原来的:

        修改后的:

        因为修改了Cookie,也就是伪造的,Cookie里的SessionId也就会改变,但服务器这边没有这个对应的SessionId,就拿不到Session了。

        

(3)简洁获取 Session(1)

        后端代码如下:

    @RequestMapping("getSess2")
    public String getSess2(HttpSession session) {
        String name = (String)session.getAttribute("name");
        return "从Session中获取name: " + name;
    }

        这里封装了 HttpSession session = Request.getSession(); 如果Session不存在,会自动创建。

        Session是放在内存中的,因为重启了程序,就要重新存储Session,浏览器要再访问一下http:127.0.0.1:8080/d1/setSess ,如下:

        浏览器访问:http:127.0.0.1:8080/d1/getSess2,页面如下:

        

(4)简洁获取 Session(2)

        后端代码如下:

    @RequestMapping("getSess3")
    public String getSess3(@SessionAttribute("name") String name) {
        return "从Session中获取name: " + name;
    }

        浏览器访问http:127.0.0.1:8080/d1/getSess3 ,页面如下:

        

下面讨论一下Spring从传统获取Session到简洁获取Session:

        如图:

        可以看到,因为getSess1方法第一行代码是有可能会写的,为了简洁方便,就给他进行了一次封装,把HttpSession对象放进参数里,但开发者觉得还不够,又进一步进行封装,省去了会重复写的代码,就是使用了注解的getSess3方法了

十一、获取Header

1、传统获取Header

        后端代码如下:

    @RequestMapping("getHeader1")
    public String getHeader1(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        return "从Header获取信息,userAgent:" + userAgent;
    }

        浏览器页面如下:

        我们使用fiddler抓包看看:

        可以看到,和请求的Header报头一样。

2、简洁获取Header

        后端代码如下:

    @RequestMapping("getHeader2")
    public String getHeader2(@RequestHeader("User-Agent") String userAgent) {
        return "从Header获取信息,userAgent:" + userAgent;
    }

        浏览器页面如下:

        可以看到,响应和上面的一样,简洁的写法就是Spring对传统的写法进行了封装,使代码更简单、易学。


都看到这了,点个赞再走吧,谢谢谢谢谢

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

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

相关文章

Fast-DetectGPT 无需训练的快速文本检测

本文提出了一种新的文本检测方法 ——Fast-DetectGPT&#xff0c;无需训练&#xff0c;直接使用开源小语言模型检测各种大语言模型&#xff0c;如GPT等生成的文本内容。 Fast-DetectGPT 将检测速度提高了 340 倍&#xff0c;将检测准确率相对提升了 75%&#xff0c;超过商用系…

Redis缓存问题:穿透,击穿,雪崩,双写一致性等

Redis缓存问题:穿透,击穿,雪崩,双写一致性等 在高并发场景下,数据库往往是最薄弱的环节,我们通常选择使用redis来进行缓存,以起到缓冲作用,来降低数据库的压力,但是一旦缓存出现问题,也会导致数据库瞬间压力过大甚至崩溃,从而导致整个系统崩溃.今天就聊聊常见的redis缓存问题.…

多路递归的一些算法题

前言 首先我想讲一下&#xff0c;我对多路递归的理解吧&#xff0c;我认为多路递归就是循环中套回调&#xff0c;对于循环有几次就是几叉树&#xff0c;就好比我们常用的二叉树的dfs(node.left) 和 dfs(node.right)等前中后序遍历&#xff0c;也就是for (int i 0; i < 2; …

AIGC - SD(中英文本生成图片) + PaddleHub/HuggingFace + stable-diffusion-webui

功能 stable-diffusion(文本生成图片)webui-win搭建&#xff08;开启api界面汉化&#xff09;PaddleHubHuggingFace: SD2&#xff0c;中文-alibaba/EasyNLP stable-diffusion-webui 下载与安装 环境相关下载 python&#xff08;文档推荐&#xff1a;Install Python 3.10.6 …

区块链技术与应用学习笔记(1-4节)——北大肖臻课程

目录 1. 区块链初识(课程简介&#xff09; 被过度炒作&#xff0c;落地应用有限&#xff1f; 下一代的价值互联网&#xff1f;世界上最慢的数据库&#xff1f; 2. BTC-密码学原理&#xff08;比特币&#xff09; 1)哈希 哈希函数特点 个人学习所得 2)签名 个人对于…

U-boot 21.10 启动流程梳理

目录 背景平台启动入口确认启动源码DuoS_SG2000_RISCVLubancat2_RK3568_ARM 初始化流程board_init_fboard_init_r 参考 背景 设备&#xff1a;MilkV Duo S 版本&#xff1a;U-boot 2021.10 编译命令 # Milkv-DuoS SD卡版本&#xff0c;对应[board]与[config]分别为&#xff1…

Leetcode_相交链表

✨✨所属专栏&#xff1a;LeetCode刷题专栏✨✨ ✨✨作者主页&#xff1a;嶔某✨✨ 题目&#xff1a; 题解&#xff1a; 看到这个题目首先我们要排除链表逆置的想法&#xff0c;如图、因为c1节点只有一个next指针&#xff0c;逆置后不可能同时指向a2和b3节点。 其次有的的同学…

24深圳杯AC题完整思路+可执行代码+参考论文!!!!

比赛题目的完整版思路可执行代码数据参考论文都会在第一时间更新上传的&#xff0c;大家可以参考我往期的资料&#xff0c;所有的资料数据以及到最后更新的参考论文都是一次付费后续免费的。注意&#xff1a;&#xff08;建议先下单占坑&#xff0c;因为随着后续我们更新资料数…

【AIGC调研系列】大型语言模型如何减少幻觉生成

在解读大型语言模型&#xff08;LLMs&#xff09;中的长格式事实性问题时&#xff0c;我们首先需要认识到这些模型在生成内容时可能会产生与既定事实不一致的情况&#xff0c;这种情况通常被称为“幻觉”[2][3]。这种现象不仅可能导致信息的误传&#xff0c;还可能对社会造成误…

新时代凌迟:考研

我不喜欢上班&#xff0c;但我很欣赏老板的品味&#xff0c;因为咱们公司竟然还在订阅报纸&#xff0c;而且只有一份&#xff0c;《中国青年报》。 这份报纸我最喜欢看的是“冰点周刊”专栏&#xff0c;因为这个栏目能让读者相信&#xff1a;报纸远远可以超越一天的生命。 昨天…

跨境代买淘宝系统,跨境代采系统,淘宝代购系统,淘宝代购集运系统,1688代采系统

淘宝代购系统是一种集成的电商平台服务&#xff0c;主要针对海外用户提供购买中国大陆商品的便利通道。以下是其核心功能与特点&#xff1a; 多语言支持&#xff1a;为了满足全球用户的需求&#xff0c;代购系统提供多语言界面&#xff0c;让不同国家和地区的用户都能方便地浏…

c++初阶——类和对象(下)

大家好&#xff0c;我是小锋&#xff0c;今天我们来学习我们类和对象的最后一个章节&#xff0c;我们本期的内容主要是类和对象的一些细节进行讲解 再谈构造函数 我们在初始化时有两种方式一种是函数体内初始化&#xff0c;一种是初始化列表 我们先来看看日期类的初始化 构造…

Web3技术解析:区块链在去中心化应用中的角色

引言 在过去几年中&#xff0c;Web3技术已经成为了互联网领域的一个热门话题。作为区块链技术的延伸&#xff0c;Web3不仅仅是数字货币的代名词&#xff0c;更是一个能够为各种应用提供去中心化解决方案的强大工具。本文将深入探讨区块链在Web3去中心化应用中的关键角色&#…

【考研数学】武忠祥考研课优缺点大盘点

虽然每年大家推荐的最多的是张宇和汤家凤&#xff0c;但是我强烈推荐武忠祥老师&#xff01; 武忠祥老师真宝藏老师&#xff0c;他讲课不像张宇老师那样段子频出&#xff0c;也不想汤家凤老师那样&#xff0c;武忠祥老师有自己的方法论&#xff0c;真的有点东西&#xff0c;武…

一周学会Django5 Python Web开发-Django5 ORM执行SQL语句

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计49条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

AI工具集:解锁智能新境界,一站式解决你的所有需求!

在这个信息爆炸的时代&#xff0c;我们每天都在与大量的数据和信息打交道。如何高效地处理这些信息&#xff0c;提高工作效率和生活品质&#xff0c;成为了我们亟待解决的问题。而AI工具集(AI-321.com)的出现&#xff0c;无疑为我们提供了一把解锁智能新境界的钥匙。 AI-321 | …

基于streamlit快速部署机器学习项目(Public URL)

基于streamlit的AIGC项目前端展示 1.Streamlit 简介与入门1.1 安装 Streamlit1.2 开发Streamlit应用程序1.3 启动并运行1.3.1 本地运行1.3.2 部署 现在LLM技术发展迅速&#xff0c;很多人在学习的时候&#xff0c;都想展示效果&#xff0c;并且想部署在服务器上&#xff0c;但是…

Zephyr sensor子系统学习

一、背景 2023年7月份nRF Connect SDK 2.4.0最新版本&#xff0c;使用的Zephyr V3.3版本。从Zephyr 3.5版本在子系统中加入了sensing子系统。 现在最新的nRF Connect SDK 2.6.0 release支持v3.5.99-ncs1&#xff0c;已经支持sensing子系统 nRF52840现在官方支持两个传感器de…

Rust中的函数指针

什么是函数指针 通过函数指针允许我们使用函数作为另一个函数的参数。函数的类型是 fn &#xff08;使用小写的 ”f” &#xff09;以免与 Fn 闭包 trait 相混淆。fn 被称为 函数指针&#xff08;function pointer&#xff09;。指定参数为函数指针的语法类似于闭包。 函数指…

阿里前端常考vue面试题汇总_阿里高级vue面试题

改变 ![](https://img-blog.csdnimg.cn/img_convert/b736620bcd29f08f3685022ab5583d8b.webp?x-oss-processimage/format,png)你会发现&#xff0c; **只有改变的栏目才闪烁&#xff0c;也就是进行重绘** &#xff0c;数据没有改变的栏目还是保持原样&#xff0c;这样就大大节…