Struts2 interceptors are a core mechanism for implementing cross-cutting concerns in web applications, leveraging aspect-oriented programming principles. Similar in concept to servlet filters, interceptors execute logic before and after an action method is invoked. However, unlike filters that operate at the servlet container level, Struts2 interceptors are tightly integrated with the framework’s action lifecycle and can access the value stack, action context, and other framework-specific constructs.
Struts2 provides a rich set of built-in interceptors—such as those for validation, file upload, internationalization (i18n), and model-driven data binding—which are preconfigured in struts-default.xml. These interceptors are often grouped into reusable stacks like defaultStack, validationWorkflowStack, and fileUploadStack, allowing developers to apply common behavior patterns with minimal configuration.
Common Built-in Interceptors
| Interceptor Class | Name | Description |
|---|---|---|
| AliasInterceptor | alias | Maps request parameters from one name to another without changing values. |
| ChainingInterceptor | chain | Shares properties from one action to the next when using chain results. |
| CheckboxInterceptor | checkbox | Handles unchecked checkboxes by setting them to false, compensating for HTML's omission of unchecked boxes. |
| CookieInterceptor | cookie | Injects cookie values into the action based on configured names. |
| StrutsConversionErrorInterceptor | conversionError | Transfers type conversion errors from the context to the action’s field errors. |
| CreateSessionInterceptor | createSession | Automatically creates an HTTP session if needed by subsequent interceptors. |
| DebuggingInterceptor | debugging | Provides debug views showing internal framework state (e.g., stack contents). |
| ExecuteAndWaitInterceptor | execAndWait | Runs long-running actions asynchronously and shows a wait page during execution. |
| ExceptionMappingInterceptor | exception | Catches exceptions and maps them to result names for error handling. |
| FileUploadInterceptor | fileUpload | Processes multiprat requests and populates uploaded files into the action. |
| I18nInterceptor | i18n | Stores the user’s selected locale in the session for consistent internationalization. |
| LoggingInterceptor | logger | Logs the name of the executed action. |
| MessageStoreInterceptor | store | Persists action messages/errors across redirects using the session. |
| ModelDrivenInterceptor | model-driven | If the action implements ModelDriven, pushes the model onto the value stack. |
| ScopedModelDrivenInterceptor | scoped-model-driven | Retrieves a model from a specific scope (e.g., session) and injects it into the action. |
| ParametersInterceptor | params | Sets request parameters onto the action’s properties via reflection. |
| PrepareInterceptor | prepare | Invokes the prepare() method if the action implements Preparable. |
| ScopeInterceptor | scope | Manages action state persistence across application or session scopes. |
| ServletConfigInterceptor | servletConfig | Injects HttpServletRequest and HttpServletResponse as mapped objects. |
| StaticParametersInterceptor | staticParams | Injects static parameters defined in struts.xml into the action. |
| RolesInterceptor | roles | Enforces JAAS role-based access control before action execution. |
| TimerInterceptor | timer | Measures and logs the execution time of an action. |
| TokenInterceptor | token | Prevents duplicate form submissions using a one-time token. |
| TokenSessionStoreInterceptor | tokenSession | Similar to token, but stores form data in the session on resubmission. |
| AnnotationValidationInterceptor | validation | Performs validation using annotations or XML validation rules. |
| DefaultWorkflowInterceptor | workflow | Triggers the validate() method and redirects to input on errors. |
| ProfilingActivationInterceptor | profiling | Enables performance profiling when activated via request parameters. |
Example: Preventing Duplicate Submissions with TokenInterceptor
The TokenInterceptor ensures a form is submitted only once. It works by embedding a unique token in the form (via <s:token/>) and validating it on submission.
Action class:
public class RegistrationAction extends ActionSupport {
private String username;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
@Override
public String execute() {
return SUCCESS;
}
}
JSP form:
<s:form action="register">
<s:token/>
<s:textfield name="username" label="Username"/>
<s:submit value="Register"/>
</s:form>
struts.xml configuration:
<action name="register" class="RegistrationAction">
<interceptor-ref name="token"/>
<interceptor-ref name="basicStack"/>
<result name="success">/success.jsp</result>
<result name="input">/register.jsp</result>
<result name="invalid.token">/duplicate.jsp</result>
</action>
If the user refreshes after submission, the token becomes invalid, and the request is routed to invalid.token.
Creating a Custom Interceptor
To build a custom interceptor, extend AbstractInterceptor and override the intercept() method. The init() and destroy() methods support lifecycle management.
Example: Session-based authentication interceptor
public class AuthInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
Map<String, Object> session = invocation.getInvocationContext().getSession();
if (session.get("user") == null) {
return "notLoggedIn";
}
return invocation.invoke(); // proceed to action
}
}
struts.xml setup:
<package name="secured" extends="struts-default">
<interceptors>
<interceptor name="auth" class="AuthInterceptor"/>
<interceptor-stack name="secureStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="auth"/>
</interceptor-stack>
</interceptors>
<global-results>
<result name="notLoggedIn">/login-required.jsp</result>
</global-results>
<action name="dashboard" class="DashboardAction">
<interceptor-ref name="secureStack"/>
<result>/dashboard.jsp</result>
</action>
</package>
Interceptors vs. Servlet Filters
- Execution model: Filters use callback (
doFilter); interceptors use Java reflection and the action invocation chain. - Container dependency: Filters require a servlet container; interceptors are framework-managed and container-agnostic.
- Scope: Filters can protect any resource (HTML, images, etc.) via URL patterns; interceptors only apply to Struts2 actions.
- Context access: Interceptors can access the value stack, action context, and OGNL expressions; filters cannot.
- Lifecycel: A filter’s
init()runs once at deployment; interceptors can be instantiated per request or reused, withinit()/destroy()called per instance lifecycle. - Flexibility: Interceptor stacks allow fine-grained composition per action; filters apply globally based on URL mappings.