首页 > 解决方案 > 在 Spring 中使用自定义解析器返回 HTTP 状态 BAD_REQUEST

问题描述

我正在使用Spring Boot 1.5.15开发一个 REST API 。我已经实现了一个客户HandlerMethodArgumentResolver来映射一个 HTTP 标头。具体来说,我分配了 HTTP 标头的值Some-Header,去掉了前缀“XXX”。

首先,我定义了一个自定义注解。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface SomeHeader {
}

然后,我实现了一个自定义解析器。

public class SomeHeaderArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterAnnotation(SomeHeader.class) != null;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) {
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
        final String headerValue = request.getHeader("Some-Header");

        return headerValue.replace("XXX ", "");
    }
}

最后,我让 Spring 意识到配置类中的解析器。

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new SomeHeaderArgumentResolver());
    }
}

现在,我可以在我需要的任何控制器中使用以下映射。

@PostMapping("/some/paath")
public void someMethod(@SomeHeader String someHeaderValue) {
   // Method body...
}

但是,Some-Header信息对我来说是强制性的。我希望如果它不存在,Spring 会向调用者返回 400 Bad Request 响应。这与我可以使用@RequestHeader("Some-Header")注释获得的行为相同。

我可以复制相同的行为吗?可能,我不想使用专门的控制器建议

标签: javaspring-bootspring-mvcspring-restcontroller

解决方案


您可以为任何情况声明自己的异常,并在控制器中设置 ExceptionHandler 以返回正确的 http-status。

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({SameHeaderException.class})
public Object onSameHeaderException(SameHeaderException e) {
    return ImmutableMap.of("reason", e.getMessage());
}

因此,如果没有标头,您可以抛出此异常:

if (someHeaderValue == null) { throw new SameHeaderException(); }

推荐阅读