java post filter_java在filter中获取POST请求中request参数以及解决ServletInputStream重复读取的问题...

想要回去GET请求中的请求参数,可以直接使用request.getParamMap()方法。但是POST请求的requestBody参数就必须使用流的方式来获取。

BufferedReader reader = null;

String body = null;

try {

reader = new BufferedReader(new InputStreamReader(request.getInputStream()));

body = IOUtils.read(reader).replaceAll("\t|\n|\r", "");

} catch (IOException e) {

logger.error("流读取错误:"+e);

return;

}finally {

if (null != reader){

try {

reader.close();

} catch (IOException e) {

logger.error("流关闭错误:"+e);

}

}

}

Map paramMap = JSON.parseObject(body);

这样将获取body中的所有json格式的参数信息。可以根据需求,进行验签或校验等一系列操作。但是当我们chain.doFilter(request, response),惊喜的发现接口400了!!

WHAT??!!

嘿嘿o( ̄▽ ̄)d

我们都知道,读取流的时候是有标志的,读取一次移动一次,读取到哪里,移动到哪里,读到最后,返回-1,表示读取完成。再次读取需要重置位置,但是ServletInputStream中是没有重置方法的,也就是说流只能被读取一次。神奇!!Σ(⊙▽⊙"a 此时的流已经被读取一次,相当于已经作废,此时请求接口必然是报错的。

行吧,你既然不让我重复读,那我就把你的流拿过来封装成自己的流,这样我想读多少次就读多少次!ψ(`∇´)ψ

加入jar包:javax.servlet

javax.servlet

javax.servlet-api

3.1.0

provided

实现HttpServletRequestWrapper类

import javax.servlet.ReadListener;

import javax.servlet.ServletInputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import java.io.*;

import java.net.URLDecoder;

import java.util.*;

/**

* @author zhoumin

* @create 2018-10-31 16:13

*/

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {

private Map paramsMap;

@Override

public Map getParameterMap() {

return paramsMap;

}

@Override

public String getParameter(String name) {// 重写getParameter,代表参数从当前类中的map获取

String[] values = paramsMap.get(name);

if (values == null || values.length == 0) {

return null;

}

return values[0];

}

@Override

public String[] getParameterValues(String name) {// 同上

return paramsMap.get(name);

}

@Override

public Enumeration getParameterNames() {

return Collections.enumeration(paramsMap.keySet());

}

private String getRequestBody(InputStream stream) {

String line = "";

StringBuilder body = new StringBuilder();

int counter = 0;

// 读取POST提交的数据内容

BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

try {

while ((line = reader.readLine()) != null) {

if (counter > 0) {

body.append("rn");

}

body.append(line);

counter++;

}

} catch (IOException e) {

e.printStackTrace();

}

return body.toString();

}

private HashMap getParamMapFromPost(HttpServletRequest request) {

String body = "";

try {

body = getRequestBody(request.getInputStream());

} catch (IOException e) {

e.printStackTrace();

}

HashMap result = new HashMap();

if (null == body || 0 == body.length()) {

return result;

}

return parseQueryString(body);

}

// 自定义解码函数

private String decodeValue(String value) {

if (value.contains("%u")) {

return Encodes.urlDecode(value);

} else {

try {

return URLDecoder.decode(value, "UTF-8");

} catch (UnsupportedEncodingException e) {

return "";// 非UTF-8编码

}

}

}

public HashMap parseQueryString(String s) {

String valArray[] = null;

if (s == null) {

throw new IllegalArgumentException();

}

HashMap ht = new HashMap();

StringTokenizer st = new StringTokenizer(s, "&");

while (st.hasMoreTokens()) {

String pair = (String) st.nextToken();

int pos = pair.indexOf('=');

if (pos == -1) {

continue;

}

String key = pair.substring(0, pos);

String val = pair.substring(pos + 1, pair.length());

if (ht.containsKey(key)) {

String oldVals[] = (String[]) ht.get(key);

valArray = new String[oldVals.length + 1];

for (int i = 0; i < oldVals.length; i++) {

valArray[i] = oldVals[i];

}

valArray[oldVals.length] = decodeValue(val);

} else {

valArray = new String[1];

valArray[0] = decodeValue(val);

}

ht.put(key, valArray);

}

return ht;

}

private Map getParamMapFromGet(HttpServletRequest request) {

return parseQueryString(request.getQueryString());

}

private final byte[] body; // 报文

public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {

super(request);

body = readBytes(request.getInputStream());

// 首先从POST中获取数据

if ("POST".equals(request.getMethod().toUpperCase())) {

paramsMap = getParamMapFromPost(this);

} else {

paramsMap = getParamMapFromGet(this);

}

}

@Override

public BufferedReader getReader() throws IOException {

return new BufferedReader(new InputStreamReader(getInputStream()));

}

@Override

public ServletInputStream getInputStream() throws IOException {

final ByteArrayInputStream bais = new ByteArrayInputStream(body);

return new ServletInputStream() {

@Override

public int read() throws IOException {

return bais.read();

}

@Override

public boolean isFinished() {

return false;

}

@Override

public boolean isReady() {

return false;

}

@Override

public void setReadListener(ReadListener arg0) {

}

};

}

private static byte[] readBytes(InputStream in) throws IOException {

BufferedInputStream bufin = new BufferedInputStream(in);

int buffSize = 1024;

ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);

byte[] temp = new byte[buffSize];

int size = 0;

while ((size = bufin.read(temp)) != -1) {

out.write(temp, 0, size);

}

bufin.close();

byte[] content = out.toByteArray();

return content;

}

}

解码

/**

* URL 解码, Encode默认为UTF-8.

*/

public static String urlDecode(String part) {

try {

return URLDecoder.decode(part, DEFAULT_URL_ENCODING);

} catch (UnsupportedEncodingException e) {

throw new InvalidTokenException(part);

}

}

那么上面读取参数的代码修改为:

ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(

(HttpServletRequest) request);

BufferedReader reader = null;

String body = null;

try {

reader = new BufferedReader(new InputStreamReader(requestWrapper.getInputStream()));

body = IOUtils.read(reader).replaceAll("\t|\n|\r", "");

} catch (IOException e) {

logger.error("流读取错误:"+e);

return;

}finally {

if (null != reader){

try {

reader.close();

} catch (IOException e) {

logger.error("流关闭错误:"+e);

}

}

}

Map paramMap = JSON.parseObject(body);

.

.

.

chain.doFilter(requestWrapper, response);

OK!又是打酱油的一天。(づ。◕ᴗᴗ◕。)づ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值