この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:guest
更新日時:2026-06-11 07:12:00

タイトル: Action
SEOタイトル: Struts 1 の Action クラス完全解説 (execute / ActionForm / forward)

この記事の要点
  • Struts 1 の Actionexecute(ActionMapping, ActionForm, request, response) で 1 メソッド 1 機能
  • 戻り値は ActionForwardstruts-config.xml<forward> 名で遷移先を解決
  • 複数機能を 1 クラスに → DispatchAction / LookupDispatchAction
  • Struts 1 は 2013 年 EOL。新規開発は Spring MVC @Controller / @RestController に移行
  • Action から Spring への移行は段階的に: DelegatingActionProxy で DI 注入 → 機能単位で @Controller

Struts 1 Action の基本形

public class LoginAction extends Action {

    @Override
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        // 1. ActionForm をキャスト
        LoginForm loginForm = (LoginForm) form;
        String userId = loginForm.getUserId();
        String pass   = loginForm.getPassword();

        // 2. 業務ロジック
        UserService svc = new UserService();
        User user = svc.authenticate(userId, pass);

        if (user == null) {
            ActionMessages errors = new ActionMessages();
            errors.add(&quot;login&quot;, new ActionMessage(&quot;error.login.failed&quot;));
            saveErrors(request, errors);
            return mapping.findForward(&quot;failure&quot;);
        }

        // 3. セッション格納
        request.getSession().setAttribute(&quot;loginUser&quot;, user);

        // 4. 遷移先を返す
        return mapping.findForward(&quot;success&quot;);
    }
}

struts-config.xml の設定

<?xml version="1.0" encoding="UTF-8"?>
<struts-config>

    <!-- form bean 定義 -->
    <form-beans>
        <form-bean name="loginForm" type="com.example.LoginForm"/>
    </form-beans>

    <!-- action 定義 -->
    <action-mappings>
        <action path="/login"
                type="com.example.LoginAction"
                name="loginForm"
                scope="request"
                validate="true"
                input="/WEB-INF/jsp/login.jsp">
            <forward name="success" path="/WEB-INF/jsp/home.jsp"/>
            <forward name="failure" path="/WEB-INF/jsp/login.jsp"/>
        </action>
    </action-mappings>

</struts-config>

ActionForm

public class LoginForm extends ActionForm {
    private String userId;
    private String password;

    public String getUserId() { return userId; }
    public void setUserId(String v) { this.userId = v; }
    public String getPassword() { return password; }
    public void setPassword(String v) { this.password = v; }

    @Override
    public ActionErrors validate(ActionMapping mapping, HttpServletRequest req) {
        ActionErrors errors = new ActionErrors();
        if (userId == null || userId.isEmpty()) {
            errors.add("userId", new ActionMessage("error.required.userid"));
        }
        if (password == null || password.length() < 8) {
            errors.add("password", new ActionMessage("error.password.length"));
        }
        return errors;
    }

    @Override
    public void reset(ActionMapping mapping, HttpServletRequest req) {
        this.userId = null;
        this.password = null;
    }
}

JSP 側

<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>

<html:form action="/login">
    ユーザーID: <html:text property="userId"/><br/>
    <html:errors property="userId"/><br/>

    パスワード: <html:password property="password"/><br/>
    <html:errors property="password"/><br/>

    <html:submit value="ログイン"/>
</html:form>

DispatchAction(1 Action 複数メソッド)

機能ごとに Action クラスを作ると膨大になるため、DispatchAction で 1 クラスに複数機能を集約:

public class UserAction extends DispatchAction {

    public ActionForward list(ActionMapping mapping, ActionForm form,
            HttpServletRequest req, HttpServletResponse res) throws Exception {
        req.setAttribute(&quot;users&quot;, new UserService().findAll());
        return mapping.findForward(&quot;list&quot;);
    }

    public ActionForward show(ActionMapping mapping, ActionForm form,
            HttpServletRequest req, HttpServletResponse res) throws Exception {
        long id = Long.parseLong(req.getParameter(&quot;id&quot;));
        req.setAttribute(&quot;user&quot;, new UserService().findById(id));
        return mapping.findForward(&quot;detail&quot;);
    }

    public ActionForward delete(ActionMapping mapping, ActionForm form,
            HttpServletRequest req, HttpServletResponse res) throws Exception {
        // ...
        return mapping.findForward(&quot;list&quot;);
    }
}
<!-- struts-config.xml: parameter で method を切り替え -->
<action path="/user"
        type="com.example.UserAction"
        parameter="method"
        scope="request">
    <forward name="list"   path="/WEB-INF/jsp/user/list.jsp"/>
    <forward name="detail" path="/WEB-INF/jsp/user/detail.jsp"/>
</action>

<!-- 呼び出し: /user.do?method=list / /user.do?method=show&id=1 -->

Action Chain (forward の連鎖)

1 Action の結果を別の Action に流す:

<action path="/login" type="com.example.LoginAction">
    <!-- 成功時に /home に forward (chain) -->
    <forward name="success" path="/home.do" redirect="false"/>
</action>

<action path="/home" type="com.example.HomeAction">
    <forward name="default" path="/WEB-INF/jsp/home.jsp"/>
</action>

注意: Action Chain は Struts 1.x で多用されたが、デバッグが困難でアンチパターン扱い。共通ロジックはサービス層 (Service) に切り出すのが正解。

Spring MVC への移行

Struts 1 は 2013 年 4 月にサポート終了。CVE が積み上がっているため、現役の Web アプリは Spring MVC への移行が必須:

// Struts 1 → Spring MVC
@Controller
@RequestMapping(&quot;/user&quot;)
public class UserController {

    @Autowired
    private UserService userService;  // DI で注入

    @GetMapping
    public String list(Model model) {
        model.addAttribute(&quot;users&quot;, userService.findAll());
        return &quot;user/list&quot;;   // → /WEB-INF/jsp/user/list.jsp
    }

    @GetMapping(&quot;/{id}&quot;)
    public String show(@PathVariable Long id, Model model) {
        model.addAttribute(&quot;user&quot;, userService.findById(id));
        return &quot;user/detail&quot;;
    }

    @PostMapping(&quot;/save&quot;)
    public String save(@Valid @ModelAttribute UserForm form,
                       BindingResult result,
                       RedirectAttributes ra) {
        if (result.hasErrors()) return &quot;user/edit&quot;;
        userService.save(form);
        ra.addFlashAttribute(&quot;msg&quot;, &quot;保存しました&quot;);
        return &quot;redirect:/user&quot;;
    }
}

Struts 1 vs Spring MVC

項目Struts 1Spring MVC
サポート2013/04 EOL継続中
設定struts-config.xmlアノテーション
FormActionForm (継承必須)POJO + @ModelAttribute
DIなし(手動 new)標準搭載
REST非対応(手作り)@RestController で標準対応
テスト困難 (ServletContainer 必須)MockMvc で容易

段階的移行: DelegatingActionProxy

一気に書き換えられない場合は Struts 1 + Spring の併用:

<!-- struts-config.xml: Action を DelegatingActionProxy 経由に -->
<action path="/login"
        type="org.springframework.web.struts.DelegatingActionProxy">
    <forward name="success" path="/WEB-INF/jsp/home.jsp"/>
</action>

<!-- applicationContext.xml: Bean として Action を定義 -->
<bean name="/login" class="com.example.LoginAction">
    <property name="userService" ref="userService"/>
</bean>

FAQ

Q: Struts 2 ではどうなる?
A: Struts 2 は別物(旧 WebWork)。Action は POJO で execute()String を返す形に。Struts 1 とは互換性なし。

Q: 既存の Struts 1 アプリはすぐ捨てるべき?
A: 公開系なら最優先。社内系でも段階的移行を計画。CVE-2014-0114 等の重大脆弱性あり。

Q: ActionServlet は何をしている?
A: Struts 1 の FrontController。web.xml*.do をマップし、URL から ActionMapping を解決して Action を呼ぶ。Spring MVC では DispatcherServlet がそれに相当。