`
luckliu521
  • 浏览: 258822 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

struts2中的标签源码解析

    博客分类:
  • java
 
阅读更多
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
  • 大小: 15.6 KB
分享到:
评论

相关推荐

    struts2.0标签使用源码

    3. 使用`s:submit`标签提交表单,Struts2会自动将表单数据封装到Action中。 4. 在Action的execute方法中处理业务逻辑,然后返回一个结果,比如"success"。 5. 在视图层,可以使用`s:property`标签显示Action返回的...

    struts2源码解析.pdf

    在"struts2源码解析.pdf"文档中,主要探讨了以下几个关键组件及其功能: 1. **ActionContext**: - `ActionContext`是Struts2的核心上下文,它存储了与当前Action执行相关的所有信息,如请求参数、session数据等。...

    struts2深入详解源码1-5章

    Ognl(Object-Graph Navigation Language)是Struts2中的默认表达式语言,用于在Action和视图之间传递数据。Ognl表达式可以方便地访问对象属性,执行运算和方法调用。Struts2的标签库,如s:form、s:textfield等,...

    struts2.1.8 struts2源码 Eclipse关联这个可以

    - **Interceptor**: 拦截器是Struts2中的一个强大特性,它们在Action执行前后按顺序执行,用于处理通用任务,如权限检查、日志记录、事务管理等。开发者可以通过实现`com.opensymphony.xwork2.interceptor栈...

    struts2 ongl包源码

    这个压缩包包含了Struts2中的ONGL包源码,对于理解Struts2的工作原理和深入学习OGNL的使用非常有帮助。 OGNL是Object-Graph Navigation Language的缩写,它的主要功能是在对象图中导航并执行操作。在Struts2中,...

    Struts2自定义分页标签

    本篇文章将深入探讨如何在Struts2中实现自定义分页标签,以及相关的源码分析和工具使用。 首先,我们需要理解分页的基本原理。分页通常涉及到两个主要部分:服务器端的分页逻辑和客户端的显示。服务器端负责处理...

    struts2.0 经典书籍 源码 标签学习合集

    这个压缩包文件包含了关于Struts2.0的经典书籍、源码以及标签的学习资源,对于想要深入理解和使用Struts2.0的人来说,是一份非常宝贵的资料。 首先,让我们从"经典书籍"入手。Struts2.0的书籍通常会涵盖以下知识点...

    struts2标签详解与实例

    本文将深入探讨Struts2中的标签及其使用实例。 一、Struts2标签库概述 Struts2标签库是基于JSP标准标签库(JSTL)的扩展,它包含了一系列用于构建动态Web应用的标签。这些标签分为两类:核心标签和主题标签。核心...

    Java EE 轻量级解决方案 — SSH 青岛东合信息技术有限公司 青岛海尔软件公司 著 教材源码 _ 第四章 Struts2标签库

    3. **标签的生命周期**:从解析到销毁,每个Struts2标签都有其特定的生命周期,理解这个过程对于优化页面性能和解决问题至关重要。 4. **自定义标签**:如果预定义的标签不能满足需求,开发者可以创建自己的标签来...

    struts2源码解析[归纳].pdf

    这份"struts2源码解析[归纳].pdf"文档显然深入探讨了Struts2的核心组件和工作原理。以下是对其中提到的关键概念的详细解释: 1. **ActionContext**: ActionContext是Struts2中一个非常重要的类,它封装了当前请求...

    struts2中xwork源码

    在Struts2中,XWork扮演着以下几个关键角色: 1. **Action管理**:XWork负责创建和管理Action实例,每个HTTP请求都会对应一个Action实例。通过`com.opensymphony.xwork2.DefaultActionInvocation`类,XWork会根据...

    Struts2 demo2

    - **对指定action方法校验**: 在Struts2中,可以通过XML配置文件定义特定Action类或方法的数据校验规则,以确保用户输入的有效性。 - **对action的所有方法进行校验**: 这种配置允许全局应用校验规则,适用于...

    Struts2 标签二

    这篇“Struts2 标签二”将深入探讨Struts2中的标签库,特别是那些在第一部分中未涵盖的内容。 一、Struts2标签库概述 Struts2的标签库主要由两个部分组成:核心标签库和自由标签库。核心标签库提供了一些基础的控制...

    Struts2分页-自定义标签-类似百度分页

    在Struts2中,自定义标签可以用来扩展JSP页面的功能,使其能够更好地与后台业务逻辑交互。 自定义标签的实现通常分为以下几个步骤: 1. **创建标签库**:定义一个XML文件(如struts-tags.xml),用于声明自定义...

    struts2 文件上传源码

    在Struts2中,实现文件上传涉及多个组件和技术。以下是关于"Struts2 文件上传源码"的相关知识点: 1. **.struts2的动作类(Action Class)**:在Struts2中,文件上传通常通过自定义Action类来处理。Action类是业务...

    Struts2 标签使用

    在Struts2中,标签库是其强大的特性之一,它提供了丰富的预定义标签,使得开发者可以在JSP页面中方便地实现业务逻辑和展示层的交互。本篇文章将深入探讨Struts2的标签使用及其背后的机制。 1. **Struts2 标签库概述...

    Struts2视频教程

    ### Struts2核心知识点解析 #### 一、Struts2框架概述 - **定义与特点**:Struts2是一款基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架,它继承了Struts1的优点,同时在设计上更加灵活、易用,...

    struts2 optiontransferselect标签使用中的问题

    在Struts2中,OptionTransferSelect标签是一个强大的组件,它允许用户在两个下拉列表之间转移选项,常用于实现多选功能。这篇博客文章可能讨论了在使用OptionTransferSelect标签时遇到的问题以及解决方法。 在...

    XSS转码 && struts2 property标签的bug

    这个问题涉及到XSS攻击的防范手段——转码,以及Struts2框架中property标签的潜在漏洞。 首先,我们来深入理解XSS攻击。XSS允许攻击者在用户浏览器中注入恶意脚本,这通常发生在网站未能充分过滤或转义用户输入的...

    struts2权威指南源代码

    《Struts2权威指南》是李刚先生撰写的一本深入解析Struts2框架的专业书籍,其源代码的提供对于读者理解和实践Struts2框架具有极大的帮助。 源代码通常包含了书中讲解的各种示例和实战项目,使得学习者能够通过实际...

Global site tag (gtag.js) - Google Analytics