前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >@RequestBody报400分析与解决方案

@RequestBody报400分析与解决方案

作者头像
叔牙
发布2020-11-19 14:40:38
2.2K0
发布2020-11-19 14:40:38
举报
文章被收录于专栏:一个执拗的后端搬砖工
代码语言:javascript
复制
spring目前来说是java最好的框架,springmvc是其中一个子集,
java web开发过程中使用springmvc来实现前端页面或者其他
客户端与后台服务层打交道,目前来说http请求最常用的就是
get和post请求,参数格式也不尽相同,有最原始的请求参数带
在url中,包括后边发展而来的表单提交,以及目前比较流行的
前后端分离使用的json格式参数做数据交互。今天就工作中
遇到的json格式的数据交互问题作出分析和解决方案.
背景
代码语言:javascript
复制
由于刚到新公司时间不太长,难免会接受别人写的
不规范的代码和业务逻辑,以及非自己负责模块业务
逻辑出现问题后由于当事人不在或者已经离职,
就不得不去分析和修复测试环境和线上的各种问题,
今天简单介绍一个案例,我们测crm2.0项目使用了
前后端分离架构方案,所有的前端和后台的数据交互
方式都是纯粹的json格式,前几天遇到几个页面上
请求后台服务报400错误的问题。
分析
代码语言:javascript
复制
根据自己的编程经验,根据400响应码,初步分析得知,
这是客户端的问题(4XX开头的错误都是客户端错误),
经过研究和分析前后端约定参数格式,问题进一步缩小
锁定到前端参数变动导致,后台接收参数使用的是bean,
前端使用的是json,springmvc接收并解析参数和赋值
给用@RequestBody注解的封装对象过程中,遇到json中
和bean中有不对应的属性时,会解析失败,框架层返回
400给客户端.
解决方案
代码语言:javascript
复制
实际上是springmvc调用jackson进行数据转换时
发生了错误。springmvc默认使用@Jackson的
objectmapper类来进行转换工作,而objectmapper
在转换的时候默认情况下是如果在目标类中找不到
json字符串中的属性就会报错。这里贴出针对1.x版本
jackson的两种解决方法,2.x版本解决方法类似

方案一

代码语言:javascript
复制
在目标类上加注解@JsonIgnoreProperties,例如

12345678

import org.codehaus.jackson.annotate.JsonIgnoreProperties;@JsonIgnoreProperties(ignoreUnknown = true)//忽略未知属性public class LoginReq implements Serializable {private String username;private String password;......}

方案二

代码语言:javascript
复制
写一个自定义的ObjectMapper注入到
MappingJacksonHttpMessageConverter中,可以永久性解决
开发测试阶段前后端参数约定不统一导致的参数解析失败的问题
自定义ObjectMapper类:

123456789

import org.codehaus.jackson.map.DeserializationConfig;import org.codehaus.jackson.map.ObjectMapper;public class CustomObjectMapper extends ObjectMapper {public MyObjectMapper(){//目标类中找不到json字符串中属性时直接忽略this.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);}}

代码语言:javascript
复制
在spring主配文件中添加一下配置:

123456

<bean id="customObjectMapper" class="com.typhoon.springBootDemo.transfer.CustomObjectMapper" /><bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"><property name="supportedMediaTypes" value="application/json;charset=UTF-8" /><property name="objectMapper" ref="customObjectMapper" /></bean>

总结
代码语言:javascript
复制
对于前端json格式请求参数,后台控制器层有两种常用的接收方式,1)
使用上述所说的Bean接收,用法是@RequestBody LoginReq req,
2)使用Map接收,用法@RequestBody Map<String,Object> params,
使用map接收,解析器默认解析成Map<String,Object>类型,
对于这两种接收方式各有利弊:
I Bean接收,优点:由于要定义Bean,所以属性比较明确,
项目换人接手后比较易于维护;参数类型明确缺点:开发测试阶段
前后端参数格式约定不明确,或者请求参数变动比较频繁时,
后台解析参数报错
II Map接收, 优点:前端参数个数变动,字段名称变动,
字段类型变动,后台解析和接收都不会报错;参数的格式
校验和类型转换比较在业务逻辑中实现,并且在参数非法时
能够自定义给前端更加人性化的响应(前后端分离时,
可以根据不同的参数错误给不同的错误码和错误信息)缺点:参数名称和类型不明确,
字段值后台统一解析成Object类型,后台需要根据具体的业务去解析和校验;
被其他人接手后完全
不知所错,不知道返回的数据类型和字段名称.个人建议:我比较习惯使用Map接收json请求参数,
因为比较灵活,和参数校验和转换可是实现自定义,
以及对参数进行自定义加工,例如:前端页面查询一个
时间段用户注册列表信息,前端传来参数
beginTime:2017-08-01,endTime:2017-08-20,那么如果
我直接去数据库查询可能就是返回空列表,而如果我在
接受参数的时候对时间区间进行装配成beginTime:2017-08-01 00:00:00,
endTime:2017-08-20 23:59:59,这样的话就能正确返回要查询的数据了.
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-08-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PersistentCoder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 分析
  • 解决方案
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档