异常描述
Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "transIpAddr" (Class com.xxx.core.dto.RechargeWapReqDTO), not marked as ignorable
at [Source: org.apache.catalina.connector.CoyoteInputStream@3dcc4d63; line: 1, column: 17] (through reference chain: com.jrd.core.dto.RechargeWapReqDTO["transIpAddr"])
问题场景
- 项目架构模式:通过 Rest 以 Http 的请求方式连接各个项目,将接口拆分到一个公共的单独的项目中,包含对外接口、server 层及dao层;
- 在另一个项目调用此核心接口项目时,抛出上述异常
- 从异常信息中了解:是调用接口位置传递的参数,比接收参数的BEAN实体类多了一个属性值,所以对应不上
- 备注:RestTemplate 方式,接口参数传递时按照 JSON格式传递,所以接收方,会进行JSON –> Bean 的转换
- 问题:如果是参数前后有差异,问题就好定位了;但是调用方与接收方参数的位置是同一个实体类Bean,不存在类中属性内容不一致的问题
- 按照如下几个思路查询问题:
- 从缺少的属性字段入手,项目空间全部项目检索,发现此属性字段是存在的,但不是在此接口的参数中,而是在此接口中,使用了BeanUtils.copyProperties(A,B);A 是接口的参数,B是copy的目的类,但B继承了C,C中包含此属性值;但是从日志上分析,接口根本就没有执行,也就是另一个项目的HTTP请求在被此核心项目接到后,就被拦截了,还没有走到方法体内部
- 从异常的内容入手,HttpMessageNotReadableException,但没有检索到在何处使用到了此JSON数据转化类
public class JRDMappingJacksonHttpMessageConverter extends MappingJacksonHttpMessageConverter {
@Override
public Object read(Type type, Class<?> contextClass,
HttpInputMessage inputMessage) throws IOException,
HttpMessageNotReadableException {
System.out.println("@RequestBody:"+contextClass.getName()+":"+inputMessage.getBody().toString());
return super.read(type, contextClass, inputMessage);
}
@Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
System.out.println("@RequestBody:"+clazz.getName()+":"+inputMessage.getBody().toString());
return super.readInternal(clazz, inputMessage);
}
}
CustomHandlerExceptionResolver 有用到,在SpringMVC.xml 配置文件中有配置,异常信息管理类
- 从配置文件入手,没有发现
<!-- 添加注解驱动 -->
<!-- <mvc:annotation-driven /> -->
<!-- HandlerMapping -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.jrd.interceptor.LogInterceptor" />
<bean class="com.jrd.interceptor.SecurityInterceptor" />
<bean class="com.jrd.interceptor.SessionTimeoutInterceptor">
<property name="allowUrls">
<list>
<value>/login</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
</bean>
<!-- validator -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
<property name="validationMessageSource" ref="messageSource"/>
</bean>
<bean id="webBindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService"/>
<property name="validator" ref="validator"/>
</bean>
<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<!-- <ref bean="mappingJacksonHttpMessageConverter" />json转换器 -->
<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter" />
<bean id="formHttpMessageConverter"
class="org.springframework.http.converter.FormHttpMessageConverter" />
<bean id="byteArrayMessageConverter"
class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
<bean id="bufferedImageHttpMessageConverter"
class="org.springframework.http.converter.BufferedImageHttpMessageConverter" />
<bean id="jacksonMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</list>
</property>
<property name="webBindingInitializer" ref="webBindingInitializer"></property>
</bean>