好吧,我一直在尝试实现一个系统,在检查请求上的参数(例如路径)后,我实际上会修改响应以使用不同的数据进行回答。想法是创建后端演示功能,这样客户端就可以演示(而不是测试)应用程序,而无需实际发出数据库请求。
所以,我的第一次尝试是使用 servlet 过滤器,对此可以找到一个非常好的答案 here ,还有一些很好的文档,名为 The Essentials of Filters 。但我无法让它工作,我想因为我将 spring 与 @Controller 和 @ResponseBody 一起使用,即使我遵循完全相同的示例,我也会得到一个 null 作为wrapperResponse。
然后我尝试了Interceptors , here有一个很好的例子,实际上也有一个很好的答案here 。但这样做的问题是,通常人们会使用 postHandle 来修改正文,而我真的不希望句柄触发,因为这意味着数据库调用也将被触发。如果我使用 preHandler 作为 here它只会创建一个新的 servlet,而我不希望这样。
最后我尝试@ControllerAdvice这基本上允许您在发送之前重写正文,但同样,处理程序和所有数据库调用都会得到处理。
我的目标是,我不必在每个处理程序中放置重复的代码,我可以让 preHandler 插入一些额外的 header 并检查 @ControllerAdvice 中的 header ,但这意味着我必须制作一些 IF/ELSE在处理程序中,所以它不会被处理,我必须在系统中的数百个@Controllers上重复这一点,我想保持干燥。
我很确定解决方案就在过滤器上,方式如下 answer
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("BEFORE filter");
PrintWriter out = response.getWriter();
CharResponseWrapper responseWrapper = new CharResponseWrapper(
(HttpServletResponse) response);
chain.doFilter(request, responseWrapper);
String servletResponse = new String(responseWrapper.toString());
out.write(servletResponse + " filtered"); // Here you can change the response
System.out.println("AFTER filter, original response: "
+ servletResponse);
}
但我无法让它与 spring 和 @ResponseBody 调用一起工作。说实话,this没有回答我的问题。
最佳答案
这就是我设法做到这一点的方法。
首先,我创建了一个拦截器,它实际上过滤请求以仅传递我们想要演示的内容。在预处理程序中,我没有尝试使用 Response 输出流创建响应,而是使用 RequestDispatcher 将请求转发到新 Controller ,我将其称为演示 Controller 。
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// TODO Auto-generated method stub
Pattern pattern = Pattern.compile("someregex");
Matcher matcher = pattern.matcher(request.getPathInfo());
if (matcher.find())
{
if (matcher.group(0).equals("SOMETHING"))
{
HandlerMethod handlerMethod = ((HandlerMethod)handler);
request.setAttribute("methodName", handlerMethod.getBeanType().getSimpleName());
request.getRequestDispatcher("/demo").forward(request, response);
return false;
}
return true;
}
else
{
return true;
}
}
在演示 Controller 中,您可以创建要演示的正确响应。这里的好处是,在新的演示中,转发的请求将具有原始请求 javax.servlet.forward.request_uri 的属性,并且您可以在转发之前插入数据,作为请求上的controllerName。所有这些数据都可以在演示 Controller 中提取,以生成所需的数据。
关于Java Spring 在处理之前更改响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38744431/