Spring版本:3.2.7
Jackson版本:
1 <!--Jackson --> 2 <dependency> 3 <groupId>com.fasterxml.jackson.core</groupId> 4 <artifactId>jackson-databind</artifactId> 5 <version>2.1.3</version> 6 </dependency> 7 <dependency> 8 <groupId>com.fasterxml.jackson.core</groupId> 9 <artifactId>jackson-core</artifactId> 10 <version>2.1.3</version> 11 </dependency> 12 <dependency> 13 <groupId>com.fasterxml.jackson.core</groupId> 14 <artifactId>jackson-annotations</artifactId> 15 <version>2.1.2</version> 16 </dependency>
背景:
需要将后端的一个对象,通过SPringMVC框架,传递到前端时,自动转换成对应的JSON格式报文。
堆栈信息:
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: No serializer found for class
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable
SerializationConfig.SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.siebre.pms.common.model.ResponseVO["data"]-
>com.siebre.pms.template.model.LiabilityTemplateDO["propertyAssignments"]->org.hibernate.collection.PersistentBag[0]-
>com.siebre.pms.template.model.PropertyAssignmentTemplateDO["propertyTemplate"]->com.siebre.pms.template.model.PropertyTemplateDO_$
$_javassist_187["handler"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable
SerializationConfig.SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.siebre.pms.common.model.ResponseVO["data"]-
>com.siebre.pms.template.model.LiabilityTemplateDO["propertyAssignments"]->org.hibernate.collection.PersistentBag[0]-
>com.siebre.pms.template.model.PropertyAssignmentTemplateDO["propertyTemplate"]->com.siebre.pms.template.model.PropertyTemplateDO_$
$_javassist_187["handler"])
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.writeInternal
(MappingJackson2HttpMessageConverter.java:207)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:179)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
$ServletHandlerMethodInvoker.writeWithMessageConverters(AnnotationMethodHandlerAdapter.java:1037)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.handleResponseBody
(AnnotationMethodHandlerAdapter.java:995)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.getModelAndView
(AnnotationMethodHandlerAdapter.java:944)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod
(AnnotationMethodHandlerAdapter.java:441)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:844)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:627)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.siebre.web.servlet.filter.CorsFilter.doFilter(CorsFilter.java:53)
at com.siebre.web.servlet.filter.CorsFilter.doFilter(CorsFilter.java:34)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.siebre.webapp.filter.WindowContextFilter.doFilterInternal(WindowContextFilter.java:274)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.SessionFixationProtectionFilter.doFilterHttp(SessionFixationProtectionFilter.java:67)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.providers.anonymous.AnonymousProcessingFilter.doFilterHttp(AnonymousProcessingFilter.java:105)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.rememberme.RememberMeProcessingFilter.doFilterHttp(RememberMeProcessingFilter.java:116)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp
(SecurityContextHolderAwareRequestFilter.java:91)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at com.siebre.security.ui.ClientLoginProcessingFilter.doFilterHttp(ClientLoginProcessingFilter.java:147)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.basicauth.BasicProcessingFilter.doFilterHttp(BasicProcessingFilter.java:174)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:277)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:230)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.siebre.webapp.filter.CacheControlFilter.doFilter(CacheControlFilter.java:34)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.siebre.webapp.filter.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:29)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:845)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:688)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1315)
at java.lang.Thread.run(Thread.java:595)
错误原因分析:
后端对象中,有部分对象是以懒加载的形式初始化的,在ObjectMapper将对象转为JSON时,这部分对象尚未初始化,报错。
解决方案分析:
这种情况,在Jackson设计的时候,一定会考虑到。
通过堆栈信息,不难发现,这个转换工作,是由框架的 MappingJackson2HttpMessageConverter 这个类完成。
通过堆栈信息,还可以发现,问题主要由ObjectMapper的这个属性:SerializationFeature.FAIL_ON_EMPTY_BEANS,引发的。
由此,我们可以自定义一个 Mapper 继承 ObjectMapper,将以上属性转成我们所需要的即可。
解决方案:
1 public class CustomMapper extends ObjectMapper { 2 3 public CustomMapper() { 4 this.setSerializationInclusion(JsonInclude.Include.NON_NULL); 5 // 设置 SerializationFeature.FAIL_ON_EMPTY_BEANS 为 false 6 this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 7 } 8 9 }
1 <bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 2 <!-- 解决 HttpMediaTypeNotAcceptableException: Could not find acceptable representation --> 3 <property name="supportedMediaTypes"> 4 <list> 5 <value>text/html;charset=UTF-8</value> 6 <value>application/x-www-form-urlencoded;charset=UTF-8</value> 7 <value>application/json;charset=UTF-8</value> 8 </list> 9 </property> 10 <!-- 解决懒加载问题 --> 11 <property name="objectMapper"> 12 <bean class="com.siebre.pms.actual.service.util.CustomMapper"> 13 </bean> 14 </property> 15 </bean>
Over,问题解决!