接上一章,使用命令mvn jetty:run启动Argo,进入localhost的页面:
58在这里给了几种常见的访问和传值方法的示例,当点击到第三条《区分queryString和form参数》时,
会进入Post提交页面,填上name和phone之后提交。
这时遇到以下的错误:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 |
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开源已经不投入人员进行维护了,以前的修改也是草草。
原文:http://www.cnblogs.com/mignet/p/argo_run.html