开发中,经常会有这样的需求 ,需要从请求体中拿出特殊的参数进行处理或者将整个请求体做为日志记录。那应该如何获取请求体或者响应体呢 ?方法很多,这里给出一个方法进行处理。下面是demo可以直接使用。
本次使用方法主要是通过 RequestWrapper 和 ResponseWrapper 进行实现。
1、创建请求wrapper
@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {
private final String body;
public RequestWrapper(HttpServletRequest request) {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try (InputStream inputStream = ()) {
if(inputStream != null){
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = (charBuffer)) > 0) {
(charBuffer, 0, bytesRead);
}
}
} catch (Exception e) {
("RequestWrapper read error :{}",());
} finally {
(bufferedReader);
}
body = ();
}
/**
* 将getInputStream重新,让它能重复获取到body里的内容,这样才不会影响后续的流程
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(());
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return ();
}
};
return servletInputStream;
}
/**
* 重写获取 字符流的方式
* @return
*/
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader((), StandardCharsets.UTF_8));
}
/**
* 获取body
* @return
*/
public String getBody() {
return ;
}
}
2、创建响应wrapper
@ControllerAdvice
public class ResponseWrapper implements ResponseBodyAdvice<Object> {
private static final Integer MAX_LENGTH = 1000;
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
String result ;
if(body instanceof JSON){
JSON jsonResult = (JSON) body;
result = (jsonResult);
}else{
result = (body);
}
Integer length = () > MAX_LENGTH ? MAX_LENGTH : ();
result = (0,length);
HttpServletRequest httpServletRequest = ((ServletRequestAttributes) ()).getRequest();
HttpSession httpSession = (true);
//放到缓存里,以便于可以在HandlerInterceptor拦截里取出并打印出返回结果
("mybody", result);
return body;
}
}
3、创建过滤器
@Component
@WebFilter(filterName = "HttpServletRequestFilter", urlPatterns = "/")
@Order(10000)
public class HttpServletRequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(servletRequest instanceof HttpServletRequest) {
requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
}
//获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中
// 在方法中传递新的request对象
if(null == requestWrapper) {
(servletRequest, servletResponse);
} else {
(requestWrapper, servletResponse);
}
}
@Override
public void destroy() {
();
}
}
4、在拦截器中使用获取请求参数
通过拦截器变更了请求,直接进行转换获取
@Slf4j
@Component
public class OpenapiInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
String requestBody = ;
if (request instanceof RequestWrapper) {
requestBody = ((RequestWrapper) request).getBody();
}
return true;
}
}
5、在拦截器中使用获取响应参数
响应获取是在响应拦截的时候,通过session缓存写入后获取的值
@Slf4j
@Component
public class OpenapiInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
HttpSession httpSession = ();
//myBody是在响应的时候写入到Session的key,可以看responseWrapper
String result = (String)("myBody");
return true;
}
}