自己实现Struts2(四)实现ActionInvocation

自己实现Struts2(五)实现StrutsPrepareAndExecuteFilter 上一章自己实现Struts2(四)实现ActionInvocation我已经实现好了action和拦截器的调用者ActionInvocation类,现在就来实现一下Struts2的入口——StrutsPrepareAndExecuteFilter类。分析StrutsPrepareAndExecuteFilter再把Struts2框架流程图贴上来 大家将FilterDispatcher看成Strut 阅读详情

上一章自己实现Struts2(三)实现ActionContext我已经实现好了Struts2的数据中心ActionContext,现在就要来实现一下action和拦截器的调用者ActionInvocation

再把Struts2框架流程图贴上来

大家可以发现拦截器链和action都是通过ActionInvocation来调用的,要实现这个功能,就必须准备好拦截器链和要被调用的action实例以及该action对应的配置信息(要通过配置信息知道调用什么方法),下面就来实现一下。

#ActionInvocation类成员变量介绍
现在我就来创建一个ActionInvocation类,当然了,在Struts2中ActionInvocation是个接口,不过接口是为了方便扩展,我又没打算扩展,就直接定义类了。

package edu.jyu.invocation;

import java.util.Iterator;

import edu.jyu.config.ActionConfig;
import edu.jyu.context.ActionContext;
import edu.jyu.interceptor.Interceptor;

/**
 * 拦截器链和action的调用类
 * 
 * @author Jason
 */
public class ActionInvocation {
	// 拦截器链
	private Iterator<Interceptor> interceptors;
	// 即将要被调用的action实例
	private Object action;
	// action配置信息
	private ActionConfig config;
	// 数据中心ActionContext
	private ActionContext invocationContext;

}

其中Interceptor可以用Struts2自带的Interceptor接口,不过在这里我自己写了一个,没什么差别的

package edu.jyu.interceptor;

import edu.jyu.invocation.ActionInvocation;

/**
 * 拦截器接口
* @author Jason
 */
public interface Interceptor {
	/**
	 * 执行拦截器初始化工作
	 */
	public void init();
	/**
	 * 拦截功能,在请求前或请求后执行一些处理
	 * @param invocation
	 * @return 
	 */
	public String intercept(ActionInvocation invocation);
	/**
	 * 让拦截器做一些释放资源工作
	 */
	public void destory();
}

可以看到上面的ActionInvocation类定义了四个成员变量,现在我就简单介绍一下这个几个变量

  1. interceptors:很明显这就是拦截器链了,存放着需要执行的拦截器,用Iterator类型是为了在后面调用的时候方便取出来。
  2. action:要调用的action实例。
  3. config:要调用的action实例对应的配置信息,要根据配置信息去调用action的方法。
  4. invocationContext:本次请求的数据中心,为action实例准备好。

下面就要来做一下准备工作了,把这几个数据都准备好。

#准备工作
数据准备工作放在构造器中,代码如下

/**
 * 准备各种需要的数据
 * 
 * @param interceptorClassNames
 *            存放着拦截器链每个拦截器的全限定类名
 * @param config
 *            需要调用的action的配置信息
 * @param request
 * @param response
 */
public ActionInvocation(List<String> interceptorClassNames, ActionConfig config, HttpServletRequest request,
		HttpServletResponse response) {
	// 准备Interceptor链
	if (interceptorClassNames != null && interceptorClassNames.size() > 0) {
		List<Interceptor> list = new ArrayList<Interceptor>();
		for (String className : interceptorClassNames) {
			try {
				Interceptor interceptor = (Interceptor) Class.forName(className).newInstance();
				interceptor.init();
				list.add(interceptor);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException("创建Interceptor失败:" + className);
			}
		}
		interceptors = list.iterator();
	}

	// 准备action实例
	this.config = config;
	try {
		action = Class.forName(config.getClassName()).newInstance();
	} catch (Exception e) {
		e.printStackTrace();
		throw new RuntimeException("创建Action失败:" + config.getClassName());
	}

	// 准备数据中心ActionContext
	invocationContext = new ActionContext(request, response, action);
}

现在就来介绍一下准备工作。

一、准备拦截器链:构造方法会接受一个集合,里面存放着全部需要调用的拦截器的全限定类名,根据拦截器的全限定类名反射生成对应的实例,执行拦截器的初始化方法init然后添加到另外一个集合中,最后调用interceptors = list.iterator();赋值给interceptors,至此拦截器链就准备完毕了。

二、准备action实例:构造方法会接受一个ActionConfig对象,这个对象存放的就是需要调用的action实例的配置信息,根据配置信息反射生成action实例。

三、准备ActionContext:这个没什么好讲的,直接new一个ActionContext对象将request、response和 action实例传进去,其中request和response对象是通过ActionInvocation的构造方法传进来的。

数据准备完成后就要开始调用了

#调用拦截器链和action

根据Struts2的框架流程图可以很清楚地看到,在调用action之前会先调用一系列的拦截器,在调用完action之后会逆序调用拦截器(其实就是执行Interceptor中intercept方法中的invocation.invoke()方法之后的代码),就是一个递归嘛,如果你会回溯法,对这个理解起来毫无压力。

不过需要注意的是,有可能拦截器直接返回一个字符串作为结果,这样action就不会被调用到了。

那么思路就是这样的:

  1. 如果拦截器链中还有其他的Interceptor,并且未被拦截器拦截(即未返回一个结果串),那么久调用下一个拦截器的拦截方法。

  2. 如果拦截器链中没有下一个拦截器了,那么根据action配置信息即config调用action实例的处理方法。

  3. 最后将结果串返回。

代码实现:

/**
 * 调用拦截器链和action处理方法
 * @param invocation 
 * @return
 */
public String invoke(ActionInvocation invocation) {
	// 结果串
	String result = null;
	// 判断拦截器链是否还有下一个拦截器或者未被拦截器拦截(result不等于null的话说明已经有拦截器直接返回结果串了)
	if (interceptors!=null && interceptors.hasNext() && result==null) {
		// 有下一个拦截器,调用下一个拦截器的拦截方法
		Interceptor next = interceptors.next();
		result = next.intercept(invocation);
	} else {
		// 没有下一个拦截器,调用action实例的处理方法
		// 获取处理的方法名
		String methodName = config.getMethod();
		try {
			Method method = action.getClass().getMethod(methodName);
			result = (String) method.invoke(action);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("action方法调用失败:" + methodName);
		}

	}
	return result;
}

拦截器链和action的整个调用流程就是这样子的了。

#获取ActionContext
在Struts2中ActionInvocation类有个方法ActionContext getInvocationContext()会返回一个ActionContext对象,其实这个对象就是我们上面定义的invocationContext,为action实例的调用而准备的,我们也可以提供获取它的方法。

public ActionContext getInvocationContext() {
	return invocationContext;
}

到了这里,整个ActionInvocation就完成了

ActionInvocation类完整代码:

package edu.jyu.invocation;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.jyu.config.ActionConfig;
import edu.jyu.context.ActionContext;
import edu.jyu.interceptor.Interceptor;

/**
 * 拦截器链和action的调用类
 * 
 * @author Jason
 */
public class ActionInvocation {
	// 拦截器链
	private Iterator<Interceptor> interceptors;
	// 即将要被调用的action实例
	private Object action;
	// action配置信息
	private ActionConfig config;
	// 数据中心ActionContext
	private ActionContext invocationContext;

	/**
	 * 准备各种需要的数据
	 * 
	 * @param interceptorClassNames
	 *            存放着拦截器链每个拦截器的全限定类名
	 * @param config
	 *            需要调用的action的配置信息
	 * @param request
	 * @param response
	 */
	public ActionInvocation(List<String> interceptorClassNames, ActionConfig config, HttpServletRequest request,
			HttpServletResponse response) {
		// 准备Interceptor链
		if (interceptorClassNames != null && interceptorClassNames.size() > 0) {
			List<Interceptor> list = new ArrayList<Interceptor>();
			for (String className : interceptorClassNames) {
				try {
					Interceptor interceptor = (Interceptor) Class.forName(className).newInstance();
					interceptor.init();
					list.add(interceptor);
				} catch (Exception e) {
					e.printStackTrace();
					throw new RuntimeException("创建Interceptor失败:" + className);
				}
			}
			interceptors = list.iterator();
		}

		// 准备action实例
		this.config = config;
		try {
			action = Class.forName(config.getClassName()).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("创建Action失败:" + config.getClassName());
		}

		// 准备数据中心ActionContext
		invocationContext = new ActionContext(request, response, action);
	}
	
	/**
	 * 调用拦截器链和action处理方法
	 * @param invocation 
	 * @return
	 */
	public String invoke(ActionInvocation invocation) {
		// 结果串
		String result = null;
		// 判断拦截器链是否还有下一个拦截器或者未被拦截器拦截(result不等于null的话说明已经有拦截器直接返回结果串了)
		if (interceptors!=null && interceptors.hasNext() && result==null) {
			// 有下一个拦截器,调用下一个拦截器的拦截方法
			Interceptor next = interceptors.next();
			result = next.intercept(invocation);
		} else {
			// 没有下一个拦截器,调用action实例的处理方法
			// 获取处理的方法名
			String methodName = config.getMethod();
			try {
				Method method = action.getClass().getMethod(methodName);
				result = (String) method.invoke(action);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException("action方法调用失败:" + methodName);
			}

		}
		return result;
	}
	
	public ActionContext getInvocationContext() {
		return invocationContext;
	}
}


好了,ActionInvocation大功告成,项目已经上传到Github上
https://github.com/HuangFromJYU/JStruts2

如果大家有什么问题或者发现什么错误可以发邮件到jasonwong_hjj@qq.com,共同学习共同进步

自己实现Struts2(一)Struts流程介绍和环境搭建 为什么要自己实现Struts2Struts2是无疑是一个经典的、优秀的框架,实现了MVC模式,层次结构清晰,而且还提供了一些非常有用的插件。当然了,我的目的不是为了介绍Struts2的全部功能,说老实话Struts2的很多功能我都没用过也不知道。虽然这几年Struts2已经式微,逐渐被Spring MVC替代,但是Struts2作为一个曾经非常流行的框架,它整体框架的实现思想无疑是十分优秀的,这系列 阅读详情

相关推荐

ActionInvocation 源码阅读

AOP 博文链接:https://cuillgln.iteye.com/blog/1705622

ActionInvocation的作用

 一个ActionInvocation实例代表一个action的执行状态,持有拦截器和将要执行的action的实例。ActionInvocation就是Action的调用者。ActionInvocation在Action的执行过程中,负责Interceptor、Action和Result等一系列元素的调度。Interceptor通过ActionInvocation可以完全的改变Action行为:不...

weixin_39553873的博客 2802

N5105核显直通PVE:从黑屏到HDMI输出的完整指南

PCI直通能让虚拟机独占物理设备,但核显直通远没有独显那么轻松。Intel核显与CPU、显示输出链路的强耦合使UEFI引导、GOP驱动、驱动签名等环节都成了黑屏陷阱。在PVE虚拟化环境中,通过IOMMU开启、vfio-pci绑定、OVMF固件和Q35机型配合,可以绕过KVM检测,让Windows虚拟机正确驱动核显,从HDMI口输出画面,并解锁Intel Quick Sync硬解能力。这种方案尤其适合N5105等低功耗迷你主机,可作为客厅HTPC、本地视频硬解或依赖硬件加速的轻量工作台。本文基于N5105平台

weixin_31082403的博客 374

ActionInvocation,(请求)数据对象

<br />  ActionInvocation 是Xworks 中Action 调度的核心。而对Interceptor 的调度,也正是由ActionInvocation负责。<br />  ActionInvocation 是一个接口, 而DefaultActionInvocation 则是Webwork 对ActionInvocation的默认实现。<br /><br /><br /> Interceptor 的调度流程大致如下:<br /><br />1. ActionInvocation初始化时,根

Lost_wings的专栏 981

量子阱技术解析:从基础原理到前沿应用

本文深入解析量子阱技术,从微观“能量游泳池”的基础原理出发,阐释了其通过限制电子实现能级量子化,从而精确调控发光波长的核心机制。文章详细探讨了量子阱在半导体激光器和LED中的革命性应用,如实现低阈值电流与高亮度显示,并展望了其在能带工程及量子级联激光器等前沿领域的发展与挑战。

weixin_29267307的博客 282

安装升级最新版本postman时遇到“无法定位程序输入点 SetDefaultDllDirectories于动态链接库KERNEL32.dll 上.”的问题

软件版本迭代更新真快,最近升级最新Postman版本时出现以下问题 我就简单纪录下解决办法: 备注:我用的是最新的postman工具包:Postman-win64-7.25.0-Setup.exe,目前是最新 0. 前提是已经到postman官网https://www.postman.com/downloads/下载好软件工具包 1.安装window7系统更新补丁KB2533623,请到微软公司官网https://support.microsoft.com/en-us/help/2...

董广明的博客 1万+

ActionInvocation的理解

1.actionInvocation是什么 ActionInvocation就是Action的调用者。ActionInvocation在Action的执行过程中,负责Interceptor、Action和Result等一系列元素的调度。 理解ActionInvocation你需要对Action的调用过程有一个全面的了解: http://tech.ddvip.com/2009-01

粉末无颜的专栏 3849

uniapp+萤石视频监控实战:解决ezuikit.js真机调试不显示的5个关键步骤

本文针对Uniapp集成萤石视频监控时ezuikit.js在真机调试中黑屏不显示的问题,提供了5个关键解决步骤。核心方案是采用Webview加载独立H5播放页,以规避跨平台环境差异,并详细阐述了资源放置、多端适配、通信处理及系统化排查方法,确保视频流稳定播放。

weixin_29001655的博客 286

ActionInvocation类的使用和探究

“将Web页面中的输入元素封装为一个(请求)数据对象”,这个对象就是ActionInvocation类型. 对于Xwork 而言,前端的Webwork 组件为其提供的是一个Map 类型的数据结构。而Action面向的却是Model对象所提供的数据结构。在何时、何处对这两种不同的数据结构进行转换? 写一个辅助类完成这样的工作,并在每次Action 调用之前由框架代码调用他完成转换工作...

suoyihen 257

实战 | OpenCV实现扫描文本矫正应用与实现详解(附源码)

导读 本文主要介绍使用OpenCV对扫描文本矫正的应用实例及详细实现步骤。 背景介绍 在使用打印机或扫描仪扫描文档时,由于摆放位置差异难免造成扫描文档的倾斜。本文将使用OpenCV将倾斜的文档矫正水平并去除黑边。 实现步骤 本文只针对包含大部分文字的文档做倾斜矫正,思路来源是大部分文字倾斜后同一行的也在同一条直线,通过拟合直线计算文本倾斜角度,然后旋转来实现文本倾斜矫正。 详细步骤: ①加载倾斜图像 ②灰度转换+腐蚀+膨胀 ③Canny边缘检测 + 霍夫线变换检测直线 ...

Color Space的博客 3400

Oracle EBS与SAP数据数据切换至迁移华为MetaERP分析

Oracle EBS到华为MetaERP的数据迁移可采用“表对表复制”思路,因其模块化设计下数据模型标准化、边界清晰。核心业务对象存储在结构明确的主表中,与MetaERP模型兼容度高,便于直接映射。而SAP到MetaERP的迁移则因SAP高度优化的复杂表结构(如簇表/池表)、数据分散冗余、深度依赖配置等特点,无法简单复制,必须采用基于业务对象的迁移方法,通过视图/BAPI提取数据并进行深度转换。两种迁移的本质差异源于源系统的数据模型设计理念不同。

金牌架构师 1379

【转】struts2的ActionInvocation分析(action调度者)

一个ActionInvocation实例代表一个action的执行状态,持有拦截器和将要执行的action的实例。 defaultActionInvocation是其默认实现。下面是定义在该类中的部分成员变量 1 public class DefaultActionInvocation implements ActionInvocation { 2 protected Objec...

weixin_30772105的博客 220

把雷达强度特征融合于 Cartographer的实现流程 :从地图构建到在线定位

摘要:本文提出在激光SLAM中融合强度特征的方法,解决几何匹配在退化环境中的失效问题。详细介绍了两种高反地图生成方式:离线使用assets_writer工具处理优化轨迹,在线实时累积高反点;以及权重网格的构建与预计算金字塔方法。定位阶段通过加权得分公式融合几何和强度信息,采用自适应缩放策略平衡特征依赖。该方案在不显著增加计算负担的前提下,有效提升了对称环境等退化场景的定位稳定性,对利用人工路标的移动机器人具有实用价值。

Studying…… 1328

struts2的ActionInvocation分析(action调度者)

一个ActionInvocation实例代表一个action的执行状态,持有拦截器和将要执行的action的实例。 defaultActionInvocation是其默认实现。下面是定义在该类中的部分成员变量 public class DefaultActionInvocation implements ActionInvocation { protected Object actio

ikaraide的专栏 1万+

HotSpot G1 GC 的分区记账、SATB 并发标记与停顿目标调优解析

线上GC毛刺该调停顿目标、加大新生代还是换收集器?本文从HotSpot G1的设计出发,梳理分区与巨型对象、卡表与记忆集、写屏障与细化线程、停顿预测、SATB并发标记、自适应IHOP、混合回收规则及Full GC兜底,并注明JDK8至JDK27的版本差异。文中在JDK8与JDK17上实测:停顿目标从200ms降到20ms,伊甸区缩小四成、P99下降但仍超目标;巨型对象会反复触发又撤销并发标记;JDK17并行Full GC平均停顿约为JDK8的三成。最后给出日志解读、参数清单、调优流程与选型。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 170万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Struts2中ActionInvocation

1.ActionInvocation是什么 ActionInvocation就是Action的调用者。ActionInvocation在Action的执行过程中,负责Interceptor、Action和Result等一系列元素的调度。 2.ActionInvocation干什么 Interceptor通过ActionInvocation可以完全的改变Action行为:不让它执行

星晴coral 1188

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

深入struts2.0(七)--ActionInvocation接口以及3DefaultActionInvocation类

1.1.1       ActionInvocation类 ActionInvocation定义为一个接口,主要作用是表现action的执行状态。它拥有拦截器和action的实例。通过反复的执行invoke方法。首先被actionProxy,然后是拦截器,所有拦截器执行完后就是action和result . 图3.3.4 ActionInvocation类的主要方法 1.1.2     

夜深人静后的码农 1903

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Struts2 ActionInvocation

Interceptor说明 Interceptor的接口定义没有什么特别的地方,除了init和destory方法以外,intercept方法是实现整个拦截器机制的核心方法。而它所依赖的参数ActionInvocation则是我们之前章节中曾经提到过的著名的Action调度者。 我在这里需要指出的是一个很重要的方法invocation.invoke()。这是ActionInvocatio

HGodsun的博客 539

Struts2.0中ActionInvocation使用

Interceptor说明 Interceptor的接口定义没有什么特别的地方,除了init和destory方法以外,intercept方法是实现整个拦截器机制的核心方法。而它所依赖的参数ActionInvocation则是我们之前章节中曾经提到过的著名的Action调度者。 我在这里需要指出的是一个很重要的方法invocation.invoke()。这是ActionInvocatio

xwnxwn的专栏 1万+

Struts2之ServletActionContext、ActionContext、ActionInvocation

1、ActionContext api详解static ActionContext getContext():返回ActionContext对象 Map<String,Object> getApplication() :返回代表ServletContext的map Map<String,Object> getContextMap() :返回代表HttpServletRequest的map Ma

gu_solo的博客 685

struts2 拦截器和actioninvocation

Interceptor说明 Interceptor的接口定义没有什么特别的地方,除了init和destory方法以外,intercept方法是实现整个拦截器机制的核心方法。而它所依赖的参数ActionInvocation则是我们之前章节中曾经提到过的著名的Action调度者。 我在这里需要指出的是一个很重要的方法invocation.invoke()。这是ActionInvocatio

gy1055277934的博客 363

actionInvocation是什么

<br />1.actionInvocation是什么<br />     ActionInvocation就是Action的调用者。ActionInvocation在Action的执行过程中,负责Interceptor、Action和Result等一系列元素的调度。<br /> <br />    理解ActionInvocation你需要对Action的调用过程有一个全面的了解:<br />             http://tech.ddvip.com/2009-01/12320909191060

wcp88888888的专栏 5810

actionInvocation.invoke()是什么意思,配置自己的验证拦截器

关于Struts2的自定义的验证截器 package ch06.struts2.Interceptor; import java.util.Map; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.i

阿狸_桃子 5598
上一篇: 自己实现Struts2(三)实现ActionContext
下一篇: 自己实现Struts2(五)实现StrutsPrepareAndExecuteFilter
腹黑大壁花
博客等级 码龄12年 157粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值