前端参数请求和后端参数接受

HTTP协议中定义了很多与服务端交互的方法,其中最基本的有四种,分别是GET,POST,PUT,DELETE,对应增删改查四种操作,最常用的是GET和POST。

请求头类型Content-Type主要有:application/x-www-form-urlencoded,multipart/form-data和application/json。

application/x-www-form-urlencoded默认传参

其中application/x-www-form-urlencoded为默认的表单提交方式,提交的参数在请求体的form-data里。此时,前端如果通过ajax的默认方式传送参数而不做任何转换的话,参数到达后端是key1=value1&key2=value2…的形式,如下图所示(通过request.getReader获得缓冲输入流):
这里写图片描述

这种形式的参数可以被spingMVC默认的ServletModelAttributeMethodProcessor解析(通过request.getParameter获取)。如下图所示:
这里写图片描述
最终在处理方法处可以自动绑定到入参DTO上:
这里写图片描述

application/x-www-form-urlencoded + json 传参

前端如果通过JSON.stringify()进行编码,或者直接以json串形式传输的话,参数到达后端则是json形式,如下图所示:
这里写图片描述
此时默认的处理器是无法处理的,如下图所示:
这里写图片描述

ServletModelAttributeMethodProcessor解析时调用WebUtils的getParametersStartingWith方法,通过request.getParameterNames()来获取参数,以“=”和“&”做截断,json格式的参数中没有这两个符号,故解析出错。
此时后端就不能使用springmvc默认的请求处理器来解析了,也不能通过加@RequestBody使用RequestMappingHandlerAdapter处理器,因为不支持application/x-www-form-urlencoded,如下图所示:
这里写图片描述

application/json + json 传参

大多数情况下是这种形式的传参,正常处理即可。

下面说说博主实际遇到的问题。

有一个后端业务信息管理系统负责对业务系统的数据进行管理,增删改查等。管理系统的所有前端请求都是通过页面的ajax提交,使用默认请求头,参数未进行序列化。后端参数接收时未加注解。

现要增加工具方法接口,直接通过请求工具来发出请求,由于具体请求参数未知,后端需要通过HttpServerletRequest来接受请求的request。通过postman工具可以正常使用,但使用公司的小工具发送请求则会出现异常,原因是跨域请求(什么是跨域请求)。

于是添加了一个过滤器,该过滤器设置允许跨域请求,同时对request进行包装,以便多次读取(正常情况下,request的输入流只能读取一次)。最后在controller层通过request的getReader获取处理方法的request的输入流:

protected String getJsonRequestData(HttpServletRequest request, HttpServletResponse response) {
    if (null == request) {
        return null;
    }
    String method = request.getMethod();
    String ret = null;
    if (method.equalsIgnoreCase("GET") || method.equalsIgnoreCase("DELETE")) {
        ret = request.getQueryString();
    } else {
        ret = getBodyData(request);//获取请求body
    }
    return ret;
}
protected String getBodyData(HttpServletRequest request) {
    StringBuffer data = new StringBuffer();
    String line = null;
    BufferedReader reader = null;
    try {
        reader = request.getReader();
        while (null != (line = reader.readLine()))
            data.append(line);
    } catch (IOException e) {
        LOG.error("get request body data error: ", e);
        return null;
    }
    return data.toString();
}

这时候接口工具可以正常使用,解决了跨域问题。

但是问题来了,由于过滤器对request请求进行了包装,导致默认请求处理器无法对包装后的request参数进行解析(因为没有重写getParameter方法),所以原来的所有接口都无法获取请求参数。

解决办法有以下几种:

1. 添加@RequestBody注解,同时在ajax发送请求时,参数进行json序列化,且指定contentType为application/json(如果不指定,则不支持默认application/x-www-form-urlencoded类型)。

2. 使用自定义注解,用自定义参数解析器进行参数解析,同时在ajax发送请求时参数进行json序列化。

3. 过滤器中排除原接口请求路径,即原来的所有接口的请求都不过滤。

4. 过滤器中只过滤新的请求。实际上与方法3是一样,根据需要来选择。

显然方法3和方法4是改动最小的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值