`
一日一博
  • 浏览: 227015 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Struts2原理浅析

阅读更多
JavaEE把MVC设计模式引入了web领域,并在此基础上机构出了称为Model2的体系。


从上图不难看出,其实在配置文件配置的拦截器顺序,在ActionInvocation调度的时候,其实是一个递归算法,每个interceptor类里面代码被invocation.invoke()分成两部分,前一部分都会在执行Action的execute方法之前执行,然后再拦截器按反序再执行后半部分。
从struts2.1.3版本开始,官方团队极力推荐用StrutsPrepareFilter取代原ActionContextCleanUp,用StrutsExecuteFilter取代原FilterDispatcher,并在全新的核心控制器StrutsPrepareAndExecuteFilter中集成了StrutsPrepareFilter和StrutsExecuteFilter的功能。

  .......
  <filter>
  	<filter-name>struts2Filter</filter-name>
  	<filter-class>
              org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
      </filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>struts2Filter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  .......

这个时候在struts2的StrutsPrepareAndExecuteFilter与一系列拦截器Interceptor实现了Model2架构,如下图:



其实图中的ActionContextCleanUp改成StrutsPrepareFilter,第三步的FilterDispatcher之前会执行StrutsExecuteFilter,不得不说官方团队也有偷懒的时候,在最新的2.3.4版本中的文档估计是以前2.1版本的图。上图是我修改后的流程图,技术粗糙请见谅。

这是官方文档中的介绍:
1.The web browser requests a resource (/mypage.action, /reports/myreport.pdf, et cetera)
2.The Filter Dispatcher looks at the request and determines the appropriate Action
3.The Interceptors automatically apply common functionality to the request, like workflow, validation, and file upload handling
4.The Action method executes, usually storing and/or retrieving information from a database
5.The Result renders the output to the browser, be it HTML, images, PDF, or something else

要想灵活运用struts2个人认为必须对常用的类非常熟悉,那么不得不提到Action的基类ActionSupport了。
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable{
...
}

这里的ActionSupport实现了很多接口,我们一一来了解:
Action:

/**
 * 定义了Action5个常用的字符串常量,并且规定至少要有一个默认的execute方法
 * 在ActionSupport实现execute方法返回值是SUCCESS
 */
public interface Action {
    public static final String SUCCESS = "success";
    public static final String NONE = "none";
    public static final String ERROR = "error";
    public static final String INPUT = "input";
    public static final String LOGIN = "login";
    public String execute() throws Exception;
}

Validateable:
/**
 * 验证框架,在ActionSupport中此方法的实现为空,如果Action中需要验证只需重写
 * validate()方法就会在执行execute之前调用,然后通过ValidationAware接口中的
 * addFieldError这些方法就可以达到服务端验证的效果。
 */
public interface Validateable {
    void validate();
}

ValidationAware:
public interface ValidationAware {
    //为当前Action添加Action级别的错误信息集
    void setActionErrors(Collection<String> errorMessages);
    Collection<String> getActionErrors();

    //为当前Action添加Action级别的错误信息集
    void setActionMessages(Collection<String> messages);
    Collection<String> getActionMessages();

    //为制定字段添加错误信息集
    void setFieldErrors(Map<String, List<String>> errorMap);
    Map<String, List<String>> getFieldErrors();

    //为当前Action添加Action级别的错误信息
    void addActionError(String anErrorMessage);

    //为当前Action添加Action级别的普通信息
    void addActionMessage(String aMessage);

    //为制定字段添加错误信息
    void addFieldError(String fieldName, String errorMessage);

    boolean hasActionErrors();//判断当前Action环境中是否存在Action级别错误
    boolean hasActionMessages();//判断当前Action环境中是否存在Action级别消息
    boolean hasErrors();//判断当前Action环境中是否存在Action级别错误
    boolean hasFieldErrors();//判断当前Action环境中是否存在字段错误消息
}

TextProvider:
/**
 * 通过key得到资源文件中的value,如果是全局类型有变量的value可以带上变量值
 * 通常此方法配合validation框架使用
 */
public interface TextProvider {
	    boolean hasKey(String key);
	    String getText(String key);
	    String getText(String key, String defaultValue);
	    String getText(String key, String defaultValue, String obj);
	    String getText(String key, List<?> args);
	    String getText(String key, String[] args);
	    String getText(String key, String defaultValue, List<?> args);
	    String getText(String key, String defaultValue, String[] args);
	    String getText(String key, String defaultValue, List<?> args, ValueStack stack);
	    String getText(String key, String defaultValue, String[] args, ValueStack stack);
	    ResourceBundle getTexts(String bundleName);
	    ResourceBundle getTexts();
	}

LocaleProvider:
public interface LocaleProvider {
	    Locale getLocale();
	}

除了ActionSupport这个关键的基类外,还有个常用的类就是ServletActionContext,这个类继承了ActionContext并实现StrutsStatics接口,所以他可以称为Struts2直接访问Servlet API(如HttpServletRequest,HttpSession,HttpServletResponse,ServletContext)的工具类
public class ServletActionContext extends ActionContext implements StrutsStatics {
	    private static final long serialVersionUID = -666854718275106687L;

	    public static final String STRUTS_VALUESTACK_KEY = "struts.valueStack";
	    public static final String ACTION_MAPPING = "struts.actionMapping";

	    @SuppressWarnings("unused")
	    private ServletActionContext(Map context) {
	        super(context);
	    }
	    public static ActionContext getActionContext(HttpServletRequest req) {
	        ValueStack vs = getValueStack(req);
	        if (vs != null) {
	            return new ActionContext(vs.getContext());
	        } else {
	            return null;
	        }
	    }
	    public static ValueStack getValueStack(HttpServletRequest req) {
	        return (ValueStack) req.getAttribute(STRUTS_VALUESTACK_KEY);
	    }
	    public static ActionMapping getActionMapping() {
	        return (ActionMapping) ActionContext.getContext().get(ACTION_MAPPING);
	    }
            //得到当前web应用中的PageContext对象
	    public static PageContext getPageContext() {
	        return (PageContext) ActionContext.getContext().get(PAGE_CONTEXT);
	    }
	    public static void setRequest(HttpServletRequest request) {
	        ActionContext.getContext().put(HTTP_REQUEST, request);
	    }
            //得到当前web应用中的HttpServletRequest对象
	    public static HttpServletRequest getRequest() {
	        return (HttpServletRequest) ActionContext.getContext().get(HTTP_REQUEST);
	    }
	    public static void setResponse(HttpServletResponse response) {
	        ActionContext.getContext().put(HTTP_RESPONSE, response);
	    }
            //得到当前web应用中的HttpServletResponse对象
	    public static HttpServletResponse getResponse() {
	        return (HttpServletResponse) ActionContext.getContext().get(HTTP_RESPONSE);
	    }
            //得到当前web应用中的ServletContext对象
	    public static ServletContext getServletContext() {
	        return (ServletContext) ActionContext.getContext().get(SERVLET_CONTEXT);
	    }
	    public static void setServletContext(ServletContext servletContext) {
	        ActionContext.getContext().put(SERVLET_CONTEXT, servletContext);
	    }
	}
  • 大小: 19.3 KB
  • 大小: 98.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics