操作方法导出excel并阻止用户重新处理操作直到完成

我试图编写一个操作方法来导出一个Excel,同时防止用户在处理时重新调用该操作。

问题是,当我重新点击提交(导出)时,要导出的excel的内容显示在网页上,当导出完成时,我有这个例外:

rg.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [default] in context with path [/myApp] threw exception java.lang.RuntimeException: org.apache.jasper.JasperException: An exception occurred processing JSP page /decorators/main.jsp at line 48 

我使用这个代码为我的行动方法:

 @Action(value = "exportExcelMdt", results = { @Result(name = "exportExcel", type = "stream", params = { "inputName", "inputStream", "contentType", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "contentDisposition", "attachment;filename=${filename};", "bufferSize", "1024" }), @Result(name = "success", type = ActionSupport.NONE) }) public String doExportExcel() { Boolean exportPending = (Boolean) this.session.get(EXPORT_EXCEL); if (exportPending == null) { // this is used as a semaphore to prevent the user from re-calling the export action (server-side of course) try { this.session.put(EXPORT_EXCEL, Boolean.TRUE); logger.debug("export excel..."); this.filename = this.getText("myApp.message.mandat.recherche.extraction.filename"); this.inputStream = this.extractExcel(this.searchResults(false)); // this will just get the related beans and write the excel file using Apache POI return "exportExcel"; } catch (Exception e) { logger.debug("export excel erreur..."); } finally { this.session.remove(EXPORT_EXCEL); } } else { // this.addActionMessage("An export excel is already running !"); } return SUCCESS; } 

调用动作的JSP代码:

 function insertExcelButtonForExtraction() { // creer le nom depuis "#gview_" + l'id de la grid var $btnExcel = $('#gview_resultGrid > div > #btnExcel'); // Check if object already exists if(!$btnExcel.length) { var $a = $('#gview_resultGrid > div > a'); var $newA = $a.clone(); $newA.attr('style', 'right: 25px; padding-top: 2px;'); $newA.attr('id', 'btnExcel'); $newA.children("span").remove(); $newA.append($('<input id="searchForm_exportExcelMdt" type="image" onclick="exportExcel();" src="/myApp/img/page_white_excel.png" title="<s:text name="myApp.message.js.button.excelExtraction"/>"/>')); $newA.insertAfter($a); } } // export excel function exportExcel() { $("#searchForm").attr("action", "exportExcelMdt.action"); $("#searchForm").submit(); } 

这里是相关的struts.xml文件:

 <struts> <constant name="struts.objectFactory" value="spring" /> <constant name="struts.convention.result.path" value="/jsp/" /> <constant name="struts.convention.default.parent.package" value="app-pkg" /> <constant name="struts.ui.theme" value="simple" /> <constant name="struts.custom.i18n.resources" value="messages" /> <constant name="struts.devMode" value="${struts.mode}" /> <constant name="struts.convention.package.locators" value="ihm,actions" /> <!-- <constant name="struts.multipart.saveDir" value="" /> --> <constant name="struts.multipart.maxSize" value="10000000" /> <package name="app-pkg" extends="json-default,struts-default"> <interceptors> <interceptor name="exception" class="amundi.sits.sigma.web.utils.interceptor.ExceptionLoggingInterceptor" /> <interceptor name="i18n" class="amundi.sits.sigma.web.utils.interceptor.I18nInterceptor" /> <!-- Basic Stack --> <interceptor-stack name="appBasicStack"> <interceptor-ref name="exception"> <param name="logEnabled">true</param> <param name="logLevel">ERROR</param> </interceptor-ref> <interceptor-ref name="i18n" /> <interceptor-ref name="fileUpload"/> <interceptor-ref name="servletConfig" /> <interceptor-ref name="prepare"> <param name="excludeMethods">search*</param> </interceptor-ref> <interceptor-ref name="checkbox" /> <interceptor-ref name="multiselect" /> <interceptor-ref name="actionMappingParams" /> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*</param> </interceptor-ref> </interceptor-stack> <interceptor-stack name="appStack"> <interceptor-ref name="appBasicStack" /> <interceptor-ref name="conversionError" /> <interceptor-ref name="validation" /> <interceptor-ref name="workflow" /> </interceptor-stack> <interceptor-stack name="annotatedStack"> <interceptor-ref name="i18n" /> <interceptor-ref name="params" /> <interceptor-ref name="conversionError" /> <interceptor-ref name="annotationWorkflow" /> </interceptor-stack> <!-- Stack basique qui priorise les params sur le prepare --> <interceptor-stack name="paramsFirstStack"> <interceptor-ref name="i18n" /> <interceptor-ref name="exception"> <param name="logEnabled">true</param> <param name="logLevel">ERROR</param> </interceptor-ref> <interceptor-ref name="checkbox" /> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*</param> </interceptor-ref> <interceptor-ref name="servletConfig" /> <interceptor-ref name="prepare" /> <interceptor-ref name="actionMappingParams" /> </interceptor-stack> <!-- Stack Json validation --> <interceptor-stack name="jsonValidationStack"> <interceptor-ref name="appBasicStack" /> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> <interceptor-ref name="jsonValidation" /> <interceptor-ref name="workflow" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="appStack" /> <global-results> <result name="exception">/jsp/view/error/error.jsp</result> <result name="login" type="redirect">/Login.action</result> <result name="accessdenied" type="redirectAction"> <param name="actionName">security/access/accessDenied.action</param> <param name="namespace">/</param> </result> </global-results> <global-exception-mappings> <exception-mapping exception="java.lang.Throwable" result="exception" /> </global-exception-mappings> </package> 

执行和等待拦截器似乎提供你所需要的