CXF實現WebService

CXF搭建WebService服務端

引入依賴

<!--cxf依賴-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
    <version>3.2.4</version>
</dependency>

編寫服務接口

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;/**
 * webservice服務端接口類
 */
@WebService
public interface CXFTestService {/**
     * 提供調用的方法,使用@WebMethod註釋
     * @param id
     * @return StudentScore
     */
    @WebMethod(operationName = "getStudentScoreById")
    StudentScore getStudentScore(@WebParam(name = "id") long id);
}

編寫服務接口實現類

import com.javatest.po.StudentScore;
import com.javatest.service.StudentScoreService;
import com.javatest.webservice.server.CXFTestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.jws.WebService;/**
 * webservice服務端實現類。注意,如果使用面向接口,那麼在此實現類中必須通過endpointInterface指定服務端接口類
 */
@WebService(targetNamespace = "http://impl.server.webservice.javatest.com/",    // 命名空間一般爲包名的倒置
        endpointInterface = "com.javatest.webservice.server.CXFTestService"
)
@Service
public class CXFTestServiceImpl implements CXFTestService {@Autowired
    private StudentScoreService service;@Override
    public StudentScore getStudentScore(long id) {
        return service.selectByPrimaryKey(id);
    }
}

編寫cxf配置類

import com.javatest.webservice.server.impl.CXFTestServiceImpl;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.xml.ws.Endpoint;/**
 * 使用cxf發佈webservice服務,實現同一端口同時提供API和webservice
 */
@Configuration
public class WebServiceConfig implements WebMvcConfigurer {@Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        return new SpringBus();
    }// 發佈cxf的webservice接口
    @Bean
    public CXFTestServiceImpl CXFTestService() {
        return new CXFTestServiceImpl();
    }
  @Bean
    public Endpoint endpointForResources() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), CXFTestService());
        endpoint.publish("/getCXF");
        return endpoint;
    }
    
    // 修改攔截的路徑,效果與在application.yml中配置cxf.path是一樣的。
    // 如果兩者都沒配置,默認路徑爲/services/*。如果兩者都配置了,以本配置類配置的爲準。非必需項
    @Bean
    public ServletRegistrationBean newServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/cxf/*");
    } 
}

啓動項目後訪問:http://localhost:9010/javatest/cxf/getCXF?wsdl ,同樣進入了wsdl文檔,說明服務端已經正常啓動。

CXF搭建WebService客戶端

使用cxf搭建client有兩種方式:代理工廠和動態調用。爲了方便調用,客戶端的代碼同樣寫在另一個項目上。

準備工作

當用cxf發佈服務後,在idea通過Tools–>WebServices—>Generate Java Code From Wsdl…—>輸入配置時,可能會有如下提示:
在這裏插入圖片描述
無法按ok了。原因是,這裏需要安裝cxf並指定有效的cxf路徑,具體做法爲:

1)進入cxf的官網http://cxf.apache.org/download.html,下載對應的zip包(windows);
2)解壓壓縮包;
3)配置cxf路徑:在Idea中Ctrl+Alt+s進入Settings–>Tools–>Web Services,在cxf那欄中,將解壓後的文件夾路徑填上去。注意,這裏建議複製文件夾路徑粘貼上去,而不是按右邊的按鈕選擇,否則無法指定文件夾路徑。文件夾路徑不能出現中文。
在這裏插入圖片描述
之後再次Generate Java Code From Wsdl就能用cxf來下載服務。這樣就能將文件下載到本地了。

這裏再次提醒一句,在下載服務前要確保服務端是啓動的。

使用代理工廠調用webservice服務

創建一個controller,利用JaxWsProxyFactoryBean來創建webservice服務。

@PostMapping("/getStudentScoreById")
public StudentScore getStudentScoreById(long id) {
    JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
    factory.setServiceClass(CXFTestService.class);
    factory.setAddress("http://localhost:9010/javatest/cxf/getCXF?wsdl");
    // 需要服務接口文件
    CXFTestService client = (CXFTestService) factory.create();
    return client.getStudentScoreById(id);
}

使用動態工廠調用webservice服務

如果不想用代理工廠,也可以用JaxWsDynamicClientFactory創建服務。這裏用到了QName來指定標籤。

@PostMapping("/getStudentScoreByIdDynamic")
public Object getStudentScoreByIdDynamic(long id) throws Exception {
    JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
    Client client = dcf.createClient("http://localhost:9010/javatest/cxf/getCXF?wsdl");
    // 用QName指定調用的服務端方法
    // 注意:第一個參數不是targetNamespace,而是wsdl文檔中,<wsdl:import>標籤裏的namespace
    QName qName = new QName("http://server.webservice.javatest.com/","getStudentScoreById");
    // client.invoke返回的是一個Object[],因爲getStudentScoreById只返回一個對象,所以取索引爲0的對象
    return client.invoke(qName, id)[0];
}

兩個調用方法的完整代碼如下:

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.xml.namespace.QName;

@RestController
@RequestMapping("/cxf")
public class CxfController {

   @PostMapping("/getStudentScoreById")
   public StudentScore getStudentScoreById(long id) {
       JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
       factory.setServiceClass(CXFTestService.class);
       factory.setAddress("http://localhost:9010/javatest/cxf/getCXF?wsdl");
       // 需要服務接口文件
       CXFTestService client = (CXFTestService) factory.create();
       return client.getStudentScoreById(id);
   }

   @PostMapping("/getStudentScoreByIdDynamic")
   public Object getStudentScoreByIdDynamic(long id) throws Exception {
       JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
       Client client = dcf.createClient("http://localhost:9010/javatest/cxf/getCXF?wsdl");
       // 用QName指定調用的服務端方法
       // 注意:第一個參數不是targetNamespace,而是wsdl文檔中,<wsdl:import>標籤裏的namespace
       QName qName = new QName("http://server.webservice.javatest.com/","getStudentScoreById");
       // client.invoke返回的是一個Object[],因爲getStudentScoreById只返回一個對象,所以取索引爲0的對象
       return client.invoke(qName, id)[0];
   }
}   

總結

webservice服務端和客戶端的開發是分離的,意思是服務端使用哪種技術搭建並不會影響客戶端選用的技術,如果服務端使用cxf技術搭建,那麼客戶端既可以用cxf,也可以用axis2、JWS、wsimport等等的技術調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章