ajax请求传递对象接收不到,Ajax 直接发送 PUT 请求,后端无法接收到数据的原因及解决方案...

标签:一、问题描述:

使用 Ajax 直接发送 PUT 请求,但 Spring MVC 封装的对象中,除过 URI 中带有的 id 字段被成功封装,请求体中的数据没有被封装到对象中。

通过测试,前端传来的请求体中有数据;通过 HttpServletRequest 对象,使用 request.getParameter() 方法却也获取不到数据

二、解决方案:

在 web.xml 中添加 HttpPutFormContentFilter 过滤器,原理向下看:

1

2

httpPutFormContentFilter

3

org.springframework.web.filter.HttpPutFormContentFilter

4

5

6

httpPutFormContentFilter

7

/*

8

三、原因分析:

1. Tomcat 会将请求体中的数据封装成一个 Map,调用 request.getParameter() 会从这个 Map 中取值,Spring MVC 封装 POJO 对象时,对于对象中的每个属性值也会调用 request.getParameter() 方法去获取,然后赋值给对象相应的属性,完成属性封装。

2. 但是,对于 PUT 请求,Tomcat 不会封装请求体中的数据为一个 Map,只会将 POST 请求的请求体中数据封装成 Map;这样的话,无论是直接调用 request.getParameter() 方法,还是 Spring MVC 封装对象,肯定都拿不到属性值了。

四、源码分析:

1. 在 Tomcat 源码中 org.apache.catalina.connector 包的 Request.java 类中 parseParameters() 方法用来解析请求参数,方法先会进行一系列设置和判断,然后再解析请求参数。其中,下面这段代码就会判断请求类型,如果符合 if 条件就会直接返回,也就是判断 parseBodyMethod 中是不是包含当前的请求方式,如果包含,Tomcat 服务器就继续处理解析请求体中的参数,封装到 Map 中;如果不包含,就直接返回,而不再执行下面的方法解析参数,那么 Map 中也就没有相应的参数了。

1 if( !getConnector().isParseBodyMethod(getMethod()) ) {

2

success = true;

3

return;

4 }

2. getConnector() 方法用来获取当前连接对象,然后调用 isParseBodyMethod() 方法判断 parseBodyMethodSet 集合中是不是包含传进来的 method 的值,这个 method 值就是当前的请求方式。

1 /**

2 * Request.java类中

3 * 获取当前的请求方式

4 */

5 public String getMethod() {

6

return coyoteRequest.method().toString();

7 }

8

9 /**

10 * Connector.java类中

11 */

12 protected boolean isParseBodyMethod(String method) {

13

return parseBodyMethodsSet.contains(method);

14 }

3. parseBodyMethodSet 集合中一般使用的都是默认值,也就是相当于将 parseBodyMethods 的值赋给了 parseBodyMethodSet,而 parseBodyMethods 的值默认是 post。

1 /**

2 * 调用 setParseBodyMethods 将 getParseBodyMethods() 获取的 parseBodyMethods 的值赋值给

3 * parseBodyMethods

4 */

5 protected void initInternal() throws LifecycleException {

6

7

// ...

8

9

// Make sure parseBodyMethodsSet has a default

10

if( null == parseBodyMethodsSet ) {

11

setParseBodyMethods(getParseBodyMethods());

12

}

13

14

// ...

15 }

16

17 /**

18 * 获取 parseBodyMethods 的值

19 */

20 protected String parseBodyMethods = "POST";

21

22 public String getParseBodyMethods() {

23

return this.parseBodyMethods;

24 }

25

26 /**

27 * 定义连接器的规则,如果连接器允许解析非POST请求的请求体,就传入规则,默认都是没有的

28 * 所以 parseBodyMethodSet 使用的是默认值

29 * 将 methods 的值赋值给 parseBodyMethods

30 * 将 methodSet 的值赋值给 parseBodyMethodsSet

31 */

32 public void setParseBodyMethods(String methods) {

33

34

HashSet methodSet = new HashSet();

35

36

if( null != methods ) {

37

methodSet.addAll(Arrays.asList(methods.split("\\s*,\\s*")));

38

}

39

40

// ...

41

42

this.parseBodyMethods = methods;

43

this.parseBodyMethodsSet = methodSet;

44 }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值