翻譯自"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來實現這個服務。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
我們就動手寫服務器和客戶端的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