京山游俠

          專注技術(shù),拒絕扯淡
          posts - 50, comments - 868, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
          在前面的隨筆中,我講了我的網(wǎng)站架構(gòu),這樣的架構(gòu)決定了我的網(wǎng)站中必須得用到WebService。比如,在用戶注冊(cè)的時(shí)候,用戶數(shù)據(jù)主要是保存在內(nèi)容服務(wù)器中,但是同時(shí)也要將部分?jǐn)?shù)據(jù)提交到索引服務(wù)器中,這時(shí),就可以讓內(nèi)容服務(wù)器訪問索引服務(wù)器提供的WebService來提交數(shù)據(jù);還可以讓內(nèi)容服務(wù)器通過定時(shí)任務(wù),訪問索引服務(wù)器的WebService來提交統(tǒng)計(jì)數(shù)據(jù)。

          我的網(wǎng)站使用SpringSide 2.0開發(fā),在SpringSide 2.0中,默認(rèn)使用的是XFire來提供WebService,但是我按照文檔進(jìn)行操作,結(jié)果卻失敗了。于是我向江南白衣請(qǐng)教,白衣推薦我使用CXF的最新版本,于是我到官方網(wǎng)站下載了CXF的最新版,按照示例來了一遍,很快就成功了。由此可見,使用CXF不僅簡(jiǎn)單,而且成功率高。因此,我在這里把我的經(jīng)驗(yàn)和大家分享。

          第一步,下載CXF的最新版本,下載地址如下圖:
          01.PNG


          第二步,將CXF中的lib文件夾中的下列jar文件拷貝到我們項(xiàng)目的webapp/WEB-INF/lib目錄下:
          commons-logging-1.1.jar
          geronimo-activation_1.1_spec-
          1.0-M1.jar?(or?Sun's?Activation?jar)
          geronimo-annotation_1.0_spec-
          1.1.jar?(JSR?250)
          geronimo-javamail_1.4_spec-
          1.0-M1.jar?(or?Sun's?JavaMail?jar)
          geronimo-servlet_2.5_spec-
          1.1-M1.jar?(or?Sun's?Servlet?jar)
          geronimo-ws-metadata_2.0_spec-
          1.1.1.jar?(JSR?181)
          jaxb-api-
          2.0.jar
          jaxb-impl-
          2.0.5.jar
          jaxws-api-
          2.0.jar
          neethi-
          2.0.jar
          saaj-api-
          1.3.jar
          saaj-impl-
          1.3.jar
          stax-api-
          1.0.1.jar
          wsdl4j-
          1.6.1.jar
          wstx-asl-
          3.2.1.jar
          XmlSchema-
          1.2.jar
          xml-resolver-
          1.2.jar

          cxf-
          2.0-incubator.jar


          這里有一些包我的項(xiàng)目中本身已經(jīng)帶有了,只不過CXF中提供的版本要更新一些。把這些包拷貝到項(xiàng)目中后,可以刪除項(xiàng)目中的較低的版本,同時(shí)刪除所有和XFire有關(guān)的包。當(dāng)然,不刪除也可以,因?yàn)槲以囘^了,就算項(xiàng)目中存在多個(gè)不同版本的包,也不會(huì)發(fā)生沖突。

          當(dāng)然,光拷貝這些包到項(xiàng)目中,還不能保證開發(fā)的順利進(jìn)行,還需要在Eclipse中設(shè)置項(xiàng)目的庫,如下圖:
          03.png

          在這里,我不得不說一下另外一個(gè)問題,那就是啟動(dòng)Tomcat服務(wù)器的時(shí)候,經(jīng)常發(fā)生java.lang.OutOfMemoryError: PermGen space異常,出現(xiàn)這個(gè)異常是什么原因呢?在網(wǎng)上搜到的答案是這樣的:PermGen space的全稱是Permanent Generation space,是指內(nèi)存的永久保存區(qū)域,這塊內(nèi)存主要是被JVM存放Class和Meta信息的,Class在被Loader時(shí)就會(huì)被放到PermGen space中,它和存放類實(shí)例(Instance)的Heap區(qū)域不同,GC(Garbage Collection)不會(huì)在主程序運(yùn)行期對(duì)PermGen space進(jìn)行清理,所以如果你的應(yīng)用中有很多CLASS的話,就很可能出現(xiàn)PermGen space錯(cuò)誤,這種錯(cuò)誤常見在web服務(wù)器對(duì)JSP進(jìn)行pre compile的時(shí)候。如果你的WEB APP下都用了大量的第三方j(luò)ar, 其大小超過了jvm默認(rèn)的大小(4M)那么就會(huì)產(chǎn)生此錯(cuò)誤信息了。

          本來,使用SpringSide 2.0就已經(jīng)包含了許多的第三方包,容易出現(xiàn)這個(gè)問題,現(xiàn)在加入CXF依賴的這些包,就不可避免要出現(xiàn)這個(gè)問題了。這個(gè)問題的解決方法有兩個(gè),其一是不使用SUN的JDK。當(dāng)然,我也懶得去下載一個(gè)別的JDK,因此就選擇了第二個(gè)方法,那就是修改Tomcat的啟動(dòng)文件。

          找到SpringSide2.0\misc\servers\tomcat-5.5.17\bin文件夾下的catalina.bat文件,使用記事本打開,找到如下行:
          set JAVA_OPTS=

          將這一行進(jìn)行修改,加入啟動(dòng)參數(shù),如下:
          set JAVA_OPTS=%JAVA_OPTS% -Xms512m -Xmx1024m -XX:MaxNewSize=512m -XX:MaxPermSize=512m -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties":noJuli

          解決了以上這些問題,就可以正式使用CXF了。


          第三步,修改webapp/WEB-INF/web.xml文件,將以前的

          <servlet>
          ??
          <servlet-name>xfire</servlet-name>
          ??
          <servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class>
          </servlet>
          <servlet-mapping>
          ??
          <servlet-name>xfire</servlet-name>
          ??
          <url-pattern>/service/*</url-pattern>
          </servlet-mapping>

          修改為:
          <servlet>
          ??
          <servlet-name>cxf</servlet-name>
          ??
          <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
          </servlet>
          <servlet-mapping>
          ??
          <servlet-name>cxf</servlet-name>
          ??
          <url-pattern>/service/*</url-pattern>
          </servlet-mapping>

          即可。


          第四步,定義一個(gè)提供WebService的接口。在我的項(xiàng)目中,我準(zhǔn)備只提供一個(gè)WebService,即IndexService,這個(gè)服務(wù)中提供多個(gè)方法來分別滿足索引服務(wù)器的各種功能。目前,我還只開發(fā)到了用戶注冊(cè)模塊,需要向索引服務(wù)器提交用戶數(shù)據(jù),因此,暫時(shí)提供一個(gè)addUser方法作為示例,如下:
          package?com.yumdays.service;

          import?javax.jws.WebService;
          import?com.yumdays.model.SUser;

          @WebService
          public?interface?IndexService?{
          ????
          public?boolean?addUser(SUser?user,String?adminName,String?adminPassword);
          }

          而它的實(shí)現(xiàn)類如下:
          package?com.yumdays.service;

          import?com.yumdays.model.SUser;
          import?javax.jws.WebService;

          @WebService(endpointInterface?
          =?"com.yumdays.service.IndexService")
          public?class?IndexServiceImpl?implements?IndexService?{

          ????
          public?boolean?addUser(SUser?user,?String?adminName,?String?adminPassword)?{
          ????????
          //?TODO?自動(dòng)生成方法存根
          ????????return?false;
          ????}

          }


          ?第五步,在項(xiàng)目的src/resource/spring目錄下,刪除所有和XFire有關(guān)的配置文件,添加一個(gè)cxf-beans.xml文件,其內(nèi)容如下:

          <?xml?version="1.0"?encoding="UTF-8"?>
          <beans?xmlns="http://www.springframework.org/schema/beans"
          ????xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
          ????xmlns:jaxws
          ="http://cxf.apache.org/jaxws"
          ????xsi:schemaLocation
          ="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
          ????http://cxf.apache.org/jaxws?http://cxf.apache.org/schemas/jaxws.xsd"
          >

          ????
          <import?resource="classpath:META-INF/cxf/cxf.xml"?/>
          ????
          <import?resource="classpath:META-INF/cxf/cxf-extension-soap.xml"?/>
          ????
          <import?resource="classpath:META-INF/cxf/cxf-servlet.xml"?/>

          ????
          <bean?id="indexServiceBean"?class="com.yumdays.service.IndexServiceImpl"?/>
          ????
          <jaxws:endpoint?id="indexService"?implementor="#indexServiceBean"?address="/IndexService"?/>
          ??????
          </beans>

          現(xiàn)在,重新構(gòu)建項(xiàng)目,部署,啟動(dòng)Tomcat,就可以通過訪問http://www.yumdays.com/service/IndexService?wsdl來測(cè)試該WebService是否成功被部署了。如下圖:
          02.PNG


          第六步,創(chuàng)建客戶端,這一步非常的容易,只需要下面這樣的配置:
          <?xml?version="1.0"?encoding="UTF-8"?>
          <beans?xmlns="http://www.springframework.org/schema/beans"
          ????xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
          ????xmlns:jaxws
          ="http://cxf.apache.org/jaxws"
          ????xsi:schemaLocation
          ="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
          ????http://cxf.apache.org/jaxws?http://cxf.apache.org/schemas/jaxws.xsd"
          >

          ????
          <import?resource="classpath:META-INF/cxf/cxf.xml"?/>
          ????
          <import?resource="classpath:META-INF/cxf/cxf-extension-soap.xml"?/>
          ????
          <import?resource="classpath:META-INF/cxf/cxf-servlet.xml"?/>

          ????
          <bean?id="client"?class="com.yumdays.service.IndexService"?factory-bean="clientFactory"?factory-method="create"/>
          ????
          ????
          <bean?id="clientFactory"?class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
          ??????
          <property?name="serviceClass"?value="com.yumdays.service.IndexService"/>
          ??????
          <property?name="address"?value="http://www.yumdays.com/service/IndexService"/>
          ????
          </bean>
          ????
          </beans>

          就可以獲得一個(gè)名稱為client的bean,通過該bean,就可以非常方便的訪問索引服務(wù)器提供的功能。

          評(píng)論

          # re: 在SpringSide 2.0中使用CXF提供Web Service服務(wù)  回復(fù)  更多評(píng)論   

          2008-03-09 11:57 by TonySoft
          其實(shí)使用XFire比使用CXF要簡(jiǎn)單一些,但是CXF提供了更多的高級(jí)特性,如果項(xiàng)目允許,切換到CXF是一個(gè)不錯(cuò)的選擇。

          # re: 在SpringSide 2.0中使用CXF提供Web Service服務(wù)  回復(fù)  更多評(píng)論   

          2008-03-18 10:23 by web
          我和樓主的配置一樣為什么通不過。
          org.apache.cxf.binding.soap.SoapFault: Error reading XMLStreamReader.
          org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:70)
          org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:35)
          org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:208)
          org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:96)
          org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:183)
          org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:56)
          org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:208)
          org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:429)
          org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1955)
          org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1791)
          org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:66)
          org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:575)
          org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
          org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:208)
          org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:276)
          org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:222)
          org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73)
          org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:135)
          $Proxy15.getCounter(Unknown Source)
          com.hbby.installation.web.action.LoginAction.login(LoginAction.java:83)
          sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          java.lang.reflect.Method.invoke(Method.java:585)
          org.apache.struts.actions.ActionDispatcher.dispatchMethod(ActionDispatcher.java:335)
          org.apache.struts.actions.ActionDispatcher.dispatchMethod(ActionDispatcher.java:318)
          org.apache.struts.actions.ActionDispatcher.execute(ActionDispatcher.java:220)
          com.hbby.installation.web.action.LoginAction.execute(LoginAction.java:44)
          org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
          org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
          org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
          org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
          com.hbby.system.EncodingFilter.doFilter(EncodingFilter.java:36)

          # re: 在SpringSide 2.0中使用CXF提供Web Service服務(wù)  回復(fù)  更多評(píng)論   

          2008-03-18 20:09 by youxia
          你還是把項(xiàng)目里面的庫文件整理一下,把名稱相同但版本較低的jar包刪除。你出的錯(cuò)可能是因?yàn)閄ML解析錯(cuò)誤引起的。

          # re: 在SpringSide 2.0中使用CXF提供Web Service服務(wù)[未登錄]  回復(fù)  更多評(píng)論   

          2008-05-05 09:34 by 阿樂
          上面的朋友是不是安裝了卡吧殺毒軟件,把它暫停一下試試.

          # re: 在SpringSide 2.0中使用CXF提供Web Service服務(wù)  回復(fù)  更多評(píng)論   

          2008-06-16 13:30 by hejianhuacn
          @youxia
          應(yīng)該是卡巴的問題,我也碰到了,把它的Web防護(hù)關(guān)掉就好了

          # re: 在SpringSide 2.0中使用CXF提供Web Service服務(wù)  回復(fù)  更多評(píng)論   

          2008-09-02 14:53 by Eclipse_lijp
          按照樓主步驟,CXF最后部署失敗,訪問http://localhost:8080/cxfServer/service/WebServiceSample?wsdl

          頁面報(bào)錯(cuò):
          java.lang.NoSuchMethodError: org.w3c.dom.Document.setXmlStandalone(Z)V
          org.apache.cxf.transport.http.WSDLQueryHandler.updateDoc(WSDLQueryHandler.java:253)
          org.apache.cxf.transport.http.WSDLQueryHandler.writeResponse(WSDLQueryHandler.java:201)
          org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:152)
          org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServlet.java:174)
          org.apache.cxf.transport.servlet.AbstractCXFServlet.doGet(AbstractCXFServlet.java:156)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

          望賜教,謝謝!

          # re: 在SpringSide 2.0中使用CXF提供Web Service服務(wù)  回復(fù)  更多評(píng)論   

          2008-09-04 14:55 by zhaoyutong
          樓主,你好,我已經(jīng)百度了cxf 官網(wǎng)的User guide 所有文章,但是有一些地方還沒明白,我心情很沉重。我覺得我還是不會(huì)cxf

          但是當(dāng)我看到了這段話。
          我的網(wǎng)站使用SpringSide 2.0開發(fā),在SpringSide 2.0中,默認(rèn)使用的是XFire來提供WebService,但是我按照文檔進(jìn)行操作,結(jié)果卻失敗了。于是我向江南白衣請(qǐng)教,白衣推薦我使用CXF的最新版本,于是我到官方網(wǎng)站下載了CXF的最新版,按照示例來了一遍,很快就成功了。由此可見,使用CXF不僅簡(jiǎn)單,而且成功率高。因此,我在這里把我的經(jīng)驗(yàn)和大家分享。

          以及文章的下邊的內(nèi)容。我覺得我是個(gè)高手了。如果我有你對(duì)待事物的態(tài)度就好了

          這里www.frcircle.com有我收集的一些資料。 我覺得webservice是個(gè)龐大的體系

          # re: 在SpringSide 2.0中使用CXF提供Web Service服務(wù)  回復(fù)  更多評(píng)論   

          2010-09-30 15:09 by 刷刷刷
          樓上是sb
          主站蜘蛛池模板: 闻喜县| 泰州市| 内江市| 中超| 林周县| 锡林浩特市| 舟曲县| 宜春市| 兰考县| 靖西县| 调兵山市| 石嘴山市| 长阳| 称多县| 黄大仙区| 永泰县| 乌海市| 轮台县| 大姚县| 钟山县| 灌云县| 阿尔山市| 常州市| 隆子县| 柳州市| 怀宁县| 杂多县| 东平县| 阜康市| 临泉县| 黔江区| 涿州市| 上杭县| 宜宾县| 嫩江县| 临泉县| 伊川县| 茶陵县| 唐河县| 蓬安县| 临高县|