2013-10-25 27 views
0

我一直試圖找到最快/接受的方式來讀取從HTTP Servlet中的XML輸入一個「參考」的例子,但似乎無法找到一個明確的答案。從POST到http servlet讀取xml的建議/最快的方式是什麼?

這裏的背景:我們有一個應用程序,這是12歲,其作品在製作得很好,但我想看看我們缺少一個竅門,並可能使其更快。

它接受由xml構成的post請求(請參閱schema和sample xml的帖子的底部),並使用JAXB 1.0將它編組爲Java對象,然後根據請求id找到請求處理器,然後處理請求並寫入響應。我想我們應該使用更多的緩衝閱讀器/作家,也許是一個掃描儀,以及任何其他'新'(即比Java 1.2更新的.. ..)。 。) 特徵。

這裏的請求目前如何處理一個粗略的總結:

public void doPost(HttpServletRequest request, HttpServletResponse response) 
     throws ServletException, IOException { 
try { 
    InputStream is = request.getInputStream(); 
    InputStreamReader reader = new InputStreamReader(is); 
    char[] buffer = new char[4096]; 
    StringWriter writer = new StringWriter(); 
    int bytes_read; 
    try 
    { //manual bufferering - can't we just use request.getReader() ? 
     while ((bytes_read = reader.read(buffer)) != -1) { 
      writer.write(buffer, 0, bytes_read); 
     } 
    } 
    catch(IOException e) 
    { 
     throw new RuntimeException("Unable to read the inputstream. Please try again."); 
    } 

    String xml = writer.toString(); 
    //now we look for the payload and extract it: 
    String tag = "payload"; 
    String header = null; 
String body = null; 
String innerPayload = null; 
String footer = null; 
    int start = xml.indexOf("<" + tag); 
    if(start < 0) 
     throw new RuntimeException("Start tag \"" + tag + "\" was not found in the xml."); 

    int end = xml.indexOf("</" + tag + ">"); 
    if(end < 0) 
     throw new RuntimeException("End tag \"" + tag + "\" was not found in the xml."); 

    int closeStart = xml.indexOf(">", start); 
    int closeEnd = xml.indexOf(">", end); 

    if(xml.charAt(closeStart - 1)=='/') 
    { 
     body = xml.substring(start, closeStart + 1); 
     innerPayload = null; 
     header = xml.substring(0, closeStart + 1); 
     footer = xml.substring(closeStart + 1, xml.length()); 
    } 
    else 
    { 
     body = xml.substring(start, closeEnd + 1); 
     innerPayload = xml.substring(closeStart + 1, end); 
     header = xml.substring(0, closeStart + 1); 
     footer = xml.substring(end, xml.length()); 
    } 
FsRequest envelope;  
Object xml = JAXBRequestHelper.bind(header + footer); 

     if(xml instanceof FsRequest) 
      envelope = (FsRequest) xml; 
     else 
      throw new RuntimeException("Invalid XML request."); 
Object payloadType = JAXBRequestHelper.bind(innerPayload); 
//because the payload type is xs:any, I don't think we can avoid a cast here 
//in this case, it's a purchase: 
Purchase purchase = (Purchase) payloadType 
//request processor then handles the purchase using purchase.getMsisdn(), etc 

一個示例XML請求可能是這樣的:

<?xml version="1.0" encoding="UTF-8"?> 
<fs-request id="100004"purchase_locale="en_GB"> 
    <payload> 
    <purchase> 
    <msisdn>13435456456</msisdn> 
    <package-id>package123</package-id> 
    </purchase> 
    </payload> 
</fs-request> 

的XSD的定義是有點特別,太。 「有效載荷」被定義爲XS:任何使編組更靠譜:

<xs:element name="fs-request"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element name="payload" type="common:payloadType" minOccurs="0"/>  
     </xs:sequence> 


<xs:complexType name="payloadType"> 
    <xs:sequence> 
     <xs:any processContents="skip" minOccurs="0" /> 
    </xs:sequence> 
</xs:complexType> 

難道只是我還是這個代碼有點亂?如果是這樣,是否有一個明顯的方法來使它更清潔/更快?我很想看到一個參考示例(儘管xs:任何有效負載類型使事情變得更復雜一些)。

+0

我想'SAX'是最好的選擇。 – 2013-10-25 10:23:19

+1

如果你編組成一個Java對象,我會認爲JAXB可能比你自己寫的任何東西都快。 –

回答

1

看一看一個JAX-RS框架像Jersey

手工做的系列化工作通常是矯枉過正。

0

如果你想這樣做,使用標準的JRE庫手工的方式,這是做它的方式。

你必須雖然考慮潛在的XML威脅。

@Override 
public void service(ServletRequest request, ServletResponse response) 
     throws ServletException, IOException { 
    try{ 
     HttpServletRequest hReq = (HttpServletRequest) request; 
     if (hReq.getMethod().equalsIgnoreCase("POST") && hReq.getContentType().equals("text/xml")){ 
      // 1. Create XML doc from input   
      logger.debug("1. create XML content from input"); 
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
      factory.setNamespaceAware(true); 
      DocumentBuilder documentBuilder = factory.newDocumentBuilder(); 
      Document doc = documentBuilder.parse(hReq.getInputStream()); 
      // 2. Do your stuff with the Doc e.g. use doc.getDocumentElement())); 

     } else { 
      HttpServletResponse hResponse = (HttpServletResponse) response; 
      // Only HTTP POST is supported 
      hResponse.sendError(500, "Unsupported"); 
     } 
    } catch (Exception e) { 
     logger.fatal(e,e); 
     throw new ServletException(e); 
    } 
} 
1

如果你希望你可以看看的StAXSAX(用於XML的簡單API)(流API XML)的速度增加。它們不需要在內存中加載整個文件來解析它,就像DOM解析器一樣。

但使用起來非常繁瑣(espesially SAX)。我會推薦檢查第一個更易於使用的庫,如JAXB(用於XML綁定的Java體系結構)。 JAXB可以爲您的任務提供可接受的速度,同時提供更大的靈活性。

相關問題