struts 中的正常操作 class 与此模式有何区别?

What the difference between a normal action class in struts and this patern?

我正在开发一个项目,该项目使用两个动作 class,一个从另一个扩展,并且具有相同的方法实现(因此没有覆盖)。 一个动作 class 和 returns 一个 ActionForward 与 execute 方法有什么区别:

package com.mkyong.common.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.mkyong.common.form.HelloWorldForm;

    public class HelloWorldAction extends Action{

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

            HelloWorldForm helloWorldForm = (HelloWorldForm) form;
            helloWorldForm.setMessage("Hello World! Struts");

            return mapping.findForward("success");
        }

    }

第二个逻辑:

SuggestCommentAction.java :

package org.dlese.dpc.suggest.action;

import org.dlese.dpc.suggest.SuggestUtils;
import org.dlese.dpc.suggest.comment.*;
import org.dlese.dpc.suggest.resource.urlcheck.*;
import org.dlese.dpc.suggest.action.form.SuggestCommentForm;
import org.dlese.dpc.xml.schema.*;
import org.dlese.dpc.xml.*;
import org.dlese.dpc.util.strings.FindAndReplace;
import org.dlese.dpc.vocab.MetadataVocab;

import java.util.*;
import java.io.*;
import java.net.*;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;


/**
 *  * Action controller for the Suggest a Comment servlet.

 * @version    $Id: SuggestCommentAction.java,
 */
public final class SuggestCommentAction extends SuggestAction {

    private static boolean debug = true;

    private SuggestCommentHelper suggestHelper = null;

    /**
     *  Gets the SuggestCommentHelper attribute of the SuggestCommentAction
     *  object
     *
     * @return                       The SuggestCommentHelper value
     * @exception  ServletException  NOT YET DOCUMENTED
     */
    protected SuggestCommentHelper getSuggestHelper () throws ServletException {
        if (suggestHelper == null) {
            try {
                suggestHelper = (SuggestCommentHelper) servlet.getServletContext().getAttribute("SuggestCommentHelper");
                if (suggestHelper == null)
                    throw new Exception ();
            } catch (Throwable t) {
                throw new ServletException ("SuggestCommentHelper is not initialized");
            }
        }
        return suggestHelper;
    }

    protected ActionForward initializeSuggestor(
                                                ActionMapping mapping,
                                                ActionForm form,
                                                HttpServletRequest request,
                                                HttpServletResponse response)
         throws ServletException {

        SuggestCommentForm scf = (SuggestCommentForm) form;
        ActionErrors errors = new ActionErrors();

        String id = request.getParameter("id");
        if (id == null || id.trim().length() == 0) {
            errors.add("error",
                new ActionError("comment.id.required"));
            saveErrors(request, errors);
            return mapping.findForward("home");
        }

        scf.clear();

        scf.setPopup("p".equals( request.getParameter("view")));
        scf.setItemID(id);

        // ensure the provided record id (itemID) corresponds to an existing record
        String itemTitle = null;
        String itemURL = null;
        try {
            Map itemRecordProps = this.getSuggestHelper().getItemRecordProps(id);
            scf.setItemURL ((String)itemRecordProps.get ("url"));
            scf.setItemTitle((String)itemRecordProps.get ("title"));
        } catch (Exception e) {
            errors.add("error",
                new ActionError("comment.resource.not.found", id));
            saveErrors(request, errors);
            return mapping.findForward("home");
        }

        saveMessages(request, errors);
        return mapping.findForward("form");

     }


    // ------------ Command Handlers ----------------------------------
    protected ActionForward handleOtherCommands(
                                                ActionMapping mapping,
                                                ActionForm form,
                                                HttpServletRequest request,
                                                HttpServletResponse response) throws ServletException {

        SuggestCommentForm scf = (SuggestCommentForm) form;
        ActionErrors errors = new ActionErrors();

        String command = request.getParameter("command");
        prtln("command: " + command);

        throw new ServletException("unsupported command: " + command);
    }


    protected ActionForward handleEditCommand(
                                              ActionMapping mapping,
                                              ActionForm form,
                                              HttpServletRequest request,
                                              HttpServletResponse response)
                                              throws Exception {


        SuggestCommentForm scf = (SuggestCommentForm) form;

        if (scf.getItemID() == null || scf.getItemID().length() == 0 ) {            
            prtln("can't edit without a id ... bailing");
            return handleStaleData(mapping, form, request);
        }


        return mapping.findForward("form");
    }


    protected ActionForward handleCancelCommand(
                                                ActionMapping mapping,
                                                ActionForm form,
                                                HttpServletRequest request,
                                                HttpServletResponse response) {

        SuggestCommentForm scf = (SuggestCommentForm) form;
        ActionErrors errors = new ActionErrors();

        scf.clear();
        scf.setItemID("");

        errors.add(ActionMessages.GLOBAL_MESSAGE,
            new ActionMessage("comment.cancel"));
        saveMessages(request, errors);
        return mapping.findForward("home");
    }



    protected ActionForward handleDoneCommand(
                                              ActionMapping mapping,
                                              ActionForm form,
                                              HttpServletRequest request,
                                              HttpServletResponse response) {

        SuggestCommentForm scf = (SuggestCommentForm) form;
        ActionErrors errors = new ActionErrors();

        // make sure there is a value for URL. If the user has previously "cancelled" and then
        // used the back buttons to return to an old form that *looks* like it holds data, but really
        // the data has been lost to the app upon cancellation
        if (scf.getItemID() == null || scf.getItemID().length() == 0) {
            prtln("can't get to done without a itemID ... bailing");
            return handleStaleData(mapping, form, request);
        }

        // Validate
        errors = validateSuggestForm(form, mapping, request);

        // report errors
        if (!errors.isEmpty()) {
            saveErrors(request, errors);
            return mapping.findForward("form");
        }

        return mapping.findForward("confirm");
    }



    protected ActionForward handleSubmitCommand(
                                                ActionMapping mapping,
                                                ActionForm form,
                                                HttpServletRequest request,
                                                HttpServletResponse response) {

        SuggestCommentForm scf = (SuggestCommentForm) form;

        // make sure there is a value for URL. If the user has previously "cancelled" and then
        // used the back buttons to return to an old form that *looks* like it holds data, but really
        // the data has been lost to the app upon cancellation
        if (scf.getItemID() == null || scf.getItemID().length() == 0) {
            prtln("can't submit without a url ... bailing");
            return handleStaleData(mapping, form, request);
        }

        ActionMessages actionMessages = new ActionMessages();
        CommentRecord rec = null;
        try {
            rec = createRecord(scf);
        } catch (Exception e) {
            System.out.println("createRecord() failed to set values\n" + e);
            e.printStackTrace();
        }

        // putRecord to DCS
        String newId = null;
        try {
            newId = this.getSuggestHelper().putRecordToDCS(rec);
        } catch (Throwable e) {
            prtln("putRecord error: " + e.getMessage());
        }

        boolean notificationSent = false;
        try {
            new CommentEmailer(newId, this.getSuggestHelper()).sendNotification(scf);
        } catch (Exception e) {
            prtlnErr ("Email error: " + e.getMessage());
        }
        if (!notificationSent) {
            prtln("Notification NOT sent!");
        }
        else {
            prtln("Notification sent");
        }

        scf.clear();
        actionMessages.add(ActionMessages.GLOBAL_MESSAGE,
            new ActionMessage("comment.confirmation"));
        saveMessages(request, actionMessages);
        return mapping.findForward("home");
    }


    /**
     *  The required fields for suggest-a-url are: url, nameFirst, nameLast,
     *  emailPrimary, instName
     *
     * @param  mapping       Description of the Parameter
     * @param  request       Description of the Parameter
     * @param  form          NOT YET DOCUMENTED
     * @return               Description of the Return Value
     */
    protected ActionErrors validateSuggestForm(ActionForm form,
                                               ActionMapping mapping,
                                               HttpServletRequest request) {

        SuggestCommentForm scf = (SuggestCommentForm) form;
        ActionErrors errors = new ActionErrors();

        String description = scf.getDescription();
        String role = scf.getRole();
        String share = scf.getShare();
        String nameFirst = scf.getNameFirst();
        String nameLast = scf.getNameLast();
        String email = scf.getEmail();
        String instName = scf.getInstName();
        Boolean coppa = scf.getCoppa();

        if ((description == null) || (description.trim().equals(""))) {
            errors.add("description", new ActionError("field.required", "Comment"));
        }

        if ((role == null) || (role.trim().equals(""))) {
            errors.add("role", new ActionError("field.required", "Role"));
        }

        if ((share == null) || (share.trim().equals(""))) {
            errors.add("share", new ActionError("this.field.required", "Share"));
        }   

        if ((nameFirst == null) || (nameFirst.trim().equals(""))) {
            errors.add("nameFirst", new ActionError("field.required", "First Name"));
        }

        if ((nameLast == null) || (nameLast.trim().equals(""))) {
            errors.add("nameLast", new ActionError("field.required", "Last Name"));
        }

        if (!coppa) {
            errors.add("coppa", new ActionError("this.field.required"));
        }

        if ((instName == null) || (instName.trim().equals(""))) {
            errors.add("instName", new ActionError("field.required.an", "Institution or Affiliation"));;
        }

        if ((email == null) || (email.trim().equals(""))) {
            errors.add("email", new ActionError("field.required.an", "Email Address"));
        }
        else {
            try {
                SuggestUtils.validateEmail (email);
            } catch (Exception e) {
                errors.add("email",
                    new ActionError("generic.error", e.getMessage()));
            }
        }

        return errors;
    }


    /**
     *  Update the SuggestionRecord (managed by SuggestCommentHelper) with values
     *  from the form bean.<P>
     *
     * @param  form           NOT YET DOCUMENTED
     * @exception  Exception  Description of the Exception
     */
    protected CommentRecord createRecord(ActionForm form)
         throws Exception {

        SuggestCommentForm scf = (SuggestCommentForm) form;
        CommentRecord rec = this.getSuggestHelper().newRecord();

        if (rec == null) {
            throw new Exception("createRecord could not get a record from SuggestCommentForm");
        }

        rec.setTitle("Comment on " + scf.getItemTitle());
        rec.setItemID(scf.getItemID());
        rec.setDescription(scf.getDescription());
        rec.setRole(scf.getRole());
        rec.setShare(scf.getShare());
        rec.setNameFirst(scf.getNameFirst());
        rec.setNameLast(scf.getNameLast());
        rec.setEmail(scf.getEmail());
        rec.setInstName(scf.getInstName());
        rec.setCreationDate(SuggestUtils.getBriefDate());

        return rec;
    }


    /**
     *  Sets the debug attribute of the SuggestCommentAction class
     *
     * @param  db  The new debug value
     */
    public static void setDebug(boolean db) {
        debug = db;
    }


    /**
     *  Print a line to standard out.
     */
    private static void prtln(String s) {
        if (debug) {
            org.dlese.dpc.schemedit.SchemEditUtils.prtln(s, "SuggestCommentAction");
        }
    }


    private static void prtlnErr(String s) {
        org.dlese.dpc.schemedit.SchemEditUtils.prtln(s, "SuggestCommentAction");
    }

}

SuggestAction.java

package org.dlese.dpc.suggest.action;

import org.dlese.dpc.suggest.*;
import org.dlese.dpc.suggest.action.form.SuggestForm;
import org.dlese.dpc.xml.schema.*;
import org.dlese.dpc.xml.*;
import org.dlese.dpc.vocab.MetadataVocab;

import java.util.*;
import java.io.*;
import java.net.*;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;

/**
 *  Abstract controller for a Suggestor Client. Implements the following flow of
 *  control:
 *  <ol>
 *    <li> Presents form for user input
 *    <li> Validates input. if there are errors returns user to form, otherwise
 *    presents confirmation page.
 *    <li> User can elect to re-edit the form, or "submit" it.
 *    <li> confirmation page is displayed upon submission
 *  </ol>
 */
public abstract class SuggestAction extends Action {

    private static boolean debug = true;


    /**
     *  Gets the suggestHelper attribute of the SuggestAction object
     *
     * @return                       The suggestHelper value
     * @exception  ServletException  NOT YET DOCUMENTED
     */
    protected abstract SuggestHelper getSuggestHelper() throws ServletException;


    /**
     *  Gets the schemaHelper attribute of the SuggestAction object
     *
     * @return    The schemaHelper value
     */
    protected SchemaHelper getSchemaHelper() {
        try {
            return getSuggestHelper().getSchemaHelper();
        } catch (Exception e) {}
        return null;
    }

    // --------------------------------------------------------- Public Methods

    /**
     *  Processes the specified HTTP request and creates the corresponding HTTP
     *  response by forwarding to a JSP that will create it. Returns an {@link
     *  org.apache.struts.action.ActionForward} instance that maps to the Struts
     *  forwarding name "xxx.xxx," which must be configured in struts-config.xml to
     *  forward to the JSP page that will handle the request.
     *
     * @param  mapping               Description of the Parameter
     * @param  form                  Description of the Parameter
     * @param  request               Description of the Parameter
     * @param  response              Description of the Parameter
     * @return                       Description of the Return Value
     * @exception  IOException       Description of the Exception
     * @exception  ServletException  Description of the Exception
     */
    public ActionForward execute(
                                 ActionMapping mapping,
                                 ActionForm form,
                                 HttpServletRequest request,
                                 HttpServletResponse response)
         throws IOException, ServletException {
        /*
            Design note:
            Only one instance of this class gets created for the app and shared by
            all threads. To be thread-safe, use only local variables, not instance
            variables (the JVM will handle these properly using the stack). Pass
            all variables via method signatures rather than instance vars.
          */
        SuggestForm sform = (SuggestForm) form;

        SchemaHelper schemaHelper = getSchemaHelper();

        sform.setSchemaHelper(schemaHelper);

        MetadataVocab vocab = (MetadataVocab) servlet.getServletContext().getAttribute("MetadataVocab");
        sform.setVocab(vocab);

        ActionErrors errors = new ActionErrors();
        ActionMessages actionMessages = new ActionMessages();

        // Query Args
        String command = request.getParameter("command");
        // prtln("\ncommand: " + command + "\n");

        org.dlese.dpc.schemedit.SchemEditUtils.showRequestParameters(request); 

        // HANDLE COMMAND
        try {
            if (command == null) {
                // return handleCancelCommand(mapping, form, request, response);
                return initializeSuggestor(mapping, form, request, response);
            }

            // NEW - present simple form to get (and validate) URL
            if (command.equalsIgnoreCase("cancel")) {
                return handleCancelCommand(mapping, form, request, response);
            }

            // EDIT - read record and present form for editing
            if (command.equalsIgnoreCase("edit")) {
                return handleEditCommand(mapping, form, request, response);
            }

            // SUBMIT - user has confirmed data - now write it to disk
            // data is valid at this point and the user has hit the submit button
            if (command.equalsIgnoreCase("submit")) {
                return handleSubmitCommand(mapping, form, request, response);
            }

            // DONE - validate data and present confirmation page to user
            if (command.equalsIgnoreCase("done")) {
                return handleDoneCommand(mapping, form, request, response);
            }

            return handleOtherCommands(mapping, form, request, response);
        } catch (Exception e) {
            prtlnErr("ERROR: " + e.getMessage());
            e.printStackTrace();
            actionMessages.add(ActionMessages.GLOBAL_MESSAGE,
                new ActionMessage("generic.error", "Server Error: " + e.getMessage()));
        } catch (Throwable t) {
            prtlnErr("UNKNOWN ERROR: " + t.getMessage());
            actionMessages.add(ActionMessages.GLOBAL_MESSAGE,
                new ActionMessage("generic.error", "Unknown Server Error"));
        }
        saveMessages(request, actionMessages);
        return mapping.findForward("home");
    }

    protected abstract ActionForward initializeSuggestor(
                                                         ActionMapping mapping,
                                                         ActionForm form,
                                                         HttpServletRequest request,
                                                         HttpServletResponse response) throws ServletException;


    /**
     *  Hook for subclasses to handle commands that are outside the ones defined in
     *  this class.
    */
    protected ActionForward handleOtherCommands(
                                                ActionMapping mapping,
                                                ActionForm form,
                                                HttpServletRequest request,
                                                HttpServletResponse response) throws ServletException {

        String command = request.getParameter("command");
        prtln("command: " + command);

        throw new ServletException("unsupported command: " + command);
    }

    /**
     *  Populate SuggestionForm, and forward user to edit-form.
     * @exception  Exception  if SuggestionForm cannot be populated with required
     *      info.
     */
    protected abstract ActionForward handleEditCommand(
                                                       ActionMapping mapping,
                                                       ActionForm form,
                                                       HttpServletRequest request,
                                                       HttpServletResponse response)
         throws Exception;

    protected abstract ActionForward handleCancelCommand(
                                                         ActionMapping mapping,
                                                         ActionForm form,
                                                         HttpServletRequest request,
                                                         HttpServletResponse response);


    /**
     *  Validate information supplied by user, return to edit form if there are
     *  errors, or display confirmation page if there are no errors.

     */
    protected abstract ActionForward handleDoneCommand(
                                                       ActionMapping mapping,
                                                       ActionForm form,
                                                       HttpServletRequest request,
                                                       HttpServletResponse response);


    /**
     *  Attempt to write the suggestion to a DCS instance, forward user to
     *  confirmation page.
     */
    protected abstract ActionForward handleSubmitCommand(
                                                         ActionMapping mapping,
                                                         ActionForm form,
                                                         HttpServletRequest request,
                                                         HttpServletResponse response);


    /**
     *  Return user to suggestor front page and show message explaining that they
     *  were apparently trying to edit or submit data from a cancelled form
     *
     * @param  mapping  Description of the Parameter
     * @param  request  Description of the Parameter
     * @param  form     NOT YET DOCUMENTED
     * @return          Description of the Return Value
     */
    protected ActionForward handleStaleData(
                                            ActionMapping mapping,
                                            ActionForm form,
                                            HttpServletRequest request) {
        SuggestForm sForm = (SuggestForm) form;
        sForm.clear();

        prtln("handleStaleData");
        ActionMessages actionMessages = new ActionMessages();
        actionMessages.add(ActionMessages.GLOBAL_MESSAGE,
            new ActionMessage("stale.data"));
        saveMessages(request, actionMessages);
        return mapping.findForward("home");
    }


    /**
     *  The required fields for suggest-a-url are: url, nameFirst, nameLast,
     *  emailPrimary, instName
     *
     * @param  mapping  Description of the Parameter
     * @param  request  Description of the Parameter
     * @param  form     NOT YET DOCUMENTED
     * @return          Description of the Return Value
     */
    protected abstract ActionErrors validateSuggestForm(ActionForm form,
                                                        ActionMapping mapping,
                                                        HttpServletRequest request);


    /**
     *  Update the SuggestionRecord (managed by SuggestResourceHelper) with values
     *  from the form bean
     *
     * @param  form           NOT YET DOCUMENTED
     * @exception  Exception  Description of the Exception
     */
    protected abstract SuggestionRecord createRecord(ActionForm form) throws Exception;


    /**
     *  Sets the debug attribute of the SuggestAction class
     *
     * @param  db  The new debug value
     */
    public static void setDebug(boolean db) {
        debug = db;
    }


    /**
     *  Print a line to standard out.
     *
     * @param  s  The String to print.
     */
    private static void prtln(String s) {
        if (debug) {
            org.dlese.dpc.schemedit.SchemEditUtils.prtln(s, "SuggestAction");
        }
    }

    private static void prtlnErr(String s) {
        org.dlese.dpc.schemedit.SchemEditUtils.prtln(s, "SuggestAction");
    }

}

抽象基础 class 是一个 classic 命令模式处理程序:

String command = request.getParameter("command");

这决定了执行哪个命令运行。因此,无论是在表单还是 URL 中,通常应该 always/will 是一个 command 来确定流程的其余部分。

默认命令是 canceleditsubmitdone,但实施 classes 可能会通过 handleOtherCommands 函数,在默认实现中抛出错误。

*请注意,在 SuggestCommentAction 中提供了一个无用的实现,该实现执行基础 class 已经执行的操作。

每个实现都应该实现 initializeSuggestor 功能。如果提供 none,此处的实现会提前检查 ID 和 returns。剩下的就是家务;确定它是否显示在弹出窗口中(view 参数),尝试查找记录,并 returns 适当的转发。

editcanceldonesubmitabstract 在基础 class 中,或多或少做你想做的期望:他们执行数据库操作并将视图路由到为 SuggestCommentAction.

定义的任何内容

每个实现都应提供处理特定表单验证要求的验证函数。

每个实现都应提供一个 createRecord 函数返回 SuggestionRecord 的实现,在本例中为 CommentRecord。这在很大程度上只是将表单数据编组到域对象中。 (请注意,有些库会自动执行此操作,但如果正在进行大量转换,则并不总是合适的。)

TL;DR:

这是一种为不同域对象委派基本 CRUD 操作的机制,其中每个域对象将由 SuggestAction.

的实现表示

这很可能(很有可能)是相当旧的代码:它打破了我认为是很多功能边界的东西,例如,它依赖于 Struts 1-specific functionality in each执行。在 S1 时代,这相当普遍,因为 S1 的架构和预期使用方式。