2016-08-24 5 views
-1

Ich habe eine Struts1-Anwendung und bin vergeblich versucht, einen Filter zum Arbeiten zu erhalten, um Header/etc zur Antwort hinzufügen, nachdem die Aktion abgeschlossen ist, aber ich bin nicht in der Lage, es zum Laufen zu bringen.Wie verwende ich einen Filter in einer Struts1-Anwendung?

Zu dem Zeitpunkt, zu dem die Struts-Aktion abgeschlossen ist und die Kontrolle an meinen Filter zurückgegeben wird, ist die Antwort bereits festgeschrieben.

web.xml:

<filter> 
     <filter-name>workflow</filter-name> 
     <filter-class>webapp.session.WorkflowModifierFilter</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>workflow</filter-name> 
     <servlet-name>action</servlet-name> 
    </filter-mapping> 


    <servlet> 
     <servlet-name>action</servlet-name> 
     <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> 
     <init-param> 
     <param-name>config</param-name> 
     <param-value>/WEB-INF/struts-config.xml</param-value> 
     </init-param> 
     <init-param> 
     <param-name>debug</param-name> 
     <param-value>0</param-value> 
     </init-param> 
     <init-param> 
     <param-name>detail</param-name> 
     <param-value>2</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

Mein Filter ist die folgende:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 

     if(!servletResponse.isCommitted()) 
      log.debug("Not Committed! Can modify it!"); 

     filterChain.doFilter(servletRequest, servletResponse); 

     // depending on the response, I'd like to add headers here 
     if(servletResponse.getStatus() == 200) 
      servletResponse.addIntHeader("x-success", 1); 

     if(servletResponse.isCommitted()) 
      log.debug("ACCCK! Response Already Committed"); 
    } 

Allerdings habe ich bemerkt, dass meine x-success Header wurde nie gegeben. Ein bisschen graben, und ich bemerkte, dass meine Antwort bereits zurückgegeben/committed wurde, als das Steuerelement zu meiner Filterkette zurückkehrte.

Was ist der richtige Weg, dies in Struts1 zu tun? Soll die Filterausführung nicht das gesamte Servlet umbrechen? Warum wird meine Antwort vor dem Abschluss meines Filters bestätigt? Wo kann ich sonst noch Header basierend auf der Antwort (Post-Action-Verarbeitung) in Struts1 hinzufügen?

+0

Verwenden Sie Kacheln oder SiteMesh. Dafür sind sie da. Aber warum benutzt du immer noch Struts 1? Es ist seit Jahren aufgegeben. –

+0

@jbnizet Leider verwendet die Legacy-App, an der ich arbeite, immer noch struts1, also versuche ich damit zu arbeiten. Ich versuche tatsächlich, Aspectj zu verwenden, um Antwortheader zu ändern, bevor sie an den Client zurückgegeben werden, und einen vorhandenen Filter zu erweitern, wenn ich auf dieses Problem stieß. Sitemesh ist mehr für die Dekoration und ich wollte den Code zentralisiert halten, so dass ich nicht anfangen wollte, den Fliesenunterricht zu beraten. –

Antwort

1

Wenn Sie filterChain.doFilter aufrufen, übergeben Sie die Kontrolle von Ihrem Filter an die angeforderte Seite (dh Struts), die dann frei ist, die Antwort zu begehen, wenn sie entscheidet. Da Sie das Ergebnis des Struts-Servlets untersuchen möchten, sollten Sie eine Antwortwrapperklasse (extends HttpServletRequestWrapper) erstellen und diese an filterChain.doFilter übergeben und nicht an den Antwortparameter, den Ihr Filter übergeben hat.

HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; 
ServletResponse wrapper = new MyHttpServletRequestWrapper(httpResponse); 
filter.doChain(servletRequest, wrapper); 

Der HttpServletRequestWrapper Konstruktor akzeptiert eine HttpServletResponse als Eingabe und die Delegierten alle Methoden zur umschlungenen Antwort, aber man kann sie in der Klasse als notwendig außer Kraft setzen. Wenn Sie verhindern möchten, dass die Antwort festgeschrieben wird, sollten Sie Methoden wie flushBuffer, getOutputSteam überschreiben (der zurückgegebene Ausgabestream kann gelöscht werden, indem die Antwort übergeben wird) und getWriter.

Aber Sie können nicht das tun müssen - versuchen, die setStatus Methode in der Wrapper-Klasse überschreiben den Statuscode zu prüfen und den Header hinzufügen, wenn sie aufgerufen wird:

public class MyHttpServletResponseWrapper extends HttpServletResponseWrapper { 
    public MyHttpServletResponseWrapper(HttpServletResponse response) { 
     super(response); 
    } 
    @Override 
    public void setStatus(int sc) { 
     if(sc == 200) { 
      addIntHeader("x-success", 1); 
     } 
     super.setStatus(sc); 
    } 
} 

Obwohl diese Frage in Bezug gefragt wurde, zu Struts 1 gilt es für jedes Web-Framework; Meine Antwort basiert auf meiner Arbeit für JSF-Filter.

+0

Interessante Idee; Ich hatte nicht daran gedacht, es so zu machen. Ich habe bereits den ResponseWrapper außer Kraft gesetzt, um nach dem Servlet den Statuscode überprüfen zu können (Servlet 2.4 spec), so dass es nicht besonders aufwändig wäre, den Header an dieser Stelle hinzuzufügen. Ich werde es versuchen und Sie wissen lassen, wie es funktioniert (unter der Annahme, dass das Struts-Servlet explizit den Statuscode setzt). –

+0

Ich habe gerade eine schnelle Suche gegen die Struts1 Codebase durchgeführt, und sehe nirgends, dass es explizit den Statuscode setzt. –

+0

Wie vermutet, gibt es keinen Standard 'setStatus()' Aufruf, da der Standardstatuscode von 'CoyoteResponse' bereits 200 ist.Es ist also nicht notwendig, dass Struts den Status ändert, es sei denn, es ist etwas anderes als 200. –

Verwandte Themen