webentwicklung-frage-antwort-db.com.de

Header als Antwort im Filter hinzufügen?

Ich muss den Header in jede Antwort einfügen. Ich plane unten zu tun

public class MyFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        filterChain.doFilter(request, response);
            response.addHeader("Access-Control-Allow-Origin", "*"); 
    }

}

Ich möchte es nach filterChain.doFilter(request, response) tun, so dass ich, sobald der Controller es verarbeitet hat, nur den Header hinzufüge, bevor ich zum Client zurückkehre. Ist es richtig ?

Aber nach Wie schreibe ich Antwortfilter?

Nachdem chain.doFilter zurückgekehrt ist, ist es zu spät, etwas mit der Antwort zu tun. Zu diesem Zeitpunkt wurde bereits die gesamte Antwort an den Client gesendet, und Ihr Code hat keinen Zugriff darauf.

Die obige Aussage sieht für mich nicht richtig aus. Kann ich nach filterChain.doFilter(request, response) keinen Header hinzufügen? Wenn nicht warum?

ich benutze Spring MVC.

9
emilly

Nachdem filterChain.doFilter aufgerufen wurde, ist es zu spät, um etwas mit der Antwort zu tun. Zu diesem Zeitpunkt wurde die gesamte Antwort bereits an den Client gesendet.

Sie müssen eine Wrap-Antwort in Ihre eigenen Klassen einbauen, diese Wrapper an die doFilter-Methode übergeben und die Verarbeitung in Ihren Wrappern ausführen.

Es gibt bereits einen Antwortwrapper: HttpServletResponseWrapper, den Sie erweitern können. Zum Beispiel:

public class MyResponseRequestWrapper extends HttpServletResponseWrapper{
    public MyResponseRequestWrapper(HttpServletResponse response) {
        super(response);
    }
}

Ihr Filter:

@Override
protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {

    HttpServletResponse myResponse = (HttpServletResponse) response;
    MyResponseRequestWrapper responseWrapper = new MyResponseRequestWrapper(myResponse);
    responseWrapper.addHeader("Access-Control-Allow-Origin", "*");
    filterChain.doFilter(request, myResponse);
}
14
Luan

Ich benutze dies in meinem Projekt mit Spring 3.0.x:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException
{
    response.addHeader("headerName", "headerValue");
    filterChain.doFilter(request, response);
}

Funktioniert gut.

0
David Balažic

Vom perfekten Artikel

Ein Filter, der eine Antwort ändert, muss normalerweise die Antwort erfassen, bevor sie an den Client zurückgegeben wird. Dazu übergeben Sie einen Stand-In-Stream an das Servlet, das die Antwort generiert. Der Stand-In-Stream verhindert, dass das Servlet den ursprünglichen Antwortstream schließt, wenn der Vorgang abgeschlossen ist, und ermöglicht dem Filter, die Antwort des Servlets zu ändern.

Um diesen Stand-In-Stream an das Servlet zu übergeben, erstellt der Filter einen Antwortwrapper, der die Methode getWriter oder getOutputStream überschreibt, um diesen Stand-In-Stream zurückzugeben. Der Wrapper wird an die doFilter-Methode der Filterkette übergeben. Wrapper-Methoden verwenden standardmäßig den Aufruf an das umschlossene Anforderungs- oder Antwortobjekt. Dieser Ansatz folgt dem bekannten Muster "Wrapper" oder "Decorator", das in Design Patterns beschrieben wird. 

0
M Sach

Dies ist etwas spät, aber das Folgende könnte einigen Helfen. Wenn Sie also wirklich Werte an einen vorhandenen Header anhängen oder neue Werte an einen vorhandenen Header anfügen möchten, können Sie einen Wrapper am besten schreiben und festlegen Wert im Wrapper.

Dann verketten Sie die Antwort im Filter

HttpServletResponse response = (HttpServletResponse) servletResponse;
ByteArrayPrinter pw = new ByteArrayPrinter();

// Create a wrapper
HttpServletResponse wrappedResp = new HttpServletResponseWrapper(response) {

    @Override
    public void setContentType(final String type) {
        super.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
    }

    @Override
    public PrintWriter getWriter() {
        return pw.getWriter();
    }

    // set the outputstream content type to JSON
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        ServletResponse response = this.getResponse();

        String ct = (response != null) ? response.getContentType() : null;
        if (ct != null && ct.contains(APPLICATION_XHTML)) {
            response.setContentType(ct + AppConstants.CONSTANT_COMMA + MediaType.APPLICATION_JSON_UTF8_VALUE);
        }
        return pw.getStream();
    }

};
chain.doFilter(httpRequest, wrappedResp);

Hier ist der ByteArrayPrinter.Java

public class ByteArrayPrinter {

    private ByteArrayOutputStream baos = new ByteArrayOutputStream();

    private PrintWriter pw = new PrintWriter(baos);

    private ServletOutputStream sos = new ByteArrayServletStream(baos);

    public PrintWriter getWriter() {
        return pw;
    }

    public ServletOutputStream getStream() {
        return sos;
    }

    byte[] toByteArray() {
        return baos.toByteArray();
    }
}

Und hier ist der ByteArrayServletOutputStream

public class ByteArrayServletStream extends ServletOutputStream {

    ByteArrayOutputStream baos;

    ByteArrayServletStream(ByteArrayOutputStream baos) {
        this.baos = baos;
    }

    @Override
    public void write(int param) throws IOException {
        baos.write(param);
    }

    @Override
    public boolean isReady() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void setWriteListener(WriteListener listener) {
        // TODO Auto-generated method stub

    }

}
0
Joey587