English
 电子信箱
 加入收藏

  威盾防火墙 >> 新闻中心 >> 威盾新闻 >> 带有复杂数据类型的Web服务

 

带有复杂数据类型的Web服务

威盾防火墙 2015-02-20

 

An Example with Richer Data Types

在TimeServer的服务中,所提供的服务操作均无输入信息,同时返回简单数据类型,比如一个字符串或一个整数。本节我们将提供一个复杂一点的例子,具体实现细节将在下一章中介绍。

示例1-11中的Teams Web服务同前面的TimeServer服务有几个重要的区别。

示例1-11:带有复杂数据类型的Teams Web服务

  1. package ch01.team;  
  2.  
  3. import java.util.List;  
  4. import javax.jws.WebService;  
  5. import javax.jws.WebMethod;  
  6.  
  7. @WebService 
  8. public class Teams {  
  9. private TeamsUtility utils; 

示例1-11:带有复杂数据类型的Teams Web服务(续例)

  1. public Teams() {   
  2.    utils = new TeamsUtility();   
  3.    utils.make_test_teams();  
  4. }  
  5.  
  6. @WebMethod 
  7. public Team getTeam(String name) { return utils.getTeam(name); }  
  8.  
  9. @WebMethod 
  10. public List<Team> getTeams() { return utils.getTeams(); }  

第一,同前面TimeServer服务分别通过SEI和SIB来实现所不同的是,Team服务由一个单独的Java类实现。这种做法只是演示了这种实现上的可能性。另一个显著的区别就是两个Team服务操作所返回的数据类型不同。操作getTeam被参数化,同时返回预先定义的复杂Team对象类型,Team中包括一个仍然是预先定义的Player对象实例集合。服务操作返回getTeams一个Java List<Team>集合。

工具类TeamsUtility负责产生模拟数据。在一些正式的环境中,这个工具类可能从一个数据库中查询,或者获取一个team或一个team的集合列表。为了尽可能简单,TeamsUtility类并没有在运行中创建team和对应的player。下面是TeamsUtility类的主要代码:

  1. package ch01.team;  
  2.  
  3. import java.util.Set;  
  4. import java.util.List;  
  5. import java.util.ArrayList;  
  6. import java.util.Map;  
  7. import java.util.HashMap;  
  8.  
  9. public class TeamsUtility {  
  10. private Map<String, Team> team_map;  
  11.  
  12. public TeamsUtility() {  
  13.    team_map = new HashMap<String, Team>();  
  14. }  
  15.  
  16. public Team getTeam(String name) { return team_map.get(name); }  
  17. public List<Team> getTeams() {  
  18.    List<Team> list = new ArrayList<Team>();  
  19.    Set<String> keys = team_map.keySet();  
  20.    for (String key : keys)  
  21.   list.add(team_map.get(key));  
  22.    return list;  
  23. }  
  24.  
  25. public void make_test_teams() {  
  26.    List<Team> teams = new ArrayList<Team>();  
  27.    ...  
  28.    Player chico = new Player("Leonard Marx""Chico");  
  29.    Player groucho = new Player("Julius Marx""Groucho");  
  30.    
  31.    Player harpo = new Player("Adolph Marx""Harpo");  
  32.    List<Player> mb = new ArrayList<Player>();  
  33.    mb.add(chico); mb.add(groucho); mb.add(harpo);  
  34.    Team marx_brothers = new Team("Marx Brothers", mb);  
  35.    teams.add(marx_brothers);  
  36.  
  37.    store_teams(teams);  
  38. }  
  39.  
  40. private void store_teams(List<Team> teams) {  
  41.    for (Team team : teams)  
  42.   team_map.put(team.getName(), team);  
  43. }  
  44. }  
  45. 发布服务并编写调用客户端  
  46.  
  47. Publishing the Service and Writing a Client  
  48.  
  49. 回想一下前面的TimeServer服务,在SEI中用到的注解:  
  50.  
  51. @SOAPBinding(style = Style.RPC)  

这个注解只允许服务使用一些像字符串、整形等简单的数据类型。相反地是,Teams服务使用了更加复杂的数据类型,因此默认情况下须将Style.RPC替换为Style.DOCUMENT。Style.DOCUMENT类型需要更多配置,这些配置细节将在下一章详细介绍。下面就是部署这个Web服务和编写简单调用客户端的操作步骤。

1. 编译源文件。在当前工作目录中,仍然以ch01作为子目录,命令如下:

  1. % javac ch01/team/*.java 

除了@WebService注解Teams类之外,在ch01/team目录中还包括Team、Player,TeamsUtility和TeamsPublisher类,如下所示:

  1. package ch01.team;  
  2. public class Player {  
  3. private String name;  
  4. private String nickname;  
  5.  
  6. public Player() { }  
  7. public Player(String name, String nickname) {  
  8.    setName(name);  
  9.    setNickname(nickname);  
  10. }  
  11.  
  12. public void setName(String name) { this.name = name; }  
  13. public String getName() { return name; }  
  14. public void setNickname(String nickname) { this.nickname = nickname; }  
  15. public String getNickname() { return nickname; }  
  16. }  
  17.    
  18. // end of Player.java  
  19.  
  20. package ch01.team;  
  21.  
  22. import java.util.List;  
  23. public class Team {  
  24. private List<Player> players;  
  25. private String name;  
  26.  
  27. public Team() { }  
  28. public Team(String name, List<Player> players) {   
  29.    setName(name);  
  30.    setPlayers(players);   
  31. }  
  32.  
  33. public void setName(String name) { this.name = name; }  
  34. public String getName() { return name; }  
  35. public void setPlayers(List<Player> players)   
  36. this.players = players; }  
  37. public List<Player> getPlayers() { return players; }  
  38. public void setRosterCount(int n) { } // no-op but needed for property  
  39. public int getRosterCount() { return (players == null) ?   
  40. 0 : players.size(); }  
  41.  
  42. }  
  43. }  
  44. // end of Team.java  
  45.  
  46. package ch01.team;  
  47. import javax.xml.ws.Endpoint;  
  48. class TeamsPublisher {  
  49. public static void main(String[ ] args) {  
  50.    int port = 8888;  
  51.    String url = "http://localhost:" + port + "/teams";  
  52.    System.out.println("Publishing Teams on port " + port);  
  53.    Endpoint.publish(url, new Teams());  
  54. }  

2. 在当前工作目录中,执行随Java SE6发布的wsgen程序。

  1. % wsgen -cp . ch01.team.Teams 

wsgen程序产生了不同的内容;其中有Endpoint.publish用来产生服务的WSDL文档Java类型,本书第2章将仔细地了解这些生成的内容,以及这些内容对WSDL产生怎样的帮助。

3. 执行TeamsPublisher程序。

4. 在工作目录下执行wsimport程序:

  1. % wsimport -p teamsC -keep http://localhost:8888/teams?wsdl 

执行此命令后,将会在子目录teamsC中产生多个类文件(标志-p标示包名称)。通过生成的这些文件很简单地编写调用服务的客户端。

步骤4使得编写客户端的工作更加快捷,如下所示:

  1. import teamsC.TeamsService;  
  2. import teamsC.Teams;  
  3. import teamsC.Team;  
  4. import teamsC.Player;  
  5. import java.util.List;  
  6. class TeamClient {  
  7. public static void main(String[ ] args) {  
  8. TeamsService service = new TeamsService();  
  9. Teams port = service.getTeamsPort();  
  10. List<Team> teams = port.getTeams();  
  11. for (Team team : teams) {  
  12. System.out.println("Team name: " + team.getName() +  
  13. " (roster count: " + team.getRosterCount() + ")");  
  14. for (Player player : team.getPlayers())  
  15. System.out.println("  Player: " + player.getNickname());  
  16. }  
  17. }  
  18. }  
  19. 执行客户端,将输出如下内容:  
  20.  
  21. Team name: Abbott and Costello (roster count: 2)  
  22.   Player: Bud  
  23.   Player: Lou  
  24. Team name: Marx Brothers (roster count: 3)  
  25.   Player: Chico  
  26.   Player: Groucho  
  27.   Player: Harpo  
  28. Team name: Burns and Allen (roster count: 2)  
  29.   Player: George  
  30.   Player: Gracie 

从这个例子可以看出,在商业级别上实现基于SOAP协议的Web服务哪些是可能完成的。只要遵循某种原则,一些自定义数据类型如Player、Team,以及以这些类型组成的任意集合类型等可以作为Web服务操作的参数传入或返回值返回。本例中已经使用了这些指导原则。针对Team和Player类,JavaBean的属性是String、int,或者是像List这样任何拥有toArray方法的Java集合对象。下一章涉及这些细节,尤其是wsgeng和wsimport工具在帮助JWS服务和客户端的快速开发上有哪些帮助作用。


相关内容: 最新内容:
讨论了那么多,究竟什么是Web App?[2015-02-20]
Web威胁保护解决方案 全新网络信誉技术抵御Web威胁[2015-02-20]
盘点从Web0.2到2.0出现的那些Web技术[2015-02-20]
基础知识--Web服务的优点[2015-02-20]
Web服务交互[2015-02-20]
且看Web流行框架之战[2015-02-20]