首页 > WEB开发 > 后台开发 > Struts2结果类型、拦截器及文件上传下载
2014
09-13

Struts2结果类型、拦截器及文件上传下载

03. Struts2结果类型、拦截器及文件上传下载23

本文思路:

首先讲解Struts2中的结果类型和拦截器,之所以把这两个知识点放在一起,也是受struts-default包中将这两者放在一起定义所启发。

最后讲解了Struts2中的文件上传和下载,因为这个是拦截器和结果类型的典型应用。

一、结果(视图)类型详解

All results (except for Action.NONE) of an Action are mapped to a View implementation. Examples of Views might be:

译:一个Action(动作方法)的返回结果会被映射到一个视图(除了返回Action.NONE)。下面是一些视图的例子:

  • ActionChainView – executes another action
  • SerlvetRedirectView – redirects the HTTP response to a URL
  • ServletDispatcherView – dispatches the HTTP response to a URL

当然,你也可以定义自己的结果视图类型。

在struts-default.xml配置文件中定义了很多结果类型,如下图所示:

03. Struts2结果类型、拦截器及文件上传下载790

1、常用结果视图类型说明:

  • dispatcher:默认结果类型。请求转发到一个页面。该结果类型有一个默认参数:location。

03. Struts2结果类型、拦截器及文件上传下载857

  • redirect:请求重定向到一个页面。
  • chain:请求转发到另一个动作。

03. Struts2结果类型、拦截器及文件上传下载898

  • redirectAction:重定向到另外一个动作。该结果类型可接受的参数有:actionName(默认)和namespace。

03. Struts2结果类型、拦截器及文件上传下载965

  • stream:文件下载时用

2、自定义结果类型(Result接口

案例:自定义一个结果视图类型,返回一个验证码图片。

① 编写一个类,实现Result接口。需要实现其中的execute方法。

public class CaptchaResult implements Result {
	public void execute(ActionInvocation arg0) throws Exception {
		int width = 120;
		int height = 30;

		//创建一副内存图像(画布)
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		//怎么创建见《Response&Request》一文,此处略
		//……………………
		//得到response对象,用于响应输出验证码图片
		HttpServletResponse response = ServletActionContext.getResponse();

		//输出
		response.setHeader("Expires", "-1");
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "no-cache");
		ImageIO.write(image, "jpg", response.getOutputStream());
	}
}

② 声明结果类型(配置struts.xml)

<package name="parent-package" extends="struts-default">
	<result-types>
		<result-type name="captcha" class="org.flyne.demo.CaptchaResult"></result-type>
	</result-types>
</package>

③ 使用(先声明,后使用):

<package name="p1" extends="parent-package">
	<action name="captcha">
		<result name="success" type="captcha">	</result>
	</action>
</package>

当用户请求captcha.action时即可得到该验证码图片。

改进:要求在使用该结果类型时可以指定验证码图片的宽度和高度。则需要:

① 改写Captcha类,增加width、height私有字段并提供setter和getter方法。

public class CaptchaResult implements Result {
	private int width = 120;//当配置文件中不指定宽度和高度参数时的默认值
	private int height = 30;
	//setter、getter方法省略
	public void execute(){……}

② 结果类型的声明不变,使用如下:

<action name="captcha">
	<result name="success" type="captcha">
		<param name="width">150</param>
		<param name="height">35</param>
	</result>
</action>

二、拦截器(AOP、责任链)

1、Struts2中定义的拦截器

在struts-default.xml配置文件中定义了很多过滤器,如下图所示:

03. Struts2结果类型、拦截器及文件上传下载2575

图中的省略号表示同类元素太多,就省略了。关于图中①②③处的说明如下:

① 拦截器声明(先声明,后使用,可以想想程序中的变量)

② 拦截器栈的声明(可引用拦截器或拦截器栈)

③ struts-default包中定义的默认拦截器栈(☆)

扩展:Struts2中的拦截器栈和Java Web中的过滤器链都是责任链设计模式的体现,详见《责任链设计模式》一文。

Eg:列举你用过的拦截器?

staticParam、params、conversionError、servletConfig、modelDriven、validation、workflow等。

2、自定义拦截器(一)

案例:自定义一个计算Struts2程序执行时间的拦截器。

分析Struts2程序的流程图(下图)可知,如果将Interceptor1视为自定义拦截器,在进入拦截器1时记下当前时间,并在出拦截器1时计算时间差值即为程序执行时间。

扩展:在执行动作方法前后进行拦截处理,这是AOP思想的体现。关于AOP思想见《动态代理技术》一文。

03. Struts2结果类型、拦截器及文件上传下载3080

1)定义一个类,继承AbstractInterceptor。

Struts2中的拦截器必须实现Interceptor接口。由于AbstractInterceptor类已经实现了该接口,因此继承AbstractInterceptor即可。

public class MyInterceptor extends AbstractInterceptor {
	public String intercept(ActionInvocation invocation) throws Exception {
		long start = System.currentTimeMillis();

		//沿着过滤器栈向下传递
		String str = invocation.invoke();

		long end = System.currentTimeMillis();
		System.out.println("耗时" + (end - start) + "毫秒");
		return str;
	}
}

2)配置:在struts.xml中声明并使用

<package name="p1" extends="struts-default">
	<interceptors>
		<interceptor name="myinterceptor" class="org.flyne.interceptor.MyInterceptor"/>
	</interceptors>

	<action name="act1" class="org.flyne.action.Demo1Action">
		<interceptor-ref name="myinterceptor"></interceptor-ref>
		<interceptor-ref name="defaultStack"></interceptor-ref>
	</action>
</package>

配置文件中的注意事项:

① 拦截器的顺序对应着<interceptor-ref>元素的顺序。要把myinterceptor放在前面才能起到计算程序执行时间的作用。

② 在action元素中一定要加入defaultStack的引用,否则defaultStack中引用的拦截器对act1就不起作用了。

上面的配置方式只能为act1指定拦截器,如果当前包中其他<action>都需要执行myinterceptor拦截器,那么就需要在每个<action>元素中引入拦截器,很麻烦。此时可以为当前包指定默认拦截器栈!

<package name="p1" extends="struts-default">
	<interceptors>
		<interceptor name="myinterceptor" class="org.flyne.interceptor.MyInterceptor"/>
		<interceptor-stack name="myStack">
			<interceptor-ref name="myinterceptor"></interceptor-ref>
			<interceptor-ref name="defaultStack"></interceptor-ref>
		</interceptor-stack>
	</interceptors>

	<default-interceptor-ref name="myStack"></default-interceptor-ref>

	<action name="act1" class="org.flyne.action.Demo1Action">
	</action>
</package>

留下一个回复

你的email不会被公开。