将UTF字符处理为JSON时,ApacheCamel异常 无效的UTF-8中间字节

问题描述

我们有一个骆驼网关服务,

  • 以JSON接收请求,将其转换为SOAP请求并调用 SOAP服务。

  • 并在收到SOAP响应后将其转换为JSON并发送 回到呼叫者服务。

现在,在将对POJO的SOAP响应转换为JSON时,它会抛出异常 在下面,

com.ctc.wstx.exc.WstxLazyException: [com.ctc.wstx.exc.WstxLazyException] Invalid UTF-8 middle byte 
0x26 (at char #8412,byte #7999)

SOAP响应带有一些 UTF字符,例如‖“,这引起了问题。 如何处理或忽略这些UTF字符并转换为JSON?

骆驼代码:Routes.java

private void getPlanDetailsRequestRoute(JacksonDataFormat jacksonDataformat,SoapJaxbDataFormat soapJaxbDataFormat,DataFormat jaxb) {
        from("servlet:/PlanDetailsRequestService?matchOnUriPrefix=true").unmarshal(jacksonDataformat).to("dozer:transformOrder?mappingFile=DozerMapping.xml&sourceModel=com.ong.vx.gatewayservice.dto.PlanRecord&targetModel=com.ong.vx.gatewayservice.wsdl.GetPlanDetailsRequest").marshal(soapJaxbDataFormat)
                .to("bean:SoapEnvelopeWrapper?method=process").to(WS_URI).choice()
                .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(500)).to("bean:ExceptionExtracter?method=process")
                .endChoice().otherwise().unmarshal(soapJaxbDataFormat).end().unmarshal(jaxb).marshal().json(JsonLibrary.Jackson)
                .setHeader(Exchange.CONTENT_TYPE,constant("application/json"));
    }

例外:

com.ctc.wstx.exc.WstxLazyException: [com.ctc.wstx.exc.WstxLazyException] Invalid UTF-8 middle byte 0x26 (at char #8412,byte #7999)
at com.ctc.wstx.exc.WstxLazyException.throwLazily(WstxLazyException.java:40)
at com.ctc.wstx.sr.StreamScanner.throwLazyError(StreamScanner.java:724)
at com.ctc.wstx.sr.BasicStreamReader.safeFinishToken(BasicStreamReader.java:3758)
at com.ctc.wstx.sr.BasicStreamReader.getTextCharacters(BasicStreamReader.java:914)
at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleCharacters(StAXStreamConnector.java:327)
at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:191)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:415)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:386)
at org.apache.camel.converter.jaxb.JaxbDataFormat.unmarshal(JaxbDataFormat.java:255)
at org.apache.camel.dataformat.soap.soapJaxbDataFormat.unmarshal(SoapJaxbDataFormat.java:284)
at org.apache.camel.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:69)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:542)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:197)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:542)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:197)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:197)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:97)
at org.apache.camel.http.common.CamelServlet.doService(CamelServlet.java:195)
at org.apache.camel.http.common.CamelServlet.service(CamelServlet.java:74)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
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:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
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:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
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.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
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.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
atorg.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at 
org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
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:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
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)
Caused by: com.ctc.wstx.exc.WstxIOException: Invalid UTF-8 middle byte 0x26 (at char #8412,byte #7999)
at com.ctc.wstx.sr.StreamScanner.constructFromIOE(StreamScanner.java:640)
at com.ctc.wstx.sr.StreamScanner.loadMore(StreamScanner.java:1004)
at com.ctc.wstx.sr.BasicStreamReader.readTextSecondary(BasicStreamReader.java:4729)
at com.ctc.wstx.sr.BasicStreamReader.finishToken(BasicStreamReader.java:3802)
at com.ctc.wstx.sr.BasicStreamReader.safeFinishToken(BasicStreamReader.java:3756)
... 71 common frames omitted
Caused by: java.io.CharConversionException: Invalid UTF-8 middle byte 0x26 (at char #8412,byte #7999)
at com.ctc.wstx.io.UTF8Reader.reportInvalidOther(UTF8Reader.java:315)
at com.ctc.wstx.io.UTF8Reader.read(UTF8Reader.java:206)
at com.ctc.wstx.io.ReaderSource.readInto(ReaderSource.java:89)
at com.ctc.wstx.io.BranchingReaderSource.readInto(BranchingReaderSource.java:57)
at com.ctc.wstx.sr.StreamScanner.loadMore(StreamScanner.java:998)
... 74 common frames omitted

Response Header in SOAP UI :

解决方法

您收到类似SOAP响应的UTF-8字符的声音的异常编码为ISO-8859-1,而不是UTF-8。另请参见this answer for details

您是否检查了响应的编码正确(根据XML声明?)并且响应的charset标头正确?如果没有,那么最好修复SOAP服务(源)。

如果您无法控制源代码,那么最好的选择就是采取变通办法。例如,在进行转换之前,使用正则表达式用正确的字符替换分散注意力的字符。