Rem*_*ndt 1 java rest spring interceptor spring-boot
我在拦截器中读取请求正文时遇到问题。两者getReader()都会getInputStream()造成问题。我的拦截器:
public class MyInterceptor extends HandlerInterceptorAdapter {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestBody = httpRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
//or
// String requestBody = new BufferedReader(new InputStreamReader(httpRequest.getInputStream()))
// .lines().collect(Collectors.joining("\n"));
//some logic...
return true;
}
Run Code Online (Sandbox Code Playgroud)
这两种方法都失败了,因为 spring 可能在内部某处使用了此类资源。第一个原因是java.lang.IllegalStateException: getReader() 已为此请求调用,并且缺少其他必需的请求正文:org.springframework.http.ResponseEntity ...
我尝试了一些包装器的解决方法,但没有效果。我认为这是因为我无法像过滤器一样传递包装器(我不想使用过滤器,因为我有常见的异常管理器(@ControllerAdvice)。
这是一个已知的问题?有什么解决方法吗?
最后我想通了,所以我将在这里为其他人留下一些简单但有用的建议。我使用了请求包装器,但为了使其正常工作,我添加了一个具有最高顺序的过滤器,以在执行拦截器之前将每个请求包装到包装器中。现在它工作得很好;)这是最重要的代码 - 过滤器将每个请求包装到多读包装器中(拦截器看起来几乎与上面相同,包装器不是我发明的,在堆栈上找到的,我发现它是最清晰和可读的):
import lombok.SneakyThrows;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
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.StandardCharsets;
import java.util.stream.Collectors;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalWrapFilter implements Filter {
@Override
@SneakyThrows
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
MultiReadRequest wrapper = new MultiReadRequest((HttpServletRequest) request);
chain.doFilter(wrapper, response);
}
@Override
public void destroy() {
}
class MultiReadRequest extends HttpServletRequestWrapper {
private String requestBody;
@SneakyThrows
public MultiReadRequest(HttpServletRequest request) {
super(request);
requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody.getBytes());
return new ServletInputStream() {
@Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
@Override
@SneakyThrows
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream(), StandardCharsets.UTF_8));
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3425 次 |
| 最近记录: |