2009-06-25 2 views
0

Ich habe eine struts2-Aktion, die auf eine AJAX-Anfrage reagiert, indem sie einige Anfrageparameter annimmt, einen Remote-Service aufruft, der XML-Daten zurückgibt, die Daten dann über XSL transformiert und das Ergebnis zurücksendet XHTML über ein Stream-Ergebnis. Die Antwort ist abhängig von den gegebenen Parametern unterschiedlich.Viele gleichzeitige AJAX-Anfragen mit einer struts2-Aktion behandeln

Hier wird die Action-Klasse mit einem Bündel Material entnommen:

public class ServiceHandler extends ActionSupport { 
    private ByteArrayInputStream inputStream; 

    public String execute(){ 

     String response = ""; 

     // Get request parameters 
     // Make a request to a remote server via an http connection 
     // Transform result via XSL 

     //uses dom4j for XML/XSL stuff 
     //this should never be empty 
     response = resultDoc.asXML(); 

     inputStream = new ByteArrayInputStream(response.getBytes()); 
     return "success"; 
    } 

    public ByteArrayInputStream getInputStream(){ 
     return inputStream; 
    } 
} 

Und hier ist der wichtige struts.xml Bits:

<action name="sh" class="ServiceHandler"> 
    <result name="success" type="stream"> 
     <param name="contentType">text/html</param> 
     <param name="contentDisposition">inline;filename="response.html"</param> 
     <param name="bufferSize">1024</param> 
     <param name="allowCaching">false</param> 
    </result> 
</action> 

Mein Problem ist, dass, wenn ich mehrere Anfragen zur gleichen Zeit alle die ServiceHandler Aktion aufrufen, manchmal ist die Antwort völlig leer (sollte nie passieren), manchmal wird die Antwort am Anfang oder Ende um einen zufälligen Betrag abgeschnitten, und manchmal sind die Antworten geschaltet, so dass die Falsche Antwort wird von einem A erhalten JAX-Anforderer

Ich weiß, dass dies ein Problem der Threadsicherheit ist, und ich habe alle wichtigen Variablendefinitionen in die execute() -Methode verschoben, so dass sie keine Instanzvariablen sind (und somit von allen geteilt werden). Die einzige interessante Variable, die eine Instanzvariable ist, ist der InputStream, und ich betrachte das als die Ursache meiner Probleme.

Gibt es eine Möglichkeit, die Variable inputStream threadsicher zu machen? Oder gibt es eine andere Lösung, die ich nicht sehe?

Antwort

0

Danke, dass Henning mich in die richtige Richtung geführt hat. Ich hatte nicht daran gedacht, direkt in den Response-Ausgabestream zu schreiben, da er nirgendwo in der struts2-Dokumentation erwähnt wird.

Der Vorteil des direkten Schreibens der Antwort auf den Ausgabestream besteht darin, dass Sie kein Instanzobjekt für inputStream erstellen müssen. Dadurch bleiben alle Daten in der execute() - Methode erhalten, die vor anderen Threads sicher ist.

Hier ist eine modifizierte Aktionsklasse, die direkt in den Ausgabestream schreibt und ein Null-Ergebnis zurückgibt.

import javax.servlet.http.HttpServletResponse; 
import org.apache.struts2.ServletActionContext; 

public class ServiceHandler extends ActionSupport { 
    public String execute(){ 

     String response = ""; 

     // Get request parameters 
     // Make a request to a remote server via an http connection 
     // Transform result via XSL 

     //uses dom4j for XML/XSL stuff 
     //this should never be empty 
     response = resultDoc.asXML(); 

     HttpServletResponse httpResponse = ServletActionContext.getResponse(); 
     try{ 
      httpResponse.getOutputStream().print(response); 
     } 
     catch(IOException e){ 
      return "failure"; 
     } 

     return null; 
    } 
} 

Dies scheint die Probleme behoben zu haben, die ich hatte.

0

Ich kenne nur Struts 1, aber werfen Sie einen Blick in DonwloadAction. Oder verwenden Sie einfach eine einfache Struts-Aktion, schreiben Sie das Ergebnis direkt in das Antwortobjekt und geben Sie null als vorwärts zurück.

0

Ich bin nicht in Struts 2 überhaupt, aber wenn Sie wirklich das "Erfolg" -Ergebnis zurückgeben müssen und keine Möglichkeit haben, auf die Ausgabe direkt zu schreiben, sieht dies wie ein guter Ort aus, um Ihre ThreadLocal zu behalten stream lokal zum aktuellen Thread. (Weitere Informationen zum Muster finden Sie unter Wikipedia article im lokalen Thread-Speicher.)

+0

Ich muss nicht "Erfolg" zurückgeben und bin nur durch struts2 soweit eingeschränkt, was ich kann und was nicht. Wenn ich eine Möglichkeit finden kann, direkt auszugeben, ohne eine Instanzvariable verwenden zu müssen, dann werde ich das tun. –

+0

Einen Weg gefunden, dies zu tun, und das Schreiben scheint direkt mein Problem gelöst zu haben. –