【问题标题】:HttpServletRequestWrapper and HttpServletResponseWrapper, what can they really do?HttpServletRequestWrapper 和 HttpServletResponseWrapper,它们究竟能做什么?
【发布时间】:2015-02-19 02:11:27
【问题描述】:

在过去的 3 天里,我一直在阅读很多内容,试图找出解决问题的方法,Is it posible to change upload path with a servlet?,我尝试了很多很多方法,现在我对 Java 的了解更多了,但是我仍然无法找到解决我的问题的方法。

最接近我发现的解决方法是使用过滤器和 HttpServletRequestWrapper 和 HttpServletResponseWrapper,但我的问题是,就像很多人在这里问的那样,得到一次响应后,它就消失了,很多建议使用包装,但使用 1 次后包装也消失了。

我的代码试图实现一个非常简单的工作示例:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {

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

    List<FileItem> items = upload.parseRequest(reqWrapper); //<--All cool 
    filterChain.doFilter(reqWrapper, response); //<--reqWrapper still
           //has request but when I try to get the file 
           //through org.apache.commons.fileupload.FileUpload, the file is null
}

如果我像这里解释的示例一样尝试它:Differences between ServletResponse and HttpServletResponseWrapper?

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {

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

    filterChain.doFilter(reqWrapper, response); //<--All cool

//**It goes and does an action, which gets Form parameters and file from a POST request and saves file to folder within context**

    List<FileItem> items = upload.parseRequest(reqWrapper);//<--throws exception: 
     //org.apache.commons.fileupload.FileUploadException: Stream Closed
}

我还为我的包装器实现了类,它们工作正常,但是当我尝试在同一个实例中再次使用请求时,它消失了。这样做的正确方法是什么,或者不可能做到?

我只敢冒着风险投反对票,因为我花了 40 多个小时试图找到解决方案,但我根本想不通。感谢您的耐心和理解。

编辑:忘了说我这样做是为了从发布请求多部分数据中获取输入值和文件

EDIT2:更改了代码上的 cmets 以使其更加清晰。

EDIT3:再次更改 cmets 以显示堆栈跟踪异常

我想要实现的是两次使用表单 POST 数据。这是为了复制上传的文件而无需修改原始操作(servlet)。我以为 HttpServletRequestWrapper 会从我的表单中包装我的 POST 数据,以便我可以重用它,但现在我明白它不会。

有没有办法做到这一点?

【问题讨论】:

  • 什么意思? null 是什么?
  • 你是什么意思尝试再次使用请求?如何重用它,在哪里? parseRequest 是做什么的?
  • null是指请求参数已经被消费,请求为null。
  • 我还是不明白。什么请求参数?你在哪里消费它们?你在哪里需要他们第二次? null 是什么请求reqWrapper 不可能是 nullhttpReq 不可能是 null,除非您有其他 Filters。
  • 请发布堆栈跟踪和/或可重现的代码,因为您所描述的事情是不可能的。在第一个 sn-p 中,标记行导致 NPE 的唯一方法是 filterChainnull。 API 排除了这一点。在您的第二个 sn-p 中,reqWrapper 不能是 null。您已经在方法的开头对其进行了初始化,并保持原样。

标签: java servlets http-post wrapper


【解决方案1】:

现在我知道他们真正做了什么,好吧,就像他们的名字所暗示的那样,他们包装了请求和响应,这有一些用处,但不是为了我想做的事。您不能向客户端请求两次数据,客户端向您发送一次数据,并且只发送一次,因此如果您包装请求再次使用,您将再次请求数据,但客户端不会再次发送它,因为它已经发送它。并且包装器不会包装 POST 数据,一旦您收到它,您必须想办法将其存储在某个地方并根据需要再次使用它。

在我的例子中,我将表单方法设为静态,我可以从过滤器中访问表单元素和值。示例:

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();

现在我不需要再次处理请求,因为无论如何我都不会获取数据,也不需要解析数据或任何东西,我只需使用表单元素值,这就是我想得到。

希望这对某人有所帮助。

【讨论】:

    猜你喜欢
    • 2012-10-06
    • 2011-07-23
    • 2011-06-25
    • 2012-07-23
    • 2016-09-10
    • 2023-03-15
    • 2012-10-17
    • 2021-06-04
    • 1970-01-01
    相关资源
    最近更新 更多