我正在尝试编写一个Action方法来导出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>