4.6.3 MVC Interceptors
The features in this section are available starting with 5.3.0.
net.hasor.web.HandlerInterceptor applies only to MVC requests with a matched Action.
HTTP filters surround MVC. Static resources and requests delegated to downstream Servlets bypass MVC interceptors.
Registration and order
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(WebApiBinder binder) {
binder.bindInterceptor(new LoginInterceptor());
binder.bindInterceptor(new AuditInterceptor());
}
}
WebApiBinder.bindInterceptor(HandlerInterceptor interceptor) runs pre-handlers in registration order.
The application chooses the sequence of registration calls in its WebMvcConfigurer implementation, and the framework uses that sequence directly.
Login enters before Audit in this example; post-handlers and completion callbacks run in reverse order.
An interceptor instance is shared between requests. Store request-specific state in the Invoker or request attributes.
Complete registration during module configuration. The Web context loads the interceptor list at initialization and reuses it for requests without repeated container lookups.
With hasor-config, use the same API inside WebMvcConfigurer.addInterceptors(WebApiBinder).
Lifecycle
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(Invoker invoker) {
if (invoker.getHttpRequest().getUserPrincipal() == null) {
invoker.getHttpResponse().setStatus(401);
return false;
}
return true;
}
@Override
public void postHandle(Invoker invoker, Object result) {
// Inspect or replace Invoker.RETURN_DATA_KEY before rendering.
}
@Override
public void afterCompletion(Invoker invoker, Throwable failure) {
// Release resources acquired by this interceptor.
}
}
preHandleruns before the Controller in registration order. Returningfalsemeans the request is handled and stops later interceptors, the Controller, and automatic rendering.postHandleruns in reverse order after a successful Controller call, before rendering. Replace the result withinvoker.put(Invoker.RETURN_DATA_KEY, result)if needed.afterCompletionruns in reverse order after rendering or termination, only for interceptors whosepreHandlereturnedtrue. An interceptor that returnedfalseor threw frompreHandledoes not receive its own completion callback.
A normal request follows: outer Filter → pre-handlers → Controller → reverse post-handlers → rendering → reverse completion callbacks → return to outer Filter.
Failures in preHandle, the Controller, or postHandle enter MVC exception handling. Rendering runs after invocation and exception handling finish; rendering failures propagate outward and are passed to afterCompletion.
Completion receives null when invocation succeeds or an exception is resolved and rendering succeeds or is skipped. Otherwise it receives the final failure propagated outward, including a rendering failure. Exception recovery does not rerun post-handlers.
Completion callback failures are logged; remaining completion callbacks still run.
Manual responses and asynchronous work
Acquiring the response Writer or output stream suppresses additional automatic rendering.
A pre-handler that only sets status or headers can return false to stop MVC execution.
In postHandle, call invoker.setSkipRender() to skip further automatic rendering, including an explicitly selected renderer or view.
The MVC pipeline checks this state before output; renderers do not check it internally.
This does not stop remaining interceptor callbacks; a pre-handler must still return false to stop MVC execution.
Query the state with invoker.isSkipRender(). The state belongs to the current request; once rendering is skipped, it cannot be re-enabled.
Framework @Async Actions run MVC callbacks on a worker thread; see asynchronous requests for response output limitations.
When an Action calls Servlet startAsync() itself, a normal return still runs postHandle, but asynchronous mode skips automatic rendering. afterCompletion runs when the current MVC invocation ends, without waiting for Servlet asynchronous completion. Use a Servlet AsyncListener for asynchronous completion, error, and timeout events.
Application-managed asynchronous tasks execute outside the MVC exception-handling stack.