restful 接口使用踩坑

不谈概念,只讨论一下怎么使用。工作上遇到的坑,记录一下。

环境:

既然是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对象上去。

你可能感兴趣的:(restful 接口使用踩坑)