场景:
描述:
客户端默认编码为GB2312,服务端默认编码方式为UTF-8。客户端请求服务端,参数有中文。在实际请求过程中,客户端将中文“你好”编码为“%C4%E3%BA%C3”,服务端接收到会按照UTF-8格式进行解码,导致解码失败,得到的中文为一堆乱码。
原因分析:客户端和服务端两者编码方式不一致。
解决方法:
1、客户端、服务端两者统一的编码,如UTF-8。如何在tomcat、jetty中设置默认编码可自行百度。(jetty设置可能会有坑)
2、重点!!!!由于我的客户端是华为IVR,默认编码为GB2312,最重要的无法修改编码,那就只能从服务端入手了。其中遇到几个坑:
a.服务端默认编码不变,保持UTF-8,以request.getParameter(“session.sce.callid”);的方式获取参数,再通过字符编码GB2312各种转换。结果是失败!!!原因在于:request.getParameter(“session.sce.callid”);获取的参数已经是一段无法是别的乱码了!!!
b.修改jetty或tomcat默认编码格式,tomcat在web.xml中修改成GB2312后成功,jetty修改,死活不行,放弃!!!
最终解决方案:
在服务端获取最原始的参数,而非request.getParameter(“session.sce.callid”)。上面的例子最原始的参数是session.sce.callid=%C4%E3%BA%C3&,java里通过request.getQueryString();可以获得。在将字符用URLDecoder进行解码,URLDecoder.decode(queryString)。参考以下代码:
HttpServletRequest request = ServletActionContext.getRequest();
String queryString= request.getQueryString();
System.out.println(queryString);
String decodeString = URLDecoder.decode(queryString);
System.out.println(decodeString);
String[] params = decodeString.split("&");
for (int i = 0; i < params.length; i++) {
System.out.println("index" + i);
System.out.println(params[i]);
}
结果:
session.sce.callid=%C4%E3%BA%C3&
session.sce.callid=你好&
index0
session.sce.callid=你好
注意!注意!注意!重要的事情说3遍:
1、jetty高版本不可行。jetty会拦截掉请求,认为请求不合法,无法进入方法:
#2019-03-29 10:17:40.020|WARN |qtp919112242-26| org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:633)|/icss/IVRFirstCell.pub
org.eclipse.jetty.http.BadMessageException: 400: Unable to parse URI query
at org.eclipse.jetty.server.Request.getParameters(Request.java:387) ~[jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.Request.getParameterMap(Request.java:1024) ~[jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.apache.struts2.dispatcher.Dispatcher.createContextMap(Dispatcher.java:642) ~[struts2-core-2.3.35.jar:2.3.35]
at org.apache.struts2.dispatcher.ng.PrepareOperations.createActionContext(PrepareOperations.java:82) ~[struts2-core-2.3.35.jar:2.3.35]
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter.doFilter(StrutsPrepareFilter.java:86) ~[struts2-core-2.3.35.jar:2.3.35]
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1759) ~[jetty-servlet-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583) [jetty-servlet-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) [jetty-security-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:513) [jetty-servlet-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.Server.handle(Server.java:539) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:333) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251) [jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:283) [jetty-io-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:108) [jetty-io-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) [jetty-io-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) [jetty-util-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) [jetty-util-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) [jetty-util-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) [jetty-util-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) [jetty-util-9.3.25.v20180904.jar:9.3.25.v20180904]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
Caused by: org.eclipse.jetty.util.Utf8Appendable$NotUtf8Exception: Not valid UTF8! byte E3 in state 2
at org.eclipse.jetty.util.Utf8Appendable.appendByte(Utf8Appendable.java:247) ~[jetty-util-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.util.Utf8Appendable.append(Utf8Appendable.java:157) ~[jetty-util-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.util.UrlEncoded.decodeUtf8To(UrlEncoded.java:354) ~[jetty-util-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.util.UrlEncoded.decodeUtf8To(UrlEncoded.java:296) ~[jetty-util-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.http.HttpURI.decodeQueryTo(HttpURI.java:613) ~[jetty-http-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.Request.extractQueryParameters(Request.java:419) ~[jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
at org.eclipse.jetty.server.Request.getParameters(Request.java:383) ~[jetty-server-9.3.25.v20180904.jar:9.3.25.v20180904]
... 27 common frames omitted
2、jetty低版本可行(上面最终解决才去这种方案)。jetty会让请求通过,but会有警告:
#2019-03-29 10:23:57.071|WARN |qtp1237550792-24| org.eclipse.jetty.util.UrlEncoded.decodeUtf8To(UrlEncoded.java:393)|org.eclipse.jetty.util.Utf8Appendable$NotUtf8Exception: Not valid UTF8! byte E3 in state 2
#2019-03-29 10:23:57.071|WARN |qtp1237550792-24| org.eclipse.jetty.util.UrlEncoded.decodeUtf8To(UrlEncoded.java:393)|org.eclipse.jetty.util.Utf8Appendable$NotUtf8Exception: Not valid UTF8! byte Ba in state 0
#2019-03-29 10:23:57.072|WARN |qtp1237550792-24| org.eclipse.jetty.util.Utf8Appendable.toReplacedString(Utf8Appendable.java:303)|org.eclipse.jetty.util.Utf8Appendable$NotUtf8Exception: Not valid UTF8! incomplete UTF8 sequence
上面的问题解决用了很长时间,挺有成就感的。有不懂的地方,可以私信我!