Какая разница между нормальным классом действий в стойках и этим паттерном? - PullRequest
0 голосов
/ 03 июня 2018

Я работаю над проектом, в котором используется класс двух действий, один из которых расширяется от другого, и который имеет одинаковую реализацию методов (поэтому переопределения не существует).Какая разница между классом действия, который возвращает один 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");
    }

}

1 Ответ

0 голосов
/ 04 июня 2018

Абстрактный базовый класс является классическим обработчиком шаблонов команд:

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

Определяет, какая команда выполняется.Таким образом, либо в форме, либо в URL-адресе всегда / всегда должен быть command, определяющий остальную часть потока.

По умолчанию используются команды cancel, edit, submit иdone, но реализующие классы могут предоставлять дополнительные команды через функцию handleOtherCommands, которая выдает ошибку в реализации по умолчанию.

* Обратите внимание, что в предоставленном SuggestCommentAction есть бесполезная реализация, которая делает то, чтобазовый класс уже делает.

Каждая реализация должна реализовывать функцию initializeSuggestor.Реализация здесь проверяет идентификатор и возвращает рано, если ничего не указано.Остальное ведение домашнего хозяйства;определяет, отображается ли оно во всплывающем окне (параметр view), пытается найти запись и возвращает соответствующий форвард.

edit, cancel, done и submit, abstract в базовом классе, делать более или менее то, что вы ожидаете: они выполняют либо действия с БД, и направляют представление к тому, что определено для SuggestCommentAction.

Каждая реализация должна обеспечиватьфункция проверки, которая обрабатывает определенные требования проверки форм.

Ожидается, что каждая реализация предоставит функцию createRecord, возвращающую реализацию SuggestionRecord, в данном случае CommentRecord.Это в основном просто объединение данных формы в объект домена.(Отметим, что есть библиотеки, которые делают это автоматически, но не всегда подходят, если происходит много преобразований.)

TL; DR:

Этомеханизм для делегирования базовых операций CRUD для различных объектов домена, где каждый объект домена будет представлен реализацией SuggestAction.

Вероятно (более чем вероятно), что это довольно старый код: он ломаетсято, что я бы назвал множеством функциональных границ, например, оно опирается на специфическую функциональность Struts 1 в каждой реализации.В дни S1 это было довольно распространенным явлением из-за того, как S1 был спроектирован и предполагалось использовать.

...