Add mappedHandler Predicate to AbstractHandlerExceptionResolver
Closes gh-26772
This commit is contained in:
parent
753409083d
commit
dd23b1d156
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.web.servlet.handler;
|
package org.springframework.web.servlet.handler;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
@ -53,6 +54,9 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
|
||||||
|
|
||||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Predicate<Object> mappedHandlerPredicate;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Set<?> mappedHandlers;
|
private Set<?> mappedHandlers;
|
||||||
|
|
||||||
|
|
@ -74,13 +78,24 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
|
||||||
return this.order;
|
return this.order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a {@code Predicate} to determine which handlers this exception
|
||||||
|
* resolver applies to, including when the request was not mapped in which
|
||||||
|
* case the handler is {@code null}.
|
||||||
|
* <p>If no handler predicate, nor handlers, nor handler classes are set,
|
||||||
|
* the exception resolver applies to all handlers.
|
||||||
|
* @since 6.1.2
|
||||||
|
*/
|
||||||
|
public void setMappedHandlerPredicate(Predicate<Object> predicate) {
|
||||||
|
this.mappedHandlerPredicate =
|
||||||
|
(this.mappedHandlerPredicate != null ? this.mappedHandlerPredicate.and(predicate) : predicate);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the set of handlers that this exception resolver should apply to.
|
* Specify the set of handlers that this exception resolver should apply to.
|
||||||
* <p>The exception mappings and the default error view will only apply to the specified handlers.
|
* <p>If no handler predicate, nor handlers, nor handler classes are set,
|
||||||
* <p>If no handlers or handler classes are set, the exception mappings and the default error
|
* the exception resolver applies to all handlers.
|
||||||
* view will apply to all handlers. This means that a specified default error view will be used
|
* @see #setMappedHandlerPredicate(Predicate)
|
||||||
* as a fallback for all exceptions; any further HandlerExceptionResolvers in the chain will be
|
|
||||||
* ignored in this case.
|
|
||||||
*/
|
*/
|
||||||
public void setMappedHandlers(Set<?> mappedHandlers) {
|
public void setMappedHandlers(Set<?> mappedHandlers) {
|
||||||
this.mappedHandlers = mappedHandlers;
|
this.mappedHandlers = mappedHandlers;
|
||||||
|
|
@ -88,19 +103,18 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the set of classes that this exception resolver should apply to.
|
* Specify the set of classes that this exception resolver should apply to.
|
||||||
* <p>The exception mappings and the default error view will only apply to handlers of the
|
* The resolver will only apply to handlers of the specified types; the
|
||||||
* specified types; the specified types may be interfaces or superclasses of handlers as well.
|
* specified types may be interfaces or superclasses of handlers as well.
|
||||||
* <p>If no handlers or handler classes are set, the exception mappings and the default error
|
* <p>If no handler predicate, nor handlers, nor handler classes are set,
|
||||||
* view will apply to all handlers. This means that a specified default error view will be used
|
* the exception resolver applies to all handlers.
|
||||||
* as a fallback for all exceptions; any further HandlerExceptionResolvers in the chain will be
|
* @see #setMappedHandlerPredicate(Predicate)
|
||||||
* ignored in this case.
|
|
||||||
*/
|
*/
|
||||||
public void setMappedHandlerClasses(Class<?>... mappedHandlerClasses) {
|
public void setMappedHandlerClasses(Class<?>... mappedHandlerClasses) {
|
||||||
this.mappedHandlerClasses = mappedHandlerClasses;
|
this.mappedHandlerClasses = mappedHandlerClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a mapped handler class.
|
* Alternative to {@link #setMappedHandlerClasses(Class[])}.
|
||||||
* @since 6.1
|
* @since 6.1
|
||||||
*/
|
*/
|
||||||
public void addMappedHandlerClass(Class<?> mappedHandlerClass) {
|
public void addMappedHandlerClass(Class<?> mappedHandlerClass) {
|
||||||
|
|
@ -177,6 +191,7 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
|
||||||
/**
|
/**
|
||||||
* Check whether this resolver is supposed to apply to the given handler.
|
* Check whether this resolver is supposed to apply to the given handler.
|
||||||
* <p>The default implementation checks against the configured
|
* <p>The default implementation checks against the configured
|
||||||
|
* {@linkplain #setMappedHandlerPredicate(Predicate) handlerPredicate}
|
||||||
* {@linkplain #setMappedHandlers handlers} and
|
* {@linkplain #setMappedHandlers handlers} and
|
||||||
* {@linkplain #setMappedHandlerClasses handler classes}, if any.
|
* {@linkplain #setMappedHandlerClasses handler classes}, if any.
|
||||||
* @param request current HTTP request
|
* @param request current HTTP request
|
||||||
|
|
@ -188,6 +203,9 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
|
||||||
* @see #setMappedHandlerClasses
|
* @see #setMappedHandlerClasses
|
||||||
*/
|
*/
|
||||||
protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) {
|
protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) {
|
||||||
|
if (this.mappedHandlerPredicate != null) {
|
||||||
|
return this.mappedHandlerPredicate.test(handler);
|
||||||
|
}
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) {
|
if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -205,11 +223,13 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether there are any handler mappings registered via
|
* Whether there are any handler mappings registered via
|
||||||
* {@link #setMappedHandlers(Set)} or {@link #setMappedHandlerClasses(Class[])}.
|
* {@link #setMappedHandlers(Set)}, {@link #setMappedHandlerClasses(Class[])}, or
|
||||||
|
* {@link #setMappedHandlerPredicate(Predicate)}.
|
||||||
* @since 5.3
|
* @since 5.3
|
||||||
*/
|
*/
|
||||||
protected boolean hasHandlerMappings() {
|
protected boolean hasHandlerMappings() {
|
||||||
return (this.mappedHandlers != null || this.mappedHandlerClasses != null);
|
return (this.mappedHandlers != null || this.mappedHandlerClasses != null ||
|
||||||
|
this.mappedHandlerPredicate != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -385,6 +385,21 @@ public class ExceptionHandlerExceptionResolverTests {
|
||||||
assertExceptionHandledAsBody(mav, "DefaultTestExceptionResolver: IllegalStateException");
|
assertExceptionHandledAsBody(mav, "DefaultTestExceptionResolver: IllegalStateException");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // gh-26772
|
||||||
|
void resolveExceptionViaMappedHandlerPredicate() throws Exception {
|
||||||
|
Object handler = new Object();
|
||||||
|
|
||||||
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyControllerAdviceConfig.class);
|
||||||
|
this.resolver.setMappedHandlerPredicate(h -> h == handler);
|
||||||
|
this.resolver.setApplicationContext(ctx);
|
||||||
|
this.resolver.afterPropertiesSet();
|
||||||
|
|
||||||
|
ModelAndView mav = this.resolver.resolveException(
|
||||||
|
this.request, this.response, handler, new IllegalStateException());
|
||||||
|
|
||||||
|
assertExceptionHandledAsBody(mav, "DefaultTestExceptionResolver: IllegalStateException");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void assertMethodProcessorCount(int resolverCount, int handlerCount) {
|
private void assertMethodProcessorCount(int resolverCount, int handlerCount) {
|
||||||
assertThat(this.resolver.getArgumentResolvers().getResolvers()).hasSize(resolverCount);
|
assertThat(this.resolver.getArgumentResolvers().getResolvers()).hasSize(resolverCount);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue