分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

httpServletRequest中的流只能读取一次的原因

发布时间:2023-09-06 01:58责任编辑:胡小海关键词:http

首先,我们复习一下InputStream read方法的基础知识,

java InputStream read方法内部有一个,postion,标志当前流读取到的位置,每读取一次,位置就会移动一次,如果读到最后,InputStream.read方法会返回-1,标志已经读取完了,如果想再次读取,可以调用inputstream.reset方法,position就会移动到上次调用mark的位置,mark默认是0,所以就能从头再读了。

当然,能否reset是有条件的,它取决于markSupported,markSupported() 方法返回是否可以mark/reset

我们再回头看request.getInputStream

request.getInputStream返回的值是ServletInputStream,查看ServletInputStream源码发现,没有重写reset方法,所以查看InputStream源码发现marksupported 返回false,并且reset方法,直接抛出异常。

InputStream.java 

public boolean markSupported() { ??return false; } ?public synchronized void reset() throws IOException { ??throw new IOException("mark/reset not supported"); }

综上所述,在request.getinputstream读取一次后position到了文件末尾,第二次就读取不到数据,由于无法reset(),所以,request.getinputstream只能读取一次。

总结:

这个问题最根本还是对java IO的read、reset方法的深入理解,尤其是read方法的内部实现原理。

附ServletInputStream.java源码

/* * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the "License"). ?You may not use this file except * in compliance with the License. * * You can obtain a copy of the license at * glassfish/bootstrap/legal/CDDLv1.0.txt or * https://glassfish.dev.java.net/public/CDDLv1.0.html. * See the License for the specific language governing * permissions and limitations under the License. * * When distributing Covered Code, include this CDDL * HEADER in each file and include the License file at * glassfish/bootstrap/legal/CDDLv1.0.txt. ?If applicable, * add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your * own identifying information: Portions Copyright [yyyy] * [name of copyright owner] * * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * * Portions Copyright Apache Software Foundation. */ package javax.servlet;import java.io.InputStream;import java.io.IOException;/** * ?* Provides an input stream for reading binary data from a client * request, including an efficient <code>readLine</code> method * for reading data one line at a time. With some protocols, such * as HTTP POST and PUT, a <code>ServletInputStream</code> * object can be used to read data sent from the client. * * <p>A <code>ServletInputStream</code> object is normally retrieved via * the {@link ServletRequest#getInputStream} method. * * * <p>This is an abstract class that a servlet container implements. * Subclasses of this class * must implement the <code>java.io.InputStream.read()</code> method. * * * @author ????Various * * @see ???????ServletRequest ?* */public abstract class ServletInputStream extends InputStream { ???/** ????* Does nothing, because this is an abstract class. ????* ????*/ ???protected ServletInputStream() { } ???????????/** ????* ????* Reads the input stream, one line at a time. Starting at an ????* offset, reads bytes into an array, until it reads a certain number ????* of bytes or reaches a newline character, which it reads into the ????* array as well. ????* ????* <p>This method returns -1 if it reaches the end of the input ????* stream before reading the maximum number of bytes. ????* ????* ????* ????* @param b ????????an array of bytes into which data is read ????* ????* @param off ????????an integer specifying the character at which ????* ???????????????this method begins reading ????* ????* @param len ???????an integer specifying the maximum number of ?????* ???????????????bytes to read ????* ????* @return ???????????an integer specifying the actual number of bytes ?????* ???????????????read, or -1 if the end of the stream is reached ????* ????* @exception IOException ???if an input or output exception has occurred ????* ????*/ ????????public int readLine(byte[] b, int off, int len) throws IOException { ???if (len <= 0) { ???????return 0; ???} ???int count = 0, c; ???while ((c = read()) != -1) { ???????b[off++] = (byte)c; ???????count++; ???????if (c == ‘\n‘ || count == len) { ???????break; ???????} ???} ???return count > 0 ? count : -1; ???}}

httpServletRequest中的流只能读取一次的原因

原文地址:https://www.cnblogs.com/zhaoyibing/p/9132513.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved