关于研究Webservice问题总结与心得体会
关于研究Webservice问题总结与心得体会 ? 一、问题描述分析 ??? 在前期我们调用edms系统中的webservice接口时,出现了问题。我们用了JDK Web服务API和第三方框架Axis1(Axis2)以及HttpClient等方式来连接webservice接口,最终均失败。在后台打印日志,错误描述如下: java.io.IOException:Server returned HTTP response code: 401for URL: https://dms-test.sfchina.bmw.com.cn/FH/FileHold/UserRoleManager/WindowsLogin.asmx/Satsun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626) 在网上查阅,401错误是没有权限。这个问题困扰了我们很久,我们研究了webservice原理和尝试了多种访问Webservice的方式与写法,最终我们采用前端javascript中拼接SOAP消息的方式发送请求,用new ActiveXObject("Microsoft.XMLHTTP")这个异步对象传递消息;这样的话只要是域用户并已成功登录ARP系统,那么在edms系统中就会验证通过。最终解决了问题。 可是,我们用了两周的时间来解决这个问题,中间着实走了很多很多弯路。现在,回忆解决这一问题一路走来的历程,总结研究的思路。想一想我们研究的过程中那些走了弯路,哪些是当时没有考虑到的,哪些又是我们的想法的有偏差的,做一总结,以便以后遇到类似问题,或者其他的问题,吸取教训,总结经验,少走弯路,更能一步到位。 ? 二、前期研究过程与结果 1.Axis1以及Axis2框架访问 首先,我们采用Axis框架访问webservice接口,关键调用实例如下: Stringendpoint="https://dms-test.sfchina.bmw.com.cn/FH/FileHold/UserRoleManager/SessionManager.asmx/";??? Stringns="http://filehold.com/userrolemanager/sessionmanager/"; StringoperationName = "IsSessionValid";?? Serviceservice = new Service();?? Callcall = (Call) service.createCall(); call.setTargetEndpointAddress(endpoint);?? call.setOperationName(newQName(ns,operationName));????? ? call.addParameter(newQName(ns,"sessionId"),org.apache.axis.encoding.XMLType.XSD_STRING,javax.xml.rpc.ParameterMode.IN);?? call.addParameter(newQName(ns,"keepAlive"),org.apache.axis.encoding.XMLType.XSD_BOOLEAN,javax.xml.rpc.ParameterMode.IN);?? call.setReturnClass(java.lang.String[].class);? call.setUseSOAPAction(true);?? call.setSOAPActionURI(ns+"IsSessionValid");? res=(boolean)call.invoke(new Object[]{"200",true}); 结果:出现问题401没有权限,不能访问。 分析:由于我们访问地址是由外网访问的,最终结果为401没有权限访问,可以看到我们访问的地址格式是https,当时我单纯的认为是由于访问https的地址,外网是没有权限。所以,我们又开始研究http和https访问的区别,现在回想起来,其实关键问题不在这里,在这里耽误了时间。不过,我们也很快证实了这一点。 2.Javaweb服务的API实现 使用基于底层java API的SOAP message的Web服务发送消息,关键代码如下: URLurlTemp=new URL("http…."); URLConnectionconnection = urlTemp.openConnection(); connection.setDoOutput(true); out =new OutputStreamWriter(connection.getOutputStream(),"UTF-8"); StringBuffersb = new StringBuffer(); sb.append("sessionId=1111&"); sb.append("keepAlive=true"); out.write(sb.toString()); out.flush(); StringsCurrentLine; sCurrentLine= ""; InputStreaml_urlStream; l_urlStream= connection.getInputStream();// 请求 BufferedReaderl_reader=newBufferedReader(newInputStreamReader(l_urlStream)); ????????????? ??while ((sCurrentLine = l_reader.readLine()) != null) { ????????????? ?????? sTotalString.append(sCurrentLine); ????????????? ??} ????????????? ??System.out.println(sTotalString); ????????????? ?} 结果:依然报同样的401错误。 分析:由1和2的访问我们得出结论: 1)401权限的问题,关键不在于访问https这种格式,因为我们证实了用这种访问其他https格式的webservie接口,依然能成功。当时我们问题定位有误。耽误了些许时间。 2)由于这两种访问方式一种是由第三方框架Axis,另一种是有JAVA JDK自带的底层访问方式,我们测试过这两种方式访问其他的接口(例如天气遇到接口)均没有问题,可是我们链接edms系统webservice接口,是连不上的,没有权限访问。当时我认为,这两种写法是没有问题的。只要我们解决访问权限问题,并把验证用户的身份信息附到访问访问程序中,一切问题就解决。所以接下来,我们把重点放到权限这里。 ??? 3.权限验证 ?? 接下来,我们想着如何将身份用户信息提交到服务端,首先我们获得一个域用户,并成功登录ARP系统。接下来,我们用Axis1来访问,并附上登录用户信息,调用call.serUserName()和call.getMessageContext().setUsername(username),可是依然报401错误,后经过沟通知道,在.Net中提供了一个NetworkCredential类,通过它我们可以在网络中提供一个凭证,只有获得该凭证的用户才能访问相应的服务的权限。之后我又到网上查,尝试java.net.Authentucator、org.apach.axis2.transport.http.HttpTransportProperties.Authenticator,这些我们都一一试过,可都无济于事。 ??? ?其实,问题进展到这一步,我们能想到权限的问题,想到只有ARP的登录用户才能访问Edms的接口,经过查阅API文档我们获取的信息得知,edms系统会记录当前用户的sessionId这一关键信息,如果当初知识储备够丰富的话,我们就该考虑到用浏览器访问,完全用前端JavaScript访问webservice,这样才可以记录当前的用户信息,这样才能做到用户和edms中的联系,而非ARP的服务端与edms的联系。现在回想起来,我们在这里耗费了太多的时间。 4.HttpClient模拟浏览器访问接口。 ??? 不过,我们在想到用js访问webservice之前,也在网上了解到使用httpclient4.*的包,用httpClient的方式模拟浏览器访问webservice,并试着在其中附用户权限,关键代码如下: 我们采用拼soap协议的方式然后发送到webservice, 结果:在调用接口任无结果,报401无法访问。 分析:做到现在,我们已经确认两点:1)我们想要进入edms,必须在ARP中登录,该用户的信息才能通过验证。2)edms能记录用户的session,那么就说明我们用浏览器访问,这样的话,才能起到用户关联edms系统。 三、后期问题分析与结果 根据前期的分析,我们已确定以下两点: 1.根据Edms系统中要求访问者是已登录用户,我们必须在ARP系统中使用域用户单点登录成功,而且在edms系统中必须有该域用户的域信息,这样方可验证成功。(在前期我们联系IT部门已将axi1975用户设为域用户并拥有访问权限)。 2.根据接口API(FileHold)开发说明文档,edms会记录当前已用户的信息sessionid,那么我们只能采用浏览器的方式去请求webservice接口,这样,类似于通过浏览器自动记住当前已登录用户的身份信息,其中包括在后面通过调用webservice返回的sessionId值。 ??? 显然,在java类中我们很难将身份信息提交到服务端,即使我们验证通过,那么当前用户的session怎么保存,怎么去控制它的失效时间。所以我们需要在浏览器中,用前端javascript中拼接SOAP消息的方式发送请求,用new ActiveXObject("Microsoft.XMLHTTP")这个异步对象传递消息;这样的话只要是域用户并已成功登录ARP系统,那么在edms系统中就会验证通过。 实例代码: vardata; document.getElementById("data").innerHTML= xmlhttp.responseText; 四、解决问题与学习总结 ??? ?经过了两周的学习与研究,利用webservice连接edms接口,这一过程我们着实走了很多的弯路,也有一些认识上的错误和理解上的偏差:没有更仔细的研究开发API文档,所以没有能想到用浏览器前端访问webservice;没有更好的拓展自己的知识来解决问题,所以忽视了用JS来访问webservice的方式。这些疏忽和认识的错误,造成了很多时间和人力的浪费。所以,这是一次教训,总结经验,扩展知识面。如果以后遇到类似问题,我们能否少走弯路,甚至一步到位。 五、心得体会 ??? 在开发webservice接口这一过程中,由于前期对webservice不够了解,所以刚开始研究其原理,掌握其用法。研究了两周由于权限问题被卡住,几乎没有进展。这也暴露出我的知识储备不够,在研究webservice知识时走马观花,没有系统全面的学习,导致没有想到用jS访问webservice。虽然进展不是很顺利,但最终解决了问题,最重要的是在这一过程中学到了很多。 1.遇到问题,一定要冷静的思考,想到问题点的入口后,继续往下钻,如果有进展,那继续研究;否则,迅速换一思路,寻找另一突破口。 2.在研究新的技术,要将该技术涉及相关的点都要了解到,想想如果自己早了解用JS访问webservice的话,可能就会少走一些弯路。 3.有的时候,询问别人也是一种方法。与别人分享自己的问题,看看别人是怎么想的,说不定你的问题别人也遇到过,他们的建议或许对自己有启发,比自己在那里独自思考可能会更好更快。 4.我们在研究一个问题时,如果自己花费了很多时间与精力在这个事情上,仍然没有解决问题,那么试着换一种思路,拓展知识面寻求其他办法,换一种思维或许会引刃而解。想想如果webservice这个问题继续按照我之前的写法与思路,也许再研究两周也没有什么进展。所以,接下来的学习中开阔知识面也很重要, 4.在编程方面,如果要测试某一功能的写法,在网络资料中找到相关代码demo,先全部Copy到环境中,确定成功执行的情况下,然后再根据自己的情况修改,这样可以减少很多不必要的错误。 5.要仔细阅读开发文档,如果我们仔细的阅读那个API文档,从中早一点发现并推敲上面的信息,或许我们能早一点找到用这一种方式去访问webservice。 6.成功=坚持冲过起步的低谷 + 良好的学习方法+ 勤敲代码的习惯 + 处理问题分析问题解决问题的能力 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |