首先說一下當時的場景,其實就是一個很簡單的添加操作,后台傳遞的值是json格式的,如下圖
,后台對應的實體類,
@Data @EqualsAndHashCode(callSuper = false) public class Route implements Serializable { private static final long serialVersionUID = 1L; /** * id */ private String id; /** * 設備id */ private String deviceId; /** * 路由地址 */ private String destNetwork; /** * 下一跳 */ private String nextHop; /** * 路由所屬zone */ private String zone; /** * 0:系統解析;1:明細路由;2:假路由 */ private String isReload; /** * nat路由 */ private String isNatDummyRoute; private String createTime; /** * 是否禁用,主要適用於系統解析路由 */ private String isDisabled; @TableField(exist = false) private Device device; /** * 路由轉化后的對象 */ @TableField(exist = false) private IpAddr ipAddr; }
后台對應的Controller中的代碼
@RequestMapping(value = "add",method = RequestMethod.POST) public R add(@RequestBody Route route){ String deviceIp = route.getDeviceId(); Device device = deviceService.getByIp(deviceIp); Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateStr = sdf.format(date); route.setDeviceId(device.getId()); route.setIsDisabled("0"); route.setCreateTime(dateStr); routeService.save(route); return R.success(); }
,看代碼可知,頁面傳遞到后台的值應該能直接轉成實體類Route對應的字段。但是並沒有,報錯信息是如下:
2020/09/28-10:52:00 WARN [http-nio-8999-exec-6] MappingJackson2HttpMessageConverter - Failed to evaluate Jackson deserialization for type [[simple type, class com.interact.firewall.base.biz.entity.Route]]: com.fasterxml.jackson.databind.JsonMappingException: Conflicting setter definitions for property "parent": com.interact.firewall.core.bean.service.Service#setParent(1 params) vs com.interact.firewall.core.bean.service.Service#setParent(1 params) 2020/09/28-10:52:00 WARN [http-nio-8999-exec-6] MappingJackson2HttpMessageConverter - Failed to evaluate Jackson deserialization for type [[simple type, class com.interact.firewall.base.biz.entity.Route]]: com.fasterxml.jackson.databind.JsonMappingException: Conflicting setter definitions for property "parent": com.interact.firewall.core.bean.service.Service#setParent(1 params) vs com.interact.firewall.core.bean.service.Service#setParent(1 params) 2020/09/28-10:52:00 ERROR [http-nio-8999-exec-6] GlobalExceptionHandler - 捕獲到Exception異常 org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:225) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:158) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:131) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)
於是我就按照這個異常信息去排查,
有人說是缺少依賴。但是並沒有解決
有人說是字段沒有映射對,就是說頁面傳遞到后台的值跟實體類對應不上,但是我反復比對沒有問題。
之前實體類中還寫了一部分處理數據的方法,我也進行刪除進行測試還是不行。
后來請教同事,同事也懷疑是實體類的問題,於是重新建了一個實體類,只要數據庫的字段,不是數據庫中的字段進行刪除,結果可以了,於是繼續排查,確認到底是哪個地方引起的,最終確認了,是因為實體類中引用了一個對象。將引用的這個對象刪掉就沒問題了,但是我們想了一下,其他的實體類也有因為需要關聯查詢直接引其他對象的,但是卻沒有出問題。為什么單單這個出問題呢。
其實報錯中已經有提示了,在異常信息上邊有兩行警告代碼:
Failed to evaluate Jackson deserialization for type [[simple type, class com.interact.firewall.base.biz.entity.Route]]: com.fasterxml.jackson.databind.JsonMappingException: Conflicting setter definitions for property "parent": com.interact.firewall.core.bean.service.Service#setParent(1 params) vs com.interact.firewall.core.bean.service.Service#setParent(1 params)
說的其實是序列化相關的問題,后來我們查看了一下在Route中引用的對象,確實,並沒有實現Serializable 這個接口,導致這個問題的發生,但是這個對象又必須引用,那怎么辦呢?想了一下,是不是有個注解能夠忽略反序列化字段呢?於是查了一下,果然有
JsonIgnore這個注解就可以將被標記屬性忽略反序列化功能。
總結一下:其實這個問題的根本原因就是實體類中引用了一個沒有實現實現Serializable 接口的對象,無法被反序列化,只需要在這個對象上添加@JsonIgnore這個注解即可。對了 一直在說沒有實現Serializable接口的對象是實體類中最后一個Ipaddr那個對象。
/** * 路由轉化后的對象 */ @TableField(exist = false) @JsonIgnore private IpAddr ipAddr;