Polishing
This commit is contained in:
parent
21f9ca088d
commit
ec7d80b851
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +17,6 @@
|
||||||
package org.springframework.web.filter;
|
package org.springframework.web.filter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
|
@ -35,8 +34,8 @@ import org.springframework.web.util.WebUtils;
|
||||||
* method with HttpServletRequest and HttpServletResponse arguments.
|
* method with HttpServletRequest and HttpServletResponse arguments.
|
||||||
*
|
*
|
||||||
* <p>As of Servlet 3.0, a filter may be invoked as part of a
|
* <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#REQUEST REQUEST} or
|
||||||
* {@link javax.servlet.DispatcherType.ASYNC ASYNC} dispatches that occur in
|
* {@link javax.servlet.DispatcherType#ASYNC ASYNC} dispatches that occur in
|
||||||
* separate threads. A filter can be configured in {@code web.xml} whether it
|
* separate threads. A filter can be configured in {@code web.xml} whether it
|
||||||
* should be involved in async dispatches. However, in some cases servlet
|
* should be involved in async dispatches. However, in some cases servlet
|
||||||
* containers assume different default configuration. Therefore sub-classes can
|
* containers assume different default configuration. Therefore sub-classes can
|
||||||
|
@ -53,7 +52,7 @@ import org.springframework.web.util.WebUtils;
|
||||||
* won't be the last one.
|
* won't be the last one.
|
||||||
*
|
*
|
||||||
* <p>Yet another dispatch type that also occurs in its own thread is
|
* <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}. Sub-classes can override
|
||||||
* {@link #shouldNotFilterErrorDispatch()} if they wish to declare statically
|
* {@link #shouldNotFilterErrorDispatch()} if they wish to declare statically
|
||||||
* if they should be invoked <em>once</em> during error dispatches.
|
* if they should be invoked <em>once</em> during error dispatches.
|
||||||
*
|
*
|
||||||
|
@ -129,7 +128,6 @@ public abstract class OncePerRequestFilter extends GenericFilterBean {
|
||||||
* in Servlet 3.0 means a filter can be invoked in more than one thread over
|
* 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
|
* the course of a single request. This method returns {@code true} if the
|
||||||
* filter is currently executing within an asynchronous dispatch.
|
* filter is currently executing within an asynchronous dispatch.
|
||||||
*
|
|
||||||
* @param request the current request
|
* @param request the current request
|
||||||
* @see WebAsyncManager#hasConcurrentResult()
|
* @see WebAsyncManager#hasConcurrentResult()
|
||||||
*/
|
*/
|
||||||
|
@ -140,7 +138,6 @@ public abstract class OncePerRequestFilter extends GenericFilterBean {
|
||||||
/**
|
/**
|
||||||
* Whether request processing is in asynchronous mode meaning that the
|
* Whether request processing is in asynchronous mode meaning that the
|
||||||
* response will not be committed after the current thread is exited.
|
* response will not be committed after the current thread is exited.
|
||||||
*
|
|
||||||
* @param request the current request
|
* @param request the current request
|
||||||
* @see WebAsyncManager#isConcurrentHandlingStarted()
|
* @see WebAsyncManager#isConcurrentHandlingStarted()
|
||||||
*/
|
*/
|
||||||
|
@ -151,7 +148,7 @@ public abstract class OncePerRequestFilter extends GenericFilterBean {
|
||||||
/**
|
/**
|
||||||
* Return the name of the request attribute that identifies that a request
|
* Return the name of the request attribute that identifies that a request
|
||||||
* is already filtered.
|
* 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,
|
* instance and appends ".FILTERED". If the filter is not fully initialized,
|
||||||
* it falls back to its class name.
|
* it falls back to its class name.
|
||||||
* @see #getFilterName
|
* @see #getFilterName
|
||||||
|
@ -188,7 +185,6 @@ public abstract class OncePerRequestFilter extends GenericFilterBean {
|
||||||
* types via {@code web.xml} or in Java through the {@code ServletContext},
|
* types via {@code web.xml} or in Java through the {@code ServletContext},
|
||||||
* servlet containers may enforce different defaults with regards to
|
* servlet containers may enforce different defaults with regards to
|
||||||
* dispatcher types. This flag enforces the design intent of the filter.
|
* 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
|
* <p>The default return value is "true", which means the filter will not be
|
||||||
* invoked during subsequent async dispatches. If "false", the filter will
|
* invoked during subsequent async dispatches. If "false", the filter will
|
||||||
* be invoked during async dispatches with the same guarantees of being
|
* be invoked during async dispatches with the same guarantees of being
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,7 +22,6 @@ import java.util.Collections;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@ -41,8 +40,8 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||||
import org.springframework.web.servlet.HandlerMapping;
|
import org.springframework.web.servlet.HandlerMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link AbstractMessageConverterMethodArgumentResolver} with the ability to handle method return
|
* Extends {@link AbstractMessageConverterMethodArgumentResolver} with the ability to handle
|
||||||
* values by writing to the response with {@link HttpMessageConverter}s.
|
* method return values by writing to the response with {@link HttpMessageConverter}s.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
@ -55,6 +54,7 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
|
|
||||||
private final ContentNegotiationManager contentNegotiationManager;
|
private final ContentNegotiationManager contentNegotiationManager;
|
||||||
|
|
||||||
|
|
||||||
protected AbstractMessageConverterMethodProcessor(List<HttpMessageConverter<?>> messageConverters) {
|
protected AbstractMessageConverterMethodProcessor(List<HttpMessageConverter<?>> messageConverters) {
|
||||||
this(messageConverters, null);
|
this(messageConverters, null);
|
||||||
}
|
}
|
||||||
|
@ -63,12 +63,12 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
ContentNegotiationManager manager) {
|
ContentNegotiationManager manager) {
|
||||||
|
|
||||||
super(messageConverters);
|
super(messageConverters);
|
||||||
this.contentNegotiationManager = (manager != null) ? manager : new ContentNegotiationManager();
|
this.contentNegotiationManager = (manager != null ? manager : new ContentNegotiationManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link HttpOutputMessage} from the given {@link NativeWebRequest}.
|
* Creates a new {@link HttpOutputMessage} from the given {@link NativeWebRequest}.
|
||||||
*
|
|
||||||
* @param webRequest the web request to create an output message from
|
* @param webRequest the web request to create an output message from
|
||||||
* @return the output message
|
* @return the output message
|
||||||
*/
|
*/
|
||||||
|
@ -81,10 +81,9 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
* Writes the given return value to the given web request. Delegates to
|
* Writes the given return value to the given web request. Delegates to
|
||||||
* {@link #writeWithMessageConverters(Object, MethodParameter, ServletServerHttpRequest, ServletServerHttpResponse)}
|
* {@link #writeWithMessageConverters(Object, MethodParameter, ServletServerHttpRequest, ServletServerHttpResponse)}
|
||||||
*/
|
*/
|
||||||
protected <T> void writeWithMessageConverters(T returnValue,
|
protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType, NativeWebRequest webRequest)
|
||||||
MethodParameter returnType,
|
|
||||||
NativeWebRequest webRequest)
|
|
||||||
throws IOException, HttpMediaTypeNotAcceptableException {
|
throws IOException, HttpMediaTypeNotAcceptableException {
|
||||||
|
|
||||||
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
|
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
|
||||||
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
|
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
|
||||||
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
|
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
|
||||||
|
@ -92,7 +91,6 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the given return type to the given output message.
|
* Writes the given return type to the given output message.
|
||||||
*
|
|
||||||
* @param returnValue the value to write to the output message
|
* @param returnValue the value to write to the output message
|
||||||
* @param returnType the type of the value
|
* @param returnType the type of the value
|
||||||
* @param inputMessage the input messages. Used to inspect the {@code Accept} header.
|
* @param inputMessage the input messages. Used to inspect the {@code Accept} header.
|
||||||
|
@ -102,23 +100,20 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
* the request cannot be met by the message converters
|
* the request cannot be met by the message converters
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> void writeWithMessageConverters(T returnValue,
|
protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType,
|
||||||
MethodParameter returnType,
|
ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
|
||||||
ServletServerHttpRequest inputMessage,
|
|
||||||
ServletServerHttpResponse outputMessage)
|
|
||||||
throws IOException, HttpMediaTypeNotAcceptableException {
|
throws IOException, HttpMediaTypeNotAcceptableException {
|
||||||
|
|
||||||
Class<?> returnValueClass = returnValue.getClass();
|
Class<?> returnValueClass = returnValue.getClass();
|
||||||
|
|
||||||
HttpServletRequest servletRequest = inputMessage.getServletRequest();
|
HttpServletRequest servletRequest = inputMessage.getServletRequest();
|
||||||
List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(servletRequest);
|
List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(servletRequest);
|
||||||
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(servletRequest, returnValueClass);
|
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(servletRequest, returnValueClass);
|
||||||
|
|
||||||
Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>();
|
Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>();
|
||||||
for (MediaType r : requestedMediaTypes) {
|
for (MediaType requestedType : requestedMediaTypes) {
|
||||||
for (MediaType p : producibleMediaTypes) {
|
for (MediaType producibleType : producibleMediaTypes) {
|
||||||
if (r.isCompatibleWith(p)) {
|
if (requestedType.isCompatibleWith(producibleType)) {
|
||||||
compatibleMediaTypes.add(getMostSpecificMediaType(r, p));
|
compatibleMediaTypes.add(getMostSpecificMediaType(requestedType, producibleType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +138,7 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
|
|
||||||
if (selectedMediaType != null) {
|
if (selectedMediaType != null) {
|
||||||
selectedMediaType = selectedMediaType.removeQualityValue();
|
selectedMediaType = selectedMediaType.removeQualityValue();
|
||||||
for (HttpMessageConverter<?> messageConverter : messageConverters) {
|
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
|
||||||
if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {
|
if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {
|
||||||
((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage);
|
((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
|
@ -154,15 +149,15 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
|
throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the media types that can be produced:
|
* Returns the media types that can be produced:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>The producible media types specified in the request mappings, or
|
* <li>The producible media types specified in the request mappings, or
|
||||||
* <li>Media types of configured converters that can write the specific return value, or
|
* <li>Media types of configured converters that can write the specific return value, or
|
||||||
* <li>{@link MediaType#ALL}
|
* <li>{@link MediaType#ALL}
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -171,9 +166,9 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
if (!CollectionUtils.isEmpty(mediaTypes)) {
|
if (!CollectionUtils.isEmpty(mediaTypes)) {
|
||||||
return new ArrayList<MediaType>(mediaTypes);
|
return new ArrayList<MediaType>(mediaTypes);
|
||||||
}
|
}
|
||||||
else if (!allSupportedMediaTypes.isEmpty()) {
|
else if (!this.allSupportedMediaTypes.isEmpty()) {
|
||||||
List<MediaType> result = new ArrayList<MediaType>();
|
List<MediaType> result = new ArrayList<MediaType>();
|
||||||
for (HttpMessageConverter<?> converter : messageConverters) {
|
for (HttpMessageConverter<?> converter : this.messageConverters) {
|
||||||
if (converter.canWrite(returnValueClass, null)) {
|
if (converter.canWrite(returnValueClass, null)) {
|
||||||
result.addAll(converter.getSupportedMediaTypes());
|
result.addAll(converter.getSupportedMediaTypes());
|
||||||
}
|
}
|
||||||
|
@ -187,7 +182,7 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
|
|
||||||
private List<MediaType> getAcceptableMediaTypes(HttpServletRequest request) throws HttpMediaTypeNotAcceptableException {
|
private List<MediaType> getAcceptableMediaTypes(HttpServletRequest request) throws HttpMediaTypeNotAcceptableException {
|
||||||
List<MediaType> mediaTypes = this.contentNegotiationManager.resolveMediaTypes(new ServletWebRequest(request));
|
List<MediaType> mediaTypes = this.contentNegotiationManager.resolveMediaTypes(new ServletWebRequest(request));
|
||||||
return mediaTypes.isEmpty() ? Collections.singletonList(MediaType.ALL) : mediaTypes;
|
return (mediaTypes.isEmpty() ? Collections.singletonList(MediaType.ALL) : mediaTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,8 +190,8 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||||
* with the q-value of the former.
|
* with the q-value of the former.
|
||||||
*/
|
*/
|
||||||
private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) {
|
private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) {
|
||||||
produceType = produceType.copyQualityValue(acceptType);
|
MediaType produceTypeToUse = produceType.copyQualityValue(acceptType);
|
||||||
return MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceType) <= 0 ? acceptType : produceType;
|
return (MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceTypeToUse) <= 0 ? acceptType : produceTypeToUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue