Understanding and Using Struts2 Interceptors

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, with init()/destroy() called per instance lifecycle.
  • Flexibility: Interceptor stacks allow fine-grained composition per action; filters apply globally based on URL mappings.

Tags: Struts2 interceptor aop JavaEE WebFramework

Posted on Fri, 14 Aug 2026 16:51:28 +0000 by mbeals