Java Spring 在处理之前更改响应
Posted
技术标签:
【中文标题】Java Spring 在处理之前更改响应【英文标题】:Java Spring change the response before handle it 【发布时间】:2016-12-09 05:23:26 【问题描述】:好的,我一直在尝试实现一个系统,在该系统中,在检查请求上的参数(如路径)后,我实际上会修改响应以使用不同的数据进行回答。想法是创建后端演示功能,这样客户端可以演示(不测试)应用程序而无需实际发出数据库请求。
所以,我的第一次尝试是使用 servlet 过滤器,可以在 here 找到一个非常好的答案,还有一些名为 The Essentials of Filters 的好文档。但我无法让它工作,我认为因为我使用带有@Controller 和 @ResponseBody 的 spring,即使我遵循完全相同的示例,我也会得到一个 null 作为 wrapperResponse。
然后我尝试了Interceptors,here 有很好的例子,并且一个很好的实际答案here。但是这样做的问题是,通常人们会使用 postHandle 来修改 body,我真的不希望句柄甚至触发,因为这意味着数据库调用也会被触发。如果我将 preHandler 用作here,它只会创建一个新的 servlet,我不希望这样。
最后我尝试@ControllerAdvice,它基本上允许您在发送之前重写正文,但同样,处理程序得到处理,所有数据库调用都使用它。
我的目标是我不必在每个处理程序中放置重复的代码,我可以让 preHandler 插入一些额外的标头并在 @ControllerAdvice 中检查该标头,但这意味着我必须制作一些 IF/ELSE在处理程序中,因此它不会被处理,我必须在系统中拥有的 100 个 @Controllers 上重复这一点,我想要 DRY。
我很确定解决方案就在这个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 没有回答我的问题。
【问题讨论】:
【参考方案1】:这就是我设法做到这一点的方式。
首先我创建了一个拦截器,它实际上过滤请求以传递我们想要演示的内容。在预处理程序中,我没有尝试使用 Response outstream 创建响应,而是使用 RequestDispatcher 将请求转发到一个新的控制器,我称之为 Demo 控制器。
@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;
在演示控制器中,您可以创建一个您想要演示的正确响应。这里的好处是,在新的演示中,转发请求将具有原始请求 javax.servlet.forward.request_uri 的属性,并且您可以插入数据,作为转发前请求的控制器名称。所有这些数据都可以在 Demo 控制器中提取,以生成所需的数据。
【讨论】:
以上是关于Java Spring 在处理之前更改响应的主要内容,如果未能解决你的问题,请参考以下文章