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

Save HTTP POST Data from Form to use it more than once with Java, possible?

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

我正在使用 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常见文件上传异常。

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

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

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

所以,在阅读了许多天和许多小时之后,我开始明白我在我的包装器中有效地保存了我的 HttpServletRequest,但是,当我再次尝试使用它时,客户端当然不会'不再发送信息,因为已经发送过一次了,所以这里的问题是:

我如何模拟这种行为?我如何存储 POST 数据以像我在过滤器中尝试做的那样使用它两次。

你试过这个吗: chain.doFilter(请求,响应);

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

如果有人遇到此问题,或出于某种原因尝试实施此问题,那么,我做不到,但我找到了解决方法。 考虑到我的主要限制是不修改上传 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 数据,我直接从表单中获取数据。非常简单的解决方案,但我花了很多天才明白,您不能指望客户端向您发送两次数据,然后想出一个变通方法来仍然获取两次数据。

希望对您有所帮助。