spring目前来说是java最好的框架,springmvc是其中一个子集,
java web开发过程中使用springmvc来实现前端页面或者其他
客户端与后台服务层打交道,目前来说http请求最常用的就是
get和post请求,参数格式也不尽相同,有最原始的请求参数带
在url中,包括后边发展而来的表单提交,以及目前比较流行的
前后端分离使用的json格式参数做数据交互。今天就工作中
遇到的json格式的数据交互问题作出分析和解决方案.
由于刚到新公司时间不太长,难免会接受别人写的
不规范的代码和业务逻辑,以及非自己负责模块业务
逻辑出现问题后由于当事人不在或者已经离职,
就不得不去分析和修复测试环境和线上的各种问题,
今天简单介绍一个案例,我们测crm2.0项目使用了
前后端分离架构方案,所有的前端和后台的数据交互
方式都是纯粹的json格式,前几天遇到几个页面上
请求后台服务报400错误的问题。
根据自己的编程经验,根据400响应码,初步分析得知,
这是客户端的问题(4XX开头的错误都是客户端错误),
经过研究和分析前后端约定参数格式,问题进一步缩小
锁定到前端参数变动导致,后台接收参数使用的是bean,
前端使用的是json,springmvc接收并解析参数和赋值
给用@RequestBody注解的封装对象过程中,遇到json中
和bean中有不对应的属性时,会解析失败,框架层返回
400给客户端.
实际上是springmvc调用jackson进行数据转换时
发生了错误。springmvc默认使用@Jackson的
objectmapper类来进行转换工作,而objectmapper
在转换的时候默认情况下是如果在目标类中找不到
json字符串中的属性就会报错。这里贴出针对1.x版本
jackson的两种解决方法,2.x版本解决方法类似
方案一
在目标类上加注解@JsonIgnoreProperties,例如
12345678 | import org.codehaus.jackson.annotate.JsonIgnoreProperties;@JsonIgnoreProperties(ignoreUnknown = true)//忽略未知属性public class LoginReq implements Serializable {private String username;private String password;......} |
---|
方案二
写一个自定义的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);}} |
---|
在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> |
---|
对于前端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,这样的话就能正确返回要查询的数据了.
本文分享自 PersistentCoder 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!