Spring Boot中使用拦截器和过滤器拦截请求并且使用包装类
2019-02-25 本文已影响17人
我的小熊不见了
拦截器
在Spring Boot中使用拦截器和过滤器可以帮助我们解决很多通用性的问题。使用拦截器只需要重写preHandle
方法。
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
问题
在进行拦截时我们一般都需要解析HttpServletRequest
中的流信息,但是HttpServletRequest
只能被读取一次,如果在拦截器中被读取了那么在后续的程序中就无法使用request
了。因此我们需要使用包装类包装request
。
包装类
以下是包装类的代码:
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = IOUtil.readByteArray(request.getInputStream());
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
代码中用到了一个工具方法:
public static byte[] readByteArray(InputStream in) throws IOException {
BufferedInputStream bufin = new BufferedInputStream(in);
int buffSize = 1024;
ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
byte[] temp = new byte[buffSize];
boolean var5 = false;
int size;
while((size = bufin.read(temp)) != -1) {
out.write(temp, 0, size);
}
bufin.close();
return out.toByteArray();
}
上面的代码中,将原始的HttpServletRequest
通过构造方法传进去保存起来,读取的时候直接读取包装类中保存的流。
if (request instanceof BodyReaderHttpServletRequestWrapper) {
String body = IOUtil.readStream(request.getInputStream(), "UTF-8");
}
问题是在什么地方去把HttpServletRequest
转换成我们自己的BodyReaderHttpServletRequestWrapper
。
过滤器
在Java中实现Filter
,对所有请求进行过滤。
@Component
@WebFilter(value = "/*")
public class WrapRequestFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
if (servletRequest.getContentType() != null && servletRequest.getContentType().contains("application/json")) {
//包装request
filterChain.doFilter(new BodyReaderHttpServletRequestWrapper(request), servletResponse);
} else {//不进行包装
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
如果符合条件就使用包装类。这样就把所有的接口都包装成我们自己的包装类了。然后就可以随心所欲的使用request
做你想做的事情了。