当@ResponseBody 为空时覆盖默认消息

Posted

技术标签:

【中文标题】当@ResponseBody 为空时覆盖默认消息【英文标题】:Override default message when @ResponseBody is null 【发布时间】:2021-08-17 02:44:44 【问题描述】:

我想从这个 Spring 类中覆盖这个行为:

public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor 
    ...
    @Override
    protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter,
            Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException 
            ...
            if (arg == null && checkRequired(parameter)) 
                throw new HttpMessageNotReadableException("Required request body is missing: " +
                    parameter.getExecutable().toGenericString(), inputMessage);
            
    ...

当@ReponseBody 来自@Controller 时,此方法处理错误。我试图让我自己的 CustomBodyMethodProcessorRequestResponseBodyMethodProcessor 扩展,如下所示:

public class CustomBodyMethodProcessor extends RequestResponseBodyMethodProcessor 

    public CustomBodyMethodProcessor(List<HttpMessageConverter<?>> converters) 
        super(converters);
    

    @Override
    protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter,
                                                   Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException 

        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        Assert.state(servletRequest != null, "No HttpServletRequest");
        ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);

        Object arg = readWithMessageConverters(inputMessage, parameter, paramType);
        if (arg == null && checkRequired(parameter)) 
            //I want to change this....
            throw new HttpMessageNotReadableException("Required request body is missing: " +
                    parameter.getExecutable().toGenericString(), inputMessage);
        
        return arg;
    


所以,添加新的 CustomBodyMethodProcessor 我做了:

@Configuration
@EnableWebMvc
public class WebMvcConfig implements  WebMvcConfigurer 

    @Autowired
    List<HttpMessageConverter<?>> converters;


    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) 
        WebMvcConfigurer.super.addArgumentResolvers(resolvers);
        resolvers.add(new CustomBodyMethodProcessor(converters));

    


但这不起作用。当我调试时,总是在 RequestResponseBodyMethodProcessorreadWithMessageConverters 方法中停止,而不是在 CustomBodyMethodProcessor

的我的覆盖方法中停止

感谢您为我提供的任何帮助!

谢谢

【问题讨论】:

如果您在列表的前面添加您的 (resolvers.add(new …, 0);) 会发生什么?或者在添加你的之前删除另一个 (resolvers.removeIf(i -&gt; i instanceof RequestResponseBodyMethodProcessor);)? 嗨! resolvers 为空,内部没有 RequestResponseBodyMethodProcessor 的实例。添加我的索引为 0 并且没有结果...谢谢! 你的回答@BeUndead 带我走上正确的道路...***.com/a/19847526/4267653 【参考方案1】:

找到了解决办法。

    @Autowired
    private RequestMappingHandlerAdapter adapter;

    @PostConstruct
    public void prioritizeCustomArgumentMethodHandlers () 
        List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(adapter.getArgumentResolvers ());
        List<HandlerMethodArgumentResolver> customResolvers = adapter.getCustomArgumentResolvers();
        argumentResolvers.removeAll(customResolvers);
        argumentResolvers.addAll (0, customResolvers);
        adapter.setArgumentResolvers (argumentResolvers);
    

我的 CustomBodyMethodProcessor 已添加到解析器列表中,但原始 RequestResponseBodyMethodProcessor 具有优先权,因此永远不会调用 CustomBodyMethodProcessor

解决方案是从解析器中删除我的 CustomBodyMethodProcessor,给予优先权并再次将其添加到列表中!

感谢https://***.com/a/19847526/4267653 和@BeUndead 提供线索!

【讨论】:

不知道它在这种情况下是否有效,但大多数 Spring 集合在类上支持 implements Ordered@Order。所以你可以在你的自定义类上尝试@Order(Ordered.HIGHEST_PRECEDENCE),它可以在没有这一步的情况下工作。很高兴你让它工作了。

以上是关于当@ResponseBody 为空时覆盖默认消息的主要内容,如果未能解决你的问题,请参考以下文章

当 ContentControl 的内容为空或为空时,在 ContentControl 中显示默认的 DataTemplate?

当字段为空时,如何让内容类型中的链接字段显示默认文本

c-string用户输入为空时如何发送错误消息?

当对象或对象属性为空时,如何安全给对象或对象属性添加默认值

vue中当数据为空时的处理

当ListView为空时Android显示文本