spring boot 1.5.4 整合webService(十五)

上一篇:springboot 1.5.4 之監控Actuator(十四)java


 

Spring Boot整合web service

經驗引用

以前用webserviceCXF框架,git

 

很方便與簡潔,可是悲催的是在部署到生產環境的WebSphere(was平臺)下後,不能正常運行.github

 

網上一查,原來WebSphereCXF的衝突問題由來已久,解決方案也五花八門,會有沒必要要的麻煩.既然如此趁項目的web service還在剛整合階段,換個組件吧.web

 

問了其它項目組同事之前是怎麼實現的,說就是由於衝突問題之前都是採用了httpClient之類的組裝xml發送原生http請求調用的.redis

 

處理方式欠妥,做者固然不能接受。既然spring能在WebSphere下正常運行,那麼spring的組件可以成功運行的可能性相對較大。spring

 

研究考慮以後,決定選用spring-ws來實現webservice。事實證實選擇是正確的。json

spring-boot相關項目源碼,api

碼雲地址:https://git.oschina.net/wyait/springboot1.5.4.git瀏覽器

github地址https://github.com/wyait/spring-boot-1.5.4.gitspringboot

 

spring-ws的資料相對較少,不像cxf那樣一找就是一大堆,不過好在有官方示例和文檔。

 

官方示例中使用了spring boot,這跟我當前的環境不謀而合,不過它示例了多個構建工具和Groovy等,看起來比較複雜難懂一些,這裏咱們就以單純的maven來實現。

 

1      web Service服務端

新建項目:ws-server(源碼地址:

碼雲地址:https://git.oschina.net/wyait/springboot1.5.4.git

github地址https://github.com/wyait/spring-boot-1.5.4.git


 

spring boot的工程,除了spring boot外還須要添加spring-wswsdl4j的依賴,固然後面生成代碼還須要添加mavenjaxb2插件

1.1    pom導入依賴

 

<dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-ws</artifactId>

        <version>1.4.5.RELEASE</version>

      </dependency>

      <dependency>

        <groupId>wsdl4j</groupId>

        <artifactId>wsdl4j</artifactId>

      </dependency>

 

1.2    編寫schema文件

spring-ws的發佈,都是以一個schema文件(xsd)定義開始的,它描述了webservice 的參數以及返回的數據。

 

這是官方示例給出的countries.xsd,這裏以它爲例,更改下命名空間,由於jaxb2插件自動生成代碼是以命名空間來肯定包名的。手動生成不影響!

<xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema"xmlns:tns="http://www.wyait.com/ws"

           targetNamespace="http://www.wyait.com/ws"elementFormDefault="qualified">

        <xs:elementname="getCountryRequest">

            <xs:complexType>

                <xs:sequence>

                    <xs:elementname="name" type="xs:string"/>

                </xs:sequence>

            </xs:complexType>

        </xs:element>

        <xs:elementname="getCountryResponse">

            <xs:complexType>

                <xs:sequence>

                    <xs:elementname="country" type="tns:country"/>

                </xs:sequence>

            </xs:complexType>

        </xs:element>

        <xs:complexTypename="country">

            <xs:sequence>

                <xs:elementname="name" type="xs:string"/>

                <xs:elementname="population" type="xs:int"/>

                <xs:elementname="capital" type="xs:string"/>

                <xs:elementname="currency" type="tns:currency"/>

            </xs:sequence>

        </xs:complexType>

        <xs:simpleTypename="currency">

            <xs:restrictionbase="xs:string">

                <xs:enumerationvalue="GBP"/>

                <xs:enumerationvalue="EUR"/>

                <xs:enumerationvalue="PLN"/>

            </xs:restriction>

        </xs:simpleType>

    </xs:schema>

1.3    jaxb2插件配置

pom文件配置jaxb2插件:

<plugin>

           <groupId>org.codehaus.mojo</groupId>

           <artifactId>jaxb2-maven-plugin</artifactId>

           <version>2.2</version>

           <configuration>

           <schemaDirectory>${project.basedir}/src/main/resources/schema</schemaDirectory>

              <outputDirectory>${project.basedir}/src/main/java</outputDirectory>

              <clearOutputDir>false</clearOutputDir>

           </configuration>

        </plugin>

eclipse開發工具:選中countries.xsd文件,右鍵:

wKioL1nPWDny8h3XAAB7xmx6idc226.png

IDEA開發工具:

coruntries.xsd右鍵,而後選中web service那一項,generatejava code from xml schema using jaxb

wKiom1nPWIaj2sJeAAFSKsmBnC8596.png

選擇要生成代碼的包位置!生成代碼結果:

 

wKioL1nPWEyh8bfrAAAcbmMgbZ0771.png

1.4    編寫EndPoint

咱們就再也不像spring-ws官方那樣再建一個Repository了,這裏直接返回。須要注意PayloadRoot註解當中的namespacelocalPart須要和xsd中對應。

/**

 *

 * @項目名稱:ws-server

 * @類名稱:CountryEndPoint

 * @類描述:編寫endpoint

 * @建立人:wyait

 * @建立時間:2017714上午11:02:49

 * @version

 */

@Endpoint

public class CountryEndPoint {

 

   privatestatic final String NAMESPACE_URI = "http://www.wyait.com/ws";

 

   @PayloadRoot(namespace= NAMESPACE_URI, localPart = "getCountryRequest")

   @ResponsePayload

   publicGetCountryResponse getCountry(

        @RequestPayloadGetCountryRequest request) {

      GetCountryResponseresponse = new GetCountryResponse();

      Countrypoland = new Country();

      poland.setName("Poland-"+ request.getName());

      poland.setCapital("Warsaw");

      poland.setCurrency(Currency.PLN);

      poland.setPopulation(38186860);

      response.setCountry(poland);

      returnresponse;

   }

}

 

1.5    Spring Boot整合web Service

/**

 *

 * @項目名稱:ws-server

 * @類名稱:WebServiceConfig

 * @類描述:spring boot整合web service

 * @建立人:wyait

 * @建立時間:2017714上午11:24:22

 * @version

 */

@EnableWs

@Configuration

public class WebServiceConfigextends WsConfigurerAdapter {

   @Bean

   publicServletRegistrationBean messageDispatcherServlet(

        ApplicationContextapplicationContext) {

      MessageDispatcherServletservlet = new MessageDispatcherServlet();

      servlet.setApplicationContext(applicationContext);

      servlet.setTransformWsdlLocations(true);

      returnnew ServletRegistrationBean(servlet, "/ws/*");

   }

 

   @Bean(name= "countries")

   publicDefaultWsdl11Definition defaultWsdl11Definition(

        XsdSchemacountriesSchema) {

      DefaultWsdl11Definitionwsdl11Definition = new DefaultWsdl11Definition();

      wsdl11Definition.setPortTypeName("CountriesPort");

      wsdl11Definition.setSchema(countriesSchema);

      returnwsdl11Definition;

   }

 

   @Bean

   publicXsdSchema countriesSchema() {

      returnnew SimpleXsdSchema(

           newClassPathResource("schema/countries.xsd"));

   }

}

 

到這裏spring-ws的全部配置和工做都已經完成了,上面的DefaultWsdl11Definitionid默認就是發佈的ws的訪問路徑。

 

1.6    啓動項目

啓動後訪問 http://localhost:8080/ws/countries.wsdl 發現web service已經成功發佈了。

 

wKiom1nPWJuRaXmkAADfq94uGXg010.png

 

這裏要注意一下spring-ws發佈的webservice是之後綴.wsdl訪問的,跟傳統的?wsdl不大同樣,也看過它的源碼,發現是在判斷後綴時寫死的,因此沒辦法配置修改了。

 

還有就是spring-ws實際上把發佈wsdl和真正的服務實現Endpoint分開了,若是你的Endpoint不正確,極可能會出現瀏覽器訪問.wsdl地址看起來正常而客戶端調用卻出現Not Found 404的錯誤。

 

2      web Service客戶端

前面咱們已經整合spring-ws實現了webservice的服務端:Spring Boot整合spring-ws開發web service客戶端

 

接下來就是實現客戶端進行調用了。

 

新建:ws-client(項目源碼:https://git.oschina.net/wyait/springboot1.5.4.git

2.1    添加依賴

<dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-ws</artifactId>

        <version>1.4.5.RELEASE</version>

      </dependency>

      <dependency>

        <groupId>wsdl4j</groupId>

        <artifactId>wsdl4j</artifactId>

      </dependency>

 

 

服務端由一個xsd文件開始,客戶端則是由一個wsdl文件開始。

 

獲取wsdl文件也十分簡單,用瀏覽器訪問webservice地址,而後另存爲便可。固然也能夠直接用url地址來生成代碼。

方式一:本地另存:

完整的wsdl文件以下:

<wsdl:definitionsxmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

   xmlns:sch="http://www.wyait.com/ws"xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

   xmlns:tns="http://www.wyait.com/ws"targetNamespace="http://www.wyait.com/ws">

   <wsdl:types>

      <xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema"

        elementFormDefault="qualified"targetNamespace="http://www.wyait.com/ws">

        <xs:elementname="getCountryRequest">

           <xs:complexType>

              <xs:sequence>

                 <xs:elementname="name" type="xs:string" />

              </xs:sequence>

           </xs:complexType>

        </xs:element>

        <xs:elementname="getCountryResponse">

           <xs:complexType>

              <xs:sequence>

                 <xs:elementname="country" type="tns:country" />

              </xs:sequence>

           </xs:complexType>

        </xs:element>

        <xs:complexTypename="country">

           <xs:sequence>

              <xs:elementname="name" type="xs:string" />

              <xs:elementname="population" type="xs:int" />

              <xs:elementname="capital" type="xs:string" />

              <xs:elementname="currency" type="tns:currency" />

           </xs:sequence>

        </xs:complexType>

        <xs:simpleTypename="currency">

           <xs:restrictionbase="xs:string">

              <xs:enumerationvalue="GBP" />

              <xs:enumerationvalue="EUR" />

              <xs:enumerationvalue="PLN" />

           </xs:restriction>

        </xs:simpleType>

      </xs:schema>

   </wsdl:types>

   <wsdl:messagename="getCountryResponse">

      <wsdl:partelement="tns:getCountryResponse" name="getCountryResponse"></wsdl:part>

   </wsdl:message>

   <wsdl:messagename="getCountryRequest">

      <wsdl:partelement="tns:getCountryRequest"name="getCountryRequest"></wsdl:part>

   </wsdl:message>

   <wsdl:portTypename="CountriesPort">

      <wsdl:operationname="getCountry">

        <wsdl:inputmessage="tns:getCountryRequest"name="getCountryRequest"></wsdl:input>

        <wsdl:outputmessage="tns:getCountryResponse"name="getCountryResponse"></wsdl:output>

      </wsdl:operation>

   </wsdl:portType>

   <wsdl:bindingname="CountriesPortSoap11" type="tns:CountriesPort">

      <soap:bindingstyle="document"

        transport="http://schemas.xmlsoap.org/soap/http"/>

      <wsdl:operationname="getCountry">

        <soap:operationsoapAction="" />

        <wsdl:inputname="getCountryRequest">

           <soap:bodyuse="literal" />

        </wsdl:input>

        <wsdl:outputname="getCountryResponse">

           <soap:bodyuse="literal" />

        </wsdl:output>

      </wsdl:operation>

   </wsdl:binding>

   <wsdl:servicename="CountriesPortService">

      <wsdl:portbinding="tns:CountriesPortSoap11"name="CountriesPortSoap11">

        <soap:address/>

      </wsdl:port>

   </wsdl:service>

</wsdl:definitions>

 

方式二:jaxb2插件配置生成wsdl文件

跟服務端根據xsd來生成代碼相似,客戶端一樣能夠根據wsdl來生成代碼。maven插件依賴:

<plugin>

           <groupId>org.jvnet.jaxb2.maven2</groupId>

           <artifactId>maven-jaxb2-plugin</artifactId>

           <version>0.12.3</version>

           <executions>

              <execution>

                 <goals>

                    <goal>generate</goal>

                 </goals>

              </execution>

           </executions>

           <configuration>

              <schemaLanguage>WSDL</schemaLanguage>

              <generatePackage>com.wyait.ws.domain</generatePackage>

              <generateDirectory>${basedir}/src/main/java</generateDirectory>

              <schemas>

                 <schema>

                    <fileset>

                      <!--Defaults to schemaDirectory. -->

                       <directory>${basedir}/src/main/resources/schema</directory>

                      <!--Defaults to schemaIncludes. -->

                      <includes>

                         <include>*.wsdl</include>

                      </includes>

                      <!--Defaults to schemaIncludes -->

                      <!--<excludes>-->

                      <!--<exclude>*.xs</exclude>-->

                      <!--</excludes>-->

                    </fileset>

                    <!--<url>http://localhost:8080/ws/countries.wsdl</url>-->

                 </schema>

              </schemas>

           </configuration>

        </plugin>

配置完,install將生成客戶端代碼。這裏生成的代碼跟咱們前面發佈的服務端代碼應該是同樣的,固然包名可能不一樣這個由本身指定。

 

在生成代碼的同時會生成META-INF文件夾,這個能夠移到resources目錄下或者直接刪除都沒有關係。生成後的項目結構圖:

wKioL1nPWGWSZEYDAAA60ofoGdM026.png

 

2.2    編寫ws客戶端

編寫ws 客戶端代碼:

public class WsClient extendsWebServiceGatewaySupport {

   publicGetCountryResponse getCountry(String name) {

      GetCountryRequestrequest = new GetCountryRequest();

      request.setName(name);

      GetCountryResponseresponse = (GetCountryResponse) getWebServiceTemplate()

           .marshalSendAndReceive(

                 "http://http://127.0.0.1:9111/ws/countries.wsdl",

                 request);

      returnresponse;

   }

}

 

2.3    spring boot配置ws客戶端

編寫完一切代碼以後,一樣須要配置到spring boot才行,ContextPath指定剛纔生成代碼所在的包名,它會到該包下去尋找相應的類自動進行數據轉換:

@Configuration

public class WSConfig {

   @Bean

   publicJaxb2Marshaller marshaller() {

      Jaxb2Marshallermarshaller = new Jaxb2Marshaller();

      marshaller.setContextPath("com.wyait.ws.domain");

      returnmarshaller;

   }

 

   @Bean

   publicWsClient wsClient(Jaxb2Marshaller marshaller) {

      WsClientclient = new WsClient();

      client.setDefaultUri("http://127.0.0.1:9111/ws/countries.wsdl");

      client.setMarshaller(marshaller);

      client.setUnmarshaller(marshaller);

      returnclient;

   }

}

 

2.4    編寫controller

使用了RestController,直接將調用ws返回的數據用json格式輸出到頁面。

@RestController

public class IndexController {

    @Autowired

    private WsClient wsClient;

    @RequestMapping("callws")

    public Object callWs() {

        GetCountryResponse response =wsClient.getCountry("hello");

        return response.getCountry();

    }

}

 

端口改成:9112 避免和服務端端口9111衝突

 

啓動,訪問:http://127.0.0.1:9112/callws

wKiom1nPWLTgKNS3AAAI6JUg9JI968.png

 

回顧1.6章節末尾:

「還有就是spring-ws實際上把發佈wsdl和真正的服務實現Endpoint分開了,若是你的Endpoint不正確,極可能會出現瀏覽器訪問.wsdl地址看起來正常而客戶端調用卻出現Not Found 404的錯誤。」

 

排查ws服務端endpoint代碼,沒問題。是包命名的時候,單詞寫錯了:

wKiom1nPWLzjay8iAABwAvj0AqY160.png

wyati改爲:wyait。啓動,訪問:http://127.0.0.1:9112/callws

wKioL1nPWH-j8Pt4AAAGhicN8UA744.png

 

3      附錄

ws-server /ws-client項目源碼:

碼雲地址:https://git.oschina.net/wyait/springboot1.5.4.git

github地址https://github.com/wyait/spring-boot-1.5.4.git

 

spring boot系列文章:

spring boot 1.5.4 概述(一)

spring boot 1.5.4 入門和原理(二)

spring boot 1.5.4 之web開發(三)

spring boot 1.5.4 整合JSP(四)

spring boot 1.5.4 集成devTools(五)

spring boot 1.5.4 集成JdbcTemplate(六)

spring boot 1.5.4 集成spring-Data-JPA(七)

spring boot 1.5.4 配置文件詳解(八)

spring boot 1.5.4 統一異常處理(九)

spring boot 1.5.4 定時任務和異步調用(十)

spring boot 1.5.4 整合log4j2(十一)

spring boot 1.5.4 整合 mybatis(十二)

spring boot 1.5.4 整合 druid(十三)

spring boot 1.5.4 之監控Actuator(十四)

spring boot 1.5.4 整合webService(十五)

spring boot 1.5.4 整合redis、攔截器、過濾器、監聽器、靜態資源配置(十六)

spring boot 1.5.4 整合rabbitMQ(十七)

spring boot 1.5.4 集成Swagger2構建Restful API(十八)

spring boot 1.5.9 整合redis(十九

相關文章
相關標籤/搜索