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