【WebService】CXF處理javaBean等複合類型以及Map等複雜類型的數據

WebService系列文章: 
【WebService】帶你走進webservice的世界 
【WebService】自定義WebService服務及其調用 
【WebService】wsdl配置詳解以及使用註解修改wsdl配置 
【WebService】CXF攔截器的設置以及自定義CXF攔截器

  在實際中除了傳入一些基本的參數以外,還需要傳入一些類似於javaBean等複合類型,或者Map等複雜類型的數據,這一篇博文主要來寫兩個demo,模擬一下CXF處理這類數據的過程。

1. CXF處理javaBean等複合類型的數據

  客戶端提交一個數據過去,要檢查權限,比如是管理員的話,就擁有多個權限,普通用戶可能就一個權限之類的。這樣的話需要一個用戶的bean和權限的bean,然後數據庫的數據我用List來模擬一下,demo如下:

public class User {

    private Integer id;
    private String name;
    private String password;
    //……
}

public class Role {

    private Integer id;
    private String roleName; //角色名稱
    //……
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

ws的程序如下:

//接口
@WebService
public interface MyWebService {

    public String sayHello(String str);

    public List<Role> getRoleByUser(User user);
}

//實現類
@WebService
public class MyWebServiceImpl implements MyWebService{

    public String sayHello(String str) {
        return "Hello" + str;
    }

    public List<Role> getRoleByUser(User user) {
        List<Role> roleList = new ArrayList<Role>();        
        if(user != null) {
            if(user.getName().equals("admin") && user.getPassword().equals("123")) {
                roleList.add(new Role(1, "技術總監"));
                roleList.add(new Role(2, "架構師"));           
            } else if(user.getName().equals("eson15") && user.getPassword().equals("123")) {
                roleList.add(new Role(3, "java菜鳥"));
            }
            return roleList;
        } else {
            return null;
        }       
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

  主要來看getRoleByUser這個方法,當然了,也可以使用註解去配置一下要生成的wsdl,這裏就不配置了,使用默認的即可,方法中自定義了一個List用來存儲角色信息的,模擬的是先判斷用戶的身份,然後根據不同的身份賦予不同的角色。 
  生成wsdl後,通過解析,然後調用該ws的代碼如下:

public class _Main {

    public static void main(String[] args) {
        MyWebServiceService service = new MyWebServiceService();
        MyWebService port = service.getMyWebServicePort();

        User user = new User();
        user.setName("admin");
        user.setPassword("123");
        List<Role> roleList = port.getRoleByUser(user);

        for(Role role : roleList) {
            System.out.println(role.getId() + "," + role.getRoleName());
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

  這裏爲了模擬,直接new一個admin用戶,然後調用ws的getRoleByUser方法獲取該用戶的角色,打印到控制檯,結果肯定是兩個角色,如果是eson15,那就是一個java菜鳥的角色了。

2. CXF處理Map等複雜類型的數據

  CXF是無法直接操作Map類型的數據的,需要進行一些處理才行。我們先寫一個獲取所有角色信息的方法,先看一下會出啥問題。

//接口
@WebService
public interface MyWebService {

    //這個註解等會有用,先註釋掉
    //@XmlJavaTypeAdapter(MapAdapter.class)
    public Map<String, List<Role>> getRoles();
}

// 實現類
@WebService
public class MyWebServiceImpl implements MyWebService{

    // 省去上面不相關代碼
    public Map<String, List<Role>> getRoles() {
        Map<String, List<Role>> map = new HashMap<String, List<Role>>();

        List<Role> roleList = new ArrayList<Role>();        
        roleList.add(new Role(1, "技術總監"));
        roleList.add(new Role(2, "架構師"));   
        map.put("admin", roleList);

        List<Role> roleList2 = new ArrayList<Role>();       
        roleList2.add(new Role(1, "java菜鳥"));
        map.put("eson15", roleList2);

        return map;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

  這裏還是使用靜態數據模擬一下,Map中存儲了兩個用戶,admin用戶有兩個角色,eson15用戶就一個角色,當這個ws發佈後,客戶端可以調用getRoles方法獲取這些角色,但是我們會發現,這個ws是無法發佈的,控制檯會報錯。因爲CXF要處理Map類型的數據,還需要一些轉換工作。 
  如何轉換呢?注@XmlJavaTypeAdapter(MapAdapter.class)就派上用場了,把上面的這個註解的註釋給去掉,也就是說我們自定義一個適配器叫MapAdapter,來適配這個Map,接下來寫這個MapAdapter:

public class MapAdapter extends XmlAdapter<MyRole[], Map<String, List<Role>>>{

    /**
     * 適配轉換 MyRole[]  ->  Map<String, List<Role>>
     */
    @Override
    public Map<String, List<Role>> unmarshal(MyRole[] v) throws Exception {
        Map<String, List<Role>> map = new HashMap<String, List<Role>>();
        for(int i = 0; i < v.length; i++) {
            MyRole role = v[i];
            map.put(role.getKey(), role.getValue());
        }
        return map;
    }

    /**
     * 適配轉換 Map<String, List<Role>>  ->  MyRole[]
     */
    @Override
    public MyRole[] marshal(Map<String, List<Role>> v) throws Exception {
        MyRole[] roles = new MyRole[v.size()];
        int i = 0;
        for(String key : v.keySet()) {
            List<Role> rolesList = v.get(key);
            roles[i] = new MyRole();
            roles[i].setKey(key);
            roles[i].setValue(rolesList);
            i++;
        }
        return roles;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

  MapAdapter需要繼承XmlAdapter,這個XmlAdapter的泛型裏兩個參數指的是從什麼轉到什麼?即那兩個對象之間在轉換,這裏需要轉Map對象,一般我們會用一個數組對象來和Map對象進行轉換,所以我們自定義一個MyRole[]數組:

public class MyRole {

    private String key;
    private List<Role> value;
    //……
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

  數組中保存了MyRole對象,而這個對象中的兩個屬性要符合Map的結構,所以我們就好轉了。 
  緊接着上面的分析,MapAdapter需要實現兩個方法,這兩個方法剛好是兩個方向的轉換,方法內部的代碼很好理解,因爲上面這個數組中的屬性就是key和value的形式,所以這兩個方法就是該數組和Map中的數據進行相互的轉換而已。這樣就可以操作Map類型的數據了。接下來就可以發佈該ws服務了。 
  然後解析完wsdl後,在客戶端就可以獲取所有的角色信息了。

public class _Main {

    public static void main(String[] args) {
        MyWebServiceService service = new MyWebServiceService();
        MyWebService port = service.getMyWebServicePort();

        // 省去不相關代碼

        List<MyRole> roles = port.getRoles().getItem();
        for(MyRole myrole : roles) {
            System.out.print("key:" + myrole.getKey() + ","); 
            System.out.print("role:");
            for(Role role : myrole.getValue()) {
                System.out.print(role.getRoleName() + " ");
            }
            System.out.println();
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

看下輸出的結果:

key:eson15,role:java菜鳥 
key:admin,role:技術總監 架構師

所以CXF處理像Map等複雜類型的數據的時候,還需要先進行一些轉換的處理,才能正常發佈ws服務,不過也不算太麻煩。

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