4.

Struts 1 の Action クラス完全解説 (execute / ActionForm / forward)

編集
この記事の要点
  • Struts 1 の Actionexecute(ActionMapping, ActionForm, request, response) で 1 メソッド 1 機能
  • 戻り値は ActionForwardstruts-config.xml 名で遷移先を解決
  • 複数機能を 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("login", new ActionMessage("error.login.failed"));
            saveErrors(request, errors);
            return mapping.findForward("failure");
        }

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

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

struts-config.xml の設定




    
    
        
    

    
    
        
            
            
        
    

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


    ユーザーID: 

パスワード:

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("users", new UserService().findAll());
        return mapping.findForward("list");
    }

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

    public ActionForward delete(ActionMapping mapping, ActionForm form,
            HttpServletRequest req, HttpServletResponse res) throws Exception {
        // ...
        return mapping.findForward("list");
    }
}


    
    


Action Chain (forward の連鎖)

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


    
    



    

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

Spring MVC への移行

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

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

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

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

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

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

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 の併用:



    




    

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 がそれに相当。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 導入方法
  2. struts-config.xmlの説明
  3. ActionForm
  4. Action
  5. エラー一覧
  6. JSP タグ
  7. カスタムタグ(tablib)