Struts2をやってみる (12) - Spring Framework -

2013-09-23T00:00:00+00:00 Java Spring Framework Struts2

struts2-spring-pluginを使えばStruts2でSpring Frameworkを利用して依存性を注入したりも出来る

build.gradle

dependencies {
    compile "org.apache.struts:struts2-spring-plugin:2.3.15.2"
}

な設定しておく

Dependency Injection概要

package sample.service;

public interface SampleService {
    String say();
}

なインターフェースがあって

package sample.service;

public class SampleServiceImpl implements SampleService {
    public String say() {
        return "hoge fuga foobar";
    }
}

っていう実装がある。でアクションでは

package sample.action;

import java.io.IOException;
import java.io.PrintWriter;

import org.apache.struts2.ServletActionContext;

import sample.service.SampleService;

import com.opensymphony.xwork2.ActionSupport;

public class IndexAction extends ActionSupport {

    private static final long serialVersionUID = 1L;
    private SampleService service;

    @Override
    public String execute() throws IOException {
        PrintWriter out = ServletActionContext.getResponse().getWriter();
        out.print(service.say());
        out.flush();
        out.close();

        return NONE;
    }

    public void setService(SampleService service) {
        this.service = service;
    }
}

っていうようにセッターメソッドを定義するけど、どこでもそれを初期化するコードは無い。Spring Frameworkによってそれを注入する事で利用できるようになる

っていう感じな事をやる。

src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <!-- 追加 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <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>

</web-app>

んでapplicationContext.xmlも作る必要あり

src/main/webapp/WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="sampleService" class="sample.service.SampleServiceImpl" />

    <bean id="indexAction" class="sample.action.IndexAction">
        <!-- IndexAction.serviceなフィールドにsampleServiceな依存性参照を注入 -->
        <property name="service" ref="sampleService" />
    </bean>
</beans>

<bean id="">で定義する場合にidで指定した名前と同名なフィールドが存在する場合には勝手に依存性を注入される模様。で上記の場合だと

public class IndexAction extends ActionSupport {
    private SampleService service;
}

となっている。つまりこういう場合にはservice == sampleServlce = falseなわけになるので依存性は注入されない。で、<property>で注入するを指定したりとかも出来るのでそういう場合にはアクションを<bean>として定義しておく

ちなみにstruts.xmlでの<action>においてclass属性を<bean>で指定したidで指定する事も可能な模様

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <constant name="struts.devMode" value="true" />

    <package name="sample" extends="struts-default" namespace="/sample">

        <action name="index" class="indexAction" />

    </package>
</struts>

っていう感じでSpring Frameworkを使った依存性注入をStruts2で利用する事も出来るっていう事で

Struts2+Spring Frameworkを使ったテストに関して

Struts2+Spring Frameworkな環境上ではテストクラスが継承するクラスはStrutsTestCaseではなく、org.apache.struts2.StrutsSpringTestCaseを継承する模様

あと上記でapplicationContext.xmlをsrc/main/webapp/WEB-INF内に作成したけれども、これが無いとテストで依存性解決が出来ない模様なので、src/test/resourcesに入れておけば良い模様

package sample.action;

import org.apache.struts2.StrutsSpringTestCase;
import org.junit.Test;

import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionSupport;

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

public class IndexActionTestCase extends StrutsSpringTestCase {

    @Test
    public void test_execute() throws Exception {
        ActionProxy proxy = getActionProxy("/sample/index.action");
        assertThat(proxy.execute(), is(ActionSupport.NONE));
        assertThat(response.getContentAsString(), is("hoge fuga foobar"));
    }
}

っていう感じで。んまぁ http://struts.apache.org/release/2.3.x/docs/spring-plugin.html は一読しておくべきかと。テストな件に関しては http://struts.apache.org/release/2.3.x/docs/struts-2-junit-plugin-tutorial.html にもちょっとだけ書いてあるので...

Struts2をやってみる (11) - Interceptor - cat - な件