将现有API公开为Web服务

时间:2011-01-31 01:04:36

标签: web-services api

我目前正致力于将API公开为Web服务。这里的想法是将JAR文件中的现有业务逻辑打包到WAR文件中,并将WAR文件公开为可返回自由格式XML字符串的Web服务。当我们将现有API公开为Web服务时,我们提供XSD&返回的XML字符串数据的WSDL文件?这是惯例还是标准做法?

2 个答案:

答案 0 :(得分:14)

这取决于您是否使用SOAP或REST。 SOAP更具限制性;因此,更期望您将拥有一个WSDL文件来生成与API接口的类。

另一方面,如果您使用REST,则只需公开RESTful URI即可满足具有统一接口的RESTful Web服务的约束。

REST往往比SOAP更具优势,因为它是一种宽松的架构风格。我更喜欢这种方法,如果您不熟悉开发Web服务,我会推荐这种方法。

根据您使用的语言,我假设使用Java,您可以使用Restlets或Spring 3.0的REST框架来帮助您构建RESTful Web服务。这些工具确实使这项工作变得更加容易,并帮助您符合6 Constraints of a RESTful Web Service并符合4 Key Goals

<强>更新

假设您已经拥有现有的面向对象代码,并假设您希望将该代码公开为REST API,那么使用Spring 3.0 MVC,创建一个将包装现有软件包的Controller子类:

示例GET

资源:Javadocs for Jackson's ObjectMapper POJO/JSON Marshaller

 // this is the wrapper around your existing Java packages.  
 @Controller
 public class UserController {

     protected static final DATA_TYPE = "json";

     // In REST, GET method is used to retrieve data with no side effects, 
         // meaning that no changes are made to the data on the server.
     @RequestMapping(value="/users/{username}", method=RequestMethod.GET)
     public void getUserData(@PathVariable("username") String userName, Model model) {

         // this is your existing class
         UserDataService userDataService = new UserDataService();

         // assume you have a class User, and getUserDetails gives you that POJO object.
         User user = userDataService.getUserDetails(username);


         // marshal the User object to JSON, using Jackson, and write as output in response
         ObjectMapper mapper = new ObjectMapper();
         mapper.writeValue(response.getWriter(), user);

     }
 }

 // assume you have an existing POJO class called User
 class User implements Serializable {

     String username;
     String age;
     String birthday;
     String mood;

     String getMood() { return this.mood; }
     String getBirthday() { return this.birthday; }
     String getAge() { return this.age; }
     String getUsername() { return this.username; }

     String setMood(String mood) { this.mood = mood; }
     String setBirthday(String birthday) { this.birthday = birthday; }
     String setAge(String age) { this.age = age; }
     String setUsername(String username) { this.username = username; }
}

请求

http://api.example.com:8080/users/jmort253/

<强>响应:

{ 
    "username":"jmort253",
    "mood":"good",
    "age":"not too old and not too young",
    "birthday","Jan 1, 1900"
}

XML而不是JSON

返回XML和返回JSON之间的主要区别在于使用的编组器。使用javax.xml.bind.annotations,您可以在POJO类上放置注释,以便编组器可以将其转换为XML,从而使您不必手动编写XML代码的详细信息:

Using javax.xml.bind.annotations to convert Java Objects to XML and XSD。如果您认为这是REST Web服务的一项要求,该资源还解释了如何生成XML Schema。

 @XmlRootElement
 class User implements Serializable {

     String username;
     String age;
     String birthday;
     String mood;

     String getMood() { return this.mood; }
     String getBirthday() { return this.birthday; }
     String getAge() { return this.age; }
     String getUsername() { return this.username; }

     String setMood(String mood) { this.mood = mood; }
     String setBirthday(String birthday) { this.birthday = birthday; }
     String setAge(String age) { this.age = age; }
     String setUsername(String username) { this.username = username; }
}

不使用Jackson API的ObjectMapper类将POJO类编组为JSON,而是使用javax.xml.bind.annotations包代替ObjectMapper:

JAXBContext context = JAXBContext.newInstance(User.class);
Marshaller marshaller = context.createMarshaller();

// pretty print XML
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
marshaller.marshal(user, System.out);

除了其他资源之外,本文还有一些使用JAXB to deserialize an ArrayList of POJO objects to XML的示例。

在处理REST Web服务包装器时,我的最终建议是将您的日志记录级别设置为“ALL”或“DEBUG”。我发现这有助于我更轻松地确定设置Web服务时遇到的任何问题的根本原因。这些库本身将输出有用的调试消息,以帮助您解决配置问题,例如缺少依赖项,缺少注释以及在处理转换为XML / JSON过程或设置Spring 3.0时可能遇到的其他问题。

一旦设置了统一的接口并且您可以发出GET请求并接收响应,您就可以将日志记录级别设置回以前的INFO或WARN级别。

答案 1 :(得分:1)

首先,在将现有API作为Web服务一对一展示之前,我会犹豫不决。编写的现有API是否可以通过网络访问?如果没有,那么它可能没有考虑到网络限制。

它可能包括涉及大量小型操作的方法调用 - 在单个进程中使用时不需要任何成本的操作。在网络上,每个调用的相关延迟远远大于在同一进程中调用方法的开销。

相反,我会设计一种服务来满足API的功能要求。该服务可能被设计为具有较少数量的操作,每个操作执行更多工作,从而最小化与网络流量相关的开销。该服务可能通过调用API来实现实现(假设它被编写为处理多线程环境,如服务)。

就WSDL而言,您正在使用的工具包可以很好地为您构建WSDL。我知道.NET中的WCF就是这样做的,我使用IBM Rational Web Developer也做了同样的事情,所以我知道Java世界也可以这样做。

否则,手写WSDL和相应的模式实际上并不困难。在任何一种情况下,都需要提供 do ,以便您的客户可以使用该服务。

如果您的API可以干净地表达为资源上的一组操作,那么使用REST没有任何问题。在这种情况下,是的,提供架构以使客户端更容易处理XML。如果它不能干净地表达为对资源的操作,我会注意强制你的API适合REST模型。