Description
David Pedowitz opened SPR-4770 and commented
Introduce @HandlerInterceptor
to create a more symmetrical relationship between @Controller
, @ModelAttribute
and @RequestParam
.
This came out of some questions and brainstorming in a Spring training session in LA, 5/1/08 with Chris Beams, Tchavdar Ivanov (FIM) and myself.
In Spring 2.5 the implementation of HandlerInterceptor has not changed leaving you to either implement the interface or extend HandlerInterceptorAdapter as before. If you use @Controller
and component scan you still must define a DefaultAnnotationHandlerMapping to configure a single list of HandlerInterceptors for all Controllers.
It'd be nice if you could define a class as a @HandlerInterceptor
and annotate methods as @AfterCompletion
, @PreHandle
and @PostHandle
. The default behavior could automagically intercept all @Controllers
scanned and fire according to the same contract as the original HandlerInterceptor. Also interaction could be similar to @Controller
with the methods allowing use of @ModelAttribute
and @RequestParam
.
Example provided by Chris Beams:
// @HandlerInterceptors are @Components, thus eligible for component scanning.
// If no class args are supplied, the interceptor applies globally to all
// registered @Controllers. Naturally, specifying one or more classes narrows
// its scope.
@HandlerInterceptor({AccountController.class, CustomerController.class}) public class ExceptionLoggingHandlerInterceptor {
@AfterCompletion
public void logException(Object handler, Throwable ex) {
logger.error(...);
}
// Or to be more explicit, do it @AspectJ-style, using
// attributes to bind by name
@AfterCompletion(handler="handler", exception="ex")
public void logException(Object handler, Throwable ex) {
logger.error(...);
}
// In keeping with @Controller methods, the user could
// request the request, response, model, etc.
@AfterCompletion(handler="handler", exception="ex")
public void logException(HttpServletRequest req, Object handler, Throwable ex) {
logger.error(...);
}
// Could even have handler methods return @ModelAttributes!
@PreHandle
public @ModelAttribute("currentDate") Date currentDate(/* no params needed, none requested */) {
return new Date();
}
}
Obviously there's a lot to be worked out. Some questions we have are:
- How do you express the order of the interceptors, something that comes naturally in the <list> configuratin.
@Order
? - Is it more natural to express the Controller classes the HandlerInterceptor applies to in the
@HandlerInterceptor
(above) or would something like@Controller
(interceptors=(@HandlerInterceptors
{class, class, ...})) be more expressive? which is more flexible?- The later does express the list naturally but you would have to repeat the list in multiple controllers to achieve the same behavior.
- Maybe an XML annotation hybrid? <handlerInterceptorList id="authInterceptors">...</handlerInterceptorList> and
@Controller
(interceptor="authInterceptors")
- Could tooling help visualize how an
@Controller
relates to it@HandlerInterceptors
(add bonus for sure!)
Issue Links:
- Apply Filter or Interceptor to Controller class via annotations [SPR-13377] #17959 Apply Filter or Interceptor to Controller class via annotations ("is duplicated by")
- Ability to restrict HandlerInterceptors to specific controller paths [SPR-4015] #8695 Ability to restrict HandlerInterceptors to specific controller paths
14 votes, 16 watchers