Polishing

This commit is contained in:
Juergen Hoeller
2014-04-27 22:52:51 +02:00
parent 9e2060707a
commit 779a6b79eb
12 changed files with 219 additions and 220 deletions

View File

@@ -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

View File

@@ -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);
}
}