我正在开发一个项目,它使用一个两个动作类,一个从另一个扩展而且具有相同的方法实现(因此没有重写)。 返回一个ActionForward的action类与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");
}
}
答案 0 :(得分:0)
The abstract base class is a classic command pattern handler:
String command = request.getParameter("command");
This determines which command is being run. So either in the form or the URL there should always/will usually be a command
that determines the rest of the flow.
The default commands are cancel
, edit
, submit
, and done
, but implementing classes may provide additional commands via the handleOtherCommands
function, which throws an error in the default implementation.
*Note that in the SuggestCommentAction
provided there is a useless implementation that does what the base class already does.
Each implementation is supposed to implement the initializeSuggestor
function. The implementation here checks for an ID and returns early if none is provided. The rest is housekeeping; determining if it's being displayed in a popup (the view
parameter), tries to find the record, and returns an appropriate forward.
edit
, cancel
, done
, and submit
, abstract
in the base class, do more or less what you'd expect: they perform either DB actions and route the view to whatever is defined for the SuggestCommentAction
.
Each implementation is expected to provide a validation function that handles specific forms' validation requirements.
Each implementation is expected to provide a createRecord
function returning an implementation of SuggestionRecord
, in this case, a CommentRecord
. This is largely just marshalling form data into a domain object. (Noting that there are libraries that do this automatically, but are not always appropriate if there are a lot of transformations going on.)
TL;DR:
It's a mechanism for delegating basic CRUD operations for different domain objects, where each domain object would be represented by an implementation of SuggestAction
.
It is likely (more than likely) that this is fairly old code: it breaks what I would consider to be a lot of functional boundaries, e.g., it relies on Struts 1-specific functionality in each implementation. During the S1 days this was fairly commonplace because of how S1 was architected and expected to be used.