SpringBoot请求及响应
- 相关配置
1 | # 端口 |
请求协议
- 参考文章
- 常见请求方式
request-method | Content-Type | postman | springboot | 说明 |
---|---|---|---|---|
post | application/json | row-json | (String userIdUrlParam, @RequestBody User user) | String userIdUrlParam 可以接受 url 中的参数,使用了@RequestBody 可以接受 body 中的参数(最终转成 User/Map/List 对象,如@RequestBody List<Map<String, Object>> items ,此时 body 中的数据不能直接通过 String 等接受),而 idea 的 http 文件中 url 参数拼在地址上无法获取(请求机制不同) |
(x)post | application/json | row-json | (@RequestParam username) | 如果前台为 application/json + {username: smale}或者 application/json + username=smalle 均报 400;此时需要 application/x-www-form-urlencoded + username=smalle 才可请求成功 |
post | application/x-www-form-urlencoded | x-www-form-urlencoded | (String name, User user, @RequestBody body) | String name 可以接受 url 中的参数,postmant 的 x-www-form-urlencoded 中的参数会和 url 中参数合并后注入到 springboot 的参数中;@RequestBody 会接受 url 整体的数据,(由于 Content-Type)此时不会转换,body 接受的参数如name=hello&name=test&pass=1234 。对于 application/x-www-form-urlencoded 类型的数据,可无需 @RequestBody 接受参数 |
post | multipart/form-data | form-data | (HttpServletRequest request, MultipartFile file, User user, @RequestParam(“hello”) String hello) | 参考文件上传下载,文件上传必须使用此类型(包含参数);javascript XHR(包括 axios 等插件)需要使用 new FormData()进行数据传输;此时参数映射到 User 对象,如果字段为 null 则会转换成’null’进行映射,如果改字段为数值类型,会导致字符串转数值出错;如果接受参数是 Map 则无法映射,可通过传入JSON字符串再反序列化;表单数据都保存在 http 的正文部分,各个表单项之间用 boundary 隔开,用 request.getParameter 是取不到数据的,这时需要通过 request.getInputStream 来取数据 |
get | - | - | (User user, Page page) | 前台传输参数为{username: ‘smalle’, pageSize: 10}时,可正确分别映射到两个对象;如果此时为 post 请求则无法映射;get 请求时,请求参数会拼接到 url 上,Google 浏览器 URL 最大长度限制为 8182 个字符,中文是以 urlencode 后的编码形式进行传递,如果浏览器的编码为 UTF8 的话,一个汉字最终编码后的字符长度为 9 个字符(中=%E4%B8%AD)。如果用 Map 接受,则数字类型的值也会映射成字符串 |
all | 如application/x-www-form-urlencoded | all | (Map<String, Object> param) | 前台传输参数为?age=&count=10000时,得到的字段数据类型均为字符串。(必须)加@RequestParam注解才能获取到Map(值也全部是字符串);除了url上的参数,form-data的时候可将其值也放到map中(x-www-form-urlencoded中的不会放到map) |
- content-type传入”MIME类型”(多用途因特网邮件扩展 Multipurpose Internet Mail Extensions)只是一个描述,决定文件的打开方式
- 请求的header中加入content-type标明数据MIME类型。如POST时,application/json表示数据存放在body中,且数据格式为json
- 服务器response设置content-type标明返回的数据类型。接口开发时,设置请求参数是无法改变服务器数据返回类型的。部分工具提供专门的设置,通过工具内部转换的方式实现设定返回数据类型
请求参数
- 如果所在类加注解
@RequestMapping("/user")
,则请求url全部要拼上/user
,如/user/hello
1 | "/hello") // 前台post请求也可以请求的到 (value = |
- GET请求
1 | // 前台GET请求 Body/Url 中含参数 userId和username(Spring可以自动注入java基础数据类型和对应的数组,Map/List无法注入) |
- POST请求
1 | // 请求头为application/x-www-form-urlencoded(不能是application/json,否则无法注入) |
- 参数映射
1 | // 1.如果user对象中有字段如 uFullName (驼峰,首字母只有一个字符的情况) |
响应
@ResponseBody
- 表示以json返回数据
- 定义在类名上,表示所有的方法都是
@ResponseBody
的,也可单独定义在方法上
@RestController
中包含@ResponseBody
- 重定向
1 |
|
前端数组/对象处理
- json字符串传输方式一(不推荐)
- 前端通过
JSON.stringify
转成json字符串,然后后台JSONObject等转成Bean/Map等
- 前端通过
Spring的Bean自动注入
- 请求类型
POST
、Content-Type: application/json
,后端方法为public Result edit(@RequestBody CustomerInfo customerInfo)
接受,chrome开发者模式看到的为json对象 - 请求类型
POST
、Content-Type: multipart/form-data
、使用FormData传输参数,后端可使用public Result edit(Multipart myFile, CustomerInfo customerInfo)
接受,chrome开发者模式看到的同上文FormData。传输文件必须格式 请求类型
POST
、Content-Type: application/x-www-form-urlencoded
- chrome开发模式看到的
FormData
(格式化后的。实际请求是将每一项通过URL encoded
进行转义之后再已&
连接组装成url参数,此时POST参数是没有长度限制的)如: 后端写好对应的Bean,且后端方法如
public Result edit(CustomerInfo customerInfo)
- 后端代码
public Result edit(Map<String, Object> params)
报错 - 后端代码
public Result edit(String customerNameCn, List customerLines)
报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15id: 766706
customerNameCn: 客户名称
// CustomerInfo中的updateTm属性可以是Date(会自动转换)
updateTm: 2018/08/17 13:02:36
// CustomerInfo中的属性customerLines(属性名/setter方法必须和前端参数名保持一致)可以是List<String>或者String[]
customerLines[0]: AustraliaLine
customerLines[1]: MediterraneanLine
customerLines[2]: SoutheastAsianLine
// CustomerInfo中包含CustomerRisk和List<CustomerContacts>
customerRisk.id: 9906
customerRisk.customerId: 766706
customerRisk.note: 客户风险备注
customerContacts[0].id: 767001
customerContacts[0].customerId: 766706
customerContacts[0].lastName: 客户联系人1- 后端代码
- chrome开发模式看到的
- 请求类型
拦截request的body数据/拦截response的数据
SpringBoot中使用Servlet
- 使用方法
1 | // 方式一: 访问 http://localhost:8080/api/test/* 都可以进入到此servlet |
RestTemplate
简单使用
1 |
|
Bean配置
- 增加超时机制、自定义拦截器、忽略证书、处理中文乱码
1 | // 如果不设置 RestTemplate 相关属性,则无需手动引入 |
客户端端口限制
- 在对服务器进行连接时,会自动获取一个随机端口用于连接。(假设此客户端也对外提供服务,那么假设此时监听的为端口8080,当此客户端请求其他服务器时,是不会用8080作为连接端口的)
- linux可设置
/etc/system.config
中的net.ipv4.ip_local_port_range
来修改随机端口范围 - windows可用
netsh
命令设置
- linux可设置
- 固定TCP连接时的客户端端口。使用场景如:部分应用因安全考虑,只能指定端口访问外网 ^1
- 存在问题:只适用于对某个服务器的连接,或者多个服务器的少量连接(如果对多个服务器有大量并发连接可能会出现端口被占用问题)
1 | public static void main(String[] args) { |
文件上传下载(调用接口形式)
1 | // 参考:https://www.cnblogs.com/zimug/archive/2020/08/12/13488517.html |
文件上传下载
- 案例参考springboot-vue.md#文件上传案例
- 常用配置
1 | spring: |
- 使用JavaBean进行静态文件映射
1 |
|
- 上传文件临时目录问题
- 项目启动默认会产生一个tomcat上传文件临时目录,如:
/tmp/tomcat.4234211497561321585.8080/work/Tomcat/localhost/ROOT
- 而linux会定期清除tmp目录下文件,尽管项目仍然处于启动状态。从而会导致错误
Caused by: java.io.IOException: The temporary upload location [/tmp/tomcat.4234211497561321585.8080/work/Tomcat/localhost/ROOT] is not valid
- 项目启动默认会产生一个tomcat上传文件临时目录,如:
1 | // 自定义上传文件临时目录 |
后台会报错:no multipart boundary was found。此问题本身不是后台的原因,解决方法如下 [^21]
- 通过
axios.create
重新定义一个axios实例,并挂载到Vue原型上。此处重新定义是防止使用项目中默认的axios实例(一般会通过axios.interceptors.request.use进行处理,而处理后的实例在上传时后台会报错)。具体见上文案例 不严谨的处理
1
2
3
4
5
6// $axios为上文提到的被处理过的axios实例
this.$axios.post('http://localhost:8080/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data;boundary = ' + new Date().getTime()
}
}).then(response => {})
- 通过
参考文章