使用Fast Infoset提高Java Web Service性能
二、在JAX-WS2.0 Web Service中使用快速信息集
在这一部分,我们将开发和测试一个基于JAX-WS的Web service的例子,在这个例子中将演示快速文档集的使用方法。
在这个例子中,Web Service模拟了一个图书目录管理系统。Web service接口CatalogPort定义了三个操作:echo、upload和retrieve。我们可以使用echo()方法来使客户端初始化一个服务请求,并为其他的信息交换创建快速信息集文档。upload()和retrieve()方法可以分别让客户端来注册(update)图书信息以及获得被存储在管理系统中图书的例子章节。
在CatalogImpl.java的实现中,upload()方法将保存以下四种信息:
1. 图书的基本信息,以及保存在book_info目录中的${isbn}.properties文件中的例子章节名。
2. 保存在book_cover目录中的封面图象。
3. 保存在book_desc目录的${isbn}.txt中的描述字符串。
4. 保存在book_sample目录的${isbn}.pdf文件中的章节目录。
upload()方法简单地返回一个Boolean类型值,这个值确定了这个方法是否成功地完成了处理工作。upload方法的部分代码如下(如果想查看服务端完整的代码,请下载本文提供的源代码):retrieve()方法则从属性文件和图书相关目录(所有的目录都是基于输入参数isbn的)中获得章节名,并向客户端返回一个章节对象。在一个完整的信息交换过程中,涉upload()方法的调用,XML的处理和传输主要和请求有关,请求信息的大小主要依赖于图书封面图象的尺寸以及章节内容。而retrieve()方法的调用、XML的处理和传输主要和响应有关。响应信息的大小主要依赖于章节内容的尺寸。我们在以后可以考虑这些内容来更进一步地优化数据传输性能。retrieve方法的实现代码如下:public boolean upload(Book bookInfo) { Properties info = new Properties(); if (bookInfo.getIsbn() == null || bookInfo.getIsbn().length() == 0) return false; if (bookInfo != null) { info.setProperty("title", bookInfo.getTitle()); info.setProperty("author", bookInfo.getAuthor()); info.setProperty("pageNumber", new Integer(bookInfo.getPageNumber()).toString()); info.setProperty("price", bookInfo.getPrice()); Chapter sample = bookInfo.getSample(); if (sample != null) info.setProperty("sample", sample.getName()); File bookInfoFile = new File(getDataDir("book_info") + bookInfo.getIsbn() + ".properties"); FileOutputStream infoOut = null; try { infoOut = new FileOutputStream(bookInfoFile); info.store(infoOut, null); infoOut.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (infoOut != null) try { infoOut.close(); } catch (IOException e) { e.printStackTrace(); } } File descFile = new File(getDataDir("book_desc") + bookInfo.getIsbn() + ".txt"); PrintWriter pw = null; try { pw = new PrintWriter(new FileWriter(descFile)); pw.write(bookInfo.getDesc()); pw.flush(); } catch (IOException e1) { e1.printStackTrace(); } finally { if (pw != null) pw.close(); } Image coverImage = bookInfo.getCoverImage(); FileOutputStream coverOut = null; ImageOutputStream stream = null; ImageWriter writer = null; if (coverImage != null) { BufferedImage bufImage; try { bufImage = convertToBufferedImage(coverImage); File bookCoverFile = new File(getDataDir("book_cover") + bookInfo.getIsbn() + ".jpg"); coverOut = new FileOutputStream( bookCoverFile); Iterator i = ImageIO.getImageWritersBySuffix("jpg"); if (i.hasNext()) { writer = (ImageWriter) i.next(); } if (writer != null) { stream = ImageIO.createImageOutputStream(coverOut); writer.setOutput(stream); writer.write(bufImage); stream.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { if (coverOut != null) try { coverOut.close(); } catch (IOException e) { e.printStackTrace(); } if (stream != null) try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } FileOutputStream sampleOut = null; if (sample != null) { File bookCoverFile = new File(getDataDir("book_sample") + bookInfo.getIsbn() + ".pdf"); try { sampleOut = new FileOutputStream(bookCoverFile); sampleOut.write(sample.getContent()); sampleOut.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (sampleOut != null) try { sampleOut.close(); } catch (IOException e) { e.printStackTrace(); } } } } return true; }
public Chapter retrieve(String isbn) { if ((isbn == null) || isbn.length() == 0) return null; Chapter ch = new Chapter(); File bookInfoFile = new File(getDataDir("book_info") + isbn + ".properties"); Properties book_info = new Properties(); FileInputStream fis = null; try { fis =new FileInputStream(bookInfoFile); book_info.load(fis); ch.setName(book_info.getProperty("sample")); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } File sampleCh = new File(getDataDir("book_sample") + isbn + ".pdf"); FileInputStream sampleIn = null; try { sampleIn = new FileInputStream(sampleCh); int availableLength = sampleIn.available(); byte[] totalBytes = new byte[availableLength]; sampleIn.read(totalBytes); ch.setContent(totalBytes); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (sampleIn != null) try { sampleIn.close(); } catch (IOException e) { e.printStackTrace(); } } return ch; }
为了更好地实验本文所提供的例子,我们可以从源代码的rar包中将web service WSDL和相关的XML文件解出来。为了使用JAX-WS2.0来实现Web Service,我们需要使用apt工具来自动产生CatalogPortType.java接口类型文件,这个类在com.company.mtom.catalog.book包中,服务类Catalog.java在客户端将获得并使用CatalogPort。
在创建服务实现类之后,我们就要为web service的部署和运行做准备了。我们首先需要建立Web Service发布表述文件(sun-jaxws.xml)和Web应用程序发布描述文件(web.xml),然后通过war包将Web Service发布的相应的容器中(在本文的例子中使用的是Tomcat)。
在客户端,我们可以在一个叫isbn的文件中输入图书信息和封面图,例子章节内容以及一些描述文本。在本例的客户端中,private方法getBook()创建一个Book对象,然后使用这个对象的upload()来上传信息。getBook方法的代码如下:
private Book getBook(Properties prop) { Chapter ch = new Chapter(); Book book = new Book(); ch.setName(prop.getProperty("sample")); //Get the sample chapter content File sampleCh = new File("./etc/" + prop.getProperty("content") + ".pdf"); FileInputStream sampleIn = null; try { sampleIn = new FileInputStream(sampleCh); int availableLength = sampleIn.available(); byte[] totalBytes = new byte[availableLength]; sampleIn.read(totalBytes); ch.setContent(totalBytes); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (sampleIn != null) try { sampleIn.close(); } catch (IOException e) { e.printStackTrace(); } } //Get cover image Image cover = getImage("./etc/" + prop.getProperty("coverImage") + ".jpg"); //Read the desc from the text file String desc = readText("./etc/" + prop.getProperty("desc") + ".txt"); book.setAuthor(prop.getProperty("author")); book.setDesc(desc); book.setPageNumber(new Integer(prop.getProperty("pageNumber"))); book.setPrice(prop.getProperty("price")); book.setTitle(prop.getProperty("title")); book.setSample(ch); book.setCoverImage(cover); return book; }
然后使用compareSample()方法可以将使用retrieve()从远程获得的图书目录和内容和本地的相应内容进行比较。要注意的是,在客户端使用的是开源的JAMon库来收集相应时的信息。compareSample方法的实现代码如下:
private void compareSample(Chapter retrieved, Properties prop){ File sampleCh = new File("./etc/" + prop.getProperty("content") + ".pdf"); FileInputStream sampleIn = null; byte[] totalBytes = null; try { sampleIn = new FileInputStream(sampleCh); int availableLength = sampleIn.available(); totalBytes = new byte[availableLength]; sampleIn.read(totalBytes); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (sampleIn != null) try { sampleIn.close(); } catch (IOException e) { e.printStackTrace(); } } boolean isTitleTheSame = (prop.getProperty("sample").equals(retrieved.getName())); boolean isContentTheSame = Arrays.equals(totalBytes, retrieved.getContent()); System.out.println("The sample chapter title is as expected:" + isTitleTheSame); System.out.println("The sample chapter content is as expected:"+ isContentTheSame); }
在本例子中提供了三本例子图书来演示这个过程。为了在传输过程中查看SOAP信息,我们可以完装用于截获TCP信息的工具,tcpmon来查看TCP信息。在后面的章节,我们将看到快速信息集什么时候进行数据交互。这些都可以通过tcpmon观察到。在下节中,我们将看到在JAX-WS中如何使用快速信息集来传输Web Service数据。
0
相关文章