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
分享到:
相关推荐
3. 使用`s:submit`标签提交表单,Struts2会自动将表单数据封装到Action中。 4. 在Action的execute方法中处理业务逻辑,然后返回一个结果,比如"success"。 5. 在视图层,可以使用`s:property`标签显示Action返回的...
在"struts2源码解析.pdf"文档中,主要探讨了以下几个关键组件及其功能: 1. **ActionContext**: - `ActionContext`是Struts2的核心上下文,它存储了与当前Action执行相关的所有信息,如请求参数、session数据等。...
Ognl(Object-Graph Navigation Language)是Struts2中的默认表达式语言,用于在Action和视图之间传递数据。Ognl表达式可以方便地访问对象属性,执行运算和方法调用。Struts2的标签库,如s:form、s:textfield等,...
- **Interceptor**: 拦截器是Struts2中的一个强大特性,它们在Action执行前后按顺序执行,用于处理通用任务,如权限检查、日志记录、事务管理等。开发者可以通过实现`com.opensymphony.xwork2.interceptor栈...
这个压缩包包含了Struts2中的ONGL包源码,对于理解Struts2的工作原理和深入学习OGNL的使用非常有帮助。 OGNL是Object-Graph Navigation Language的缩写,它的主要功能是在对象图中导航并执行操作。在Struts2中,...
本篇文章将深入探讨如何在Struts2中实现自定义分页标签,以及相关的源码分析和工具使用。 首先,我们需要理解分页的基本原理。分页通常涉及到两个主要部分:服务器端的分页逻辑和客户端的显示。服务器端负责处理...
这个压缩包文件包含了关于Struts2.0的经典书籍、源码以及标签的学习资源,对于想要深入理解和使用Struts2.0的人来说,是一份非常宝贵的资料。 首先,让我们从"经典书籍"入手。Struts2.0的书籍通常会涵盖以下知识点...
本文将深入探讨Struts2中的标签及其使用实例。 一、Struts2标签库概述 Struts2标签库是基于JSP标准标签库(JSTL)的扩展,它包含了一系列用于构建动态Web应用的标签。这些标签分为两类:核心标签和主题标签。核心...
3. **标签的生命周期**:从解析到销毁,每个Struts2标签都有其特定的生命周期,理解这个过程对于优化页面性能和解决问题至关重要。 4. **自定义标签**:如果预定义的标签不能满足需求,开发者可以创建自己的标签来...
这份"struts2源码解析[归纳].pdf"文档显然深入探讨了Struts2的核心组件和工作原理。以下是对其中提到的关键概念的详细解释: 1. **ActionContext**: ActionContext是Struts2中一个非常重要的类,它封装了当前请求...
在Struts2中,XWork扮演着以下几个关键角色: 1. **Action管理**:XWork负责创建和管理Action实例,每个HTTP请求都会对应一个Action实例。通过`com.opensymphony.xwork2.DefaultActionInvocation`类,XWork会根据...
- **对指定action方法校验**: 在Struts2中,可以通过XML配置文件定义特定Action类或方法的数据校验规则,以确保用户输入的有效性。 - **对action的所有方法进行校验**: 这种配置允许全局应用校验规则,适用于...
这篇“Struts2 标签二”将深入探讨Struts2中的标签库,特别是那些在第一部分中未涵盖的内容。 一、Struts2标签库概述 Struts2的标签库主要由两个部分组成:核心标签库和自由标签库。核心标签库提供了一些基础的控制...
在Struts2中,自定义标签可以用来扩展JSP页面的功能,使其能够更好地与后台业务逻辑交互。 自定义标签的实现通常分为以下几个步骤: 1. **创建标签库**:定义一个XML文件(如struts-tags.xml),用于声明自定义...
在Struts2中,实现文件上传涉及多个组件和技术。以下是关于"Struts2 文件上传源码"的相关知识点: 1. **.struts2的动作类(Action Class)**:在Struts2中,文件上传通常通过自定义Action类来处理。Action类是业务...
在Struts2中,标签库是其强大的特性之一,它提供了丰富的预定义标签,使得开发者可以在JSP页面中方便地实现业务逻辑和展示层的交互。本篇文章将深入探讨Struts2的标签使用及其背后的机制。 1. **Struts2 标签库概述...
### Struts2核心知识点解析 #### 一、Struts2框架概述 - **定义与特点**:Struts2是一款基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架,它继承了Struts1的优点,同时在设计上更加灵活、易用,...
在Struts2中,OptionTransferSelect标签是一个强大的组件,它允许用户在两个下拉列表之间转移选项,常用于实现多选功能。这篇博客文章可能讨论了在使用OptionTransferSelect标签时遇到的问题以及解决方法。 在...
这个问题涉及到XSS攻击的防范手段——转码,以及Struts2框架中property标签的潜在漏洞。 首先,我们来深入理解XSS攻击。XSS允许攻击者在用户浏览器中注入恶意脚本,这通常发生在网站未能充分过滤或转义用户输入的...
《Struts2权威指南》是李刚先生撰写的一本深入解析Struts2框架的专业书籍,其源代码的提供对于读者理解和实践Struts2框架具有极大的帮助。 源代码通常包含了书中讲解的各种示例和实战项目,使得学习者能够通过实际...