17
17
package org .springframework .web .servlet .handler ;
18
18
19
19
import java .util .Set ;
20
+ import java .util .function .Predicate ;
20
21
21
22
import jakarta .servlet .http .HttpServletRequest ;
22
23
import jakarta .servlet .http .HttpServletResponse ;
@@ -53,6 +54,9 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti
53
54
54
55
private int order = Ordered .LOWEST_PRECEDENCE ;
55
56
57
+ @ Nullable
58
+ private Predicate <Object > mappedHandlerPredicate ;
59
+
56
60
@ Nullable
57
61
private Set <?> mappedHandlers ;
58
62
@@ -74,33 +78,43 @@ public int getOrder() {
74
78
return this .order ;
75
79
}
76
80
81
+ /**
82
+ * Use a {@code Predicate} to determine which handlers this exception
83
+ * resolver applies to, including when the request was not mapped in which
84
+ * case the handler is {@code null}.
85
+ * <p>If no handler predicate, nor handlers, nor handler classes are set,
86
+ * the exception resolver applies to all handlers.
87
+ * @since 6.1.2
88
+ */
89
+ public void setMappedHandlerPredicate (Predicate <Object > predicate ) {
90
+ this .mappedHandlerPredicate =
91
+ (this .mappedHandlerPredicate != null ? this .mappedHandlerPredicate .and (predicate ) : predicate );
92
+ }
93
+
77
94
/**
78
95
* Specify the set of handlers that this exception resolver should apply to.
79
- * <p>The exception mappings and the default error view will only apply to the specified handlers.
80
- * <p>If no handlers or handler classes are set, the exception mappings and the default error
81
- * view will apply to all handlers. This means that a specified default error view will be used
82
- * as a fallback for all exceptions; any further HandlerExceptionResolvers in the chain will be
83
- * ignored in this case.
96
+ * <p>If no handler predicate, nor handlers, nor handler classes are set,
97
+ * the exception resolver applies to all handlers.
98
+ * @see #setMappedHandlerPredicate(Predicate)
84
99
*/
85
100
public void setMappedHandlers (Set <?> mappedHandlers ) {
86
101
this .mappedHandlers = mappedHandlers ;
87
102
}
88
103
89
104
/**
90
105
* Specify the set of classes that this exception resolver should apply to.
91
- * <p>The exception mappings and the default error view will only apply to handlers of the
92
- * specified types; the specified types may be interfaces or superclasses of handlers as well.
93
- * <p>If no handlers or handler classes are set, the exception mappings and the default error
94
- * view will apply to all handlers. This means that a specified default error view will be used
95
- * as a fallback for all exceptions; any further HandlerExceptionResolvers in the chain will be
96
- * ignored in this case.
106
+ * The resolver will only apply to handlers of the specified types; the
107
+ * specified types may be interfaces or superclasses of handlers as well.
108
+ * <p>If no handler predicate, nor handlers, nor handler classes are set,
109
+ * the exception resolver applies to all handlers.
110
+ * @see #setMappedHandlerPredicate(Predicate)
97
111
*/
98
112
public void setMappedHandlerClasses (Class <?>... mappedHandlerClasses ) {
99
113
this .mappedHandlerClasses = mappedHandlerClasses ;
100
114
}
101
115
102
116
/**
103
- * Add a mapped handler class .
117
+ * Alternative to {@link #setMappedHandlerClasses(Class[])} .
104
118
* @since 6.1
105
119
*/
106
120
public void addMappedHandlerClass (Class <?> mappedHandlerClass ) {
@@ -177,6 +191,7 @@ public ModelAndView resolveException(
177
191
/**
178
192
* Check whether this resolver is supposed to apply to the given handler.
179
193
* <p>The default implementation checks against the configured
194
+ * {@linkplain #setMappedHandlerPredicate(Predicate) handlerPredicate}
180
195
* {@linkplain #setMappedHandlers handlers} and
181
196
* {@linkplain #setMappedHandlerClasses handler classes}, if any.
182
197
* @param request current HTTP request
@@ -188,6 +203,9 @@ public ModelAndView resolveException(
188
203
* @see #setMappedHandlerClasses
189
204
*/
190
205
protected boolean shouldApplyTo (HttpServletRequest request , @ Nullable Object handler ) {
206
+ if (this .mappedHandlerPredicate != null ) {
207
+ return this .mappedHandlerPredicate .test (handler );
208
+ }
191
209
if (handler != null ) {
192
210
if (this .mappedHandlers != null && this .mappedHandlers .contains (handler )) {
193
211
return true ;
@@ -205,11 +223,13 @@ protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object han
205
223
206
224
/**
207
225
* Whether there are any handler mappings registered via
208
- * {@link #setMappedHandlers(Set)} or {@link #setMappedHandlerClasses(Class[])}.
226
+ * {@link #setMappedHandlers(Set)}, {@link #setMappedHandlerClasses(Class[])}, or
227
+ * {@link #setMappedHandlerPredicate(Predicate)}.
209
228
* @since 5.3
210
229
*/
211
230
protected boolean hasHandlerMappings () {
212
- return (this .mappedHandlers != null || this .mappedHandlerClasses != null );
231
+ return (this .mappedHandlers != null || this .mappedHandlerClasses != null ||
232
+ this .mappedHandlerPredicate != null );
213
233
}
214
234
215
235
/**
0 commit comments