Java Spring 在处理之前更改响应

标签 java spring spring-mvc servlet-filters interceptor

好吧,我一直在尝试实现一个系统,在检查请求上的参数(例如路径)后,我实际上会修改响应以使用不同的数据进行回答。想法是创建后端演示功能,这样客户端就可以演示(而不是测试)应用程序,而无需实际发出数据库请求。

所以,我的第一次尝试是使用 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/

相关文章:

java - 使用 org.codehaus.jackson 反序列化 JSON 字符串

java - 使用 spring 获取位于 Web 应用程序的 src 文件夹中的文件路径。

java - Log4j DailyRollingFileAppender 与 ConsoleAppender 性能对比

java - j2me中如何设置组件方向从右到左?

java - 使用 Mongodb 版本 4 和副本配置 flapdoodle 嵌入式 mongo

spring - Heroku H14(没有网络进程在运行)+ Spring-boot

Java 比较器多参数

java - 如何使用JAVA一次更新mongo db的单个文档中的多个字段(数组字段和普通字段)?

Spring 框架下载为 OSGi 包

java - 消息: HTTP method POST is not supported by this URL