一、Apache CXF是什麼?
Apache CXF 是一個開源的 Services 框架,CXF 幫助您利用 Frontend 程式設計 API 來構建和開發 Services ,像 JAX-WS 。這些 Services 可以支援多種協議,比如:SOAP、XML/HTTP、RESTful HTTP 或者 CORBA ,並且可以在多種傳輸協議上執行,比如:HTTP、JMS 或者 JBI,CXF 大大簡化了 Services 的建立,同時它繼承了 XFire 傳統,一樣可以天然地和 Spring 進行無縫整合。
二、SpringBoot整合Apache CXF實踐例子
本次例子為Client-Server(客戶端-服務端)。還是以我最喜歡的Blog為例。
本次涉及兩個專案,一個是blog-cxf-client,另外一個是blog-cxf-server。
1.blog-cxf-server
(1)匯入Maven依賴
<dependencies> <!-- SpringBoot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- CXF webservice --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.2.4</version> </dependency> <!-- Lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <artifactId>blog-cxf-server</artifactId> <groupId>com.blog.cxf</groupId> <version>1.0</version> </dependency> </dependencies>
(2)編寫相關程式碼
a.編寫主類
package com.blog.cxf.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; /** * @description: * @author: youcong * @time: 2020/10/24 22:30 */ @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class BlogCxfServerApplication { public static void main(String[] args) { SpringApplication.run(BlogCxfServerApplication.class, args); System.out.println("====啟動Blog Cxf Server===="); } }
b.編寫application.yml配置檔案
# Tomcat server: tomcat: uri-encoding: UTF-8 #最小執行緒數 min-spare-threads: 500 #最大執行緒數 max-threads: 2500 #最大連線數 max-connections: 5000 #最大等待佇列長度 accept-count: 1000 #請求頭最大長度kb max-http-header-size: 1048576 #啟動APR(非阻塞IO) protocol: org.apache.coyote.http11.Http11AprProtocol port: 9090 # Spring spring: application: # 應用名稱 name: blog-cxf-server cxf: path: /cxf
c.編寫service程式碼
UserService.java
package com.blog.cxf.server.service; import com.blog.cxf.server.dto.UserReqDto; import javax.jws.WebParam; import javax.jws.WebService; /** * @description: * @author: youcong * @time: 2020/10/24 22:32 */ @WebService(targetNamespace = "http://service.server.cxf.blog.com/") public interface UserService { /** * 新增使用者 * @param email * @param username * @param password * @return */ int addUser(@WebParam(name = "email") String email, @WebParam(name = "username") String username, @WebParam(name = "password") String password); /** * 更新使用者資訊 * @param userReqDto * @return */ int updateUser(@WebParam(name="user")UserReqDto userReqDto); }
UserServiceImpl.java
package com.blog.cxf.server.service.impl; import com.blog.cxf.server.dto.UserReqDto; import com.blog.cxf.server.service.UserService; import org.springframework.stereotype.Component; import javax.jws.WebService; /** * @description: * @author: youcong * @time: 2020/10/24 22:35 */ @WebService(serviceName = "userService",//對外發布的服務名 targetNamespace = "http://service.server.cxf.blog.com/",//指定你想要的名稱空間,通常使用使用包名反轉 endpointInterface = "com.blog.cxf.server.service.UserService") @Component public class UserServiceImpl implements UserService { public int addUser(String email, String username, String password) { System.out.println("註冊使用者:"+email); return 1; } public int updateUser(UserReqDto userReqDto) { return 1; } }
資料傳輸類(UserReqDto.java):
package com.blog.cxf.server.dto; import lombok.Data; /** * @description: * @author: youcong * @time: 2020/10/24 22:49 */ @Data public class UserReqDto { private Long ID; private String email; private String username; private String password; }
c.編寫配置類(服務釋出)
package com.blog.cxf.server.config; import com.blog.cxf.server.service.UserService; import com.blog.cxf.server.service.impl.UserServiceImpl; import org.apache.cxf.Bus; import org.apache.cxf.bus.spring.SpringBus; import org.apache.cxf.jaxws.EndpointImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @description: * @author: youcong * @time: 2020/10/24 22:37 */ @Configuration public class CxfConfig { @Bean(name = Bus.DEFAULT_BUS_ID) public SpringBus springBus() { return new SpringBus(); } @Bean public UserService userService() { return new UserServiceImpl(); } /** * 釋出服務並指定訪問URL * @return */ @Bean public EndpointImpl userEnpoint() { EndpointImpl endpoint = new EndpointImpl(springBus(), userService()); endpoint.publish("/user"); return endpoint; } }
(3)啟動BlogCxfServerApplication主類並訪問對應的WSDL
訪問路徑:
http://localhost:9090/cxf/user?wsdl
2.blog-cxf-client
(1)匯入Maven依賴
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>blog-cxf</artifactId> <groupId>com.blog.cxf</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>blog-cxf-client</artifactId> <dependencies> <!-- SpringBoot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- CXF webservice --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.2.4</version> </dependency> <!-- Lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <artifactId>blog-cxf-server</artifactId> <groupId>com.blog.cxf</groupId> <version>1.0</version> </dependency> </dependencies> </project>
(2)編寫主類
package com.blog.cxf.client; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; /** * @description: * @author: youcong * @time: 2020/10/24 23:35 */ @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class BlogCxfClientApplication { public static void main(String[] args) { SpringApplication.run(BlogCxfClientApplication.class, args); System.out.println("====啟動Blog Cxf Client===="); } }
(3)編寫application.yml
# Tomcat server: tomcat: uri-encoding: UTF-8 #最小執行緒數 min-spare-threads: 500 #最大執行緒數 max-threads: 2500 #最大連線數 max-connections: 5000 #最大等待佇列長度 accept-count: 1000 #請求頭最大長度kb max-http-header-size: 1048576 #啟動APR(非阻塞IO) protocol: org.apache.coyote.http11.Http11AprProtocol port: 9091 # Spring spring: application: # 應用名稱 name: blog-cxf-client
(4)編寫Controller
package com.blog.cxf.client.controller; import com.blog.cxf.server.dto.UserReqDto; import com.blog.cxf.server.service.UserService; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.springframework.web.bind.annotation.*; /** * @description: * @author: youcong * @time: 2020/10/24 23:37 */ @RestController @RequestMapping("/user") public class UserApiController { @PostMapping("/add") public int add(@RequestParam String email, @RequestParam String username, @RequestParam String password) { try { // 介面地址 String address = "http://127.0.0.1:9090/cxf/user?wsdl"; // 代理工廠 JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean(); // 設定代理地址 jaxWsProxyFactoryBean.setAddress(address); // 設定介面型別 jaxWsProxyFactoryBean.setServiceClass(UserService.class); // 建立一個代理介面實現 UserService userService = (UserService) jaxWsProxyFactoryBean.create(); return userService.addUser(email, username, password); } catch (Exception e) { e.printStackTrace(); return -1; } } }
注意:
實際中這段程式碼應該放在blog-cxf-server裡面的Controller,然後客戶端通過http-client或者其它http工具包進行請求。
還有如果是服務是都在一起,可按照maven依賴匯入的方式來實現兩個不同專案進行呼叫。
(5)使用PostMan測試
三、程式碼例子
程式碼例子已上傳到我的GitHub上。