【问题标题】:Spring - How can I add a header to ALL responses that I return?Spring - 如何为我返回的所有响应添加标题?
【发布时间】:2017-09-14 20:17:37
【问题描述】:

假设我有一个 Spring REST API,它在整个代码中返回了许多响应。

如果我想在发送的每个响应中返回两个特定的标头,我该如何以比在返回之前手动将它们添加到每个响应中更智能的方式做到这一点?

是否有一种机制允许我在发送响应之前捕获响应并添加标头?

编辑:对于未来的访问者提出这个问题。这里没有一个答案实际上会导致拦截器工作。我建议去别处看看。

【问题讨论】:

  • 你需要一个拦截器。 This question 您可能会感兴趣。 postHandle() 方法可能更适合您要完成的工作

标签: java spring rest


【解决方案1】:

正确的答案是使用过滤器。拦截器对此并不正确,不管网上的人怎么说。拦截器无法正常工作。

工作解决方案是创建一个过滤器,如下所示:

public class myAwesomeFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response, FilterChain filterChain)  throws ServletException, IOException {

        response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        response.addHeader("pragma", "no-cache");
        filterChain.doFilter(request, response);
    }
}

然后,在 web.xml - 你需要以下内容:

<filter>
    <filter-name>sensitiveFormHeaderFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

【讨论】:

  • 来自文档:docs.spring.io/spring/docs/current/spring-framework-reference/… - “请注意,postHandle 对于 @ResponseBody 和 ResponseEntity 方法的用处不大,因为这些方法的响应是在 HandlerAdapter 中和 postHandle 之前写入和提交的。这意味着为时已晚对响应进行任何更改,例如添加额外的标头。"
  • 但是使用 preHandle 拦截器(而不是上面建议的 postHandle),您仍然可以根据需要向所有请求添加标头。
  • 但是这样我只能在请求处理之前添加过滤器,如果我需要在之后添加它?
  • 你可以将过滤器定义为@Component——不需要web.xml
【解决方案2】:

我让它工作的方式是使用 ResponseBodyAdvice,如 Faxy 链接的 example 所示。

这是我为每个请求添加缓存控制标头的解决方案:

@ControllerAdvice
public class HeaderModifierAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(final MethodParameter returnType, final Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(final Object body,
                                  final MethodParameter returnType,
                                  final MediaType selectedContentType,
                                  final Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  final ServerHttpRequest request,
                                  final ServerHttpResponse response) {
        response.getHeaders().add("Cache-Control", "no-cache, no-store, must-revalidate");
        response.getHeaders().add("Pragma", "no-cache");
        response.getHeaders().add("Expires", "0");
        return body;
    }
}

【讨论】:

  • 我认为这个解决方案只有在你的控制器方法返回一个对象时才有效。任何返回 404、201、204 状态且没有内容的控制器方法都不会有上述 headers。
  • 此方法也不适用于返回模型和视图的控制器
  • 但是您一般不应该尝试这样做,如果您在从控制器方法返回 HttpEntity/ResponseEntity 时尝试这样做会失败,因为 HttpEntity 将其标头设置为只读。
  • 确认它不适用于@VijayKalidindi 指出的201
【解决方案3】:

您可以使用 Handler Interceptors 轻松完成这些工作,它允许您在 Spring MVC 中修改请求处理生命周期。拦截器是一个非常强大的工具,它允许我们在 3 个不同的点向请求处理生命周期添加功能:

  1. 在控制器处理请求之前
  2. 控制器方法完成其代码执行后
  3. 当视图即将被渲染并作为响应返回给客户端时

我认为选项 2 将满足您的需求。

那么你可以这样写:

public class MyInterceptor extends HandlerInterceptorAdapter {

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);

        //add your two headers on the response here
    }


}

第 2 步是在您的配置文件中注册该拦截器,将下一行添加到您的 XML 配置中:

<mvc:interceptors>
   <bean Class="your interceptor class">
</mvc:interceptors>

从现在开始,该拦截器将适用于每个请求。

【讨论】:

  • 这听起来可能有点傻 - 但是我应该把 XML 放在哪里呢?是否有它所属的特定文件?
  • 你想创建一个 Spring Bean XML 配置文件并放在资源文件夹下,但这还不够,你还需要将它显式加载到 Spring IOC 容器中
  • 好的,我得到了 Spring Bean XML 配置 - 但什么是 IOC 容器?很抱歉,XML 配置方面让我感到困惑。
  • 看来你需要从理论的角度多了解一下spring,我建议先看几本书或者从视频中学习。 IOC 容器是 Spring 实现依赖注入的方式,容器是 bean 存在和管理的地方。
  • 我知道我可以学到更多关于 Spring 的知识——但是,我只是为本周和下周休假的 Java 开发人员提供帮助。我通常是一名 C++ 开发人员 - 我只需要同时让它工作。
【解决方案4】:

您可以为此目的使用spring interceptors。 或者有更通用的方法来做到这一点,这不需要 Spring。我是filter

【讨论】:

    【解决方案5】:

    相信你可以实现HandlerInterceptorAdapter接口,重写postHandle()方法。

    example

    【讨论】:

      猜你喜欢
      • 2018-10-31
      • 2015-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多