Polishing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.web.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
@@ -35,25 +34,25 @@ import org.springframework.web.util.WebUtils;
|
||||
* method with HttpServletRequest and HttpServletResponse arguments.
|
||||
*
|
||||
* <p>As of Servlet 3.0, a filter may be invoked as part of a
|
||||
* {@link javax.servlet.DispatcherType.REQUEST REQUEST} or
|
||||
* {@link javax.servlet.DispatcherType.ASYNC ASYNC} dispatches that occur in
|
||||
* {@link javax.servlet.DispatcherType#REQUEST REQUEST} or
|
||||
* {@link javax.servlet.DispatcherType#ASYNC ASYNC} dispatches that occur in
|
||||
* separate threads. A filter can be configured in {@code web.xml} whether it
|
||||
* should be involved in async dispatches. However, in some cases servlet
|
||||
* containers assume different default configuration. Therefore sub-classes can
|
||||
* override the method {@link #shouldNotFilterAsyncDispatch()} to declare
|
||||
* statically if they shouuld indeed be invoked, <em>once</em>, during both types
|
||||
* statically if they should indeed be invoked, <em>once</em>, during both types
|
||||
* of dispatches in order to provide thread initialization, logging, security,
|
||||
* and so on. This mechanism complements and does not replace the need to
|
||||
* configure a filter in {@code web.xml} with dispatcher types.
|
||||
*
|
||||
* <p>Sub-classes may use {@link #isAsyncDispatch(HttpServletRequest)} to
|
||||
* determine when a filter is invoked as part of an async dispatch, and
|
||||
* use {@link #isAsyncStarted(HttpServletRequest)} to determine when the
|
||||
* request has been placed in async mode and therefore the current dispatch
|
||||
* won't be the last one.
|
||||
* <p>Subclasses may use {@link #isAsyncDispatch(HttpServletRequest)} to
|
||||
* determine when a filter is invoked as part of an async dispatch, and use
|
||||
* {@link #isAsyncStarted(HttpServletRequest)} to determine when the request
|
||||
* has been placed in async mode and therefore the current dispatch won't be
|
||||
* the last one for the given request.
|
||||
*
|
||||
* <p>Yet another dispatch type that also occurs in its own thread is
|
||||
* {@link javax.servlet.DispatcherType.ERROR ERROR}. Sub-classes can override
|
||||
* {@link javax.servlet.DispatcherType#ERROR ERROR}. Subclasses can override
|
||||
* {@link #shouldNotFilterErrorDispatch()} if they wish to declare statically
|
||||
* if they should be invoked <em>once</em> during error dispatches.
|
||||
*
|
||||
@@ -128,7 +127,6 @@ public abstract class OncePerRequestFilter extends GenericFilterBean {
|
||||
* in Servlet 3.0 means a filter can be invoked in more than one thread over
|
||||
* the course of a single request. This method returns {@code true} if the
|
||||
* filter is currently executing within an asynchronous dispatch.
|
||||
*
|
||||
* @param request the current request
|
||||
* @see WebAsyncManager#hasConcurrentResult()
|
||||
*/
|
||||
@@ -139,7 +137,6 @@ public abstract class OncePerRequestFilter extends GenericFilterBean {
|
||||
/**
|
||||
* Whether request processing is in asynchronous mode meaning that the
|
||||
* response will not be committed after the current thread is exited.
|
||||
*
|
||||
* @param request the current request
|
||||
* @see WebAsyncManager#isConcurrentHandlingStarted()
|
||||
*/
|
||||
@@ -150,7 +147,7 @@ public abstract class OncePerRequestFilter extends GenericFilterBean {
|
||||
/**
|
||||
* Return the name of the request attribute that identifies that a request
|
||||
* is already filtered.
|
||||
* <p>Default implementation takes the configured name of the concrete filter
|
||||
* <p>The default implementation takes the configured name of the concrete filter
|
||||
* instance and appends ".FILTERED". If the filter is not fully initialized,
|
||||
* it falls back to its class name.
|
||||
* @see #getFilterName
|
||||
@@ -187,7 +184,6 @@ public abstract class OncePerRequestFilter extends GenericFilterBean {
|
||||
* types via {@code web.xml} or in Java through the {@code ServletContext},
|
||||
* servlet containers may enforce different defaults with regards to
|
||||
* dispatcher types. This flag enforces the design intent of the filter.
|
||||
*
|
||||
* <p>The default return value is "true", which means the filter will not be
|
||||
* invoked during subsequent async dispatches. If "false", the filter will
|
||||
* be invoked during async dispatches with the same guarantees of being
|
||||
|
||||
@@ -67,14 +67,15 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
HttpServletResponse responseToUse = response;
|
||||
if (!isAsyncDispatch(request)) {
|
||||
response = new ShallowEtagResponseWrapper(response);
|
||||
responseToUse = new ShallowEtagResponseWrapper(response);
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
filterChain.doFilter(request, responseToUse);
|
||||
|
||||
if (!isAsyncStarted(request)) {
|
||||
updateResponse(request, response);
|
||||
updateResponse(request, responseToUse);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,34 +84,33 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
||||
WebUtils.getNativeResponse(response, ShallowEtagResponseWrapper.class);
|
||||
Assert.notNull(responseWrapper, "ShallowEtagResponseWrapper not found");
|
||||
|
||||
response = (HttpServletResponse) responseWrapper.getResponse();
|
||||
byte[] body = responseWrapper.toByteArray();
|
||||
HttpServletResponse rawResponse = (HttpServletResponse) responseWrapper.getResponse();
|
||||
int statusCode = responseWrapper.getStatusCode();
|
||||
byte[] body = responseWrapper.toByteArray();
|
||||
|
||||
if (isEligibleForEtag(request, responseWrapper, statusCode, body)) {
|
||||
String responseETag = generateETagHeaderValue(body);
|
||||
response.setHeader(HEADER_ETAG, responseETag);
|
||||
|
||||
rawResponse.setHeader(HEADER_ETAG, responseETag);
|
||||
String requestETag = request.getHeader(HEADER_IF_NONE_MATCH);
|
||||
if (responseETag.equals(requestETag)) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("ETag [" + responseETag + "] equal to If-None-Match, sending 304");
|
||||
}
|
||||
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
rawResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
}
|
||||
else {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("ETag [" + responseETag + "] not equal to If-None-Match [" + requestETag +
|
||||
"], sending normal response");
|
||||
}
|
||||
copyBodyToResponse(body, response);
|
||||
copyBodyToResponse(body, rawResponse);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Response with status code [" + statusCode + "] not eligible for ETag");
|
||||
}
|
||||
copyBodyToResponse(body, response);
|
||||
copyBodyToResponse(body, rawResponse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user