struts2 の interceptor とは何か(構築方法含む)
struts2 v2.3.28
実行環境: Mac OSX EI Capitan 10.11.4
interceptor とは何か
action ごと(リクエストごと)に、共通化された前処理を実行したい時がある
(主な例: action 実行前の logging)
この「actionごとの、前処理実行」を実現する手段が interceptor
構築方法
前提環境
projectSpace | ├── pom.xml └── src └── main ├── java │ └── jp │ └── ymatsukawa │ ├── interceptors │ │ └── Logger.java │ └── top │ └── Index.java ├── resources │ └── struts.xml └── webapp ├── WEB-INF │ └── web.xml └── index.jsp
pom.xml
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>jp.ymatsukawa</groupId>
<artifactId>baseStruts</artifactId>
<name>Struts2Base</name>
<description>Struts 2 Base application</description>
<version>0.0.1</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.24.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>
<build>
<finalName>basic-struts</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.7.v20160115</version>
<configuration>
<stopKey>CTRL+C</stopKey>
<stopPort>8999</stopPort>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
</plugin>
</plugins>
</build>
</project>
src/main/webapp/WEB-INF/web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<webapp>
<display-name>Struts 2 Web Application</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</webapp>
src/main/webapp/index.jsp
<h1>Hello world</h1>
src/main/java/main/jp/ymatsukawa/top/Index.java
package jp.ymatsukawa.top;
import com.opensymphony.xwork2.ActionSupport;
public class Index extends ActionSupport {
public String execute() {
return SUCCESS;
}
}
interceptors の構築方法
src/main/resources/struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.ui.theme" value="simple" />
<package name="top" extends="struts-default">
<interceptors>
<interceptor name="myLog" class="jp.ymatsukawa.interceptors.Logger" />
</interceptors>
<action name="index" class="jp.ymatsukawa.top.Index">
<interceptor-ref name="myLog" />
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
package.interceptors と package.interceptors.interceptor について
package 下に interceptors を定義
interceptors 下に interceptor を定義
| (interceptor 属性) | name | class |
|---|---|---|
| - | 必須 一意な識別子 |
必須 interceptor のロジックが定義された Java クラス パッケージ名も指定 |
interceptor を実行する action について
action.interceptor-ref の name 属性に、実行したい interceptor を
package.interceptors.interceptor#name の値を割当
(複数の interceptor を action に割当てる場合は
interceptor-ref を複数 action 下で定義する
ただし、interceptor は上から順に実行される
下の例だと myLogger, myTest の順 )
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.ui.theme" value="simple" />
<package name="top" extends="struts-default">
<interceptors>
<interceptor name="myLog" class="jp.ymatsukawa.interceptors.Logger" />
</interceptors>
<action name="index" class="jp.ymatsukawa.top.Index">
<interceptor-ref name="myLog" />
<interceptor-ref name="myTest" />
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
src/main/java/jp/ymatsukawa/interceptors/Logger.java
package jp.ymatsukawa.interceptors;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.Action;
public class Logger extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("[myLogger:logged] foo"); // think this as logging logic
return invocation.invoke();
}
}
実行
console
$ mvn jetty:run # when got request from browser # GET /top/index.action [myLogger:logged] foo # interception # and <h1>Hello world</h1> is rendered by jsp # after interception
他註記
- interception が実行されるのは action の result が call された後
- result が call される前に interception を実行したい時は
PreResultListenerを使う
- result が call される前に interception を実行したい時は
- interceptor はスレッドセーフであるべき
- Struts2 の action は全てスレッドセーフである必要がない
- interceptor は 全 action 間で共有される
- 従って interceptor はスレッドセーフでなければいけない
余談
interception での「後片付け」処理
src/main/java/jp/ymatsukawa/interceptors/Logger.java
本モジュール以外は上記掲載通りとする
package jp.ymatsukawa.interceptors;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.Action;
public class Logger extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
try {
System.out.println("[myLogger:logged] foo"); // think this as logging logic
return invocation.invoke();
} catch(Exception e) {
System.out.println("[myLogger:logged... error]");
return Action.ERROR;
}
}
}
(interception 実行時 Exception が throw された時
catch 句が実行される
トランザクション後処理などに使えそう)
[参考元]
https://struts.apache.org/docs/writing-interceptors.html