我需要某些HTTP请求必须重定向到
Spring Boot Web应用程序/服务,但是在请求方,Spring应用程序什么都不做,也可以作为HTTP客户端(另一个服务)和请求的真实的传递目的地.但是当响应回到Spring应用程序(从目的地)时,我需要Spring应用程序才能检查响应,如果需要的话可以采取措施.所以:
> HTTP客户端提出要求,比如说http://someapi.example.com
>网络魔术将请求传递给我的Spring应用程序,比如http://myproxy.example.com
>根据请求,此应用程序/代理不执行任何操作,因此请求将在http://someapi.example.com转发
> http://someapi.example.com处的服务端点将HTTP响应返回给代理
> http://myproxy.example.com处的代理检查此响应,并可能在将响应返回原始客户端之前发送警报
所以本质上,一个过滤器作为请求上的传递,只有远程服务执行后才能做任何事情并返回响应.
我最好的尝试是设置一个servlet过滤器:
@Override void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException { chain.doFilter(request,response) // How and where do I put my code? if(responseContainsFizz(response)) { // Send an alert (don't worry about this code) } }
这可以做吗如果是这样,我在哪里将代码检查并作出响应?以我的代码为例,当尝试从浏览器中点击控制器时,我会收到异常:
java.lang.IllegalStateException: STREAM at org.eclipse.jetty.server.Response.getWriter(Response.java:910) ~[jetty-server-9.2.16.v20160414.jar:9.2.16.v20160414] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92] rest of stack trace omitted for brevity
有任何想法吗?
解决方法
根据Servlet API文档,您获取IllegalStateException的原因是因为您在ServletResponse.getOutputStream已被调用后尝试调用ServletResponse.getWriter.所以看来你需要调用的方法是ServletResponse.getOutputStream().
但是,如果您尝试访问响应的正文,最佳解决方案是将响应包装在ServletResponseWrapper中,以便可以捕获数据:
public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest request,FilterChain chain) throws IOException,ServletException { MyServletResponseWrapper responseWrapper = new MyServletResponseWrapper((HttpServletResponse) response); chain.doFilter(request,responseWrapper); if (evaluateResponse(responseWrapper)) { // Send an alert } } private boolean evaluateResponse(MyServletResponseWrapper responseWrapper) throws IOException { String body = responseWrapper.getResponseBodyAsText(); // Perform business logic on the body text return true; } private static class MyServletResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream copyOutputStream; private ServletOutputStream wrappedOutputStream; public MyServletResponseWrapper(HttpServletResponse response) { super(response); } public String getResponseBodyAsText() throws IOException { String encoding = getResponse().getCharacterEncoding(); return copyOutputStream.toString(encoding); } @Override public ServletOutputStream getOutputStream() throws IOException { if (wrappedOutputStream == null) { wrappedOutputStream = getResponse().getOutputStream(); copyOutputStream = new ByteArrayOutputStream(); } return new ServletOutputStream() { @Override public boolean isReady() { return wrappedOutputStream.isReady(); } @Override public void setWriteListener(WriteListener listener) { wrappedOutputStream.setWriteListener(listener); } @Override public void write(int b) throws IOException { wrappedOutputStream.write(b); copyOutputStream.write(b); } @Override public void close() throws IOException { wrappedOutputStream.close(); copyOutputStream.close(); } }; } } }