Springboot学习之Http Form请求参数丢失处理

Springboot学习之Http请求参数丢失处理


前言

最近使用springboot开发一后端程序,遇到了一些奇怪的问题,今天分享一下关于参数丢失的问题,和相关的解决方案和调试手段。

且看一下demo,这是一个简单的controller,这里我使用了swaager2生成RESTful Api文档

@Controller
public class CcbHouseController {
    @ApiOperation(value = "1.1说hello")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用户id", required = true, paramType = "form", dataType = "String")
    })
    @RequestMapping(value = "/sayhello", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String sayhello(String id) {
        Response mResponse = new Response();
        if (IsNullUtil.stringIsNull(id)) {
            return mResponse.error("参数不能为null");
        }
        return mResponse.ok("返回成功","hello");
    }
}

后端代码很简单,前端使用ajax进行请求

    $.ajax({
        type: "post",
        url: "http://127.0.0.1:8080/sayhello",
        async: true,
        data: "id=1",
        success: function(data) {

        }
    });

代码看似很简单,运行时也不会报错,但是如果在ajax请求加上contentType这个属性,很多小伙伴就会出错。

第一类错误contentType协议不正确

很多人会使用contentType:”application/json”这种协议。
错误示例:

    var postData={id:1};
    $.ajax({
        type: "post",
        url: "http://127.0.0.1:8080/sayhello",
        async: true,
        data: JSON.stringify(postData),
        contentType: "application/json",
        success: function(data) {

        }
    });

我们的后端是接收的是Form请求,这里发送的是json格式,后端肯定接收不了参数,于是报了错。
正确的应该是:

contentType: "application/x-www-form-urlencoded;charset=UTF-8",

application/x-www-form-urlencoded协议发送form请求,后端才会收到请求。
一般ajax请求不加contentType,默认是application/x-www-form-urlencoded协议。
所以前言中的代码不会报错。初学者容易犯这类错误。

第二类错误:特殊字符乱码导致参数丢失

这类错误,我在查资料时,看到一些人遇到过这类错误。这类错误多发在GET请求,参数中包含一些特殊符号。
使用encodeURIComponent可以解决,这里不详细描述,我没遇到过。机智。

主要是第三类错误,也是最难查找的一类。

第三类错误:UTF-8 BOM编码,不能被处理

这是一个同事使用c#进行作为C端,进行请求时,显现出来的问题。

问题描述:

这个同事调用我的接口,经常出现有时候能请求成功,有时候不能请求成功的问题。

刚拿到这个问题时,我查了一下日志,发现提示id参数丢失,这么短会丢失?心里一万个草泥马奔腾而过。
我立马用swagger2生成的API文档测试了一下,发现没问题啊,怎么回事?初步怀疑是同事的代码有问题。和同事沟通,查看了一下他请求的代码,并使用Fiddler进行抓包。发现一切正常。

这里就不得不说一下fiddler了,一个很好的抓包工具。但是有一个缺点,服务端的包好像抓不到。只能抓到C端的包。不知道是不是我的打开方式不对。

抓包后发现别人的请求参数没问题啊,于是心惊胆颤的查看自己的代码,也没问题啊。并且使用ajax请求也没问题。苦苦在某度上搜索了很久,没找到答案,于是准备再次抓包。这次抓服务端的包。

问题解决

于是使用了wireshark进行抓包。这个工具很强大,可以抓到请求和返回的二进制数据。
抓包结果如下

POST /sayhello HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Accept: */*
Host: 192.168.0.101:8090
Content-Length: 7
Expect: 100-continue
Connection: Keep-Alive

...id=1HTTP/1.1 200 
Content-Type: text/plain;charset=UTF-8
Content-Length: 84
Date: Tue, 10 Jul 2018 06:40:52 GMT

{"resultCode":1,"resultMsg":"...............null.........","resultType":1,"data":""}

发现请求参数前面有3个…,这3个…是什么鬼?使用二进制查看了一下,是一串ef bb bf,于是打开某度,搜索了一下出来了utf-8 bom,初步查看了一下他们的区别,原来就是当初的协议制时,搞得一个东西,很多语言,不支持此种格式。java也包含其中。

确定了问题,那就让C#端的同事去掉请求时的这个东西。

using System.Text;
var encoding = new UTF8Encoding(false);

使用这个可以去除,其它语言,请自行去除。

第四类错误:请求头Accept未设置

Accept代表客户端希望接受的数据类型
这类错误,比较容易发现,只要对比请求头即可。
解决办法:加上Accept:/ 即可。

好了,问题解决了,折腾了一两天。又可以happy的玩耍了。

猜你喜欢

转载自blog.csdn.net/u012489412/article/details/81109763