Thymeleaf响应的ResponseBodyAdvice

时间:2018-07-02 13:47:24

标签: spring spring-mvc spring-boot

TLDR;有没有办法为Thymeleaf模板引擎的响应编写ResponseBodyAdvice?

对于带有@RequestMapping和@ResponseBody注释的“正常”端点,我可以编写ResponseBodyAdvice来修改/处理响应,然后再将其写入输出流。现在,有没有一种方法可以使端点返回模板视图的名称(在本例中为Thymeleaf)呢?

有效的示例:

@Controller
public class MyController
{
    @GetMapping("/path")
    @ResponseBody
    public String dispatch(final HttpServletRequest request,
                           final HttpServletResponse response)
        throws Exception
    {
        return "my output string...";
    }
}

@ControllerAdvice
public class MyControllerAdvice implements ResponseBodyAdvice<String>
{
    @Override
    public boolean supports(final MethodParameter returnType,
                            final Class<? extends HttpMessageConverter<?>> converterType)
    {
        // This is called
        return true;
    }

    @Override
    public String beforeBodyWrite(final String body,
                                  final MethodParameter returnType,
                                  final MediaType selectedContentType,
                                  final Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  final ServerHttpRequest request,
                                  final ServerHttpResponse response)
    {
        // This is called

        // Perform the response logic...
        return body;
    }
}

无效的示例:

@Controller
public class MyController
{
    @GetMapping("/path")
    public String dispatch(final HttpServletRequest request,
                           final HttpServletResponse response)
        throws Exception
    {
        return "viewName"; // will be resolved to a view by the templating engine (Thymeleaf) - typically viewName.html - and evaluated
    }
}

@ControllerAdvice
public class MyControllerAdvice implements ResponseBodyAdvice<Object>
{
    @Override
    public boolean supports(final MethodParameter returnType,
                            final Class<? extends HttpMessageConverter<?>> converterType)
    {
        // This is never called

        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)
    {
        // This is never called

        // Perform the response logic...
        return body;
    }
}

很难判断上述控制器建议是否仅与模板引擎的输出不匹配,或者是否存在针对其选择的更具体类型的控制器建议...

关于, 亵渎

1 个答案:

答案 0 :(得分:0)

您应该可以使用HandlerInterceptorAdapter来做到这一点:

public class MyResponseInterceptor extends HandlerInterceptorAdapter 
{
    @Override
    public void postHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler, 
                           ModelAndView modelAndView) 
        throws Exception 
    {
        // Your logic here, which will be called after the controller method returns
    }
}

您还需要将此类添加到您的WebMvcConfigurerAdapter

    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(new MyResponseInterceptor());
    }

请注意,这存在相反的问题,因为它不适用于直接返回ResponseBody的Controller方法