精华帖 (4) :: 良好帖 (0) :: 新手帖 (8) :: 隐藏帖 (18)
|
|
---|---|
作者 | 正文 |
发表时间:2011-01-27
最后修改:2011-01-27
------------------------- 搞了大半天,总是奇怪问题的现象,最后附录自己的思考过程。 --------------------------------------- 现象: 由于当用户在上传文件的时候,由于文件在上传过程中流还没传送完毕结果客户端就断开了链接(可能耗时比较久,造成浏览器假死的状态,然后用户强制关闭了浏览器的进程),导致上传组件抛出异常,而且这个异常在关闭上传页面之后再打开的时候还是存在,引起上传的功能点崩溃。 ----------------------分析------------------- 原因分析: 原先使用 struts2 自带的common-fileupload 组件上传文件。 当文件上传出错时(包括强行关闭浏览器导致的流关闭错误),会产生actionerror对象 。 在进入Action之前 会 经过 validate 方法, validate 方法 检测到 actionerror 后,会直接转向input页面,导致错误信息一直出现,从而导致上传组件不可用。只能通过服务器重启来解决。 (PS:spring 配置的action是单列) ---------STRUTS2源码-------- 源码大家自己去看吧。 大概流程就是 FilterDispatcher--->Dispatcher--->MultiPartRequestWrapper 然后交由Apache的commons-fileupload组件来解析了。 在MultiPartRequestWrapper的构造方法中,会调用MultiPartRequest(默认为JakartaMultiPartRequest类)的parse方法来解析请求。 -------------------------------------------------------------- 解决方案如下: 1. 覆盖组件中的JakartaMultiPartRequest方法,丢弃error对象。 (据说还诡异的出现问题。) 2. 修改action类,重写validate ()方法,清除ErrorsAndMessages 。 3. 更换组件。采用smartupload组件(但是这个组件对大文件上传存在着内存溢出的问题,只支持到100M 左右) 所以妥妥的 方案2.。。。。。。。。。。。 ---------------方案一----------------- public void parse(HttpServletRequest servletRequest, String saveDir) throws IOException { DiskFileItemFactory fac = new DiskFileItemFactory(); // Make sure that the data is written to file fac.setSizeThreshold(0); if (saveDir != null) { fac.setRepository(new File(saveDir)); } // Parse the request try { ServletFileUpload upload = new ServletFileUpload(fac); upload.setSizeMax(maxSize); List items = upload.parseRequest(createRequestContext(servletRequest)); for (Object item1 : items) { FileItem item = (FileItem) item1; if (log.isDebugEnabled()) log.debug("Found item " + item.getFieldName()); if (item.isFormField()) { log.debug("Item is a normal form field"); List<String> values; if (params.get(item.getFieldName()) != null) { values = params.get(item.getFieldName()); } else { values = new ArrayList<String>(); } // note: see http://jira.opensymphony.com/browse/WW-633 // basically, in some cases the charset may be null, so // we're just going to try to "other" method (no idea if this // will work) String charset = servletRequest.getCharacterEncoding(); if (charset != null) { values.add(item.getString(charset)); } else { values.add(item.getString()); } params.put(item.getFieldName(), values); } else { log.debug("Item is a file upload"); // Skip file uploads that don't have a file name - meaning that no file was selected. if (item.getName() == null || item.getName().trim().length() < 1) { log.debug("No file has been uploaded for the field: " + item.getFieldName()); continue; } List<FileItem> values; if (files.get(item.getFieldName()) != null) { values = files.get(item.getFieldName()); } else { values = new ArrayList<FileItem>(); } values.add(item); files.put(item.getFieldName(), values); } } } catch (FileUploadException e) { log.error(e); e.printStackTrace(); //注意此处的修改~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //errors.add(e.getMessage()); } } 方案1的方法:别忘记了配置struts.xml的bean ,和struts.properties. --------------思考过程--------------- 1. 为什么关闭浏览器后,问题依旧存在。。 自然会想到单列~~~~~~~~~~~~ 2. 为什么后续问题不进ACTION 自然会想到拦截·····是什么拦截呢?(结合源码分析中的error对象, 这个对象校验使用到,那么 自然而然 变成是 校验拦截) 3.结合起来,问题就不奇怪了········· ,要发现问题现象和JAVA领域知识相结合。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-01-27
是你自己弄的悲剧,struts2的action需要是prototype的。你配置成singleton的当然会保留之前的状态。验证的时候有那个Error的状态自然会错。
|
|
返回顶楼 | |
发表时间:2011-01-28
Agrael 写道 是你自己弄的悲剧,struts2的action需要是prototype的。你配置成singleton的当然会保留之前的状态。验证的时候有那个Error的状态自然会错。 spring 里的action 配置 相信大家基本都是配的单列。 项目配置的问题。 我也不明白为什么把action配置成singleton有什么好处。 |
|
返回顶楼 | |
发表时间:2011-01-28
不要过度用单例,struts2的action不要用单例
|
|
返回顶楼 | |
发表时间:2011-01-28
lyy3323 写道 spring 里的action 配置 相信大家基本都是配的单列。
都是singleton吗? 以前没见过,孤陋寡人了。 |
|
返回顶楼 | |
发表时间:2011-01-28
action单例。难道你的系统只有一个在线用户?
|
|
返回顶楼 | |
发表时间:2011-01-28
action不需要用单例,而且action中往往会包含一些成员变量,使用单例不太合适~~
|
|
返回顶楼 | |
发表时间:2011-01-28
struts2 的action, 不建议用单例
|
|
返回顶楼 | |
发表时间:2011-01-28
类似的问题也遇到过,Struts2的Action不能设置为单例。
|
|
返回顶楼 | |
发表时间:2011-01-28
最后修改:2011-01-28
ych516 写道 action不需要用单例,而且action中往往会包含一些成员变量,使用单例不太合适~~
但这里是struct的action再搞成单利就不是“不太合适了”,是有问题哈。 |
|
返回顶楼 | |