struts2中的标签源码解析

转载 2012年03月26日 16:22:28
struts2中的标签源码解析
2012-02-05 23:15

struts2标签库的源代码主要在三个包内,org.apache.struts2.components,org.apache.struts2.views.jsp.ui
和org.apache.struts2.views.jsp。
org.apache.struts2.views.jsp.ui包主要包括struts2的所有的标签类(如TextFieldTag)及其公共的抽象基类
AbstractUITag。
org.apache.struts2.views.jsp包与struts标签相关的类主要是ComponentTagSupport和StrutsBodyTagSupport。
org.apache.struts2.components包主要包括所有标签类所对应的组件类(如TextFieldTag对应TextField)以及他
们的公共抽象基类UIBean和UIBean的父类Component。
他们的继承关系如下图所示。


struts2的标签之所以能够利用ognl与action类属性相关联起来,是因为标签组件类的基类Component存储了值栈
成员变量stack,在其构造函数中进行赋值,如下
/**
     * Constructor.
     *
     * @param stack  OGNL value stack.
     */
    public Component(ValueStack stack) {
        this.stack = stack;
        this.parameters = new LinkedHashMap();
        getComponentStack().push(this);
    }
何时构造这个Component呢,来看其他两个包中的类了
StrutsBodyTagSupport类继承自javax.servlet.jsp.tagext.BodyTagSupport,BodyTagSupport或
SimpleTagSupport都是jsp自定义标签必须继承的类。StrutsBodyTagSupport类主要提供获取值栈对象,查找值栈
属性,获取页面body内容的api,我们主要看下获取值栈对象的方法:

protected ValueStack getStack() {
        return TagUtils.getStack(pageContext);
    }

TagUtils中getStack方法代码:

public static ValueStack getStack(PageContext pageContext) {
        HttpServletRequest req = (HttpServletRequest) pageContext.getRequest();
        ValueStack stack = (ValueStack) req.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

        if (stack == null) {

            HttpServletResponse res = (HttpServletResponse) pageContext.getResponse();
            Dispatcher du = Dispatcher.getInstance();
            if (du == null) {
                throw new ConfigurationException("The Struts dispatcher cannot be found.  This is usually caused by "+
                        "using Struts tags without the associated filter. Struts tags are only usable when the request "+
                        "has passed through its servlet filter, which initializes the Struts dispatcher needed for this tag.");
            }
            stack = du.getContainer().getInstance(ValueStackFactory.class).createValueStack();
            Map<String, Object> extraContext = du.createContextMap(new RequestMap(req),
                    req.getParameterMap(),
                    new SessionMap(req),
                    new ApplicationMap(pageContext.getServletContext()),
                    req,
                    res,
                    pageContext.getServletContext());
            extraContext.put(ServletActionContext.PAGE_CONTEXT, pageContext);
            stack.getContext().putAll(extraContext);
            req.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);

            // also tie this stack/context to the ThreadLocal
            ActionContext.setContext(new ActionContext(stack.getContext()));
        } else {
            // let's make sure that the current page context is in the action context
            Map<String, Object> context = stack.getContext();
            context.put(ServletActionContext.PAGE_CONTEXT, pageContext);

            AttributeMap attrMap = new AttributeMap(context);
            context.put("attr", attrMap);
        }

        return stack;
    }

利用TagUtils的静态方法,在PageContext对象(pageContext是TagSupport类中的成员,BodyTagSupport继承自TagSupport)中获取HttpServletRequest实例,然后由request实例取得值栈属性对象,如果没有取到则在

HttpServletResponse实例中获取。

抽象类ComponentTagSupport类继承自StrutsBodyTagSupport,来看这个类的全部代码:

/**
 */
public abstract class ComponentTagSupport extends StrutsBodyTagSupport {
    protected Component component;

    public abstract Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res);

    public int doEndTag() throws JspException {
        component.end(pageContext.getOut(), getBody());
        component = null;
        return EVAL_PAGE;
    }

    public int doStartTag() throws JspException {
        component = getBean(getStack(), (HttpServletRequest) pageContext.getRequest(), (HttpServletResponse) pageContext.getResponse());
        Container container = Dispatcher.getInstance().getContainer();
        container.inject(component);
        
        populateParams();
        boolean evalBody = component.start(pageContext.getOut());

        if (evalBody) {
            return component.usesBody() ? EVAL_BODY_BUFFERED : EVAL_BODY_INCLUDE;
        } else {
            return SKIP_BODY;
        }
    }

    protected void populateParams() {
    }

    public Component getComponent() {
        return component;
    }
}

该类重写了TagSupport类(StrutsBodyTagSupport继承自BodyTagSupport,BodyTagSupport继承自TagSupport)的几个重要方法doStartTag(),doEndTag()。而且自己定义了一个抽象方法getBean,getBean将在其具体的标签类中有各自的实现,比如TextFieldTag的getBean实现为:

public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
        return new TextField(stack, req, res);
    }

它将获得一个标签类所对应的组件类的一个实例。

当用户发出请求时,doStartTag()开始执行(具体是怎样执行的还有待学习),首先就调用getBean获取对应的标签组件类实例,构造函数参数

值栈stack由基类StrutsBodyTagSupport的getStack()获得,request和response对象在PageContext实例中获取。然后调用populateParams();进行初始参数值的填充,populateParams()也将调用具体类中的populateParams()对自己的属性成员进行初始化,看TextFieldTag类中的populateParams():

/**
 * @see TextField
 */
public class TextFieldTag extends AbstractUITag {

    private static final long serialVersionUID = 5811285953670562288L;

    protected String maxlength;
    protected String readonly;
    protected String size;

    public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
        return new TextField(stack, req, res);
    }

    protected void populateParams() {
        super.populateParams();

        TextField textField = ((TextField) component);
        textField.setMaxlength(maxlength);
        textField.setReadonly(readonly);
        textField.setSize(size);
    }
   ......//set属性成员方法,省略
}

先调用父类AbstractUITag中的populateParams()对所有标签共有的属性进行初始化,然后给具体自己的个性成员赋值,我们可以看到初始化是将对应的组件类成员初始化,TextFieldTag标签类有的属性成员,其对应的组件类也都有,这些初始化的值其实是初始化到对应的组件类中的对应属性,包括super.populateParams()调用AbstractUITag中的populateParams进行初始化。可以看到,AbstractUITag类抽象了所有标签的公共属性,它对应的UIBean组件基类也抽象了这些公共属性。

初始化完成之后,回到doStartTag()中,就调用Component中的start进行输出了

boolean evalBody = component.start(pageContext.getOut());

完成之后就应该调用doEndTag(),将调用component的end方法,完成html标签的输出,最后将此组件对象销毁。

从宏观上看,当用户请求页面时,将会构造页面中的标签元素,即同时也会构造出对应的组件类,当页面构造好回显到浏览器后,服务器中的该页面关联的对象都应该予以销毁。

本文转自:http://hi.baidu.com/%B7%DC%B6%B7%B2%BB%CD%A3%D0%AA/blog/item/a0911e1504ecb61e4a90a799.html

学习笔记:struts2的package,action,result标签解析

package标签1. 类似于代码包,区别于不同的action,要配置action,必须首先写package标签,在package里面才能配置action 2.name属性 name属性值和功能...
  • Master_Spark
  • Master_Spark
  • 2017年05月13日 23:40
  • 214

struts2标签详解&Struts2常用标签总结

要在jsp中使用Struts2的标志,先要指明标志的引入。通过jsp的代码的顶部加入以下的代码:   If elseif  else 描述: 执行基本的条件流转。 参数: ...
  • kimliu2009
  • kimliu2009
  • 2016年10月30日 14:12
  • 1500

Struts2原理及源码分析

struts介绍 strtus2是WebWork的升级版,是一个运行稳定、性能优异、设计成熟的web框架,而struts则实现了MVC思想中的controller模块,而控制器实际上是由两部分...
  • wxryzq
  • wxryzq
  • 2015年03月22日 20:26
  • 2231

Struts2源码分析(二)Struts2运行流程分析

Struts2是很早之前学过的。刚刚学完Servlet之后就开始学习Struts2。学完Struts2的基础知识后就着手开始做了个小项目。现在正在学SpringMVC,感觉SpringMVC确实是比S...
  • canot
  • canot
  • 2016年04月09日 16:04
  • 3414

struts2源码的解读 .

引用地址:http://www.cnblogs.com/dengjiali/articles/2846354.html 学习开源框架最好的方法,莫过于仔细阅读源代码,这样既可...
  • rengq126
  • rengq126
  • 2013年02月27日 18:50
  • 5202

Struts2标签之set

Struts2标签可以分为UI标签,非UI标签和ajax标签。1.UI标签:主要用于显示页面,生成HTML。2.非UI标签:主要是访问数据,其中它可以分为数据标签(数据储存和处理)和控制标签(条件和循...
  • lkk1344
  • lkk1344
  • 2015年09月25日 23:37
  • 403

【Struts2框架】第四节Struts标签-通用标签简述与常用标签大例子

一.通用标签简述 1.通用标签    a)property    b)set      i.默认为action scope,会将值放入request和ActionContext中      ii.pa...
  • u013517797
  • u013517797
  • 2015年07月27日 15:43
  • 1000

struts2标签库——UI标签

1、要使用标签,必须修改web.xml,让控制器拦截所有请求 /* 2、Struts 2提供了功能强大的标签库,JSP页面导入标签库: ” 3、设置用户界面主题,默认值为xhtml风格 ...
  • cuifugang124428
  • cuifugang124428
  • 2014年03月14日 23:05
  • 1592

spring 源码探索--xml的默认标签解析

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));这行代码完成了applicat...
  • crazyzhb2012
  • crazyzhb2012
  • 2016年11月16日 22:55
  • 497

struts2标签遍历各种形式数据集合

在类中定义的集合类型如下: private String [] arryStr; private List list; private Map map; private Map userM...
  • menghuannvxia
  • menghuannvxia
  • 2015年07月31日 14:11
  • 4251
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:struts2中的标签源码解析
举报原因:
原因补充:

(最多只允许输入30个字)