目录
🎍序言
访问不同的路径,就是发送不同的请求.在发送请求时,可能会带⼀些参数,所以我们在学习Spring的请求时,主要是学习如何传递参数到后端以及后端如何接收.
下面会对传递参数进行一个详解,咱们主要是使⽤浏览器和Postman来模拟
注:上篇文章聊了RequestMapping之后,之后在类上都加上RequestMapping,防止同一类中不同的方法使用同一请求方式的注解并且路径相同,就会报错
🌴传递单个参数
代码:
站在前端的角度:现在一般都是前后端分离,前端并不关心后端如何接收,只需要把参数传递过去就可以了,只需知道key是什么,value的一个格式即可。前后端交互,交互的是url,请求方法,请求参数。
站在后端的角度:也不需要关系前端怎么传过来,只需要接收即可。后端接收参数也只能加在方法上。
Postman传参:可以使用Params传,也可使用Body中的form表单的方式
使用Params传递:
当后端收到这个url,Spring就自动的帮我们绑定到这个方法里面了。
若我们修改一下key:此时后端收到这个url时,Spring发现没有地方要userName1,也就是说userName没有收到传递过来的参数,赋值为null
使用Body的form表单传参:注意将Params中的参数勾选掉。通过Body的form表单传输发现url没有拼接key,value的值。注意通过Body传参要使用Post请求
通过Fiddler抓取两种方式对比:
通过浏览器传参:
如果使⽤基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误:
小结:总之后端并不关心前端通过什么样的方式来调用我的接口。如果参数传递不一致,比如后端需要接收一个String类型,你传了19,此时Spring就会帮我自动的转过去,若转不了,例如后端需要接收一个Integer类型,你传了一个字符串,就会报400,并且后端会有错误日志。
传递包装类型和基本类型的差异:
代码:
传参结果:
不传参结果:
观察发现如果使⽤基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误,报的是服务器错误,简单的来说,未传值,相当于age=null,age又是一个int类型,int类型不能等于null,改成包装类型即可。后续在设计接口时,建议都使用包装类型
🍀传递多个参数
上述传递一个参数时,我们说后端是不需要关注前端的,现在我们传递多个参数,同样的后端也是不需要关注前端如何传的。
那么参数也不能加在注解上,还是声明在方法上即可。
代码:
传参结果:
即使我通过该变传参顺序也不影响:
原理:我们传过去的参数是一个key value的键值对,key是userName,value是zhangsan,类似一个Map这样的结构,Spring在接收的时候,它就会从这个Map里面去找key为userName的参数,找到了就把这个key的value映射(赋值)出来,没有就赋值为null。
有时候我们在设计完接口之后,在里面设计的参数只是当时够用,但是到后面发现此时的参数不够用了,还需要在添加一些参数,一种方式是直接在方法中直接添加,但是一般不建议,有一个开闭原则,也就是说在工作中,当前接口已经上线了,尽量不要去修改,不确定会不会造成影响
方式二:再添加一个接口,让之前的业务切换到新接口上,让之前的接口慢慢的废弃掉(横杠)
但是方式二感觉又很麻烦,如果后续又加的话又要搞一个新的接口,此时我们就可以把这些参数封装成一个对象,直接传递对象即可。
🎄传递对象
封装对象:此时想要加参数直接再这个对象中加即可
通过String类型接收整个对象:
传参结果:
通过UserInfo类型接收:
传参结果:
在上述传递单个参数是,如果是int类型,不进行传参的话会报500错误;当前将UserInfo中age类型改为int类型,看看不传参会发生什么。
传参结果:发现默认赋值为0
🌳后端参数重命名(后端参数映射)
比如以及告诉前端传过来的参数是userName,但是后端因为一些原因不想叫这个名字,就想用name去接收,该如何做?
代码:
传参结果:
🚩@ReuqestParam注解
就可以通过@ReuqestParam注解给后端参数进行重命名,将前端的UserName绑定给后端的name
代码:
传参结果:此时就可以收到值了
当使用@ReuqestParam注解后(绑定name之后),前端不传userName,就会报400
那我们查看param4不传userName:
传参结果:此时userName为null
上述param6和param4的代码区别就是加了一个@ReuqestParam注解进行绑定,但是param6不传userName就报400了,也可以查看后端的错误日志
大概就是这个注解的原因了。
查看@ReuqestParam注解源码:里面有一个属性为required,默认值为true,也就是说加上这个注解之后,当前的这个参数默认值是一个必填项。
但是我们初衷只是想与前端进行绑定,不需要有这些要求,修改一下即可:
参数传递(还是不传userName):此时就为null了
🌲传递数组
Spring MVC 可以⾃动绑定数组参数的赋值
代码:
传递参数方式一:
传递参数方式二:
🎍传递集合
集合参数:和数组类似,同⼀个请求参数名有为多个
但是传过去的是数组,List识别不到这个数组,加上@RequestParam注解进行绑定
代码:
参数传递:
🌴传递JSON数据
🚩JSON概念
JSON:JavaScript Object Notation【JavaScript对象表⽰法】
JSON是⼀种轻量级的数据交互格式.它基于ECMAScript(欧洲计算机协会制定的js规范)的⼀个⼦集,采⽤完全独⽴于编程语⾔的⽂本格式来存储和表⽰数据。
简单来说:JSON就是⼀种数据格式,有⾃⼰的格式和语法,使⽤⽂本表⽰⼀个对象或数组的信息,因此JSON本质是字符串.
主要负责在不同的语⾔中数据传递和交换
🚩JSON的语法
- 数据在 键值对(Key/Value) 中
- 数据由逗号 , 分隔
- 对象⽤ {} 表⽰
- 数组⽤ [] 表⽰
- 值可以为对象,也可以为数组,数组中可以包含多个对象
🚩JSON的两种结构
- 对象:⼤括号 {} 保存的对象是⼀个⽆序的 键值对 集合.⼀个对象以左括号 { 开始,右括号 }结束。每个"键"后跟⼀个冒号 : ,键值对使⽤逗号 , 分隔
- 数组: 中括号 [ ] 保存的数组是值(value)的有序集合.⼀个数组以左中括号 [ 开始,右中括号 ] 结束,值之间使⽤逗号 , 分隔。
🚩JSON字符串和Java对象互转
JSON本质上是⼀个字符串,通过⽂本来存储和描述数据 Spring MVC框架也集成了JSON的转换⼯具,我们可以直接使⽤,来完成JSON字符串和Java对象的互转
本质上是jackson-databind提供的功能,SpringMVC框架中已经把该⼯具包引⼊了进来,咱们直接使 ⽤即可,如果脱离SpringMVC使⽤,需要引⼊相关依赖
JSON的转换⼯具包有很多,jackson-databind只是其中的⼀种.
代码:对象转JSON
转换结果:
代码:JSON转对象
转换结果:
🚩JSON的优点
- 简单易⽤:语法简单,易于理解和编写,可以快速地进⾏数据交换
- 跨平台⽀持:JSON可以被多种编程语⾔解析和⽣成,可以在不同的平台和语⾔之间进⾏数据交换和传输
- 轻量级:相较于XML格式,JSON数据格式更加轻量级,传输数据时占⽤带宽较⼩,可以提⾼数据传输速度
- 易于扩展:JSON的数据结构灵活,⽀持嵌套对象和数组等复杂的数据结构,便于扩展和使⽤
- 安全性:JSON数据格式是⼀种纯⽂本格式,不包含可执⾏代码,不会执⾏恶意代码,因此具有较⾼的安全性
基于以上特点,JSON在Web应⽤程序中被⼴泛使⽤,如前后端数据交互、API接⼝数据传输等
🚩传递JSON对象
接收JSON对象,需要使⽤ @RequestBody 注解
RequestBody:请求正⽂,意思是这个注解作⽤在请求正⽂的数据绑定,请求参数必须在写在请求正⽂中
代码:
传递参数:
🎋获取URL中参数@PathVariable
有的时候需要获取url中的参数,拿着这个参数去做某些事情,这里的参数指的时url中?之前的参数,非键值对格式,上述讲的url参数是指?之后的参数,键值对格式,也就是查询字符串。
path variable:路径变量
和字⾯表达的意思⼀样,这个注解主要作⽤在请求URL路径上的数据绑定
默 认传递参数写在URL上,SpringMVC就可以获取到
代码:param10后面也是跟的路径,是个必传参数
传递参数:
还可以传递多个参数
代码:
传递参数:
🍃上传文件@RequestPart
代码:
发送请求:
查看对应路径是否上传成功:
🎄获取Cooki/Session
由于内容较多,这里单独写了一篇文章
链接:【JavaEE进阶】获取Cookie/Session-CSDN博客
🍀获取Header
有时候需要获取Header中的信息,比如User-Agent,Referer等,获取Header也分为两种方式
🚩传统获取 header
代码:
获取Header:
🚩注解获取header
代码:
获取Header:
总结:
在此可能会有一点疑问,我们当前是在Chrome浏览器上设置Session,获取Session,如果我换成了edge浏览器来进行访问,会不会导致线程不安全问题?首先是不会的!
我们的接口都是线程安全的,在接口方便不考虑线程安全问题,这么Tomcat已经帮助我们解决了,我们每发送的一个请求都是单独的一个线程。每一个Session对应不同的SessionId。