SpringBoot | 第三十三章:Spring web Servcies集成和使用

第三十三章:Spring web Servcies集成和使用

前言

最近有個(gè)單位內(nèi)網(wǎng)系統(tǒng)需要對(duì)接統(tǒng)一門戶悦昵,進(jìn)行單點(diǎn)登錄和待辦事項(xiàng)對(duì)接功能。一般上政府系統(tǒng)都會(huì)要求做統(tǒng)一登錄功能辛臊,這個(gè)沒啥問題疹味,反正業(yè)務(wù)系統(tǒng)都是做單點(diǎn)登錄的仅叫,改下shiro相關(guān)類就好了〔谵啵看了接入方案惑芭,做坑爹的是需要業(yè)務(wù)系統(tǒng)提供一個(gè)webService服務(wù),供統(tǒng)一平臺(tái)調(diào)用继找。對(duì)于ws服務(wù),是真的除了大學(xué)期間要去寫個(gè)調(diào)用天氣預(yù)報(bào)的作業(yè)后逃沿,就再也沒有接觸過了婴渡。查閱了SpringBoot文檔后,發(fā)現(xiàn)確實(shí)有一章節(jié)是將webService的凯亮,所以边臼,今天就來簡單介紹下Spring Web Service的集成和使用吧。

一點(diǎn)知識(shí)

何為WebService

Web Service技術(shù)假消,能使得運(yùn)行在不同機(jī)器上的不同應(yīng)用無須借助附加的柠并、專門的第三方軟件或硬件, 就可相互交換數(shù)據(jù)或集成富拗。依據(jù)Web Service規(guī)范實(shí)施的應(yīng)用之間臼予,無論它們所使用的語言、平臺(tái)或內(nèi)部協(xié)議是什么啃沪,都可以相互交換數(shù)據(jù)粘拾。

簡單的說,WebService就是一種跨編程語言和跨操作系統(tǒng)平臺(tái)的遠(yuǎn)程調(diào)用技術(shù)创千。

WebServcie技術(shù)支持

以下內(nèi)容摘自百度百科:Web Service

Web Service平臺(tái)需要一套協(xié)議來實(shí)現(xiàn)分布式應(yīng)用程序的創(chuàng)建缰雇。任何平臺(tái)都有它的數(shù)據(jù)表示方法和類型系統(tǒng)。要實(shí)現(xiàn)互操作性追驴,Web Service平臺(tái)必須提供一套標(biāo)準(zhǔn)的類型系統(tǒng)械哟,用于溝通不同平臺(tái)、編程語言和組件模型中的不同類型系統(tǒng)殿雪。這些協(xié)議有:

XML和XSD

可擴(kuò)展的標(biāo)記語言Web Service平臺(tái)中表示數(shù)據(jù)的基本格式暇咆。除了易于建立和易于分析外,XML主要的優(yōu)點(diǎn)在于它既與平臺(tái)無關(guān),又與廠商無關(guān)糯崎。XML是由萬維網(wǎng)協(xié)會(huì)(W3C)創(chuàng)建几缭,W3C制定的XML SchemaXSD定義了一套標(biāo)準(zhǔn)的數(shù)據(jù)類型,并給出了一種語言來擴(kuò)展這套數(shù)據(jù)類型沃呢。
Web Service平臺(tái)是用XSD來作為數(shù)據(jù)類型系統(tǒng)的年栓。當(dāng)你用某種語言如VB. NETC#來構(gòu)造一個(gè)Web Service時(shí),為了符合Web Service標(biāo)準(zhǔn)薄霜,所有你使用的數(shù)據(jù)類型都必須被轉(zhuǎn)換為XSD類型某抓。如想讓它使用在不同平臺(tái)和不同軟件的不同組織間傳遞,還需要用某種東西將它包裝起來惰瓜。這種東西就是一種協(xié)議否副,如 SOAP

XSD全稱為XML Schemas Definition,即:XML結(jié)構(gòu)定義崎坊。是描述xml的备禀,同時(shí)遵循xml規(guī)范。

SOAP

SOAP即簡單對(duì)象訪問協(xié)議(Simple Object Access Protocol)奈揍,它是用于交換XML(標(biāo)準(zhǔn)通用標(biāo)記語言下的一個(gè)子集)編碼信息的輕量級(jí)協(xié)議曲尸。它有三個(gè)主要方面:XML-envelope為描述信息內(nèi)容和如何處理內(nèi)容定義了框架,將程序?qū)ο缶幋a成為XML對(duì)象的規(guī)則男翰,執(zhí)行遠(yuǎn)程過程調(diào)用(RPC)的約定另患。SOAP可以運(yùn)行在任何其他傳輸協(xié)議上。例如蛾绎,你可以使用 SMTP昆箕,即因特網(wǎng)電子郵件協(xié)議來傳遞SOAP消息,這可是很有誘惑力的租冠。在傳輸層之間的頭是不同的鹏倘,但XML有效負(fù)載保持相同。
Web Service 希望實(shí)現(xiàn)不同的系統(tǒng)之間能夠用“軟件-軟件對(duì)話”的方式相互調(diào)用顽爹,打破了軟件應(yīng)用第股、網(wǎng)站和各種設(shè)備之間的格格不入的狀態(tài),實(shí)現(xiàn)“基于Web無縫集成”的目標(biāo)话原。

WSDL

Web Service描述語言WSDL就是用機(jī)器能閱讀的方式提供的一個(gè)正式描述文檔而基于XML的語言夕吻,用于描述Web Service及其函數(shù)、參數(shù)和返回值繁仁。因?yàn)槭腔赬ML的涉馅,所以WSDL既是機(jī)器可閱讀的,又是人可閱讀的黄虱。

UDDI

UDDI的目的是為電子商務(wù)建立標(biāo)準(zhǔn)稚矿;UDDI是一套基于Web的、分布式的、為Web Service提供的晤揣、信息注冊(cè)中心的實(shí)現(xiàn)標(biāo)準(zhǔn)規(guī)范桥爽,同時(shí)也包含一組使企業(yè)能將自身提供的Web Service注冊(cè),以使別的企業(yè)能夠發(fā)現(xiàn)的訪問協(xié)議的實(shí)現(xiàn)標(biāo)準(zhǔn)昧识。

何為Spring-Web-Services

Spring Web servicesSpring推出的一款構(gòu)建webservice服務(wù)的框架钠四。其主要側(cè)重點(diǎn)是創(chuàng)建文檔驅(qū)動(dòng)的Web服務(wù)。Spring Web Services項(xiàng)目促進(jìn)了契約優(yōu)先的SOAP服務(wù)開發(fā)跪楞,提供了多種方式來創(chuàng)建靈活的Web服務(wù)缀去,這些服務(wù)可以通過多種方式處理XML負(fù)載〉榧溃可無縫地使用Spring依賴注入和配置等概念缕碎。

image

Spring-WS項(xiàng)目由由以下幾個(gè)項(xiàng)目組成:

  • Spring-WS Core(spring-ws-core.jar) - 它是主要模塊,提供WebServiceMessage和SoapMessage等中央接口池户,服務(wù)器端框架咏雌,強(qiáng)大的消息分發(fā)功能和支持類來實(shí)現(xiàn)Web服務(wù)端點(diǎn)。 它還提供Web Service消費(fèi)者客戶端作為:WebServiceTemplate校焦。

  • Spring-WS Support(spring-ws-support.jar) ? 該模塊為JMS处嫌,電子郵件等提供支持。

  • Spring-WS Security(spring-ws-security.jar) - 該模塊負(fù)責(zé)提供與核心Web服務(wù)模塊集成的WS-Security實(shí)現(xiàn)斟湃。 使用這個(gè)模塊,可以添加主體令牌檐薯,簽名凝赛,加密和解密SOAP消息。該模塊允許使用現(xiàn)有的Spring Security實(shí)現(xiàn)進(jìn)行認(rèn)證和授權(quán)坛缕。

  • Spring XML(spring-xml.jar) ? 該模塊為Spring Web Services提供XML支持類墓猎。 該模塊由Spring-WS框架內(nèi)部使用。

  • Spring OXM - 該模塊提供了XML與對(duì)象映射的支持類赚楚。

之間的依賴關(guān)系毙沾,如下圖所示:

image

簡單來說,看了官網(wǎng)文檔后宠页,一切遵循契約優(yōu)先原則左胞,請(qǐng)求和響應(yīng)的參數(shù)都應(yīng)遵循約定,不然wsdl文件生成是錯(cuò)誤的举户,這里踩了坑烤宙。。

Spring-WS服務(wù)端發(fā)布

spring-wsspring-mvc一樣俭嘁,在集成到web項(xiàng)目時(shí)躺枕,前端有個(gè)servlet分發(fā)請(qǐng)求消息的概念。
這個(gè)servlet接受soap消息,通過映射轉(zhuǎn)發(fā)到后端的服務(wù)實(shí)現(xiàn)類方法中(Endpiont)
在請(qǐng)求進(jìn)來處理過程中拐云,可以添加罢猪,攔截器(Interceptor),異常處理器(ExceptionResolver)叉瘩。
通過攔截器可以做一些額外的定制功能膳帕,比如安全。通過異常處理器定制異常信息顯示房揭,處理等备闲。

這個(gè)servlet就是MessageDispatcher,來看看官網(wǎng)給出的處理流程圖:

處理流程圖

所以在需要對(duì)請(qǐng)求參數(shù)或者響應(yīng)參數(shù)做處理時(shí)捅暴,可以編寫對(duì)應(yīng)的攔截器進(jìn)行處理的恬砂。

現(xiàn)在,以一個(gè)簡單示例來發(fā)布一個(gè)webService服務(wù)蓬痒。創(chuàng)建工程:spring-boot-webservice-server泻骤。

0.引入POM依賴。

        <!-- spirng ws 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>
        <!-- 生成wsdl文件 -->
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
        </dependency>

1.創(chuàng)建一個(gè)xsd文件梧奢,用來描述請(qǐng)求和響應(yīng)的各實(shí)體信息狱掂。這里簡單以一個(gè)獲取作者信息為例子。
author.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.lqdev.cn/webservice"
           targetNamespace="http://www.lqdev.cn/webservice" elementFormDefault="qualified">

    <!-- 定義請(qǐng)求實(shí)體 -->
    <xs:element name="authorRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
         
     <!-- 定義響應(yīng)實(shí)體 -->
    <xs:element name="authorResponse">
               <xs:complexType>
            <xs:sequence>
                <xs:element name="author" type="tns:author"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    
    <!-- 定義請(qǐng)求實(shí)體 -->
    <xs:element name="authorListRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="nonce" type="xs:string" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    
    <!-- 定義響應(yīng)實(shí)體 -->
    <xs:element name="authorListResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="author" type="tns:author" minOccurs="1" maxOccurs="unbounded" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
 
    <!-- 定義作者 信息 -->
    <xs:complexType name="author">
        <xs:sequence>
                <xs:element name="name" type="xs:string" />
                <!-- 愛好 列表形式 nillable=true 可為空 亲轨,maxOccurs=unbouned 無限 -->
                <xs:element name="hobby" type="xs:string" nillable="true" maxOccurs="unbounded" />
                <!-- 性別 枚舉類型 限定 -->
                <xs:element name="sex" type="tns:sex" />
                <!-- 生日 -->
                <xs:element name="birthday" type="xs:string" />
                <!-- 描述 -->
                <xs:element name="description" type="xs:string" />
        </xs:sequence>
    </xs:complexType>

    <!-- 枚舉類型 性別:男 女 -->
    <xs:simpleType name="sex">
        <xs:restriction base="xs:string">
            <xs:enumeration value="male"/>
            <xs:enumeration value="female"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

這里需要注意趋惨,請(qǐng)求和返回的名字是有要求的,兩個(gè)名字前面要一樣惦蚊,后綴分別是固定的配置器虾,默認(rèn)為Request和Response; 當(dāng)然可以通過requestSuffixresponseSuffix屬性來修改默認(rèn)值的,在配置小節(jié)會(huì)說到蹦锋。

關(guān)于xsd規(guī)則兆沙,可以查看:http://www.w3school.com.cn/schema/index.asp

2.根據(jù)XSD文件創(chuàng)建實(shí)體對(duì)象莉掂。這里直接使用maven創(chuàng)建自動(dòng)生成葛圃。pom中加入插件:jaxb2-maven-plugin

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>1.6</version>
                <executions>
                    <execution>
                        <id>xjc</id>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <schemaDirectory>${project.basedir}/src/main/resources/</schemaDirectory>
                    <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                    <clearOutputDir>false</clearOutputDir>
     <!-- 包名路徑 -->               <packageName>cn.lqdev.learning.springboot.ws.webservice</packageName>
                </configuration>
            </plugin>

然后運(yùn)行下命令:mvn install就會(huì)自動(dòng)創(chuàng)建了憎妙。正常情況下库正,添加后,xsd文件有變動(dòng)厘唾,都會(huì)實(shí)時(shí)創(chuàng)建對(duì)應(yīng)實(shí)體對(duì)象的诀诊。此時(shí),生成的對(duì)象如下:

實(shí)體對(duì)象

3.創(chuàng)建Endpoint服務(wù)阅嘶,有點(diǎn)類似Controller属瓣,請(qǐng)求服務(wù)的入口载迄。

/**
 * 創(chuàng)建endpoint 類似于創(chuàng)建controller了。
 * @author oKong
 *
 */
@Endpoint
public class AuthorEndpoint {

    @PayloadRoot(namespace = WsConst.NAMESPACE_URI, localPart = "authorRequest")
    @ResponsePayload 
    public AuthorResponse getAuthor(@RequestPayload AuthorRequest authorReq){
        AuthorResponse resp = new AuthorResponse();
        Author author = new Author();
        author.setBirthday("1990-01-23");
        author.setName("姓名:" + authorReq.getName());
        author.setSex(Sex.FEMALE);
        author.getHobby().addAll(Arrays.asList("電影","旅游"));
        author.setDescription("描述:一枚趔趄的猿÷胀埽現(xiàn)在時(shí)間:" + new Date().getTime());
        resp.setAuthor(author);
        return resp;
    }
    
    @PayloadRoot(namespace = WsConst.NAMESPACE_URI, localPart = "authorListRequest")
    @ResponsePayload 
    public AuthorListResponse getAuthorList(@RequestPayload AuthorListRequest request){
        AuthorListResponse resp = new AuthorListResponse();
        Author author = new Author();
        author.setBirthday("1990-01-23");
        author.setName("姓名:oKong");
        author.setSex(Sex.FEMALE);
        author.getHobby().addAll(Arrays.asList("電影","旅游"));
        author.setDescription("描述:一枚趔趄的猿』っ粒現(xiàn)在時(shí)間:" + new Date().getTime());
        resp.getAuthor().add(author);
        resp.getAuthor().add(author);
        return resp;
    }
}

示例代碼,只是為了演示粗截,大部分信息都固定寫死了惋耙。實(shí)際開發(fā)中,可以加入各自的業(yè)務(wù)邏輯熊昌,引入相應(yīng)的service類的妇智。

而且类咧,這里需要注意:

  1. 方法聲明上的 @PayloadRoot標(biāo)注中的namespacelocalPart分別就是wsdl中的targetNamespacesoap方法名稱。
  2. @ResponsePayload@RequestPayload 這兩個(gè)標(biāo)注的用法,以及它們對(duì)應(yīng)的數(shù)據(jù)類型就是此前通過maven插件對(duì)wsdl定義生成的java類杠袱。

關(guān)于請(qǐng)求參數(shù)的類型截粗,是否需要加@RequestPayload說明:

Handling method parameters

一般上袱巨,都是使用JAXB2對(duì)象了适篙,也就是先前生成的實(shí)體對(duì)象。當(dāng)然蜂奸,有興趣的同學(xué)可以試試犁苏,其他的對(duì)象參數(shù),可以獲取到不同的參數(shù)值的扩所。

比如:

public void handle(@RequestPayload Element element)

一個(gè)org.w3c.dom.Element對(duì)象围详。

public void handle(@RequestPayload DOMSource domSource, SoapHeader header)

這樣,能獲取到SOAP的頭部信息祖屏。

其他相關(guān)用法助赞,可以查看此地址:https://docs.spring.io/spring-ws/docs/2.4.2.RELEASE/reference/#server-atEndpoint-methods

關(guān)于響應(yīng)的參數(shù),是否需要加@ResponsePayload赐劣,一下是官網(wǎng)給出的說明信息:

Handling method return types

這個(gè)有個(gè)坑:嘗試無參數(shù)請(qǐng)求時(shí),使用postman發(fā)送xml數(shù)據(jù)可以正常請(qǐng)求哩都,但使用spirng-ws調(diào)用就調(diào)用不到了魁兼,嗯,我想應(yīng)該是我調(diào)用方法不多漠嵌。咐汞。⊙﹏⊙‖∣

4.創(chuàng)建配置類儒鹿,生效webservice服務(wù)化撕。

/**
 * ws-配置
 * @author oKong
 *
 */
@EnableWs //開啟webService
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter{
        
    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);//true 地址會(huì)進(jìn)行轉(zhuǎn)換,不然都是本地地址
      //這里可以設(shè)置 請(qǐng)求的工廠類约炎,實(shí)現(xiàn)有兩個(gè):SaajSoapMessageFactory 和 AxiomSoapMessageFactory
        //默認(rèn)是 SaajSoapMessageFactory
//        servlet.setMessageFactoryBeanName(messageFactoryBeanName);
        return new ServletRegistrationBean(servlet, "/ws/*");
    }
    
    //name 就是對(duì)應(yīng) wsdl名如 :/ws/author.wsdl
    @Bean(name = "author")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema authorSchema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("AuthorPort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setSchema(authorSchema);
        wsdl11Definition.setTargetNamespace(WsConst.NAMESPACE_URI);
        return wsdl11Definition;
    }
    
    //可自定義SaajSoapMessageFactory 然后指定其SOAP版本
    @Bean
    public SaajSoapMessageFactory messageFactory() {
        SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
        //指定版本
        messageFactory.setSoapVersion(SoapVersion.SOAP_11);//SoapVersion.SOAP_12
        return messageFactory;
    }
    
    @Bean
    public XsdSchema authorSchema() {
        return new SimpleXsdSchema(new ClassPathResource("author.xsd"));
    }
    
    @Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        //可以自定義攔截器 
    }
}

常量類:WsConst.java

/**
 * 常量類
 * @author oKong
 *
 */
public class WsConst {
    public static final String NAMESPACE_URI = "http://www.lqdev.cn/webservice";
}

5.編寫啟動(dòng)類植阴。

/**
 * web-service 簡單示例
 * 
 * @author oKong
 *
 */
@SpringBootApplication
@Slf4j
public class WebServiceApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(WebServiceApplication.class, args);
        log.info("spring-boot-webservice-server-chapter33啟動(dòng)!");
    }
}

6.啟動(dòng)應(yīng)用蟹瘾,訪問下:http://127.0.0.1:8090/ws/author.wsdl ,可以看見wsdl文件內(nèi)容了。

wsdl文件

接著掠手,我們使用postman調(diào)用下:POST http://127.0.0.1:8090/ws

image

說明已經(jīng)正常發(fā)布了憾朴。接下來,我們使用spring-ws直接調(diào)用喷鸽。

Spirng-WS客戶端調(diào)用

創(chuàng)建一個(gè)新工程:spring-boot-webservice-client

0.引入POM依賴众雷。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
        </dependency>

1.獲取wsdl文件,放入src\main\resources\schemas\文件夾中做祝,同時(shí)加入maven插件:maven-jaxb2-plugin使其生成對(duì)應(yīng)實(shí)體列砾省。

           <plugin>
                <groupId>org.jvnet.jaxb2.maven2</groupId>
                <artifactId>maven-jaxb2-plugin</artifactId>
                <version>0.13.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <schemaLanguage>WSDL</schemaLanguage>
                    <generatePackage>cn.lqdev.webservice</generatePackage>
                    <generateDirectory>${basedir}/src/main/java</generateDirectory>
                    <schemas>
                        <schema>
                            <fileset>
                                <!-- Defaults to schemaDirectory. -->
                                <directory>${basedir}/src/main/resources/schemas</directory>
                                <!-- Defaults to schemaIncludes. -->
                                <includes>
                                    <include>*.wsdl</include>
                                </includes>
                            </fileset>
                        </schema>
                    </schemas>
                </configuration>
            </plugin>

wsdl文件就不貼了。目錄為:

image

生成后對(duì)應(yīng)實(shí)體類為:

image

注意:寫此文章前混槐,嘗試過使用cxf進(jìn)行調(diào)用编兄,而調(diào)用過程中,發(fā)現(xiàn)請(qǐng)求的實(shí)體需要在包cn.lqdev.webservice路徑下纵隔,不然校驗(yàn)不通過翻诉。所以為了兼容,我直接寫成此路徑了捌刮。對(duì)于spring ws而言碰煌,包名可以自定義的。不知道cxf是不是可以修改绅作,跟蹤了下源碼也沒有找到具體這個(gè)規(guī)則是怎么來的芦圾,不知道是不是和targetNamespace的值http://www.lqdev.cn/webservice有關(guān),有待測(cè)試俄认。

2.創(chuàng)建客戶端調(diào)用類个少。

/**
 * 編寫客戶端 繼承WebServiceGatewaySupport 類 方便調(diào)用
 * @author oKong
 *
 */
public class WsAuthorClient extends WebServiceGatewaySupport{

    /**
     *  獲取作者信息
     *  @author oKong
     */
    public AuthorResponse getAuthor(String name) {
        AuthorRequest req = new AuthorRequest();
        req.setName(name);
        //使用 marshalSendAndReceive 進(jìn)行調(diào)用
        return (AuthorResponse) getWebServiceTemplate().marshalSendAndReceive(req);
    }
    
    /**
     *  獲取作者列表信息
     *  @author oKong
     */
    public AuthorListResponse getAuthorList(){
        AuthorListRequest request = new AuthorListRequest();
        request.setNonce(UUID.randomUUID().toString());
        return (AuthorListResponse) getWebServiceTemplate().marshalSendAndReceive(request);
    }
}

此類,就是調(diào)用webservice服務(wù)的眯杏。

4.創(chuàng)建配置類.

/**
 * 客戶端調(diào)用配置
 * @author oKong
 *
 */
@Configuration
public class WsClientConfig {
    
    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        //會(huì)掃描此類下面的對(duì)應(yīng)的 jaxb2實(shí)體類 因?yàn)槭鞘褂?Marshaller和 unmarshaller來進(jìn)行xml和bean直接轉(zhuǎn)換的
        //具體是判斷此路徑下是否包含 ObjectFactory.class 文件
        //設(shè)置 JAXBContext 對(duì)象
        marshaller.setContextPath("cn.lqdev.webservice");
        //或者使用 以下方式設(shè)置
//        marshaller.setPackagesToScan(packagesToScan);
//        marshaller.setClassesToBeBound(classesToBeBound);
        return marshaller;
    }
    
    /*
     * 創(chuàng)建bean
     */
    @Bean
    public WsAuthorClient wsClient(Jaxb2Marshaller marshaller) {
        WsAuthorClient client = new WsAuthorClient();
        //默認(rèn)對(duì)應(yīng)的ws服務(wù)地址 client請(qǐng)求中還能動(dòng)態(tài)修改的
        client.setDefaultUri("http://127.0.0.1:8090/ws");
        client.setMarshaller(marshaller);//指定轉(zhuǎn)換類
        client.setUnmarshaller(marshaller);
        return client;
    }
}

關(guān)于marshallerunmarshaller解析xml和讀取xml相關(guān)知識(shí)夜焦,沒有過多了解,感興趣的可以自行搜索相關(guān)資料下岂贩。

5.創(chuàng)建示例控制層茫经,調(diào)用各服務(wù)接口。

/**
 * 簡單調(diào)用示例
 * @author oKong
 *
 */
@RestController
@RequestMapping("/author")
public class DemoController {

    @Autowired
    WsAuthorClient authorClient;
    
    @GetMapping("/get")
    public AuthorResponse getAuthor(String name) {
        return authorClient.getAuthor(name);
    }
    
    @GetMapping("/list")
    public AuthorListResponse getAuthorList() {
        return authorClient.getAuthorList();
    }
}

6.修改端口號(hào)為:8096萎津,同時(shí)啟動(dòng)應(yīng)用卸伞。

server.port=8096

使用Postman,訪問:http://127.0.0.1:8096/author/get?name=程序員

正常情況下可以看見以下返回內(nèi)容:

get

說明調(diào)用成功了。

訪問下列表:http://127.0.0.1:8096/author/list

list

簡單使用CXF調(diào)用webService

接下類锉屈,嘗試下使用cxf來訪問下服務(wù)荤傲。

0.引入cxf相關(guān)依賴。

    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
        <version>3.1.11</version>
    </dependency>

1.controller類新增一個(gè)方法颈渊,使用cxf方式調(diào)用服務(wù)遂黍。

    @GetMapping("/cxf/{method}")
    public Object cxf(@PathVariable String method,String name) throws Exception{
        //獲取客戶端工廠類
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        //創(chuàng)建client對(duì)象
        Client client = dcf.createClient("http://127.0.0.1:8090/ws/author.wsdl");
    
        AuthorListRequest listReq = new AuthorListRequest();
        listReq.setNonce(UUID.randomUUID().toString());
        
        AuthorRequest req = new AuthorRequest();
        req.setName(name);
        //調(diào)用 第一個(gè)方法是operation 值终佛,即調(diào)用方法,
        //其后是調(diào)用參數(shù)妓湘。
        Object[] objects = new Object[0];
        //相關(guān) operation值 可以根據(jù) client.getEndpoint().getBinding().getBindingInfo().getOperations(); 獲取
        //有興趣可以看下 client.getEndpoint().getBinding().getBindingInfo()提供的一些方法查蓉。
        
        //這里就簡單的判斷了 
        if("authorList".equalsIgnoreCase(method)) {
          objects = client.invoke("authorList", listReq);
        } else {
             objects = client.invoke("author", req);
        }
        //返回的對(duì)象objects[0]即為返回的值
        return objects[0];
    }

這里需要注意:對(duì)應(yīng)的實(shí)體類,需要符合wsdl文件中解析出來的type Classes 對(duì)應(yīng)上榜贴,本例子為:cn.lqdev.webservice.AuthorListRequest豌研,猜猜應(yīng)該和targetNamespace值有關(guān),不然會(huì)出現(xiàn)以下類似提示:

Part {http://www.lqdev.cn/webservice}authorListRequest should be of type cn.lqdev.webservice.AuthorListRequest, not cn.lqdev.learning.webservice.AuthorListRequest

最后發(fā)現(xiàn)使用cxf也很簡單呀唬党,下次試試鹃共。是利用JAX-WS規(guī)范的。

2.重啟應(yīng)用驶拱,訪問下:http://127.0.0.1:8096/author/cxf/author?name=趔趄的猿 最后效果是一樣的霜浴。

image

訪問:http://127.0.0.1:8096/author/cxf/authorList

image

有待補(bǔ)充

以上只是基于官方文檔,簡單的示例了一遍蓝纲,具體一些高級(jí)用法以及相關(guān)安全校驗(yàn)阴孟、過濾器等等,沒有過多涉及的税迷。之后有時(shí)間再填坑吧永丝,畢竟這個(gè)用的真的不多呀。

參考資料

  1. https://docs.spring.io/spring-ws/docs/2.4.2.RELEASE/reference/

  2. https://spring.io/guides/gs/producing-web-service/

  3. https://spring.io/guides/gs/consuming-web-service/

總結(jié)

本章節(jié)主要簡單介紹了spring-ws的使用箭养。原本是沒有打算寫關(guān)于WebService相關(guān)的慕嚷。只是機(jī)緣巧合下剛好有個(gè)對(duì)接系統(tǒng)需要用上,就臨時(shí)嘗試一下了毕泌。還有很多深入的功能喝检,就沒有過多涉及了。等到時(shí)候真正開始對(duì)接時(shí)撼泛,有碰到一些問題或者有些知識(shí)點(diǎn)補(bǔ)充的挠说,再來補(bǔ)充吧。畢竟愿题,我想現(xiàn)在除了舊系統(tǒng)和政府部門的系統(tǒng)损俭,應(yīng)該很少再去開發(fā)webservice服務(wù)了吧。官網(wǎng)文檔大致看了下抠忘,也確實(shí)覺得有點(diǎn)復(fù)雜呀撩炊,不知道是不是理解能力問題外永,⊙﹏⊙‖∣崎脉。理論上,按著規(guī)則走伯顶,問題應(yīng)該也不是很大囚灼。就是一些比如無參數(shù)如何調(diào)用骆膝,或者返回參數(shù)節(jié)點(diǎn)自定義問題,這些理論上都可以使用提供的攔截器來完成的灶体。有問題阅签,還是建議查看官網(wǎng)吧,真的比較詳細(xì)蝎抽。最后看了cxf政钟,也比較簡單。下一篇就來寫寫使用cxf來發(fā)布webservice樟结,多嘗試幾種方式~

最后

目前互聯(lián)網(wǎng)上很多大佬都有SpringBoot系列教程养交,如有雷同,請(qǐng)多多包涵了瓢宦。原創(chuàng)不易碎连,碼字不易,還希望大家多多支持驮履。若文中有所錯(cuò)誤之處鱼辙,還望提出,謝謝玫镐。

老生常談

  • 個(gè)人QQ:499452441
  • 微信公眾號(hào):lqdevOps
公眾號(hào)

個(gè)人博客:http://blog.lqdev.cn

完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-33

原文地址:http://blog.lqdev.cn/2018/11/09/springboot/chapter-thirty-three/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末倒戏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子摘悴,更是在濱河造成了極大的恐慌峭梳,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹂喻,死亡現(xiàn)場離奇詭異葱椭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)口四,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門孵运,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蔓彩,你說我怎么就攤上這事治笨。” “怎么了赤嚼?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵旷赖,是天一觀的道長。 經(jīng)常有香客問我更卒,道長等孵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任蹂空,我火速辦了婚禮俯萌,結(jié)果婚禮上果录,老公的妹妹穿的比我還像新娘。我一直安慰自己咐熙,他們只是感情好弱恒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棋恼,像睡著了一般返弹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爪飘,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天琉苇,我揣著相機(jī)與錄音,去河邊找鬼悦施。 笑死并扇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抡诞。 我是一名探鬼主播穷蛹,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼昼汗!你這毒婦竟也來了肴熏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤顷窒,失蹤者是張志新(化名)和其女友劉穎蛙吏,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鞋吉,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸦做,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谓着。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泼诱。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖赊锚,靈堂內(nèi)的尸體忽然破棺而出治筒,到底是詐尸還是另有隱情,我是刑警寧澤舷蒲,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布耸袜,位于F島的核電站,受9級(jí)特大地震影響牲平,放射性物質(zhì)發(fā)生泄漏堤框。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胰锌。 院中可真熱鬧,春花似錦藐窄、人聲如沸资昧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽格带。三九已至,卻和暖如春刹枉,著一層夾襖步出監(jiān)牢的瞬間叽唱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國打工微宝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棺亭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓蟋软,卻偏偏與公主長得像镶摘,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岳守,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354