response与findForward之间的冲突问题

KAKUKYOWU 2010-04-28 10:52:29
工程框架:struts1

需求:在一个页面上有个csv下载的button,点击后即实现csv下载功能
现在要添加一个loding页面,点击button后页面跳转到loding页面
loding页面1秒执行一次,然后报百分比进度

方法:在action的doexportCsv()方法中
起个线程去实现csv下载
之后findForward到loding页面1秒重复执行一次doloding()方法
doloding()方法就是个监听作用
每次执行都会判断线程是否执行100%
没完就继续findForward到loding页面
完了就跳转到成功页面

问题:线程执行到csv下载时需要用到response
但是同时另一个方法doloding()又需要不断的return findForward("xxxx");
于是每次执行都会抛异常:java.lang.IllegalStateException:Cannot forward after response has been committed
查了很多相关内容,大致意思是用到response的话,在它之后如果有return findForward("xxxx");就会报这个异常
下载后的csv内容也受影响,700多条记录只有200多条


哪位大侠有遇到过这种情况,给小弟指点指点,谢谢了~~~ 先解决的50分全给!
...全文
160 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
shine333 2010-05-03
  • 打赏
  • 举报
回复

这个和我说的方法,没什么区别。
但愿得,你说的“如果action中的loding方法得到的全局变量percent为100”不是指static
KAKUKYOWU 2010-05-03
  • 打赏
  • 举报
回复
其实就是一个js的事儿:
function setAuto(time) {
var intervalTime = time;
var interval = setInterval("auto()", intervalTime * 1000); // 定时执行action中的loding方法
var percent = document.forms[0].percent.value;
if (percent != null && percent == '100') {
clearInterval(interval); // 如果action中的loding方法得到的全局变量percent为100,证明线程已经结束(线程执行的步骤只是查询数据库和组织beanList,然后放session里),停掉定时
csvDownload(); // 执行action中的csvDownload方法,从session中获取到beanList,然后完成download
}
}


关于进度百分比,也是在action中定义一个全局变量,根据代码执行的进度去往request中set百分比数值,
然后页面不断获取并显示即可。
shine333 2010-05-03
  • 打赏
  • 举报
回复
愿闻其详
KAKUKYOWU 2010-05-03
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 shine333 的回复:]
我说的最简单。
问自己一个问题,进度是动态的,而html(包括json,即使是动态生成的)如果没有新的请求,是不会自动变化的。
[/Quote]

大哥,问题我已经解决,其实非常简单,根本不用你这么麻烦。不过还是谢谢了~
shine333 2010-04-28
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 kakukyowu 的回复:]

引用 7 楼 shine333 的回复:
java.lang.IllegalStateException:Cannot forward after response has been committed

一个response(普通的response,content-type=multipart/...类型的除外)不能即包含下载,又包含页面跳转。

action方法应该return n……
[/Quote]

跟你说了,你还偏不信。你这个违反HTTP协议,无论你用struts/servlet还是asp.net,php都无法实现的。
1.你的response先接到了下载线程的header内容(告诉客户端,这个response是个csv文件)
2.然后开始输出entity内容,也就是csv文件。
3.此时,action线程开始工作,forward页面,jsp代码开始往客户端输出自己header(告诉客户端,这个response是个text/html)
此时,就报错了。
因为HTTP协议规定了,header必须在entity上面,中间用空行分开。你在一个response尝试放两种(csv/html),除了改用multipart方式,否则,就是我上面说的方式。

但愿得你迷途知返,否则“好良言难劝该死的鬼”
KAKUKYOWU 2010-04-28
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 lababa 的回复:]
可能是web容器生成的servlet代码中有out.write(""),这个和JSP中调用的response.getOutputStream()产生冲突
在jsp上加段 下面代码试试
out.clear();
out = pageContext.pushBody();
[/Quote]

加完页面都进不去了
KAKUKYOWU 2010-04-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 shine333 的回复:]
java.lang.IllegalStateException:Cannot forward after response has been committed

一个response(普通的response,content-type=multipart/...类型的除外)不能即包含下载,又包含页面跳转。

action方法应该return null;

如果要同时显示新的页面,又显示……
[/Quote]

方法是不错,但是不想改动这么大,如果实在不行的话我再试试这个吧,谢啦
lababa 2010-04-28
  • 打赏
  • 举报
回复
可能是web容器生成的servlet代码中有out.write(""),这个和JSP中调用的response.getOutputStream()产生冲突
在jsp上加段 下面代码试试
out.clear();
out = pageContext.pushBody();
shine333 2010-04-28
  • 打赏
  • 举报
回复
java.lang.IllegalStateException:Cannot forward after response has been committed

一个response(普通的response,content-type=multipart/...类型的除外)不能即包含下载,又包含页面跳转。

action方法应该return null;

如果要同时显示新的页面,又显示下载的话,比较简单的做法是,下载单独作为一个action,页面中包含了一个隐藏的iframe,指向这个路径。

下载的线程往session里面设置百分比,页面上ajax定时索取。
KAKUKYOWU 2010-04-28
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 lababa 的回复:]
return null 试试还报错么
[/Quote]

可是return null 页面就没法跳转了啊
KAKUKYOWU 2010-04-28
  • 打赏
  • 举报
回复
public ActionForward doloading(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request,
HttpServletResponse response) throws Exception {

if (loadingBean.getPercent() == 100) {
logger.info("AllCustAccountInfoAction.doloading() ==> success!!! ");
return actionMapping.findForward("success");
}

request.setAttribute("percent", loadingBean.getPercent());

return actionMapping.findForward("loading");
}
lababa 2010-04-28
  • 打赏
  • 举报
回复
return null 试试还报错么
KAKUKYOWU 2010-04-28
  • 打赏
  • 举报
回复
public static void exportCsv(HttpServletResponse response, String file, List<String[]> rows) throws IOException {

StringBuffer record = new StringBuffer();

for (int i = 0; i < rows.size(); i++) {
String[] cells = rows.get(i);

if (cells != null) {
for (int j = 0; j < cells.length; j++) {
record.append(cells[j] + ",");
}
record.append("\r\n");
}
}

response.reset();
response.setContentType("Application/text/csv");

response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(file, DEFAULT_ENCODING)
+ "\"");

ServletOutputStream servletout = response.getOutputStream();
PrintWriter outpw = new PrintWriter(new OutputStreamWriter(servletout, SHIFTJIS_ENCODING));

outpw.write(record.toString());
outpw.close();
servletout.close();
}
KAKUKYOWU 2010-04-28
  • 打赏
  • 举报
回复
public void run() {

AllCustAccountInfoService aais = new AllCustAccountInfoService();

try {
CsvExportUtil.exportCsv(loadingBean.getResponse(), loadingBean.getFileName(), aais
.buildCsvFile(loadingBean));
} catch (Exception e) {
logger.error("AllCustAccountInfoAction.run() exportCsv error!!!", e);
}

loadingBean.setPercent(100);// 线程执行结束设置百分比为100
}
KAKUKYOWU 2010-04-28
  • 打赏
  • 举报
回复
public ActionForward doexportCsv(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request,
HttpServletResponse response) throws Exception {

Thread exportCsvThread = new Thread(this, "");
exportCsvThread.setName("loading");
loadingBean = new LoadingBean();
loadingBean.setOpenStatus(request.getParameter("openStatus"));
loadingBean.setFileName("customerinfo.csv");
loadingBean.setResponse(response);
loadingBean.setPercent(0); // 起始的百分比,线程执行的过程中根据执行情况而不断变化
exportCsvThread.start();

return actionMapping.findForward("loading");
}
shine333 2010-04-28
  • 打赏
  • 举报
回复
我说的最简单。
问自己一个问题,进度是动态的,而html(包括json,即使是动态生成的)如果没有新的请求,是不会自动变化的。
KAKUKYOWU 2010-04-28
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 shine333 的回复:]
引用 9 楼 kakukyowu 的回复:

引用 7 楼 shine333 的回复:
java.lang.IllegalStateException:Cannot forward after response has been committed

一个response(普通的response,content-type=multipart/...类型的除外)不能即包含下载,又包含页面跳……
[/Quote]

兄弟,我没有不信你,只是在考虑怎样改最简单。用json应该可以实现吧?

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧