Struts2 execAndWait拦截器示例,用于长时间运行的动作
有时,我们需要长时间运行,因此用户必须等待最终结果。
在这种情况下,用户可能会无响应而烦恼,并且可能会刷新导致应用程序出现问题的页面。
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>
一个简单的响应页面,它是操作类返回的最终结果。