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(十九

相关文章
相关标签/搜索