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