Struts2 execAndWait拦截器示例,用于长时间运行的动作

时间:2020-02-23 14:36:05  来源:igfitidea点击:

有时,我们需要长时间运行,因此用户必须等待最终结果。
在这种情况下,用户可能会无响应而烦恼,并且可能会刷新导致应用程序出现问题的页面。

Struts2提供了execAndWait拦截器,我们可以将其用于长时间运行的动作类,以便在服务器端进行处理时向用户返回中间结果。
处理完成后,将向用户显示最终结果页面。

Struts-default包中已经定义了Struts2 execAndWait拦截器,我们只需要为我们的操作类配置它即可。
该实现存在于" ExecuteAndWaitInterceptor"类中,该类返回" wait"结果页,直到操作类的处理完成。

拦截器提供了两个变量-延迟第一次返回等待响应和延迟SleepInterval以检查动作类处理是否完成。
这两个变量都可以在struts配置中被覆盖并以毫秒为单位进行测量。

我们将通过一个简单的Web应用程序项目对此进行研究,其项目结构如下图所示。
在Eclipse中创建名为Struts2ExecAndWait的动态Web项目,并将其配置为maven项目。

项目配置

在web.xml中添加以下过滤器,以配置Web应用程序以使用Struts2框架。

<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

在pom.xml文件中添加struts2-core依赖项,如下所示。

<dependencies>
	<dependency>
		<groupId>org.apache.struts</groupId>
		<artifactId>struts2-core</artifactId>
		<version>2.3.15.1</version>
	</dependency>
</dependencies>

struts.xml配置

struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"https://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<!-- constant to define result path locations to project root directory -->
	<constant name="struts.convention.result.path" value="/"></constant>
	
	<package name="user" namespace="/" extends="struts-default">
		<action name="run">
			<result>/run.jsp</result>
		</action>
		<action name="ExecuteTask" class="com.theitroad.struts2.actions.ExecuteTaskAction">
			<interceptor-ref name="defaultStack"></interceptor-ref>
			<interceptor-ref name="execAndWait">
				<!-- override delay and delaySleepInterval parameters of execAndWait to 500ms -->
				<param name="delay">500</param>
				<param name="delaySleepInterval">500</param>
			</interceptor-ref>
			<result name="wait">/running.jsp</result>
			<result name="success">/success.jsp</result>
		</action>
	</package>

</struts>

应用程序的入口点是run.action,通过它用户将以秒为单位提供执行任务的时间。
该任务将由ExecuteTaskAction执行。
我们已经重写了ExecuteTask操作的拦截器,使其首先具有defaultStack,然后具有execAndWait拦截器。

注意execAndWait拦截器应该是拦截器堆栈中的最后一个。
我们也将delay和delaySleepInterval值重写为500ms。
延迟的默认值为0,delaySleepInterval为100ms。

ExecuteAndWaitInterceptor返回等待结果作为中间响应,因此我们需要将其配置为操作的结果页面。
处理完成后,成功结果将返回给用户。

Action类

package com.theitroad.struts2.actions;

import java.util.Date;

import com.opensymphony.xwork2.ActionSupport;

public class ExecuteTaskAction extends ActionSupport {

	@Override
	public String execute() {
		//process task for given time
		System.out.println("Starting execution. Current time: "+new Date());
		processTask();
		System.out.println("Ending execution. Current time: "+new Date());
		return SUCCESS;
	}

	private void processTask() {
		System.out.println("Time to process:"+processingTime);
		try {
			Thread.sleep(getProcessingTime()*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private int processingTime;

	public int getProcessingTime() {
		return processingTime;
	}

	public void setProcessingTime(int processingTime) {
		this.processingTime = processingTime;
	}

	
}

动作类非常简单,只需等待输入时间即可返回成功响应。
在现实生活中,可能涉及大量处理,导致响应延迟。

JSP页面

run.jsp

<%@ page language="java" contentType="text/html; charset=US-ASCII"
  pageEncoding="US-ASCII"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Long Process Input Page</title>
</head>
<body>
<h3>ExecAndWait Interceptor Example</h3>
<s:form action="ExecuteTask">
<s:textfield name="processingTime" label="Enter seconds to execute task"></s:textfield>
<s:token 
<s:submit name="submit" label="Run" align="center"></s:submit>
</s:form>
</body>
</html>

这是应用程序的入口,并在运行操作中使用。
我们需要使用令牌的形式,以便execAndWait拦截器可以识别请求。

running.jsp

<%@ page language="java" contentType="text/html; charset=US-ASCII"
  pageEncoding="US-ASCII"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<meta http-equiv="refresh" content="2;url=<s:url includeParams="all" "
<%-
<meta http-equiv="refresh" content="2""
Above refresh meta will also work as long as browser supports cookie, 
by including params above we are making sure that it will work even when cookies are disabled
 --%>
<title>Processing intermediate page</title>
</head>
<body>
<h3>Your request is getting processed</h3>
<img alt="processing" src="images/processing.gif" align="middle">
</body>
</html>

这是execAndWait拦截器返回的中间响应。
该页面应具有"刷新"元,将请求发送到服务器以获取最终响应。
如果我们没有这个选项,那么浏览器将不会发送进一步的请求并停留在此页面上。
我们每2秒刷新一次页面,并将所有输入参数传递给服务器。
我们还在页面中显示processing.gif,看起来正在进行某些处理。

success.jsp

<%@ page language="java" contentType="text/html; charset=US-ASCII"
  pageEncoding="US-ASCII"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Long Process Success Page</title>
</head>
<body>
<h3>Task executed for <s:property value="processingTime" seconds successfully.</h3>
</body>
</html>

一个简单的响应页面,它是操作类返回的最终结果。