不谈概念,只讨论一下怎么使用。工作上遇到的坑,记录一下。
环境:
既然是restful api,那么,前端使用jQuery ajax发送http请求,传递json类型的值。后端使用springboot来接收。
方式1
前端代码
var data = {
"bizData": "abc",
"bizSignature":"xxx",
"transSignature":"xxx",
"trans" : {
"type":"1",
"mac":"xxxx",
"serverNo":"xxxx",
"supvLoctNo":"xxxx"
}
};
$.ajax({
url: "http://localhost:9200/bbb1",
type: "GET",
data: data,
success: function () {
//
}
});
后端代码
@RestController
public class OutSystemApi {
@GetMapping("/bbb1")
public void OutInfoSystemIOgdsdclBsc(OutSystemVO outSystemVO){
int a = 1;
}
}
//POJO类
@Data
public class OutSystemVO {
//业务数据
private String bizData;
//业务签名
private String bizSignature;
//传输签名
private String transSignature;
}
很奇怪data中第一层的字段在java后端是可以正确映射的,而trans里面的内容,前端把他解析成了trans[mac]数组的形式,后端解析就直接报错了,不知道为什么。
Resolved exception caused by Handler execution: org.springframework.beans.InvalidPropertyException: Invalid property 'trans[mac]' of bean class [com.demo.model.vo.OutSystemVO]: Property referenced in indexed property path 'trans[mac]' is neither an array nor a List nor a Map; returned value was [cn.gov.customs.hsservice.model.vo.OutSystemTranVO@46146ca3]
然后在来看一段正常的代码
方式2
var data = {
bizData: "abc",
bizSignature:"xxx",
transSignature:"xxx",
trans: {
type:"1",
mac:"xxxx",
serverNo:"xxxx",
supvLoctNo:"xxxx"
}
};
$.ajax({
url: "http://localhost:9200/bbb1",
type: "POST",
data: JSON.stringify(data),
contentType: "application/json",
success: function () {
//
}
});
@PostMapping("/bbb1")
public void OutInfoSystemIOgdsdclBsc(@RequestBody OutSystemVO outSystemVO){
int a = 1;
}
这里 contentType: "application/json",http头部是需要指明为application/json类型。如果指定了类型,那么后端就要使用@RequestBody接收。但是其实浏览器还是很智能的,如果没有设置header的conten-type, 在body中传递了对象,浏览器会自动将content-type改成application/json。
而再来看看@RequestBody标签的意思:
@requestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。
方式3
一般正常的提交操作都是用方式2的,但在一些特殊的情况下可能就不满足需求了。
我们假设有这样一个需求,先需要取出提交上来数据的值,然后把值都拼在一起,拼成一个字符串,之后再进行业务操作。这里对前端提交的数据字段顺序就有要求了,如果每次都使用一样的顺序,可能就会出现问题。
java端我们使用的是一个pojo对象来接收前端的json数据。spring会自己使用Jackson包来把json字符串序列化成一个对象,那么就无法获得前端提交的字段顺序了。
也许我们可以这么干:
前端代码:
var bizData = {"idno":"360415844564456","igdsdclBscNo":"ccc804505f2a4f1d88267bf009acf751"}
var data = {
"transSignature":"xxx",
"bizData": bizData,
"bizSignature":"xxx",
"trans" : {
"type":"1",
"mac":"xxxx",
"serverNo":"xxxx",
"supvLoctNo":"xxxx"
}
};
$.ajax({
url:"http://localhost:9200/bbb",
type: "POST",
data: JSON.stringify(data),
contentType: "application/json"
});
后端代码:
@PostMapping("/bbb")
public void OutInfoSystemIOgdsdclBsc2(HttpServletRequest request){
JSONObject jsonParam = null;
try {
// 获取输入流
BufferedReader streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
// 写入数据到Stringbuilder
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = streamReader.readLine()) != null) {
sb.append(line);
}
jsonParam = JSONObject.parseObject(sb.toString(), Feature.OrderedField);
// 直接将json信息打印出来
System.out.println(jsonParam.toJSONString());
} catch (Exception e) {
e.printStackTrace();
}
int a = 1;
}
通过HttpServletRequest 对象来获取到输入流,然后将输入流的数据写入到字符串里面,最后转化为JSON对象。注意这里的parseObject存储对象内容使用的map,这将导致最后取得的数据是无顺序的,我们需要再添加一个参数Feature.OrderedField。 获得所有的json内容之后,再映射到具体的pojo对象上去。