接上一章,使用命令mvn jetty:run启动Argo,进入localhost的页面:
58在这里给了几种常见的访问和传值方法的示例,当点击到第三条《区分queryString和form参数》时,
会进入Post提交页面,填上name和phone之后提交。
这时遇到以下的错误:
com.bj58.argo.ArgoException: invoke exception. at com.bj58.argo.ArgoException$ArgoExceptionBuilder.build(ArgoException.java:98) at com.bj58.argo.internal.ActionInfo.invoke(ActionInfo.java:222) at com.bj58.argo.internal.MethodAction.matchAndInvoke(MethodAction.java:61) at com.bj58.argo.internal.DefaultRouter.route(DefaultRouter.java:45) at com.bj58.argo.internal.DefaultArgoDispatcher.route(DefaultArgoDispatcher.java:89) at com.bj58.argo.internal.DefaultArgoDispatcher.service(DefaultArgoDispatcher.java:70) at com.bj58.argo.servlet.ArgoFilter.doFilter(ArgoFilter.java:45) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at com.bj58.argo.internal.ActionInfo.invoke(ActionInfo.java:217) ... 21 more Caused by: java.lang.NullPointerException at com.bj58.argo.servlet.ArgoRequest.getParamsString(ArgoRequest.java:213) at com.bj58.argo.servlet.ArgoRequest.queryString(ArgoRequest.java:178) at com.bj58.argo.client.ClientContext$DefaultClientContext.queryString(ClientContext.java:187) at com.bj58.argo.controllers.HomeController.postForm(HomeController.java:34) ... 26 more
查看报异常的源码片段:
public Map<String, Collection<String>> queryStrings() { if (queryStrings != null) return queryStrings; MultiMap<String> params = new MultiMap<String>(); String originQueryString = super.getQueryString(); if(queryStrings != null){ UrlEncoded.decodeTo(originQueryString, params, "UTF-8", maxFormKeys); queryStrings = NullToEmptyMap.safeWrapper(params, getSafeParameter()); } return queryStrings; }
发现这个代码在逻辑上的确有问题:
if (queryStrings != null) return..
那么接下来又是一个
if (queryStrings != null)
中途又没有对queryStrings赋值,那么queryStrings无论是不是null值,下面的逻辑都毫无意义
显然下面的逻辑不对
将下面的条件改为queryStrings==null,提交成功了。
但是,这样就完了吗?没有
我们看一下ArgoRequest的修改记录,发现最后的改动是因为 同学报告说有BUG:
post提交时,遇到url如http://ip/a/b/,没有?以及参数情况.ArgoRequest.queryStrings()中调用super.getQueryString()时会返回null,所以要在UrlEncoded中加卫语句
58code认为不应该直接修改urlEncode的代码,理由是:
我们将此判断提前至ArgoRequest中,原则上不修改thirdparty内的source,不利于日后排查问题。
于是才有了后来的修改,把空值判断放ArgoRequest里,但是很显然把空值判断写错了,并且没有经过任何测试,正确的修改应该是这样的:
if(originQueryString != null)
而不是
if(queryStrings != null)
至此,问题解决!
同时,我们看到,58code开源已经不投入人员进行维护了,以前的修改也是草草。不过,Argo项目里面大量的注释写的都很清晰,简明扼要。