Java InputStream到servletInputStream
我有一个输入流:Java InputStream到servletInputStream,java,inputstream,Java,Inputstream,我有一个输入流: InputStream inputStream = new ByteArrayInputStream(myString.getBytes(StandardCharsets.UTF_8)); 如何将其转换为ServletInputStream 我试过: ServletInputStream servletInputStream = (ServletInputStream) inputStream; 但是不起作用 编辑: 我的方法是: private static class
InputStream inputStream = new ByteArrayInputStream(myString.getBytes(StandardCharsets.UTF_8));
如何将其转换为ServletInputStream
我试过:
ServletInputStream servletInputStream = (ServletInputStream) inputStream;
但是不起作用
编辑:
我的方法是:
private static class LowerCaseRequest extends HttpServletRequestWrapper {
public LowerCaseRequest(final HttpServletRequest request) throws IOException, ServletException {
super(request);
}
@Override
public ServletInputStream getInputStream() throws IOException {
ServletInputStream servletInputStream;
StringBuilder jb = new StringBuilder();
String line;
String toLowerCase = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(super.getInputStream()));
while ((line = reader.readLine()) != null) {
toLowerCase = jb.append(line).toString().toLowerCase();
}
InputStream inputStream = new ByteArrayInputStream(toLowerCase.getBytes(StandardCharsets.UTF_8));
servletInputStream = (ServletInputStream) inputStream;
return servletInputStream;
}
}
我正在尝试将所有请求转换为小写 试试这段代码
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(myString.getBytes(StandardCharsets.UTF_8));
ServletInputStream servletInputStream=new ServletInputStream(){
public int read() throws IOException {
return byteArrayInputStream.read();
}
}
你只能投这样的东西:
ServletInputStream servletInputStream = (ServletInputStream) inputStream;
如果您试图强制转换的inputStream实际上已经是ServletInputStream。如果是InputStream的其他实现,它会抱怨。不能将对象强制转换为它不是的对象
在Servlet容器中,您可以从ServletRequest获取ServletInputStream:
ServletInputStream servletInputStream = request.getInputStream();
那么,你到底想做什么
编辑
我很好奇为什么要将请求转换为小写-为什么不让servlet不区分大小写?换句话说,您的代码可以将请求数据的大小写复制到您的servlet中,然后它可以在那里处理它。。。始终寻找最简单的解决方案 我的建议是:不要创建
ByteArrayInputStream
,只需使用从getBytes
方法获得的字节数组即可。这应该足以创建一个ServletInputStream
最基本的解决方案
不幸的是,Aksapy的答案只覆盖了read
方法。虽然这在ServletAPI 3.0及以下版本中可能就足够了,但在ServletAPI的更高版本中,还有三种方法需要实现
下面是我对该类的实现,尽管随着它变得相当长(由于ServletAPI3.1中引入了新方法),您可能需要考虑将其分解为一个嵌套类,甚至是顶级类
final byte[] myBytes = myString.getBytes("UTF-8");
ServletInputStream servletInputStream = new ServletInputStream() {
private int lastIndexRetrieved = -1;
private ReadListener readListener = null;
@Override
public boolean isFinished() {
return (lastIndexRetrieved == myBytes.length-1);
}
@Override
public boolean isReady() {
// This implementation will never block
// We also never need to call the readListener from this method, as this method will never return false
return isFinished();
}
@Override
public void setReadListener(ReadListener readListener) {
this.readListener = readListener;
if (!isFinished()) {
try {
readListener.onDataAvailable();
} catch (IOException e) {
readListener.onError(e);
}
} else {
try {
readListener.onAllDataRead();
} catch (IOException e) {
readListener.onError(e);
}
}
}
@Override
public int read() throws IOException {
int i;
if (!isFinished()) {
i = myBytes[lastIndexRetrieved+1];
lastIndexRetrieved++;
if (isFinished() && (readListener != null)) {
try {
readListener.onAllDataRead();
} catch (IOException ex) {
readListener.onError(ex);
throw ex;
}
}
return i;
} else {
return -1;
}
}
};
添加预期的方法
根据您的需求,您可能还希望覆盖其他方法。正如romfret指出的,最好覆盖一些方法,例如close
和available
。如果不实现它们,流将始终报告有0个字节可读取,并且close
方法不会影响流的状态。您可能不需要重写skip
,因为默认实现只需多次调用read
@Override
public int available() throws IOException {
return (myBytes.length-lastIndexRetrieved-1);
}
@Override
public void close() throws IOException {
lastIndexRetrieved = myBytes.length-1;
}
写一个更好的封闭方法
不幸的是,由于匿名类的性质,您很难编写有效的close
方法,因为只要流的一个实例没有被Java垃圾收集,即使流已经关闭,它也会维护对字节数组的引用
但是,如果将该类分解为嵌套类或顶级类(甚至是匿名类,其中包含从定义该类的行调用的构造函数),myBytes
可以是非最终字段,而不是最终的局部变量,并且可以添加如下行:
myBytes = null;
关闭方法,这将允许Java释放字节数组占用的内存
当然,这需要您编写一个构造函数,例如:
private byte[] myBytes;
public StringServletInputStream(String str) {
try {
myBytes = str.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("JVM did not support UTF-8", e);
}
}
标记并重置
如果要支持标记/重置,您可能还需要覆盖标记
、标记支持
和重置
。我不确定他们是否真的被你的容器调用过
private int readLimit = -1;
private int markedPosition = -1;
@Override
public boolean markSupported() {
return true;
}
@Override
public synchronized void mark(int readLimit) {
this.readLimit = readLimit;
this.markedPosition = lastIndexRetrieved;
}
@Override
public synchronized void reset() throws IOException {
if (markedPosition == -1) {
throw new IOException("No mark found");
} else {
lastIndexRetrieved = markedPosition;
readLimit = -1;
}
}
// Replacement of earlier read method to cope with readLimit
@Override
public int read() throws IOException {
int i;
if (!isFinished()) {
i = myBytes[lastIndexRetrieved+1];
lastIndexRetrieved++;
if (isFinished() && (readListener != null)) {
try {
readListener.onAllDataRead();
} catch (IOException ex) {
readListener.onError(ex);
throw ex;
}
readLimit = -1;
}
if (readLimit != -1) {
if ((lastIndexRetrieved - markedPosition) > readLimit) {
// This part is actually not necessary in our implementation
// as we are not storing any data. However we need to respect
// the contract.
markedPosition = -1;
readLimit = -1;
}
}
return i;
} else {
return -1;
}
}
ServletInputStream不是抽象的吗?如果重写此方法,则应重写其他方法(
close
,等等)。它是抽象的,但此答案说明了通过使用匿名内部类实现抽象方法来实例化抽象类,所以这是可以的。但是,我们不应该创建自己的ServletInputStream实例,我们应该根据我的回答从ServletRequest中获取它们。Wawoo,太棒了:)谢谢您,请问哪个包是ServletInputStream
?似乎在java8中被删除。@romfret它是Java Servlet API的一部分,而不是标准Java平台的一部分。ServletAPI有一个不同的版本控制方案,例如编写本文时的最新版本是3.1。因此,您使用的Java版本(例如5、6、7、8)并不重要,更重要的是您使用的ServletAPI的版本(以及您的容器支持的版本)。