1. 前言
ServletRequest
是我们搞
Java Web
经常接触的
Servlet Api
。有些时候我们要经常对其进行一些操作。这里列举一些经常的难点操作。
2. 提取 body 中的数据
前后端交互我们会在
body
中传递数据。我们如何从
body
中提取数据。通常我们会通过
IO
操作:
/**
* obtain request body
*
* @param request the ServletRequest
* @return body string it maybe is null
*/
public static String obtainBody(ServletRequest request) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
try {
br = request.getReader();
String str;
while ((str = br.readLine()) != null) {
sb.append(str);
}
br.close();
} catch (IOException e) {
log.error(" requestBody read error");
} finally {
if (null != br) {
try {
br.close();
} catch (IOException e) {
log.error(" close io error");
}
}
}
return sb.toString();
}
复制代码
看起来比较凌乱,各种异常处理,
IO
开关操作,很不优雅。 如果你使用了
Java 8
你可以这样简化这种操作:
String body = request.getReader().lines().collect(Collectors.joining());
复制代码
BufferedReader
提供了获取
Java 8 Stream
流的方法
lines()
,我们可以通过以上方法非常方便的获取
ServletRequest
中的
body
3. ServletRequest 中的流是一次性的
不要以为上面的读取
body
操作是完美无瑕的,这里有一个坑。
如果按照上面的操作
ServletRequest
中的
body
只能读取一次
。 我们传输的数据都是通过流来传输的。
ServletRequest
中我们实际上都是通过:
ServletInputStream inputStream = request.getInputStream()
复制代码
来获取输入流,然后通过
read
系列方法来读取。
Java
中的
InputStream
read
方法内部有一个
postion
, **它的作用是标志当前流读取到的位置,每读取一次,位置就会移动一次,如果读到最后,
read
方法会返回
-1
,标志已经读取完了,如果想再次读取,可以调用
reset
方法,
position
就会移动到上次调用
mark
的位置,
mark
默认是
0
,所以就能从头再读了。
能否
reset
是有条件的,它取决于
markSupported()
,
markSupported()
方法返回是否可以进行
mark/reset
。