从表单中保存HTTP POST数据以使用Java多次使用它,可能吗?

时间:2015-02-20 02:14:10

标签: java forms servlets http-post struts

也许我没有以正确的方式提出问题,但这是另一次尝试,这次我会更加彻底。我做了一个超级简单的项目来举例说明我想要实现的目标。

我正在使用netbeans和struts 1.3。

我有这个非常简单的形式:

 <html:form action="/firstUse.do" enctype="multipart/form-data" method="post">
        <html:hidden property="anyname" value="whatevername" />
        <input type="file" name="file" />
        <input type="submit" value="Submit" />
    </html:form>

我有我的ActionForm:

public class MyActionForm extends org.apache.struts.action.ActionForm {

private org.apache.struts.upload.FormFile file;
private String anyname;

public FormFile getFile() {
    return file;
}

public void setFile(FormFile file) {
    this.file = file;
}

public String getAnyname() {
    return anyname;
}

public void setAnyname(String anyname) {
    this.anyname = anyname;
}

public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
    ActionErrors errors = new ActionErrors();

    int tamArchivo = file.getFileSize();
    String nomArchivo = file.getFileName();

    String extArchivo = nomArchivo.substring(nomArchivo.indexOf(".") + 1).toUpperCase();

    if (tamArchivo <= 0) {
        errors.add("", new ActionMessage("documentosEntregados.imagenVacia"));
    } else if (tamArchivo >= 1048576) { // 1 Mega
        errors.add("", new ActionMessage("documentosEntregados.imagenGrande"));
    }
    return errors;
}
}

我有我的行动:

public class FirstUse extends org.apache.struts.action.Action {

private static final String SUCCESS = "success";
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {
    MyActionForm myf = (MyActionForm) form;
    String name;
    String filename;

    name = myf.getAnyname();
    FormFile file = myf.getFile();
    filename = file.getFileName();

    System.out.println("FirstUse Action");
    System.out.println(name);
    System.out.println(filename);
    return mapping.findForward(SUCCESS);
}
}

我有我的过滤器:

    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain)
        throws IOException, ServletException {

    Throwable problem = null;
    try {

        String strPath = ((HttpServletRequest) request).getServletPath();

        if (strPath.endsWith("firstUse.do")) {

            System.out.println("Entered filter first");

            HttpServletRequest httpReq = (HttpServletRequest) request;
            HttpServletRequestWrapper reqWrapper = new HttpServletRequestWrapper(httpReq);

            DiskFileItemFactory factory = new DiskFileItemFactory();

            // Configure a repository (to ensure a secure temp location is used)
            ServletContext servletContext = filterConfig.getServletContext();
            File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
            factory.setRepository(repository);

            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload(factory);

            List<FileItem> items = upload.parseRequest(reqWrapper);

            Iterator<FileItem> iter = items.iterator();
            if (!iter.hasNext()) {
                System.out.println("iter super empty");
            } else {
                System.out.println("iter not super empty");
                while (iter.hasNext()) {
                    FileItem item = iter.next();
                    if (item.isFormField()) {
                        System.out.println("Field name: " + item.getFieldName() + " Field value: " + item.getString());
                    } else {
                        System.out.println("File found");
                    }
                }
            }

            System.out.println("Finished FirstUse, Now I want to do a second use");

            chain.doFilter(reqWrapper, response);
        }else{
            chain.doFilter(request, response);
        }

    } catch (Throwable t) {
        System.out.println("reqWrapper emtpy or not accessible");
        problem = t;
        t.printStackTrace();
    }
    if (problem != null) {
        if (problem instanceof ServletException) {
            throw (ServletException) problem;
        }
        if (problem instanceof IOException) {
            throw (IOException) problem;
        }
    }
}

当我按下提交时,会调用过滤器,我在此处提交请求:

    HttpServletRequest httpReq = (HttpServletRequest) request;
    HttpServletRequestWrapper reqWrapper = new HttpServletRequestWrapper(httpReq);

现在,关注下一个,这是我的问题。我要解释一下这种行为以及我想要实现的目标。

如果我先拨打下一行:

chain.doFilter(reqWrapper, response);

该操作正确执行,我开始系统记录我的数据:

FirstUse Action
whatevername
Elastix.jpg
Finished FirstUse, Now I want to do a second use
iter super empty

但是当我尝试用apache commons迭代请求时,在这里:

List<FileItem> items = upload.parseRequest(reqWrapper);

            Iterator<FileItem> iter = items.iterator();
            if (!iter.hasNext()) {
                System.out.println("iter super empty");
            }

POST数据不可访问,所以我得到一个空的迭代器,流被关闭,这就是抛出的apache常见的fileupload异常。

现在,如果我首先执行迭代,而不是调用chain.doFilter,迭代就完成了,我得到了我的结果:

iter not super empty 
Field name: anyname 
Field value: whatevername 
File found

但当它到达chain.doFilter时,POST数据再次无法访问,所以当我尝试执行操作时,我得到空指针异常,它甚至在验证之前崩溃,如果验证表单打开,如表单值为null,后期数据消失。

所以,经过阅读了很多天和几个小时后,我才明白我在我的包装器中有效地保存了我的HttpServletRequest,但是当我再次尝试使用它时,当然客户端不发送因为它曾经给过一次iformation,所以这里的问题是:

我怎么能模仿这种行为?如何存储POST数据以便像我在我的过滤器中那样使用它。

2 个答案:

答案 0 :(得分:0)

你尝试过这个: chain.doFilter(request,response);

而不是这个: chain.doFilter(reqWrapper,response);

答案 1 :(得分:0)

如果有人遇到这个问题,或者由于某种原因试图实现这个问题,那么,我无法做到,但我找到了解决方法。 考虑到我的主要限制是不修改上传servlet(本例中的FirstUse.Action),我在这个问题中没有提到,我做了以下操作从表单中检索数据在我的行动已经执行之后。

首先,我将表单变量和方法更改为静态:

public class MyActionForm extends org.apache.struts.action.ActionForm {

private static org.apache.struts.upload.FormFile file;
private static String anyname;

public static FormFile getFile() {
    return file;
}

public void setFile(FormFile file) {
    this.file = file;
}

public static String getAnyname() {
    return anyname;
}

public void setAnyname(String anyname) {
    this.anyname = anyname;
}

然后,这样我就可以从我的过滤器中访问它们,只需调用表单方法:

    String name = MyActionForm.getAnyname();                
    FormFile imagen = MyActionForm.getFile();

就是这样,我不再需要从客户端再次请求POST数据,我从表单中直接采取。非常简单的解决方案,但花了我很多天才明白,你不能指望客户端向你发送两次数据,并找出解决方法仍能获得两次数据。

希望这有帮助。