在此我们通过过滤器来完成本功能
@WebFilter(filterName = "RequestBodyFilter", urlPatterns = "/**")
public class RequestBodyFilter implements Filter {
public static final String LOGTHREAD_ID="logthreadId";
private static final Logger LOGGER = LoggerFactory.getLogger(RequestBodyFilter.class);
public static final String URI_ENCODING = NsConfiguration.getInstance()
.getConf(NsConfiguration.KEY_URI_ENCODING);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//日志打印唯一标识
MDC.put(LOGTHREAD_ID,java.util.UUID.randomUUID().toString().replace("-",""));
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
request.setCharacterEncoding("UTF-8");
//获取body数据
BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
String line = null;
StringBuilder sb = new StringBuilder();
while((line = reader.readLine())!=null){
sb.append(line);
}
String postContent = sb.toString();
//如果body中存在数据放入HttpServletRequest
if (!RequestBodyFilter.isEmpty(postContent) ){
request = new ParameterRequestWrapper(request);
LOGGER.debug(postContent);
String[] params = postContent.split("&");
for (String param : params) {
String[] pkv = param.split("=");
String data = URLDecoder.decode(pkv[1], URI_ENCODING);
((ParameterRequestWrapper)request).addParameter(pkv[0],data);
}
}
filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
public static boolean isEmpty(Object str) {
return str == null || "".equals(str) || "{}".equals(str);
}
}
@WebFilter
filterName | String | 指定过滤器的 name 属性,等价于 |
value | String[] | 该属性等价于 urlPatterns 属性。但是两者不应该同时使用。 |
urlPatterns | String[] | 指定一组过滤器的 URL 匹配模式。等价于 |
ParameterRequestWrapper类 : 重构
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
private Map params = new HashMap();
@SuppressWarnings("unchecked")
public ParameterRequestWrapper(HttpServletRequest request) {
// 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
super(request);
//将参数表,赋予给当前的Map以便于持有request中的参数
this.params.putAll(request.getParameterMap());
}
@Override
public String getParameter(String name) {//重写getParameter,代表参数从当前类中的map获取
String[]values = params.get(name);
if(values == null || values.length == 0) {
return null;
}
return values[0];
}
public String[] getParameterValues(String name) {//同上
return params.get(name);
}
public void addAllParameters(MapotherParams) {//增加多个参数
for(Map.Entryentry : otherParams.entrySet()) {
addParameter(entry.getKey() , entry.getValue());
}
}
public void addParameter(String name , Object value) {//增加参数
if(value != null) {
if(value instanceof String[]) {
params.put(name , (String[])value);
}else if(value instanceof String) {
params.put(name , new String[] {(String)value});
}else {
params.put(name , new String[] {String.valueOf(value)});
}
}
}
}
在springboot中配置过滤器:可以直接在启动类中添加以下代码
@Bean
public FilterRegistrationBean someFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean(new RequestBodyFilter());
registration.addUrlPatterns("/*");
//registration.addInitParameter("paramName", "paramValue");
registration.setName("requestBodyFilter");
return registration;
}
也可以创建被@configuration注解的类中
由于body只能被读取一次,也就是说,在本次读取后,下面就不能对body进行操作了,为了解决该问题,对
HttpServletRequestWrapper重写
import com.bailian.middleware.util.HttpHelper;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
public class BodyRequestWrapper extends HttpServletRequestWrapper {
private byte[] body;
public BodyRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
}
@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 readListener) {
}
};
}
public void setInputStream(byte[] body) {
this.body = body;
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
public class HttpHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
/**
* 获取请求Body
* @param request
* @return
*/
public static String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
LOGGER.error(e.getMessage(),e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
LOGGER.error(e.getMessage(),e);
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
LOGGER.error(e.getMessage(),e);
}
}
}
return sb.toString();
}
}