最近工作中需要用到webservice,而且結合spring boot進行開發,參照了一些網上的資料,配置過程中出現的了一些問題,於是寫了這篇博客,記錄一下我這次spring boot+cxf開發的webservice的配置過程,僅供參考。
聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出, 原文地址 如有問題, 可郵件(249780464@qq.com)咨詢.
一、本次開發除了用到spring boot基礎jar包外,還用到了cxf相關jar包:
1 <!-- cxf支持 --> 2 <dependency> 3 <groupId>org.apache.cxf</groupId> 4 <artifactId>cxf-rt-frontend-jaxws</artifactId> 5 <version>3.1.6</version> 6 </dependency> 7 <dependency> 8 <groupId>org.apache.cxf</groupId> 9 <artifactId>cxf-rt-transports-http</artifactId> 10 <version>3.1.6</version> 11 </dependency>
二、首先我們創建一個實體類,內容是關於用戶信息的查詢和記錄:
1 import java.io.Serializable;
2 import java.util.Date;
3
4 public class User implements Serializable {
5
6 private static final long serialVersionUID = -5939599230753662529L;
7 private String userId;
8 private String username;
9 private String age;
10 private Date updateTime;
11 //getter setter ......
12 public void setUserId(String userId) {
13 this.userId=userId;
14 }
15 public void setUsername(String username) {
16 this.username=username;
17 }
18 public void setAge(String age) {
19 this.age=age;
20 }
21 public void setUpdateTime(Date updateTime) {
22 this.updateTime=updateTime;
23 }
24
25
26 public String getUserId() {
27 return userId;
28 }
29 public String getUserName() {
30 return username;
31 }
32 public String getAge() {
33 return age;
34 }
35 public Date getUpdateTime() {
36 return updateTime;
37 }
38 }
三、接下來我們創建接口類:
1 import javax.jws.WebMethod;
2 import javax.jws.WebParam;
3 import javax.jws.WebService;
4
5 import cn.paybay.demo.entity.User;
6
7
8 @WebService
9 public interface UserService {
10
11 @WebMethod
12 String getName(@WebParam(name = "userId") String userId);
13 @WebMethod
14 User getUser(String userId);
15 }
四、有了接口類,那么接下來我們對接口進行實現,也就是接口實現類(也就是業務類)代碼:
1 package cn.paybay.demo.service.impl;
2
3 import java.util.Date;
4 import java.util.HashMap;
5 import java.util.Map;
6
7
8
9 import javax.jws.WebService;
10
11 import cn.paybay.demo.entity.User;
12 import cn.paybay.demo.service.UserService;
13
14 @WebService(targetNamespace="http://service.demo.paybay.cn/",endpointInterface = "cn.paybay.demo.service.UserService")
15 public class UserServiceImpl implements UserService{
16
17 private Map<String, User> userMap = new HashMap<String, User>();
18 public UserServiceImpl() {
19 System.out.println("向實體類插入數據");
20 User user = new User();
21 user.setUserId("411001");
22 user.setUsername("zhansan");
23 user.setAge("20");
24 user.setUpdateTime(new Date());
25 userMap.put(user.getUserId(), user);
26
27 user = new User();
28 user.setUserId("411002");
29 user.setUsername("lisi");
30 user.setAge("30");
31 user.setUpdateTime(new Date());
32 userMap.put(user.getUserId(), user);
33
34 user = new User();
35 user.setUserId("411003");
36 user.setUsername("wangwu");
37 user.setAge("40");
38 user.setUpdateTime(new Date());
39 userMap.put(user.getUserId(), user);
40 }
41 @Override
42 public String getName(String userId) {
43 return "liyd-" + userId;
44 }
45 @Override
46 public User getUser(String userId) {
47 System.out.println("userMap是:"+userMap);
48 return userMap.get(userId);
49 }
50
51 }
注釋(PS):在發布服務之前,我們要在這里對業務實現類進行一下說明,請大家看下圖箭頭指向的方框部分
(圖一)

下面我來解釋一下加上圖方框箭頭所指代碼的目的:
http://impl.service.demo.paybay.cn/:這是我的業務類所在路徑;
http://service.demo.paybay.cn/:這是我的接口類所在路徑;
在不加上圖方框箭頭所指代碼的情況下,你最后發服務的結果是這樣的(如下圖):
(圖二)
並且會在你進行客戶端調用的時候回報錯:No operation was found with the name {http://impl.service.demo.paybay.cn/}getUser.
那么原因就是:在CXF發布服務的時候,發布的是業務類(UserServiceImpl.java),那么默認的命名空間就會是業務類所在包(路徑),而對外界暴露的則是接口類(UserService.java),那么對於客戶端調用的時侯,需要按照接口類所在路徑進行命名空間的定義。
所以在發布之前我們要在業務類(UserServiceImpl.java)上增加注解,指定命名空間,然后再進行發布,
那么我們最終在加上(圖一)方框箭頭所指代碼情況下,發布服務的結果為下圖(請看圖三):
(圖三)

五、(發布服務)接口類,業務類代碼都已經准備好,那么我接下來我就要對webservice服務進行發布:
代碼如下:
1 2
3 import javax.xml.ws.Endpoint;
4
5 import org.apache.cxf.Bus;
6 import org.apache.cxf.bus.spring.SpringBus;
7 import org.apache.cxf.jaxws.EndpointImpl;
8 import org.apache.cxf.transport.servlet.CXFServlet;
9 import org.springframework.boot.web.servlet.ServletRegistrationBean;
10 import org.springframework.context.annotation.Bean;
11 import org.springframework.context.annotation.Configuration;
12
13 import cn.paybay.demo.service.UserService;
14 import cn.paybay.demo.service.impl.UserServiceImpl;
15
16
17 @Configuration
18 public class TestConfig {
19
20 @Bean
21 public ServletRegistrationBean dispatcherServlet() {
22 return new ServletRegistrationBean(new CXFServlet(), "/test/*");
23 }
24 @Bean(name = Bus.DEFAULT_BUS_ID)
25 public SpringBus springBus() {
26 return new SpringBus();
27 }
28 @Bean
29 public UserService userService() {
30 return new UserServiceImpl();
31 }
32 @Bean
33 public Endpoint endpoint() {
34 EndpointImpl endpoint = new EndpointImpl(springBus(), userService());
35 endpoint.publish("/user");
36 return endpoint;
37 }
38
39 }
那么到這里呢,我們的所有的步驟基本完成了,啟動spring boot 然后再瀏覽器中輸入url:http://localhost:8080/webservice/test/user?wsdl
可以看到有相關的wsdl描述信息輸出了,說明服務已經發布了。
那么這里我又要增加注釋了,請大家注意,我在最初查詢資料,配置demo的時候,啟動以后,發布時候總是報404,網上有很多關於什么端口沖突等說法,我試過后,根本不是那一回事,然后我無意中嘗試了一下,在url地址處加入工程名,結果,問題解決了。
因此請大家注意:在測試發布服務的時候,你在瀏覽器中輸入的url地址應該是:http://localhost:8080/你的工程名/test/user?wsdl;
然后就是發布結果如下圖(見圖四):
(圖四)
到此為止,我們的服務發布成功了。
六、調用服務
1 2
3
4
5
6 import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
7
8
9 public class Client {
10
12 public static void main(String args[]) throws Exception{
13
14 JaxWsDynamicClientFactory dcf =JaxWsDynamicClientFactory.newInstance();
15 org.apache.cxf.endpoint.Client client =dcf.createClient("http://localhost:8080/webservice/test/user?wsdl");
16 //getUser 為接口中定義的方法名稱 張三為傳遞的參數 返回一個Object數組
17 Object[] objects=client.invoke("getUser","411001");
18 //輸出調用結果
19 System.out.println("*****"+objects[0].toString());
20 }
21
22 }
七、最后附上我的工程結構圖(見圖五):
(圖五)

寫這篇博客,參照了一些大神的貼子,學習到很多知識,總結出來的,僅供參考,如有錯誤,請各位指導!

