翻译自"Service Oriented Architecture with Java"(使用Java开发面向服务的架构)一书之第二章
[接上篇Web服务和SOA(一)]现在,我们来看看如何使用Java实现findById这个SOA服务。我们将使用JAXB库来实现XML的自动绑定,JAXB库已经包含在最新的JDK6中。因此,如果您使用的是JDK6,您不需要下载额外的jar包,否则,您需要下载JAXB,并把它显式地加到您的服务器和客户端的类路径中。但是,因为下面的代码使用了Java注解功能(Annotations),所以您需要JDK5或者更高版本编译和执行下面的代码。我们采用Tomcat5.5实现服务器端的SOA服务,实际上,我们只用了一个简单的Servlet来实现这个服务。
我们就动手写服务器和客户端的Java类来实现客户和服务器端的交互,这些类包括Item、ItemAction和ItemActionResponse。它们都是带有Java注解的POJO对象(Plain Oil Java Objects),Java注解在XML序列化和反序列化的过程中起了很重要的作用,示例代码如下所示:
代码清单3 – XML和注解进行绑定
- @XmlRootElement(name="Item")
- public class Item {
- private int id;
- private String code;
- private String description;
- ... getter/setter methods omitted ...
- @XmlRootElement(name="ItemAction")
- public class ItemAction{
- private String method;
- private Item item; ...
- @XmlRootElement(name="ItemActionResponse")
- public class ItemActionResponse {
- private String retCode;
- private Item item; ...
下面的代码是服务实现的主要部分,所有实现代码都包含在Servlet的doPost()方法中,该Servlet在Web.xml中的URL映射名为itemCrudService。
程序清单4—itemCrudService服务的服务器端实现
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException
- {
- try{
- JAXBContext jaxbContext = JAXBContext.newInstance (ItemAction.class, ItemActionResponse.class);
- Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
- //Receiving the XML request and transform it into a Java object
- ItemAction itemAction = (ItemAction)
- unmarshaller.unmarshal(request.getInputStream());
- //Do some action depending on the request content
- String method = itemAction.getMethod();
- //Prepare the response as a Java object
- ItemActionResponse itemActionResponse = new ItemActionResponse();
- if ("findById".equals(method)){
- int id = itemAction.getItem().getId();
- //Retrieve item (e.g. from db)
- Item item = new Item();
- item.setId(id);
- item.setCode("Item XYZ");
- item.setDescription("Description item XYZ");
- //Fill the response
- itemActionResponse.setRetCode("OK");
- itemActionResponse.setItem(item);
- }
- Marshaller marshaller = jaxbContext.createMarshaller();
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
- Boolean.TRUE);
- //The following line is not required, it was inserted
- //just to see the content of the generated XML message
- marshaller.marshal(itemActionResponse, System.out);
- //Send the XML message to the client
- marshaller.marshal( itemActionResponse,
- response.getOutputStream());
- }
- catch (JAXBException e){
- throw new ServletException(e);
- }
- }
到现在为止,我们完成了一个基本服务的实现,其工作流程非常明了:
1. 把XML请求序列化
2. 进行处理操作
3. 准备和序列化应答XML
请注意上面的服务可供任何语言和技术调用,只要客户端程序能够对XML进行序列化和反序列化及对信息交换的协议有所了解即可。
程序清单5—itemCrudService服务的客户端实现
- //Prepare the request
- ItemAction itemAction = new ItemAction();
- Item item = new Item();
- item.setId(26);
- itemAction.setMethod("findById");
- itemAction.setItem(item);
- //Prepare and establish the connection with the service
- URL url = new URL("http://localhost/SoaBookPoxHttp/itemCrudService");
- HttpURLConnection con = (HttpURLConnection) url.openConnection();
- con.setDoOutput(true);
- //Set the HTTP request method
- con.setRequestMethod("POST");
- con.connect();
- JAXBContext jaxbContext = JAXBContext.newInstance (ItemAction.class, ItemActionResponse.class);
- Marshaller marshaller = jaxbContext.createMarshaller();
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
- //The following line is not required, it was inserted
- //just to see the content of the generated XML message
- marshaller.marshal(itemAction, System.out);
- //Send the XML request to the service
- marshaller.marshal(itemAction, con.getOutputStream());
- //Get the XML response from the service and deserialize it
- Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
- ItemActionResponse itemActionResponse = (ItemActionResponse)
- unmarshaller.unmarshal(con.getInputStream());
- //Show the response content
- System.out.println("retCode="+itemActionResponse.getRetCode()+ "/r" +
- "id="+itemActionResponse.getItem().getId()+ "/r" +
- "code="+itemActionResponse.getItem().getCode()+ "/r"+"description="+itemActionResponse.getItem() .getDescription());
通过以上代码您会看到,所有参与消息交换的类(包括Item, ItemAction及ItemActionResponse)对客户端必须是可见的。在本例中,客户端和服务器端都使用Java,因此我们只需要简单地这些类从服务器端的项目中拷贝到客户端的项目中即可。但一般说来,这并不是必需的(请思考一下如果客户端和服务器端使用不同语言的情况)。服务实现过程中唯一的要求就是,您要传输的对象必须满足序列化和反序列化的要求。我们可以使用同样的方法来实现findAllItems服务,为此,我们新建一个Servlet,这个Servlet不需要任何输入,并返回所有的商品列表。该服务的实现代码如下:
程序清单6—findAllItems服务的服务器端实现
- protected void doPost(HttpServletRequest request,
- HttpServletResponse response)
- throws ServletException, IOException
- {
- try {
- JAXBContext jaxbContext = JAXBContext.newInstance (ItemList.class, Item.class);
- ItemList itemList = new ItemList();
- itemList.setList(new ArrayList());
- Item i1 = new Item();
- i1.set ... ;
- itemList.getList().add(i1);
- ... populate itemList ...
- Marshaller marshaller = jaxbContext.createMarshaller();
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
- Boolean.TRUE);
- //Just to see the content of the generated XML message
- marshaller.marshal(itemList, System.out);
- //Send the XML message to the client
- marshaller.marshal(itemList, response.getOutputStream());
- }
- catch (JAXBException e) {
- throw new ServletException(e);
- }
- }
请注意,这里我们还需要定义一个ItemList类,其代码如下:
程序清单7—ItemList类的源代码
- import java.util.List;
- import javax.xml.bind.annotation.XmlRootElement;
- @XmlRootElement(name="ItemList")
- public class ItemList {
- private List list;
- ...
相应的客户端测试代码应如下所示:
程序清单8— findAllItems服务的客户端端测试代码
- URL url = new URL("http://localhost/SoaBookPoxHttp/findAllItems");
- HttpURLConnection con = (HttpURLConnection) url.openConnection();
- con.setRequestMethod("POST");
- con.connect();
- //Void Request
- //Get Response
- JAXBContext jaxbContext = JAXBContext.newInstance (ItemList.class, Item.class);
- Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
- ItemList itemList = (ItemList)
- unmarshaller.unmarshal(con.getInputStream());
- for (Iterator iterator = itemList.getList().iterator();
- iterator.hasNext();)
- {
- Item item = (Item) iterator.next();
- System.out.println( item.getId()+" - "+ item.getCode()+" - "+
- item.getDescription());
- }
译者注:如果您想增加对SOA服务的理解,并有兴趣动手一试,请不妨补齐上面的源代码,看看能否在Tomcat中运行并通过测试。译者补齐了源代码并在Tomcat6.0+Java6的环境下测试通过,源代码的链接如下,供您参考。
http://carllgc.blog.ccidnet.com/job-htm-action-download-itemid-777373-aid-86781.html