1. 程式人生 > >Spring Boot整合webservice

Spring Boot整合webservice

一:概念

Web Service平臺需要一套協議來實現分散式應用程式的建立。任何平臺都有它的資料表示方法和型別系統。要實現互操作性,Web Service平臺必須提供一套標準的型別系統,用於溝通不同平臺、程式語言和元件模型中的不同型別系統。這些協議有: XML和XSD 可擴充套件的標記語言標準通用標記語言下的一個子集)是Web Service平臺中表示資料的基本格式。除了易於建立和易於分析外,XML主要的優點在於它既與平臺無關,又與廠商無關。XML是由全球資訊網協會(W3C)建立,W3C制定的XML SchemaXSD 定義了一套標準的資料型別,並給出了一種語言來擴充套件這套資料型別
。 Web Service平臺是用XSD來作為資料型別系統的。當你用某種語言如VB. NET或C# 來構造一個Web Service時,為了符合Web Service標準,所有你使用的資料型別都必須被轉換為XSD型別。如想讓它使用在不同平臺和不同軟體的不同組織間傳遞,還需要用某種東西將它包裝起來。這種東西就是一種協議,如 SOAP。 SOAP SOAP即簡單物件訪問協議(Simple Object Access Protocol),它是用於交換XML標準通用標記語言下的一個子集)編碼資訊的輕量級協議。它有三個主要方面:XML-envelope為描述資訊內容和如何處理內容定義了框架,將程式物件編碼成為XML物件的規則,執行
遠端過程呼叫
(RPC)的約定。SOAP可以執行在任何其他傳輸協議上。例如,你可以使用 SMTP,即因特網電子郵件協議來傳遞SOAP訊息,這可是很有誘惑力的。在傳輸層之間的頭是不同的,但XML有效負載保持相同。 Web Service 希望實現不同的系統之間能夠用“軟體-軟體對話”的方式相互呼叫,打破了軟體應用、網站和各種裝置之間的格格不入的狀態,實現“基於Web無縫整合”的目標。 WSDL Web Service描述語言WSDL 就是用機器能閱讀的方式提供的一個正式描述文件而基於XML標準通用標記語言下的一個子集)的語言,用於描述Web Service及其函式、引數和返回值。因為是基於XML的,所以WSDL既是機器可閱讀的,又是人可閱讀的。 UDDI
UDDI 的目的是為電子商務建立標準;UDDI是一套基於Web的、分散式的、為Web Service提供的、資訊註冊中心的實現標準規範,同時也包含一組使企業能將自身提供的Web Service註冊,以使別的企業能夠發現的訪問協議的實現標準。 呼叫RPC與訊息傳遞 Web Service本身其實是在實現應用程式間的通訊。我們有兩種應用程式通訊的方法:RPC遠端過程呼叫 和訊息傳遞。使用RPC的時候,客戶端的概念是呼叫伺服器上的遠端過程,通常方式為例項化一個遠端物件並呼叫其方法和屬性。RPC系統試圖達到一種位置上的透明性:伺服器暴露出遠端物件的介面,而客戶端就好像在本地使用的這些物件的介面一樣,這樣就隱藏了底層的資訊,客戶端也就根本不需要知道物件是在哪臺機器上。

二:springboot整合

 1.新增maven依賴
<groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>1.5.8.RELEASE</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Compile -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
</dependency>
<dependency>
    <groupId>org.jdom</groupId>
    <artifactId>jdom2</artifactId>
</dependency>
<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
</dependency>
<plugins>
   <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
   </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>
    </configuration>
</plugin>
</plugins>
2.新增XML Schema定義資料結構,檔名為countries.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://wind.com/webservices/service"
targetNamespace="http://wind.com/webservices/service" elementFormDefault="qualified">
    <xs:element name="getCountryRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="getCountryResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="country" type="tns:country"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="country">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="population" type="xs:int"/>
            <xs:element name="capital" type="xs:string"/>
            <xs:element name="currency" type="tns:currency"/>
        </xs:sequence>
    </xs:complexType>
    <xs:simpleType name="currency">
        <xs:restriction base="xs:string">
            <xs:enumeration value="GBP"/>
            <xs:enumeration value="EUR"/>
            <xs:enumeration value="PLN"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>
3.生成實體類,在當前專案根目錄下執行mvn clean install
生成路徑為
com.wind.webservices.service,跟上面
targetNamespace="http://wind.com/webservices/service"對應
4.建立一個Repository
@Component
public class CountryRepository {

    private static final Map<String, Country> countries = new HashMap<>();
@PostConstruct
public void initData() {
        Country spain = new Country();
spain.setName("Spain");
spain.setCapital("Madrid");
spain.setCurrency(Currency.EUR);
spain.setPopulation(46704314);
countries.put(spain.getName(), spain);
Country poland = new Country();
poland.setName("Poland");
poland.setCapital("Warsaw");
poland.setCurrency(Currency.PLN);
poland.setPopulation(38186860);
countries.put(poland.getName(), poland);
Country uk = new Country();
uk.setName("United Kingdom");
uk.setCapital("London");
uk.setCurrency(Currency.GBP);
uk.setPopulation(63705000);
countries.put(uk.getName(), uk);
}

    public Country findCountry(String name) {
        Assert.notNull(name, "The country's name must not be null");
        return countries.get(name);
}
}
5.建立一個服務EndPoint
@Endpoint
public class CountryEndpoint {
    
    //跟countries.xsd檔案中得保持一致
private static final String NAMESPACE_URI = "http://wind.com/webservices/service";
private CountryRepository countryRepository;@Autowiredpublic CountryEndpoint(CountryRepository countryRepository) { this.countryRepository = countryRepository;}
    //配置對外介面
    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
    @ResponsePayload
public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) {
        GetCountryResponse response = new GetCountryResponse();
response.setCountry(countryRepository.findCountry(request.getName()));
        return response;
}
}
6.新增webservice配置
@Configuration
@EnableWs
public class WebServiceConfig extends WsConfigurerAdapter {

    @Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
       //配置對外服務根路徑
        return new ServletRegistrationBean(servlet, "/ws/*");
}

    @Bean(name = "countries")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("CountriesPort");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://wind.com/webservices/service");
wsdl11Definition.setSchema(countriesSchema);
        return wsdl11Definition;
}

    @Bean
public XsdSchema countriesSchema() {
        return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
}

}
7.啟動應用
@SpringBootApplication
public class SampleWebServicesApplication {

   public static void main(String[] args) throws Exception {
      SpringApplication.run(SampleWebServicesApplication.class, args);
}

}
在瀏覽器中訪問:http://localhost:8080/ws/countries.wsdl 。
8.傳送SOAP請求
定義請求檔案
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:gs="http://wind.com/webservices/service">
    <soapenv:Header/>
    <soapenv:Body>
        <gs:getCountryRequest>
            <gs:name>Spain</gs:name>
        </gs:getCountryRequest>
    </soapenv:Body>
</soapenv:Envelope>
傳送curl請求(window上可以用SoapUI工具,unix/linux可以直接用命令列)
curl --header "content-type: text/xml" -d @request.xml http://localhost:8080/ws
或者HttpURLConnection傳送請求
InputStream is = null;
OutputStream os = null;
HttpURLConnection conn = null;
//服務的地址
try {
    URL wsUrl = new URL("http://localhost:8080/ws");
conn = (HttpURLConnection) wsUrl.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
os = conn.getOutputStream();
//請求體
String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
            "                  xmlns:gs=\"http://wind.com/webservices/service\">\n" +
            "    <soapenv:Header/>\n" +
            "    <soapenv:Body>\n" +
            "        <gs:getCountryRequest>\n" +
            "            <gs:name>Spain</gs:name>\n" +
            "        </gs:getCountryRequest>\n" +
            "    </soapenv:Body>\n" +
            "</soapenv:Envelope>";
os.write(soap.getBytes());
is = conn.getInputStream();
    byte[] b = new byte[1024];
    int len = 0;
String s = "";
    while((len = is.read(b)) != -1){
        String ss = new String(b,0,len,"UTF-8");
s += ss;
}
    System.out.println(s);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if(is != null){
        try {
            is.close();
} catch (IOException e) {
            e.printStackTrace();
}
    }

    if(os != null){
        try {
            os.close();
} catch (IOException e) {
            e.printStackTrace();
}
    }

    if(conn != null){
        conn.disconnect();
}
}