Struts2值栈ValueStack源码阅读笔记
来源:互联网 发布:锁机软件下载 编辑:程序博客网 时间:2024/05/16 07:24
我们要从ActionContext开始说起,首先看StrutsPrepareAndExecuteFilter核心过滤器,也是整个程序的入口,doFilter()方法中的 ——->
prepare.createActionContext(request, response);
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; try { prepare.setEncodingAndLocale(request, response); prepare.createActionContext(request, response); prepare.assignDispatcherToThread(); if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) { chain.doFilter(request, response); } else { request = prepare.wrapRequest(request); ActionMapping mapping = prepare.findActionMapping(request, response, true); if (mapping == null) { boolean handled = execute.executeStaticResourceRequest(request, response); if (!handled) { chain.doFilter(request, response); } } else { execute.executeAction(request, response, mapping); } } } finally { prepare.cleanupRequest(request); } }
进入PrepareOpreration类的createActionContext()方法。
public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) { ActionContext ctx; Integer counter = 1; Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER); if (oldCounter != null) { counter = oldCounter + 1; } ActionContext oldContext = ActionContext.getContext(); //如果ActionContext 不为null的话,重新new一个,在这里我们也可看到,ActionContext的数据结构,HashMap,用于查询最快的集合类。这段代码的意义在于使每一次请求,每一个action,都有其对应的ActionContext if (oldContext != null) { // detected existing context, so we are probably in a forward ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap())); } else { //如果为null通过IoC容器ContainerImpl中的getInstance()方法创建对应实例,值栈在这里创建完成 ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();//创建一个名字叫做extraContext的Map,里面存储了request,response,servletContext信息,并将其放入ActionContext stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext)); ctx = new ActionContext(stack.getContext()); } request.setAttribute(CLEANUP_RECURSION_COUNTER, counter); ActionContext.setContext(ctx); return ctx; }
在上面的注释中,我们提到ActionContext的数据结构是HashMap,那么ValueStack的数据结构是怎样的?
进入createValueStack()方法,进入OgnlValueStackFactory类,这个类继承ValueStackFactory接口
public class OgnlValueStackFactory implements ValueStackFactory
进入ValueStackFactory 接口中发现,这个接口就是用来创建值栈的。
public interface ValueStackFactory { ValueStack createValueStack(); ValueStack createValueStack(ValueStack stack);}
回到OgnlValueStackFactory,找到createValueStack()方法.
public ValueStack createValueStack() { ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider, allowStaticMethodAccess); container.inject(stack); stack.getContext().put(ActionContext.CONTAINER, container); return stack; }
进入OgnlValueStack的构造方法之中
protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticAccess) { setRoot(xworkConverter, accessor, new CompoundRoot(), allowStaticAccess); push(prov); }
发现构造方法是protected 修饰符,我认为是确保了安全性,进入setRoot()方法。
protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot, boolean allowStaticMethodAccess) { //栈对象是一个CompountRoot类型的栈结构 this.root = compoundRoot; //设定OGNL所需的MemeberAccess实现类 this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess); //创建OGNL的上下文 this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter), securityMemberAccess); context.put(VALUE_STACK, this); Ognl.setClassResolver(context, accessor); ((OgnlContext) context).setTraceEvaluations(false); ((OgnlContext) context).setKeepLastEvaluation(false); }
这才是真正的OgnlValueStack的初始化过程,我们接下来进入CompoundRoot类
public class CompoundRoot extends ArrayList { public CompoundRoot() { } public CompoundRoot(List list) { super(list); } public CompoundRoot cutStack(int index) { return new CompoundRoot(subList(index, size())); } public Object peek() { return get(0); } public Object pop() { return remove(0); } public void push(Object o) { add(0, o); }}
发现这个类继承了ArrayList类,我们发现其实OgnlValueStack的底层实际上是通过链表实现的栈结构。
接下来,我们要往回走,回到OgnlValueStackFactory的createValueStack()方法
public ValueStack createValueStack() { ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider, allowStaticMethodAccess); //将返回的值栈对象注入容器 container.inject(stack); //将容器存入上下文,也就是ActionContext stack.getContext().put(ActionContext.CONTAINER, container); return stack; }
到这里ActionContext和值栈的初始化过程,以及他们之间的关系似乎已经弄清楚了,借用一张网上的图来说明他们之间的关系。
学习了值栈以后,引发了我的思考,xwork与ognl之间的信息是怎样交互的?他们之间的类型转换是怎样完成的?留待后续完成。
- Struts2值栈ValueStack源码阅读笔记
- Struts2.x 学习笔记 之 值栈(ValueStack)
- 【Struts2】Struts2: ValueStack值栈
- struts2 源码阅读笔记 - FilterDispatcher
- struts2 值栈 valuestack
- Struts2值栈ValueStack介绍
- struts2拦截器源码阅读笔记
- Struts2容器Container源码阅读笔记
- Struts2类型转换TypeConverter源码阅读笔记
- Struts2的ValueStack(值栈)介绍
- Struts2的ValueStack(值栈)
- Struts2之ValueStack(值栈)讲解
- Struts2-----ValueStack
- Struts2:ValueStack
- struts2 valuestack
- Struts2 ValueStack
- Struts2--ValueStack
- struts2源码阅读2
- Android使用ADB启动应用程序
- MySql-5.7.17 -winx64的安装配置
- Linux Mint输入法配置
- 《DSAA》 10.5.1 收费公路重建问题
- 刘贺稳排名专家-专业研究下拉框推广
- Struts2值栈ValueStack源码阅读笔记
- JSONP跨域请求+简答实现百度搜索
- NDK如何编译别人的.lib文件生成so
- android studio gradle 编译又报错了,求帮助
- 2017 —— 新年计划
- 统计某年的字段总数
- 网站大流量分析
- Centos7搭建Ngrok
- 数据结构(十) 链队列的基本操作 ----入队列,出队列,判断队列是否为空