从上⾯的案例中,也发现了⼀个新的问题,就是我们测试后端⽅法时,还需要去写前端代码.这对我们来 说,是⼀件⿇烦⼜痛苦的事情.

随着互联⽹的发展,也随着项⽬难度的增加,企业也按照开发的功能,把⼈员拆分成了不同的团队.界⾯ 显⽰交给"前端开发⼯程师",业务逻辑的实现交给"后端开发⼯程师".

后端开发⼯程师,不要求也不需要掌握前端技能了.

那后端开发⼯程师,如何测试⾃⼰的程序呢?--使⽤专业的接⼝测试⼯具

下载安装postman

下载链接:https://www.postman.com/downloads/

也可以使⽤课件中提供的app来安装: Postman-win64-Setup.exe

安装后会提⽰有版本升级,点击Dismiss即可(⽆需升级)

创建请求

界面介绍

传参介绍

1. 普通传参,也就是通过查询字符串来传参

学习HTTP环节时,我们通过URL来访问互联⽹上的某⼀个资源

URL的格式如下:

其中,查询字符串就是请求的参数

2. form-data(完整表⽰为:multipart/form-data)

表单提交的数据,在form标签中加上enctyped="multipart/form-data" ,通常⽤于提交图 ⽚/⽂件.对应 Content-Type: multipart/form-data 

3. x-www-form-urlencoded

form表单,对应 Content-Type: application/x-www-from-urlencoded

4. raw

可以上传任意格式的⽂本,可以上传text、json、xml、html等

请求

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

传递参数,咱们主要是使⽤浏览器和Postman来模拟.

后端开发⼈员⽆需过度关注如何传递参数,了解即可,实际开发中以Postman测试为主.

⽐如餐厅的厨师,不关注⽤⼾是在店⾥下单,还是外卖平台下单,或者⼩程序下单,只需要知道如何接 收订单,根据订单做出对应的菜肴就可以了.

传递单个参数

接收单个参数,在SpringMVC中直接⽤⽅法中的参数就可以,⽐如以下代码:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/param")
public class ParamController {
 @RequestMapping("/m1")
 public String method1(String name){
 return "接收到参数name:"+ name;
 }
}

咱们使⽤浏览器发送请求并传参  http://127.0.0.1:8080/param/m1?name=spring

可以看到,后端程序正确拿到了name参数的值.

SpringMVC会根据⽅法的参数名,找到对应的参数,赋值给⽅法

如果参数不⼀致,是获取不到参数的.

⽐如请求URL:http://127.0.0.1:8080/param/m1?name1=spring

响应结果:

注意事项

使⽤基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误 类型不匹配时,会报400错误.

@RequestMapping("/m1/int")
public Object method1GetInt(int age){
 return "接收到参数age:" + age;
}

1. 正常传递参数

http://127.0.0.1:8080/param/m1/int?age=1

浏览器响应情况:

通过Fiddler观察请求和响应,HTTP响应状态码为200,Content-Type 为text/html

2. 不传递age参数

http://127.0.0.1:8080/param/m1/int

浏览器响应情况:

通过Fiddler观察请求和响应,HTTP响应状态码为500

尝试观察程序的错误⽇志,并解决

⼀般看⽇志堆栈信息的⾸⾏,报错信息显⽰: int类型的参数'age',虽然为可选的,但由于被声明为基本类型⽽不能转换为空值.考虑将其声明为对 应基本类型的包装类型.

按照错误信息解决错误即可

最开始学习时,会遇到各种各样的问题,我们要养成看错误⽇志的习惯,根据错误⽇志来解决问题. 最开始可能会看不懂,或者⽐较懵,要耐下⼼来,慢慢看,后⾯课堂中也会教⼤家更多看⽇志的思路.

3. 传递参数类型不匹配

http://127.0.0.1:8080/param/m1/int?age=abc

浏览器响应情况:

通过Fiddler观察请求和响应, HTTP响应状态码为400

对于包装类型,如果不传对应参数,Spring接收到的数据则为null

所以企业开发中,对于参数可能为空的数据,建议使⽤包装类型

传递多个参数

如何接收多个参数呢? 和接收单个参数⼀样,直接使⽤⽅法的参数接收即可.使⽤多个形参.

@RequestMapping("/m2")
public Object method2(String name, String password) {
 return "接收到参数name:" + name + ", password:" + password;
}

使⽤浏览器发送请求并传参:http://127.0.0.1:8080/param/m2?name=zhangsan&password=123456

可以看到,后端程序正确拿到了name和password参数的值

当有多个参数时,前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置是不影响后 端获取参数的结果.

⽐如访问:http://127.0.0.1:8080/param/m2?password=123456&name=zhangsan同样可以拿到正 确的结果

传递对象

如果参数⽐较多时,⽅法声明就需要有很多形参.并且后续每次新增⼀个参数,也需要修改⽅法声明. 我们不妨把这些参数封装为⼀个对象.

SpringMVC也可以⾃动实现对象参数的赋值,⽐如Person对象:

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

传递对象代码实现:

@RequestMapping("/m3")
public Object method3(Person p){
 return p.toString();
}

使⽤浏览器发送请求并传参:http://127.0.0.1:8080/param/m3? id=5&name=zhangsan&password=123456

可以看到,后端程序正确拿到了Person对象⾥各个属性的值

Spring会根据参数名称⾃动绑定到对象的各个属性上,如果某个属性未传递,则赋值为null(基本类型则 赋值为默认初识值,⽐如int类型的属性,会被赋值为0)

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

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

具体⽰例如下,后端实现代码:

@RequestMapping("/m4")
public Object method_4(@RequestParam("time") String createtime) {
 return "接收到参数createtime:" + createtime;
}

使⽤浏览器发送请求并传参:http://127.0.0.1:8080/param/m4?time=2023-09-12

可以看到,Spring可以正确的把浏览器传递的参数time绑定到了后端参数caretetime参数上 此时,如果浏览器使⽤createtime进⾏参数传递呢?

访问URL:http://127.0.0.1:8080/param/m4?createtime=2023-09-12 浏览器响应结果:

错误⽇志信息为:

控制台打印⽇志显⽰:请求参数'time'不存在

可以得出结论:1. 使⽤ @RequestParam 进⾏参数重命名时,请求参数只能和 @RequestParam 声明的名称⼀ 致,才能进⾏参数绑定和赋值.

 2. 使⽤ @RequestParam 进⾏参数重命名时,参数就变成了必传参数.

⾮必传参数设置

如果我们的实际业务前端的参数是⼀个⾮必传的参数,针对上述问题,如何解决呢? 先来了解下参数必传的原因,我们查看 @RequestParam 注解的实现细节就可以发现端倪,注解 实现如下:

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
 @AliasFor("name")
 String value() default "";
 @AliasFor("value")
 String name() default "";
 boolean required() default true;
 String defaultValue() default 
"\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

可以看到 required 的默认值为true,表⽰含义就是:该注解修饰的参数默认为必传 既然如此,我们可以通过设置@RequestParam 中的required=false 来避免不传递时报错, 具体实现如下:

@RequestMapping("/m4")
public Object method4(@RequestParam(value = "time", required = false) String 
createtime) {
 return "接收到参数createtime:" + createtime;
}

可以看到,添加required=false之后, time前⾯也加了key,变成了value = "time" 注解属性赋值时,没有指明key的话,默认为value属性.

 如果需要有多个属性进⾏赋值时,需要写上key

传递数组

SpringMVC可以⾃动绑定数组参数的赋值

后端实现代码:

@RequestMapping("/m5")
public String method5(String[] arrayParam) {
 return Arrays.toString(arrayParam);
}

使⽤浏览器发送请求并传参:

数组参数:请求参数名与形参数组名称相同且请求参数为多个,后端定义数组类型形参即可接收参数 http://127.0.0.1:8080/param/m5? arrayParam=zhangsan&arrayParam=lisi&arrayParam=wangwu 或者使⽤http://127.0.0.1:8080/param/m6?listParam=zhangsan%2clisi%2cwangwu 或者使⽤http://127.0.0.1:8080/param/m5?arrayParam=zhangsan,lisi,wangwu

浏览器响应结果:

可以看到后端对数组参数进⾏了正确的接收和响应. 或者使⽤Postman来发送请求

传递集合

集合参数:和数组类似,同⼀个请求参数名有为多个,且需要使⽤@RequestParam 绑定参数关系

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

请求⽅式和数组类似:

浏览器传参:

⽅式⼀:http://127.0.0.1:8080/param/m6?listParam=zhangsan&listParam=lisi&listParam=wangwu

⽅式⼆:http://127.0.0.1:8080/param/m6?listParam=zhangsan%2clisi%2cwangwu %2c是逗号的转义编码,解码后的url为:http://127.0.0.1:8080/param/m6? listParam=zhangsan,lisi,wangwu

后端接收代码:

@RequestMapping("/m6")
public String method6(@RequestParam List<String> listParam){
 return "size:"+listParam.size() + ",listParam:"+listParam;
}

Postman传参测试:

传递JSON数据

JSON概念

JSON:JavaScriptObjectNotation【JavaScript对象表⽰法】

JSON是⼀种轻量级的数据交互格式.它基于ECMAScript(欧洲计算机协会制定的js规范)的⼀个⼦集, 采⽤完全独⽴于编程语⾔的⽂本格式来存储和表⽰数据。--百度百科

简单来说:JSON就是⼀种数据格式,有⾃⼰的格式和语法,使⽤⽂本表⽰⼀个对象或数组的信息,因此 JSON本质是字符串.主要负责在不同的语⾔中数据传递和交换.

类似于:

• 国际通⽤语⾔-英语

• 中国56个⺠族不同地区的通⽤语⾔-普通话

有⾃⼰的语法,其他语⾔也认识.

JSON与Javascript的关系

没有关系,只是语法相似,js开发者能更快的上⼿⽽已,但是他的语法本⾝⽐较简单,所以也很好学

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", "Radiation 
blast"]
 }, {
 "name": "Madame Uppercut",
 "age": 39,
 "secretIdentity": "Jane Wilson",
 "powers": ["Million tonne punch", "Damage resistance", "Superhuman 
reflexes"]
 }, {
 "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","Radiation blast"]},{"name":"Madame 
Uppercut","age":39,"secretIdentity":"Jane Wilson","powers":["Million tonne 
punch","Damage resistance","Superhuman reflexes"]},{"name":"Eternal 
Flame","age":1000000,"secretIdentity":"Unknown","powers":["Immortality","Heat 
Immunity","Inferno","Teleportation","Interdimensional travel"]}]}

和上⾯描述的数据⼀样,只不过上⾯的进⾏了格式化,更易读.

JSON的语法:

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

2. 数据由逗号, 分隔

3. 对象⽤{} 表⽰

4. 数组⽤ [] 表⽰

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

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校验格式化⼯具(BeJSON)

 JSON字符串和Java对象互转

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

SpringMVC框架也集成了JSON的转换⼯具,我们可以直接使⽤,来完成JSON字符串和Java对象的互转

本质上是jackson-databind提供的功能,SpringMVC框架中已经把该⼯具包引⼊了进来,咱们直接使 ⽤即可,如果脱离SpringMVC使⽤,需要引⼊相关依赖

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

JSON的转换⼯具包有很多,jackson-databind只是其中的⼀种.

public class JSONUtils {
 private static ObjectMapper objectMapper = new ObjectMapper();
 public static void main(String[] args) throws JsonProcessingException {
 Person person = new Person();
 person.setId(5);
 person.setName("zhangsan");
 person.setPassword("123456");
 //对象转为JSON字符串 
 String jsonStr = objectMapper.writeValueAsString(person);
 System.out.println("JSON字符串为:"+jsonStr);
 //JSON字符串转为对象 
 Person p = objectMapper.readValue(jsonStr,Person.class);
 System.out.println("转换的对象
id:"+p.getId()+",name:"+p.getName()+",password:"+p.getPassword());
 }
}

使⽤ObjectMapper对象提供的两个⽅法,可以完成对象和JSON字符串的互转 writeValueAsString:把对象转为JSON字符串 readValue:把字符串转为对象

JSON优点

1. 简单易⽤:语法简单,易于理解和编写,可以快速地进⾏数据交换

2. 跨平台⽀持: JSON可以被多种编程语⾔解析和⽣成,可以在不同的平台和语⾔之间进⾏数据交换和 传输

3. 轻量级:相较于XML格式,JSON数据格式更加轻量级,传输数据时占⽤带宽较⼩,可以提⾼数据传输 速度

4. 易于扩展: JSON的数据结构灵活,⽀持嵌套对象和数组等复杂的数据结构,便于扩展和使⽤

 5. 安全性:JSON数据格式是⼀种纯⽂本格式,不包含可执⾏代码,不会执⾏恶意代码,因此具有较⾼ 的安全性

基于以上特点,JSON在Web应⽤程序中被⼴泛使⽤,如前后端数据交互、API接⼝数据传输等.

 传递JSON对象

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

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

后端实现:

@RequestMapping(value = "/m7")
public Object method7(@RequestBody Person person) {
 return person.toString();
}

使⽤Postman来发送json请求参数:

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

尝试去除掉@RequestBody 试试

@RequestMapping(value = "/m7")
public Object method7(Person person) {
 return person.toString();
}

请求响应结果如下:

后端未能成功给Person对象赋值.

获取URL中参数@PathVariable

pathvariable:路径变量

和字⾯表达的意思⼀样,这个注解主要作⽤在请求URL路径上的数据绑定 默认传递参数写在URL上,SpringMVC就可以获取到

后端实现代码:

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

使⽤浏览器发送请求:http://127.0.0.1:8080/param/m8/5/zhangsan 或者使⽤Postman发送请求

可以看到,后端正确获取到了URL中的参数 参数对应关系如下:

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

如果⽅法参数名称和需要绑定的URL中的变量名称不⼀致时,需要@PathVariable的属性value赋值, 如上述例⼦中的userName变量.

上传⽂件@RequestPart

后端代码实现:

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

使⽤Postman发送请求:

观察D:/temp路径下,⽂件是否上传成功

获取Cookie/Session

回顾Cookie HTTP协议⾃⾝是属于"⽆状态"协议.

 "⽆状态"的含义指的是:

默认情况下HTTP协议的客⼾端和服务器之间的这次通信,和下次通信之间没有直接的联系.

 但是实际开发中,我们很多时候是需要知道请求之间的关联关系的.

例如登陆⽹站成功后,第⼆次访问的时候服务器就能知道该请求是否是已经登陆过了.

上述图中的"令牌"通常就存储在Cookie字段中.

⽐如去医院挂号

1. 看病之前先挂号.挂号时候需要提供⾝份证号,同时得到了⼀张"就诊卡",这个就诊卡就相当于患 者的"令牌".

2. 后续去各个科室进⾏检查,诊断,开药等操作,都不必再出⽰⾝份证了,只要凭就诊卡即可识别出当 前患者的⾝份.

3. 看完病了之后,不想要就诊卡了,就可以注销这个卡.此时患者的⾝份和就诊卡的关联就销毁了.(类 似于⽹站的注销操作)

4. ⼜来看病,可以办⼀张新的就诊卡,此时就得到了⼀个新的"令牌"

此时在服务器这边就需要记录"令牌"信息,以及令牌对应的⽤⼾信息,这个就是Session机制所做的⼯ 作.

理解Session

我们先来了解⼀下什么是会话. 会话:对话的意思

在计算机领域,会话是⼀个客⼾与服务器之间的不中断的请求响应.对客⼾的每个请求,服务器能够识 别出请求来⾃于同⼀个客⼾.当⼀个未知的客⼾向Web应⽤程序发送第⼀个请求时就开始了⼀个会话. 当客⼾明确结束会话或服务器在⼀个时限内没有接受到客⼾的任何请求时,会话就结束了.

⽐如我们打客服电话 每次打客服电话,是⼀个会话.挂断电话,会话就结束了 下次再打客服电话,⼜是⼀个新的会话. 如果我们⻓时间不说话,没有新的请求,会话也会结束.

服务器同⼀时刻收到的请求是很多的.服务器需要清楚的区分每个请求是属于哪个⽤⼾,也就是属于哪 个会话,就需要在服务器这边记录每个会话以及与⽤⼾的信息的对应关系. Session是服务器为了保存⽤⼾信息⽽创建的⼀个特殊的对象.

Session的本质就是⼀个"哈希表",存储了⼀些键值对结构.Key就是SessionID,Value就是⽤⼾信息(⽤ ⼾信息可以根据需求灵活设计).

SessionId是由服务器⽣成的⼀个"唯⼀性字符串",从Session机制的⻆度来看,这个唯⼀性字符串称 为"SessionId".但是站在整个登录流程中看待,也可以把这个唯⼀性字符串称为"token". 上述例⼦中的令牌ID,就可以看做是SessionId,只不过令牌除了ID之外,还会带⼀些其他信息,⽐如时 间,签名等.

1. 当⽤⼾登陆的时候,服务器在Session中新增⼀个新记录,并把sessionId返回给客⼾端.(通过 HTTP响应中的Set-Cookie字段返回).

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

3. 服务器收到请求之后,根据请求中的sessionId在Session信息中获取到对应的⽤⼾信息,再进⾏后 续操作.找不到则重新创建Session,并把SessionID返回

Session默认是保存在内存中的.如果重启服务器则Session数据就会丢失.

 Cookie和Session的区别

• Cookie是客⼾端保存⽤⼾信息的⼀种机制.Session是服务器端保存⽤⼾信息的⼀种机制.

 • Cookie和Session之间主要是通过SessionId关联起来的,SessionId是Cookie和Session之间的 桥梁

• Cookie和Session经常会在⼀起配合使⽤.但是不是必须配合.

         ◦ 完全可以⽤Cookie来保存⼀些数据在客⼾端.这些数据不⼀定是⽤⼾⾝份信息,也不⼀定是 SessionId        

        ◦ Session中的sessionId也不需要⾮得通过Cookie/Set-Cookie传递,⽐如通过URL传递.

获取Cookie

传统获取Cookie

@RequestMapping("/m10")
public String method10(HttpServletRequest request,HttpServletResponse response)
 {
 // 获取所有 cookie 信息 
 Cookie[] cookies = request.getCookies();
 //打印Cookie信息 
 StringBuilder builder = new StringBuilder();
 if (cookies!=null){
 for (Cookie ck:cookies) {
 builder.append(ck.getName()+":"+ck.getValue());
 }
 }
 return "Cookie信息:"+builder;
}

SpringMVC是基于ServletAPI构建的原始Web框架,也是在Servlet的基础上实现的

 HttpServletRequest ,HttpServletResponse 是Servlet提供的两个类,是Spring MVC⽅法的内置对象.需要时直接在⽅法中添加声明即可. HttpServletRequest 对象代表客⼾端的请求,当客⼾端通过HTTP协议访问服务器时,HTTP请 求头中的所有信息都封装在这个对象中,通过这个对象提供的⽅法,可以获得客⼾端请求的所有信 息. HttpServletResponse 对象代表服务器的响应.HTTP响应的信息都在这个对象中,⽐如向客⼾ 端发送的数据,响应头,状态码等.通过这个对象提供的⽅法,可以获得服务器响应的所有内容 SpringMVC在这两个对象的基础上进⾏了封装,给我们提供更加简单的使⽤⽅法. 此时没有设置Cookie,通过浏览器访问:http://127.0.0.1:8080/param/m10 ,得到Cookie为null

我们设置⼀下Cookie的值

再次访问:

从这个例⼦中,也可以看出Cookie是可以伪造的,也就是不安全的,所以使⽤Cookie时,后端需要进⾏ Cookie校验

简洁获取Cookie

也有更简洁的⽅式获取Cookie

@RequestMapping("/getCookie")
public String cookie(@CookieValue("bite") String bite) {
 return "bite:" + bite;
}

运⾏结果:http://127.0.0.1:8080/param/getCookie

获取Session

Session存储和获取

Session是服务器端的机制,我们需要先存储,才能再获取

Session也是基于HttpServletRequest来存储和获取的

Session存储

@RequestMapping("/setSess")
public String setsess(HttpServletRequest request) {
 // 获取Session对象 
 HttpSession session = request.getSession();
 if (session != null) {
 session.setAttribute("username", "java");
 }
 return "session 存储成功";
}

这个代码中看不到SessionId这样的概念的.getSession操作内部提取到请求中的Cookie⾥的 SessionId,然后根据SessionId获取到对应的Session对象, Session对象⽤HttpSession来描述

获取Session有两种⽅式

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

HttpSessiongetSession(booleancreate):参数如果为true,则当不存在会话时新建会话;参数如果 为false,则当不存在会话时返回null

HttpSessiongetSession():和getSession(true)含义⼀样,默认值为true.

 voidsetAttribute(Stringname,Objectvalue):使⽤指定的名称绑定⼀个对象到该session会话

Session读取

读取Session可以使⽤HttpServletRequest

@RequestMapping("/getSess")
public String sess(HttpServletRequest request) {
 // 如果 session 不存在, 不会⾃动创建 
 HttpSession session = request.getSession(false);
 String username = null;
 if (session != null && session.getAttribute("username") != null) {
 username = (String) session.getAttribute("username");
 }
 return "username:" + username;
}

ObjectgetAttribute(Stringname):返回在该session会话中具有指定名称的对象,如果没有指定名 称的对象,则返回null.

运⾏

先设置Session:http://127.0.0.1:8080/param/setSess

通过Fiddler观察Http请求和响应情况:

可以看到,Http响应中,通过Set-Cookie告知客⼾端,把SessionID存储在Cookie中 通过浏览器,可以观察到运⾏结果:

获取Session:http://127.0.0.1:8080/param/getSess

通过Fiddler观察Http请求和响应

可以看到,Http请求时,把SessionId通过Cookie传递到了服务器.

简洁获取Session(1)

@RequestMapping("/getSess2")
public String sess2(@SessionAttribute(value = "username",required = false) 
String username) {
 return "username:"+username;
}

运⾏结果:http://127.0.0.1:8080/param/getSess2

简洁获取Session(2) 通过SpringMVC内置对象HttpSession来获取

@RequestMapping("/getSess3")
public String sess3(HttpSession session) {
 String username = (String)session.getAttribute("username");
return "username:"+username;
}

HttpSessionsession=request.getSession(); Session不存在的话,会⾃动进⾏创建

运⾏结果:http://127.0.0.1:8080/param/getSess3

获取Header

获取Header

传统获取header

获取Header也是从 HttpServletRequest 中获取

@RequestMapping("/param10")
public String param10(HttpServletRequest request, HttpServletResponse response)
 {
 String userAgent = request.getHeader("User-Agent");
 return name + ":"+userAgent;
}

使⽤HttpServletRequest提供的getHeader⽅法来获取,参数对应HTTP请求报头的"Key"

运⾏结果:http://127.0.0.1:8080/param/getHeader

通过Fiddler观察,获取的User-Agent是否正确

简洁获取Header

@RequestMapping("/header")
public String header(@RequestHeader("User-Agent") String userAgent) {
 return "userAgent:"+userAgent;
}

@RequestHeader注解的参数值为HTTP请求报头中的"Key"

运⾏结果:http://127.0.0.1:8080/param/getHeader2

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐