1. 程式人生 > >SpringBoot整合cxf發布webService和客戶端的調用

SpringBoot整合cxf發布webService和客戶端的調用

wire 註解 pac point login isp 3.1 component amp

SpringBoot整合cxf發布webService

1. 看看項目結構圖

技術分享圖片

2. cxf的pom依賴

1 <dependency>
2     <groupId>org.apache.cxf</groupId>
3     <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
4     <version>3.2.4</version>
5 </dependency>

3. 開始編寫webService服務端

3.1 實體類entity

 1 package com.example.demo.entity;
 2 
 3 import java.io.Serializable;
 4 /**
 5  * @ClassName:User
 6  * @Description:測試實體
 7  * @author Jerry
 8  * @date:2018年4月10日下午3:57:38
 9  */
10 public class User implements Serializable{
11 
12     private static final long serialVersionUID = -3628469724795296287L;
13 14 private String userId; 15 private String userName; 16 private String email; 17 public String getUserId() { 18 return userId; 19 } 20 public void setUserId(String userId) { 21 this.userId = userId; 22 } 23 public String getUserName() { 24 return
userName; 25 } 26 public void setUserName(String userName) { 27 this.userName = userName; 28 } 29 public String getEmail() { 30 return email; 31 } 32 public void setEmail(String email) { 33 this.email = email; 34 } 35 @Override 36 public String toString() { 37 return "User [userId=" + userId + ", userName=" + userName + ", email=" + email + "]"; 38 } 39 40 }

3.2 服務接口

package com.example.demo.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

import com.example.demo.entity.User;
/**
 * @ClassName:UserService
 * @Description:測試服務接口類
 *              include:兩個測試方法
 * @author Jerry
 * @date:2018年4月10日下午3:58:10
 */
//@WebService(targetNamespace="http://service.demo.example.com")如果不添加的話,動態調用invoke的時候,會報找不到接口內的方法,具體原因未知.
@WebService(targetNamespace="http://service.demo.example.com")
public interface UserService {

    @WebMethod//標註該方法為webservice暴露的方法,用於向外公布,它修飾的方法是webservice方法,去掉也沒影響的,類似一個註釋信息。
    public User getUser(@WebParam(name = "userId") String userId);

    @WebMethod
    @WebResult(name="String",targetNamespace="")
    public String getUserName(@WebParam(name = "userId") String userId);

}

3.3 服務接口的實現類

package com.example.demo.service.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.jws.WebService;

import org.springframework.stereotype.Component;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
/**
 * @ClassName:UserServiceImpl
 * @Description:測試服務接口實現類
 * @author Jerry
 * @date:2018年4月10日下午3:58:58
 */
@WebService(serviceName="UserService",//對外發布的服務名
            targetNamespace="http://service.demo.example.com",//指定你想要的名稱空間,通常使用使用包名反轉
            endpointInterface="com.example.demo.service.UserService")//服務接口全路徑, 指定做SEI(Service EndPoint Interface)服務端點接口
@Component
public class UserServiceImpl implements UserService{

    private Map<String, User> userMap = new HashMap<String, User>();
    public UserServiceImpl() {
        System.out.println("向實體類插入數據");
        User user = new User();
        user.setUserId(UUID.randomUUID().toString().replace("-", ""));
        user.setUserName("test1");
        user.setEmail("[email protected]");
        userMap.put(user.getUserId(), user);

        user = new User();
        user.setUserId(UUID.randomUUID().toString().replace("-", ""));
        user.setUserName("test2");
        user.setEmail("[email protected]");
        userMap.put(user.getUserId(), user);

        user = new User();
        user.setUserId(UUID.randomUUID().toString().replace("-", ""));
        user.setUserName("test3");
        user.setEmail("[email protected]");
        userMap.put(user.getUserId(), user);
    }
    @Override
    public String getUserName(String userId) {
        return "userId為:" + userId;
    }
    @Override
    public User getUser(String userId) {
        System.out.println("userMap是:"+userMap);
        return userMap.get(userId);
    }

}

3.4 發布webService的配置

package com.example.demo.config;

import javax.xml.ws.Endpoint;

import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.example.demo.service.UserService;
/**
 * @ClassName:CxfConfig
 * @Description:cxf發布webservice配置
 * @author Jerry
 * @date:2018年4月10日下午4:12:24
 */
@Configuration
public class CxfConfig {
    @Autowired
    private Bus bus;

    @Autowired
    UserService userService;

    /**
     * 此方法作用是改變項目中服務名的前綴名,此處127.0.0.1或者localhost不能訪問時,請使用ipconfig查看本機ip來訪問
     * 此方法被註釋後:wsdl訪問地址為http://127.0.0.1:8080/services/user?wsdl
     * 去掉註釋後:wsdl訪問地址為:http://127.0.0.1:8080/soap/user?wsdl
     * @return
     */
    @SuppressWarnings("all")
    @Bean
    public ServletRegistrationBean dispatcherServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/soap/*");
    }

    /** JAX-WS 
     * 站點服務
     * **/
    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(bus, userService);
        endpoint.publish("/user");
        return endpoint;
    }

}

4. 項目啟動後的wsdl信息

技術分享圖片

由於圖省事,我將項目的服務端口改為了80,這樣就省去了IP後面寫端口號的麻煩。

5. 兩種調用方式

package com.example.demo.client;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

import com.example.demo.service.UserService;
/**
 * @ClassName:CxfClient
 * @Description:webservice客戶端:
 *                 該類提供兩種不同的方式來調用webservice服務
 *              1:代理工廠方式
 *              2:動態調用webservice
 * @author Jerry
 * @date:2018年4月10日下午4:14:07
 */
public class CxfClient {


    public static void main(String[] args) {
        CxfClient.main1();
        CxfClient.main2();
    }

    /**
     * 1.代理類工廠的方式,需要拿到對方的接口地址
     */
    public static void main1() {
        try {
            // 接口地址
            String address = "http://127.0.0.1/soap/user?wsdl";
            // 代理工廠
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            // 設置代理地址
            jaxWsProxyFactoryBean.setAddress(address);
            // 設置接口類型
            jaxWsProxyFactoryBean.setServiceClass(UserService.class);
            // 創建一個代理接口實現
            UserService us = (UserService) jaxWsProxyFactoryBean.create();
            // 數據準備
            String userId = "maple";
            // 調用代理接口的方法調用並返回結果
            String result = us.getUserName(userId);
            System.out.println("返回結果:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 2:動態調用
     */
    public static void main2() {
        // 創建動態客戶端
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient("http://127.0.0.1/soap/user?wsdl");
        // 需要密碼的情況需要加上用戶名和密碼
        // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
        Object[] objects = new Object[0];
        try {
            // invoke("方法名",參數1,參數2,參數3....);
            objects = client.invoke("getUserName", "maple");
            System.out.println("返回數據:" + objects[0]);
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }
    }
}

6. 註意點.

誠如之前所說,如果接口的註解上不加targetNamespace的話,動態調用的時候,會報如下的錯誤。

技術分享圖片

SpringBoot整合cxf發布webService和客戶端的調用