Struts源码分析1:org.apache.struts.action.Action

by sundy 8/7/2009 11:53:32 AM

前言:发现很多j2ee的程序员基础都差得不行 ,会用ssh的甚至都不知道为何要这样,以及如何设计的 。因此为大家简单的剖析一下Struts的设计 ,以资借鉴 。

actoin中的方法 大多是针对 Messages,Errors,token的一些操作。

package org.apache.struts.action;
import org.apache.struts.Globals;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.util.MessageResources;
import org.apache.struts.util.ModuleUtils;
import org.apache.struts.util.RequestUtils;
import org.apache.struts.util.TokenProcessor;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Locale;
/**
*  Action必须以线程安全的方式编写,
* 因为controller会为同时存在的多个request共享一个实例。
* 所以编写时要注意:
*
* 实例和static变量不能存储与具体request相关的信息。
*
*  存取受保护的JavaBeans, session 变量等资源时,必须使用同步(synchronized)。

*
*  当一个Action实例被第一次创建时,controller会用一个非空参数
*(标识这个servlet实例和附属他的Action)调用 setServlet 。
*   当实例被关闭时,setServlet会被再次调用,用一个null
*   参数来清空这个Action的信息
*          
*/
public class Action {
/**
     * org.apache.struts.util.TokenProcessor类:令牌产生器,用于防止事务重复提交 
*/
private static TokenProcessor token = TokenProcessor.getInstance();
// NOTE: We can make the token  variable protected and remove Action's
// token methods or leave it private and allow the token methods to
// delegate(委托) their calls.
// ----------------------------------------------------- Instance Variables
/**
     * Action附属的servlet。
*/
protected transient ActionServlet servlet = null;
// ------------------------------------------------------------- Properties
public ActionServlet getServlet() {
return (this.servlet);
    }
/**
     * 设置Action附属的servlet,或释放所有资源(servlet=null)       
     * @param servlet The new controller servlet, if any
*/
public void setServlet(ActionServlet servlet) {
this.servlet = servlet;
// :FIXME: Is this suppose to release resources?
    }
// --------------------------------------------------------- Public Methods
/**
     *      非HTTP的execute方法,一般不用。
     * /
    public ActionForward execute(ActionMapping mapping, ActionForm form,
        ServletRequest request, ServletResponse response)
        throws Exception {
        try {
            return execute(mapping, form, (HttpServletRequest) request,
                (HttpServletResponse) response);
        } catch (ClassCastException e) {
            return null;
        }
    }
    /**
     * 处理 HTTP request, 创建相应的(corresponding)
     * HTTP response (或定向到其他创建response 的组件
     * ), 返回 { ActionForward} 实例 来通知control如何跳转。
     * 或当处理完成时返回null
     * 注:当请求发送到Action时就会自动执行这个execute方法,所以一般简单的Action就重写这个方法即可//by wzl.
     * @param mapping  The ActionMapping used to select this instance (用来选择这个实例??)
     * @param form     可选的 ActionForm bean 
     * @param request  The HTTP request 
     * @param response The HTTP response 
     * @return forward  通知 control 应该跳转的页面, 或null (当业务完成时)
     * @throws Exception if the application business logic throws an
     *                   exception
     * @since Struts 1.1
*/
public ActionForward execute(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
throws Exception {
return null;
    }
// ---------------------------------------------------- Protected Methods
/**
     * 为request添加 messages 
     * 在JSP用用 < html:messages> 标签使用 (if messages="true" is set),
     *  参数message 必须被初始化                                                          //org.apache.struts.action.ActionMessages 
     *  Otherwise, ensure that the request attribute is not set.???
     *
     * @param request  被添加message的request请求
     * @param messages ActionMessages 需要添加的message
     * @since Struts 1.2.1
*/
protected void addMessages(HttpServletRequest request,
        ActionMessages messages) {
if (messages == null) {
//  bad programmer! *slap*
return;
        }
// 取得request中的requestMessages, 没有就创建一个
        ActionMessages requestMessages =
            (ActionMessages) request.getAttribute(Globals.MESSAGE_KEY);   //"org.apache.struts.action.ACTION_MESSAGE";
if (requestMessages == null) {
            requestMessages = new ActionMessages();
        }
// messages加入到requestMessages
        requestMessages.add(messages);
// if still empty, just wipe it out from the request
if (requestMessages.isEmpty()) {
            request.removeAttribute(Globals.MESSAGE_KEY);
return;
        }
// Save the messages
        request.setAttribute(Globals.MESSAGE_KEY, requestMessages);
    }
/**
     * Adds the specified errors keys into the appropriate request attribute
     * for use by the &lt;html:errors&gt; tag, if any messages are required.
     * Initialize the attribute if it has not already been. Otherwise, ensure
     * that the request attribute is not set.
     *  注:基本与addMessages相同,只是这里的ActionMessages含的是错误信息,在页面用 <html:errors>使用。/by wzl
     * @param request The servlet request we are processing
     * @param errors  Errors object
     * @since Struts 1.2.1
*/
protected void addErrors(HttpServletRequest request, ActionMessages errors) {
if (errors == null) {
//  bad programmer! *slap*
return;
        }
// get any existing errors from the request, or make a new one
        ActionMessages requestErrors =
            (ActionMessages) request.getAttribute(Globals.ERROR_KEY);
if (requestErrors == null) {
            requestErrors = new ActionMessages();
        }
// add incoming errors
        requestErrors.add(errors);
// if still empty, just wipe it out from the request
if (requestErrors.isEmpty()) {
            request.removeAttribute(Globals.ERROR_KEY);
return;
        }
// Save the errors
        request.setAttribute(Globals.ERROR_KEY, requestErrors);
    }
/**
     * <p>Generate a new transaction token, to be used for enforcing a single
     * request for a particular transaction.</p>
     * 为需要处理特殊事务的request生成一个 事务token
     * @param request The request we are processing
     * @return The new transaction token.
*/
protected String generateToken(HttpServletRequest request) {
return token.generateToken(request);
    }
/**
     * Retrieves any existing errors placed in the request by previous
     * actions. This method could be called instead of creating a <code>new
     * ActionMessages()</code> at the beginning of an <code>Action</code>.
     * This will prevent saveErrors() from wiping out any existing Errors
     *
     * 获得被上一个Action设置的error信息,这个方法可用来
     *初始化一个ActionMessages。可以用来防止saveErrors()清空已存在的Errors。
     *
     * @param request The servlet request we are processing
     * @return the Errors that already exist in the request, or a new
     *         ActionMessages object if empty.
     * @since Struts 1.2.1
*/
protected ActionMessages getErrors(HttpServletRequest request) {
        ActionMessages errors =
            (ActionMessages) request.getAttribute(Globals.ERROR_KEY);
if (errors == null) {
            errors = new ActionMessages();
        }
return errors;
    }
/**
     * 返回用户当前选择的 Locale。  //java.util.Locale 对象表示了特定的地理、政治和文化地区。
     *
     * @param request The request we are processing
     * @return The user's currently selected Locale.
*/
protected Locale getLocale(HttpServletRequest request) {
return RequestUtils.getUserLocale(request, null);
    }
/**
     * 大体同getError(request)
     * <p> Retrieves any existing messages placed in the request by previous
     * actions. This method could be called instead of creating a <code>new
     * ActionMessages()</code> at the beginning of an <code>Action</code> This
     * will prevent saveMessages() from wiping out any existing Messages </p>
     * 
     * @param request The servlet request we are processing
     * @return the Messages that already exist in the request, or a new
     *         ActionMessages object if empty.
     * @since Struts 1.2.1
*/
protected ActionMessages getMessages(HttpServletRequest request) {
        ActionMessages messages =
            (ActionMessages) request.getAttribute(Globals.MESSAGE_KEY);
if (messages == null) {
            messages = new ActionMessages();
        }
return messages;
    }
/**
     * 为当前模型返回默认的MessageResources         ?? //org.apache.struts.util.MessageResources 
     *
     * @param request The servlet request we are processing
     * @return The default message resources for the current module.
     * @since Struts 1.1
*/
protected MessageResources getResources(HttpServletRequest request) {
return ((MessageResources) request.getAttribute(Globals.MESSAGES_KEY));
    }
/**
     * <p>Return the specified message resources for the current module.</p>
     * 根据key为当前module返回特定的MessageResources
     * 看不懂
     * @param request The servlet request we are processing
     * @param key     The key specified in the message-resources element for
     *                the requested bundle.
     * @return The specified message resource for the current module.
     * @since Struts 1.1
*/
protected MessageResources getResources(HttpServletRequest request,
        String key) {
// Identify the current module
        ServletContext context = getServlet().getServletContext();
        ModuleConfig moduleConfig =
            ModuleUtils.getInstance().getModuleConfig(request, context);
// Return the requested message resources instance
return (MessageResources) context.getAttribute(key
+ moduleConfig.getPrefix());
    }
/**
     * <p>Returns <code>true</code> if the current form's cancel button was
     * pressed. This method will check if the <code>Globals.CANCEL_KEY</code>
     * request attribute has been set, which normally occurs if the cancel
     * button generated by <strong>CancelTag</strong> was pressed by the user
     * in the current request. If <code>true</code>, validation performed by
     * an <strong>ActionForm</strong>'s <code>validate()</code> method will
     * have been skipped by the controller servlet.</p>
     *
     * 当form的cancel按键?被按下时返回true。该方法会检查 request的
     *  Globals.CANCEL_KEY属性。若为true,ActionForm中的validate()将被跳过。
     *
     * <p> Since Action 1.3.0, the mapping for a cancellable Action must also have
     * the new "cancellable" property set to true. If "cancellable" is not set, and
     * the magic Cancel token is found in the request, the standard Composable
     * Request Processor will throw an InvalidCancelException. </p>
     *
     * @param request The servlet request we are processing
     * @return <code>true</code> if the cancel button was pressed;
     *         <code>false</code> otherwise.
*/
protected boolean isCancelled(HttpServletRequest request) {
return (request.getAttribute(Globals.CANCEL_KEY) != null);
    }
/**
     * 在当前session中存有事务token时 返回true。当存在以下情况时返回false:
     * <ul>
     *
     *  request中无session
     * 
     * session中无事务token
     * <li>No transaction token included as a request parameter</li>
     * request中没有事务token属性。
     *
     * 存在是事务token属性与session中的不匹配。
     * </ul>
     *
     * @param request The servlet request we are processing
     * @return <code>true</code> if there is a transaction token and it is
     *         valid; <code>false</code> otherwise.
*/
protected boolean isTokenValid(HttpServletRequest request) {
return token.isTokenValid(request, false);
    }
/**
     * <p>Return <code>true</code> if there is a transaction token stored in
     * the user's current session, and the value submitted as a request
     * parameter with this action matches it. Returns <code>false</code> under
     * any of the following circumstances:</p>
     * 重写上一个方法,添加参数 reset 决定是否在确认后重置token
     * <ul>
     *
     * <li>No session associated with this request</li> <li>No transaction
     * token saved in the session</li>
     *
     * <li>No transaction token included as a request parameter</li>
     *
     * <li>The included transaction token value does not match the transaction
     * token in the user's session</li>
     * 
     * </ul>
     *
     * @param request The servlet request we are processing
     * @param reset   Should we reset the token after checking it?
     * @return <code>true</code> if there is a transaction token and it is
     *         valid; <code>false</code> otherwise.
*/
protected boolean isTokenValid(HttpServletRequest request, boolean reset) {
return token.isTokenValid(request, reset);
    }
/**
     * <p>Reset the saved transaction token in the user's session. This
     * indicates that transactional token checking will not be needed on the
     * next request that is submitted.</p>
     * 重置token
     * @param request The servlet request we are processing
*/
protected void resetToken(HttpServletRequest request) {
        token.resetToken(request);
    }
/**
     * <p>Save the specified error messages keys into the appropriate request
     * attribute for use by the &lt;html:errors&gt; tag, if any messages are
     * required. Otherwise, ensure that the request attribute is not
     * created.</p>
     * 重置并设置Errors。
     * @param request The servlet request we are processing
     * @param errors  Error messages object
     * @since Struts 1.2
*/
protected void saveErrors(HttpServletRequest request, ActionMessages errors) {
// Remove any error messages attribute if none are required
if ((errors == null) || errors.isEmpty()) {
            request.removeAttribute(Globals.ERROR_KEY);
return;
        }
// Save the error messages we need
        request.setAttribute(Globals.ERROR_KEY, errors);
    }
/**
     * <p>Save the specified messages keys into the appropriate request
     * attribute for use by the &lt;html:messages&gt; tag (if messages="true"
     * is set), if any messages are required. Otherwise, ensure that the
     * request attribute is not created.</p>
     * 重置并设置request中的Messages
     * @param request  The servlet request we are processing.
     * @param messages The messages to save. <code>null</code> or empty
     *                 messages removes any existing ActionMessages in the
     *                 request.
     * @since Struts 1.1
*/
protected void saveMessages(HttpServletRequest request,
        ActionMessages messages) {
// Remove any messages attribute if none are required
if ((messages == null) || messages.isEmpty()) {
            request.removeAttribute(Globals.MESSAGE_KEY);
return;
        }
// Save the messages we need
        request.setAttribute(Globals.MESSAGE_KEY, messages);
    }
/**
     * <p>Save the specified messages keys into the appropriate session
     * attribute for use by the &lt;html:messages&gt; tag (if messages="true"
     * is set), if any messages are required. Otherwise, ensure that the
     * session attribute is not created.</p>
     *  重置并设置session中的Messages
     * @param session  The session to save the messages in.
     * @param messages The messages to save. <code>null</code> or empty
     *                 messages removes any existing ActionMessages in the
     *                 session.
     * @since Struts 1.2
*/
protected void saveMessages(HttpSession session, ActionMessages messages) {
// Remove any messages attribute if none are required
if ((messages == null) || messages.isEmpty()) {
            session.removeAttribute(Globals.MESSAGE_KEY);
return;
        }
// Save the messages we need
        session.setAttribute(Globals.MESSAGE_KEY, messages);
    }
/**
     * <p>Save the specified error messages keys into the appropriate session
     * attribute for use by the &lt;html:messages&gt; tag (if
     * messages="false") or &lt;html:errors&gt;, if any error messages are
     * required. Otherwise, ensure that the session attribute is empty.</p>
     * 重置并设置session中的Errors
     * @param session The session to save the error messages in.
     * @param errors  The error messages to save. <code>null</code> or empty
     *                messages removes any existing error ActionMessages in
     *                the session.
     * @since Struts 1.3
*/
protected void saveErrors(HttpSession session, ActionMessages errors) {
// Remove the error attribute if none are required
if ((errors == null) || errors.isEmpty()) {
            session.removeAttribute(Globals.ERROR_KEY);
return;
        }
// Save the errors we need
        session.setAttribute(Globals.ERROR_KEY, errors);
    }
/**
     * <p>Save a new transaction token in the user's current session, creating
     * a new session if necessary.</p>
     * 
     * @param request The servlet request we are processing
*/
protected void saveToken(HttpServletRequest request) {
        token.saveToken(request);
    }
/**
     * <p>Set the user's currently selected <code>Locale</code> into their
     * <code>HttpSession</code>.</p>
     *
     * @param request The request we are processing
     * @param locale  The user's selected Locale to be set, or null to select
     *                the server's default Locale
*/
protected void setLocale(HttpServletRequest request, Locale locale) {
        HttpSession session = request.getSession();
if (locale == null) {
            locale = Locale.getDefault();
        }
        session.setAttribute(Globals.LOCALE_KEY, locale);
    }
}

Currently rated 4.5 by 2 people

  • Currently 4.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Java & OpenSource Domain

Related posts

Comments

11/1/2009 10:37:55 AM

online personal loans

I like what I see. keep it going

online personal loans us

12/12/2009 12:44:24 PM

loans

I like your blog but how do I subscribe?

loans us

12/22/2009 11:11:25 AM

cash advance

Interesting ... as always - is your blog making any cash advance ? ;)

cash advance us

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2007 - 2008 Design by Sundy Linghua-Zhang 蜀ICP备08108648号

About the author

Name of author Author name
Something about me and what I do.

E-mail me Send mail

Calendar

<<  February 2012  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
2728291234
567891011

View posts in large calendar

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2012

Sign in