[17.0.0.2 and later]

配置 Liberty Web 应用程序以重新读取 POST 数据

Web 应用程序可以使用输入流、阅读器或者已解析的参数来重新读取作用域内的请求的 POST 数据。设置 Web 容器属性以使用此重新读取行为。

开始之前

Java™ Servlet 规范允许 Web 应用程序通过使用输入流、使用阅读器或者使用已解析的参数来读取请求的 POST 数据。但是,Web 应用程序在请求的作用域中只能使用这些方法中的一个方法来读取 POST 数据。

当您设置 Web 容器属性时,Web 应用程序可以多次重新读取 POST 数据。但是,必须关闭阅读器或者输入流才能完成读取操作,然后才能开始新的读取操作。在关闭阅读器或者输入流之前,不需要完全读取数据。可以完成部分读取数据。对于已解析的参数,Web 容器将读取整个 POST 数据,然后在已解析所有参数之后关闭读取操作。

应用程序可以执行非分块重新读取 POST 数据。例如,应用程序可以使用异步读取侦听器 (AsyncReadListener) 来执行非分块读取,执行关闭,然后执行分块读取。应用程序还可以使用异步读取侦听器来执行非分块读取,执行关闭,然后使用新的异步读取侦听器来执行第二个非分块读取。

当应用程序使用非分块读取来后续读取 POST 数据时,服务器首先将提供先前读取的数据。如果先前完成的读取操作未读取请求中发送的所有 POST 数据,那么当应用程序读取其余 POST 数据时,新的读取将执行分块。

关于此任务

将 Web 容器属性设置为 true。然后,运行可以重新读取 POST 数据的 Web 应用程序。提供了一些示例。

过程

  1. 启用重新读取 POST 数据。

    当您在 server.xml 文件中将 enablemultireadofpostdata 定制属性设置为 true 时,将在服务器级别设置该定制属性。重新读取行为适用于服务器上的所有 Web 应用程序。如果您希望重新读取行为适用于特定 Web 应用程序,那么在 web.xml 文件中将 com.ibm.ws.webcontainer.SET_MULTI_READ_WEBAPP 上下文参数设置为 true。对于特定 Web 应用程序,应用程序级别的设置将覆盖服务器级别的设置。

    enablemultireadofpostdata 定制属性和 com.ibm.ws.webcontainer.SET_MULTI_READ_WEBAPP 上下文参数的缺省值都是 false

    要在服务器级别启用此行为,请将以下语句添加至 server.xml 文件:
    <webContainer enablemultireadofpostdata="true" />
    要在 Web 应用程序级别启用此行为,请将以下 context-param 语句添加至 web.xml 文件:
                    
    	<context-param>
        <param-name>com.ibm.ws.webcontainer.SET_MULTI_READ_WEBAPP</param-name>                    
        <param-value>true</param-value>
    </context-param>
  2. 运行可以重新读取 POST 数据的 Web 应用程序。

示例

分块读取示例

下列步骤和代码段说明了应用程序可以如何使用 getInputStream () 方法、getParameter () 方法和 getReader () 方法来重新读取 POST 数据。但是,您可以在应用程序中使用任意组合的方法。
  1. 使用 getInputStream () 方法来获取输入流。
  2. 读取数据。
  3. 关闭该输入流。
  4. 使用 getInputStream () 方法来获取新的输入流。
  5. 读取数据。
  6. 关闭该输入流。
  7. 使用 getParameter () 方法来获取参数。
  8. 使用 getReader () 方法来获取阅读器。
  9. 读取数据。
  10. 关闭阅读器。
  11. 再次使用 getParameter () 方法来获取参数。
          java.io.InputStream in = request.getInputStream();
          byte[] inBytes = new byte[5];

          int readLen = in.read(inBytes);
          if (readLen > 0){
		
	     }              
          if (close)
                in.close();
	
	  java.io.InputStream in2 = request.getInputStream();
          byte[] inBytes = new byte[2048];

          for (int n; (n = in2.read(inBytes, 0, 2048)) != -1;) {
                readLen += n;
          }
          if (close)
                in2.close();

	  String param = request.getParameter("Test");
		
	  java.io.BufferedReader rdr = request.getReader();         
          StringBuffer inBuffer = new StringBuffer();
          char[] inChars = new char[1024];
          for (int n; (n = rdr.read(inChars,0,1024)) != -1;) {
             inBuffer.append(new String(inChars, 0, n));
          }
          rdr.close();

	  String param2 = request.getParameter("Test");

非分块读取示例

下列步骤和代码段说明了应用程序可以如何使用 getInputStream () 方法和 getParameter () 方法来重新读取 POST 数据。但是,您可以在应用程序中使用任意组合的方法。
  1. 使用 getInputStream () 方法来获取输入流。
  2. 使用 setReadListener () 方法从 Servlet 输入流中获取侦听器。
  3. 读取 onDataAvailable () 方法中的数据。
  4. 关闭该输入流。

    关闭输入流之后,不会对此侦听器调用 onAllDataRead () 方法和 onError () 方法。

  5. 使用 getParameter () 方法来获取参数。
  6. 使用 getInputStream () 方法来获取新的输入流。
  7. 使用 setReadListener () 方法从 Servlet 输入流中获取新的侦听器。
  8. 读取 onDataAvailable () 方法中的数据。
  9. 如果读取了所有数据,那么会对此侦听器调用 onAllDataRead () 方法。
        java.io.InputStream input = request.getInputStream();
	RL1 = ((ServletInputStream) input).setReadListener(readListener);
	
	RL1
	onDataAvailable(){

		if (input.isReady()) {
                         Len = input.read(inBytes);                 
                }
		input.close();

	        String param = request.getParameter("Test");

       	        java.io.InputStream input = request.getInputStream();
		RL2 = ((ServletInputStream) input).setReadListener(readListener);
	}

        RL1 // onAllDataRead() or onError() will not be called for RL1, as the stream has been closed for RL1
     
        RL2
        onDataAvailable(){

		if (input.isReady()) {
                        Len = input.read(inBytes);                 
               }

	 }
	
	 RL2 // If all data read
	 onAllDataRead(){
	 	 AsncContext.complete();
	 }

用于指示主题类型的图标 任务主题

文件名:twlp_reread_post.html