0

对于我所有的 RestControllers 处理程序,它们都返回一个子类型MyResponseType,我想编写一个 SpringResponseBodyAdvice来操作基于 some 的响应@ModelAttribute。但是,我不知道如何访问ModelView这个地方。

@ControllerAdvice
public class MyGoldenAdvice implements ResponseBodyAdvice<MyResponseType> {

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

    @Override
    public RepresentationModel<?> beforeBodyWrite(
        final MyResponseType body,
        final MethodParameter returnType,
        final MediaType selectedContentType,
        final Class<? extends HttpMessageConverter<?>> selectedConverterType,
        final ServerHttpRequest request,
        final ServerHttpResponse response) {
        // here I would like to access the ModelView
        return body;
    }

}

不幸的是,由于我必须实现接口ResponseBodyAdvice,所以我不能有@ModelAttribute参数。

当然,我也可以使用拦截器。但是,响应已经写入,因此我只能操作MyResponseType实例的 JSON。

任何想法?

4

1 回答 1

1

虽然它不是具体问题(Access zu @ModelAttributes)的解决方案并且违反了背后的想法@ControllerAdvice,但您可以将@RequestAttributes 用于相同目的。为此,通知需要对 current 的依赖来HttpServletRequest存储和获取属性(的ServerHttpRequest参数beforeBodyWrite不提供请求属性)。

public class MyGoldenAdvice implements ResponseBodyAdvice<MyResponseType> {

    public final static String ATTRIBUTE_NAME="MyGoldenAdviceAttribute";

    private final HttpServletRequest currentRequest;

   // spring injects a proxy to the current request
    @Autowired
    public MyGoldenAdvice(HttpServletRequest currentRequest) {
        this.currentRequest = currentRequest;
    }

    // in order that the advice method is triggered, we have to annotate it
    // with @ModelAttribute, although we store the attribute in the request
    @ModelAttribute
    public MyModelAttributeType createModelAttribute() {
        MyModelAttributeType attribute = MyModelAttributeType.build();
        currentRequest.setAttribute(ATTRIBUTE_NAME, attribute);
        return attribute;
    }

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

    @Override
    public RepresentationModel<?> beforeBodyWrite(
        final MyResponseType body,
        final MethodParameter returnType,
        final MediaType selectedContentType,
        final Class<? extends HttpMessageConverter<?>> selectedConverterType,
        final ServerHttpRequest request,
        final ServerHttpResponse response) {

        // get the request attribute
        MyModelAttributeType attribute = (MyModelAttributeType) currentRequest.getAttribute(ATTRIBUTE_NAME);

        // do something with the body

        return body;
    }
}

在某些 REST 控制器中,您可以按如下方式使用请求属性

@GetMapping
public handleGetRequest(@RequestAttribute(name=MyGoldenAdvice.ATTRIBUTE_NAME) 
    MyModelAttributeType attribute) {
    // pass attribute around in services and so on...
}
于 2020-06-15T09:18:56.450 回答