cxf處理java bean及List、Map類型


      項目中經常是處理復合類型比如集合List、Map,下面就cxf處理復合類型進行講解。

具體例子如下:

   這里實例是客戶端傳一個JavaBean,服務器端返回集合類型;

 一、  接口返回List處理:

    在原來的項目實例(cxf開發webService服務端口)基礎上,我們先創建一個實體類User:

 1 /**
 2  * 
 3  */
 4 package com.hik.entity;
 5 
 6 /**
 7  * @ClassName: User
 8  * @Description: 用戶實體類
 9  * @author jed
10  * @date 2017年7月30日下午2:44:41
11  *
12  */
13 public class User {
14 
15     private Integer id; // 編號
16     private String userName; //用戶名
17     private String password; //密碼
18     
19     public Integer getId() {
20         return id;
21     }
22     public void setId(Integer id) {
23         this.id = id;
24     }
25     public String getUserName() {
26         return userName;
27     }
28     public void setUserName(String userName) {
29         this.userName = userName;
30     }
31     public String getPassword() {
32         return password;
33     }
34     public void setPassword(String password) {
35         this.password = password;
36     }
37     
38     
39 }
View Code

再創建一個Role實體類:

 1 /**
 2  * 
 3  */
 4 package com.hik.entity;
 5 
 6 /**
 7  * @ClassName: Role
 8  * @Description: TODO
 9  * @author jed
10  * @date 2017年7月30日下午2:46:45
11  *
12  */
13 public class Role {
14 
15     private Integer id; //編號
16     private String roleName; //角色名稱
17     
18     public Role() {
19         super();
20     }
21 
22     public Role(Integer id, String roleName) {
23         super();
24         this.id = id;
25         this.roleName = roleName;
26     }
27     
28     public Integer getId() {
29         return id;
30     }
31     public void setId(Integer id) {
32         this.id = id;
33     }
34     public String getRoleName() {
35         return roleName;
36     }
37     public void setRoleName(String roleName) {
38         this.roleName = roleName;
39     }
40     
41     
42 }
View Code

然后HelloWorld再加一個接口方法getRoleByUser,通過用戶查找角色:

 1 /**
 2  * 
 3  */
 4 package com.hik.webservice;
 5 
 6 import java.util.List;
 7 
 8 import javax.jws.WebService;
 9 
10 import com.hik.entity.Role;
11 import com.hik.entity.User;
12 
13 /**
14  * @ClassName: HelloWorld
15  * @Description: TODO
16  * @author jed
17  * @date 2017年7月30日上午10:20:35
18  *
19  */
20 @WebService
21 public interface HelloWorld {
22 
23     public String say(String str);
24     
25     public List<Role> getRoleByUser(User user);
26 }
View Code

然后HelloWorld接口實現類 HelloWorldImpl寫下新增的方法的具體實現,我們這里寫死,模擬下即可:

 1 /**
 2  * 
 3  */
 4 package com.hik.webservice.impl;
 5 
 6 import java.util.ArrayList;
 7 import java.util.List;
 8 
 9 import javax.jws.WebService;
10 
11 import com.hik.entity.Role;
12 import com.hik.entity.User;
13 import com.hik.webservice.HelloWorld;
14 
15 /**
16  * @ClassName: HelloWorldImpl
17  * @Description: TODO
18  * @author jed
19  * @date 2017年7月30日上午10:24:46
20  *
21  */
22 @WebService
23 public class HelloWorldImpl implements HelloWorld{
24 
25     public String say(String str) {
26         return "hello "+str;
27     }
28 
29     public List<Role> getRoleByUser(User user) {
30         List<Role> roleList = new ArrayList<Role>();
31         if(user!=null){
32             if(user.getUserName().equals("jack") && user.getPassword().equals("123456")){
33                 roleList.add(new Role(1, "技術總監"));
34                 roleList.add(new Role(2, "產品經理"));
35             }else if(user.getUserName().equals("lili") && user.getPassword().equals("123456")){
36                 roleList.add(new Role(3, "程序員"));
37             }
38             return roleList;
39         }else{
40             return null;
41         }
42                 
43     }
44 
45 }
View Code

服務端其他地方不用動;再重新發布下webService接口。

下面我們來處理下客戶端,和前面講的一樣。我們用wsdl2java工具重新生成代碼(參考cxf開發webService客戶端及調用服務端的理解 )

 

我們改下Client類:

 1 /**
 2  * 
 3  */
 4 package com.hik.webservice;
 5 
 6 import java.util.List;
 7 
 8 /**
 9  * @ClassName: Client
10  * @Description: TODO
11  * @author jed
12  * @date 2017年7月30日下午1:58:36
13  *
14  */
15 public class Client {
16 
17     public static void main(String[] args) {
18         HelloWorldService service = new HelloWorldService();
19         HelloWorld helloWorld = service.getHelloWorldPort(); //代理
20         //System.out.println(helloWorld.say("你好!"));
21         User user = new User();
22         user.setUserName("lili");
23         user.setPassword("123456"); 
24         List<Role> roleList = helloWorld.getRoleByUser(user);
25         for(Role role : roleList){
26             System.out.println(role.getId()+" , "+role.getRoleName());
27         }
28     }
29 }
View Code

運行截圖:

二、接口返回Map處理

      map類型比較特殊,由其數據結構而決定。XmlAdapter類源碼也有說明:

 因此,需要寫一個適配器來做轉換,使用注解annotation注解 。該適配器類需實現抽象類XmlAdapter的兩個轉換方法。

 

 

 代碼例子如下:

  如增加接口:獲取所有用用戶以及對應的每個用戶所有角色信息;

 

服務器端:

HelloWorld接口加方法:

 1 /**
 2      * 
 3      * @MethodName: getRoles
 4      * @Description: 獲取所有用戶及對應角色
 5      * @author jed
 6      * @date 2017年8月4日下午10:36:59
 7      * @param @return    
 8      * @return Map<String,List<Role>>    返回類型
 9      * @return
10      *
11      */
12     @XmlJavaTypeAdapter(MapAdapter.class)
13     public Map<String, List<Role>> getRoles();
View Code

 

 HelloWorldImpl實現類加方法實現:

 1 public Map<String, List<Role>> getRoles() {
 2         Map<String, List<Role>> map = new HashMap<String, List<Role>>();
 3         List<Role> roleList1 = new ArrayList<Role>();
 4         roleList1.add(new Role(1, "技術總監"));
 5         roleList1.add(new Role(2, "產品經理"));
 6         map.put("admin", roleList1);
 7         List<Role> roleList2 = new ArrayList<Role>();
 8         roleList2.add(new Role(3, "程序員"));
 9         map.put("jack", roleList2);
10         return map;
11     }
View Code

然后我們啟動Server類:發現報錯:

 報錯顯示不支持該類型,解決方案,可以使用適配器,把cxf不能接受的類型通過適配器,轉能接受的類型。

 

      我們使用@XmlJavaTypeAdapter注解,加在接口定義上,完整接口代碼如下:

 

 1 /**
 2  * 
 3  */
 4 package com.hik.webservice;
 5 
 6 import java.util.List;
 7 import java.util.Map;
 8 
 9 import javax.jws.WebService;
10 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
11 
12 import com.hik.adapter.MapAdapter;
13 import com.hik.entity.Role;
14 import com.hik.entity.User;
15 
16 /**
17  * @ClassName: HelloWorld
18  * @Description: TODO
19  * @author jed
20  * @date 2017年7月30日上午10:20:35
21  *
22  */
23 @WebService
24 public interface HelloWorld {
25 
26     public String say(String str);
27     
28     /**
29      * 
30      * @MethodName: getRoleByUser
31      * @Description: 獲取用戶角色 
32      * @author jed
33      * @date 2017年8月4日下午10:37:30
34      * @param @param user
35      * @param @return    
36      * @return List<Role>    返回類型
37      * @param user
38      * @return
39      *
40      */
41     public List<Role> getRoleByUser(User user);
42     
43     /**
44      * 
45      * @MethodName: getRoles
46      * @Description: 獲取所有用戶及對應角色
47      * @author jed
48      * @date 2017年8月4日下午10:36:59
49      * @param @return    
50      * @return Map<String,List<Role>>    返回類型
51      * @return
52      *
53      */
54     @XmlJavaTypeAdapter(MapAdapter.class)
55     public Map<String, List<Role>> getRoles();
56 }
View Code

這里參數需要一個實現了XmlAdapter類的適配器類;

這里的話XmlAdapter要加兩個參數,XmlAdapter<ValueType,BoundType> 

ValueType是cxf能接收的類型,這里我用了數組;

BoundType是cxf不能接受的類型,也就是我例子里的需求的Map類型;

 1 /**
 2  * 
 3  */
 4 package com.hik.adapter;
 5 
 6 import java.util.HashMap;
 7 import java.util.List;
 8 import java.util.Map;
 9 
10 import javax.xml.bind.annotation.adapters.XmlAdapter;
11 
12 import com.hik.entity.Role;
13 
14 /**
15  * @ClassName: MapAdapter
16  * @Description: Map適配器
17  * @author jed
18  * @date 2017年8月4日下午10:56:41
19  *
20  */
21 public class MapAdapter extends XmlAdapter<MyRole[], Map<String, List<Role>>>{
22 
23     /**
24      * 適配轉換  MyRole[] -> Map<String, List<Role>>
25      */
26     @Override
27     public Map<String, List<Role>> unmarshal(MyRole[] v) throws Exception {
28         Map<String, List<Role>> map = new HashMap<String, List<Role>>();
29         for(int i=0;i<v.length;i++){
30             MyRole r = v[i];
31             map.put(r.getKey(), r.getValue());
32         }
33         return map;
34     }
35 
36      /**
37      * 適配轉換  Map<String, List<Role>> -> MyRole[]
38      */
39     @Override
40     public MyRole[] marshal(Map<String, List<Role>> v) throws Exception {
41         MyRole[] roles = new MyRole[v.size()];
42         int i=0;
43         for(String key : v.keySet()){
44             roles[i] = new MyRole();
45             roles[i].setKey(key);
46             roles[i].setValue(v.get(key));
47             i++;
48         }
49         
50         return roles;
51     }
52 
53 }
View Code

 

還有一個MyRole自定義類型,key:value。我們搞成兩個屬性,具體實現如下:

 1 /**
 2  * 
 3  */
 4 package com.hik.adapter;
 5 
 6 import java.util.List;
 7 
 8 import com.hik.entity.Role;
 9 
10 /**
11  * @ClassName: MyRole
12  * @Description: 自定義實體 cxf能接受
13  * @author jed
14  * @date 2017年8月4日下午11:01:23
15  *
16  */
17 public class MyRole {
18 
19     private String key;
20     private List<Role> value;
21     
22     public String getKey() {
23         return key;
24     }
25     public void setKey(String key) {
26         this.key = key;
27     }
28     public List<Role> getValue() {
29         return value;
30     }
31     public void setValue(List<Role> value) {
32         this.value = value;
33     }
34     
35     
36 }
View Code

 

OK  好了。我們運行Server類,發布webservice接口:

發布成功。然后就到了webservice客戶端,我們用wsdl2java工具生成下最新代碼

 

我們修改下Client類:

 1 /**
 2  * 
 3  */
 4 package com.hik.webservice;
 5 
 6 import java.util.List;
 7 
 8 /**
 9  * @ClassName: Client
10  * @Description: TODO
11  * @author jed
12  * @date 2017年7月30日下午1:58:36
13  *
14  */
15 public class Client {
16 
17     public static void main(String[] args) {
18         HelloWorldService service = new HelloWorldService();
19         HelloWorld helloWorld = service.getHelloWorldPort(); //代理
20         //System.out.println(helloWorld.say("你好!"));
21         /*User user = new User();
22         user.setUserName("lili");
23         user.setPassword("123456"); 
24         List<Role> roleList = helloWorld.getRoleByUser(user);
25         for(Role role : roleList){
26             System.out.println(role.getId()+" , "+role.getRoleName());
27         }*/
28         MyRoleArray array = helloWorld.getRoles();
29         List<MyRole> roleList = array.item;
30         for(int i=0;i<roleList.size();i++){
31             MyRole mr = roleList.get(i);
32             System.out.println(mr.key+":");
33             for(Role r: mr.getValue()){
34                 System.out.println(r.getId()+","+r.getRoleName()+" ");
35             }
36             System.out.println();
37         }
38     }
39 }
View Code

運行結果:

 

    總結: webService處理過程如下:

1、webservice服務器端開發webservice接口,然后發布webservice;

2、通過一個Url調用webservice接口,發布的url是 http://192.168.0.102/helloWorld,則我們請求的url就是 http://192.168.0.102/helloWorld?wsdl  

3、請求成功,返回一大串xml標記。這一大串xml即使wsdl。   wsdl (Web Services Description Language) 也就是Web Service描述語言,描述服務器端定義的webservice接口的相關信息。

4、wsdl描述可看到發布的方法。如:wsdl:types就是定義了一些變量,wsdl:message相當於定義方法,wsdl:portType相當與調用與返回。

5、客戶端通過這個url請求,獲得wsdl規范的xml文檔片段信息,需用到SOAP(Simple Object Access Protocol)即簡單對象訪問協議,我們通過這個協議,來實現客戶端,服務器端消息交互,SOAP使用XML消息調用遠程方法;

     當然交互的媒介就是xml,具體交互內容根據wsdl文檔描述來。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM