在 Spring 中使用自定义解析器返回 HTTP 状态 BAD_REQUEST

我正在使用Spring Boot 1.5.15开发 REST API 。我已经实施了一个客户HandlerMethodArgumentResolver来映射 HTTP 标头。具体来说,我分配了 HTTP header 的值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")。


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


慕森王
浏览 124回答 3
3回答

拉风的咖菲猫

您可以为任何情况声明自己的异常,并在控制器中设置 ExceptionHandler 以返回正确的 http-status。@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler({SameHeaderException.class})public Object onSameHeaderException(SameHeaderException e) {&nbsp; &nbsp; return ImmutableMap.of("reason", e.getMessage());}因此,如果标头不存在,您可以抛出此异常:if (someHeaderValue == null) { throw new SameHeaderException(); }

茅侃侃

RequestHeaderMethodArgumentResolver如果您看到which is used for的实现,您将看到抽象类方法@RequestHeader的重写实现,如下所示:handleMissingValueAbstractNamedValueMethodArgumentResolver@Overrideprotected void handleMissingValue(String name, MethodParameter parameter) throws ServletRequestBindingException {&nbsp; &nbsp; &nbsp; &nbsp; throw new ServletRequestBindingException("Missing request header '" + name +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "' for method parameter of type " + parameter.getNestedParameterType().getSimpleName());}该handleMissingValue方法用于resolveArgument的方法中AbstractNamedValueMethodArgumentResolver,它RequestHeaderMethodArgumentResolver根据某些条件进行扩展。因此,当标头不存在并ServletRequestBindingException抛出时,SpringDefaultHandlerExceptionResolver将处理该问题并发送400响应。这就是验证在@RequestHeader. resolveArgument所以你可以在你的类的方法中实现类似的东西,SomeHeaderArgumentResolver如下所示:public class SomeHeaderArgumentResolver implements HandlerMethodArgumentResolver {&nbsp; &nbsp; @Override&nbsp; &nbsp; public boolean supportsParameter(MethodParameter parameter) {&nbsp; &nbsp; &nbsp; &nbsp; return parameter.getParameterAnnotation(SomeHeader.class) != null;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public Object resolveArgument(MethodParameter parameter,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ModelAndViewContainer mavContainer,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NativeWebRequest webRequest,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WebDataBinderFactory binderFactory) {&nbsp; &nbsp; &nbsp; &nbsp; HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();&nbsp; &nbsp; &nbsp; &nbsp; final String headerValue = request.getHeader("Some-Header");&nbsp; &nbsp; &nbsp; &nbsp; if(headerValue != null){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return headerValue.replace("XXX ", "");&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//handle scenario if header absent with ServletRequestBindingException&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; }

富国沪深

我明白了扩展哪个类是让 Spring 发挥魔力的正确类。RequestHeaderMethodArgumentResolverSpring 用来解析 Java 对象中的 HTTP 标头值的类扩展了抽象类AbstractNamedValueMethodArgumentResolver。此类允许您使用createNamedValueInfo方法指定标头值是否具有某些默认值。所以,它遵循代码。public class SomeHeaderArgumentResolver extends AbstractNamedValueMethodArgumentResolver {&nbsp; &nbsp; @Override&nbsp; &nbsp; protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {&nbsp; &nbsp; &nbsp; &nbsp; // The second parameter specifies if the value is required,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; // and the third if there is some default value.&nbsp; &nbsp; &nbsp; &nbsp; return new NamedValueInfo("", true, null);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; protected Object resolveName(String name,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MethodParameter parameter,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NativeWebRequest request) {&nbsp; &nbsp; &nbsp; &nbsp; final String headerValue = request.getHeader("Some-Value");&nbsp; &nbsp; &nbsp; &nbsp; if (StringUtils.isEmpty(headerValue)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Returning null tells Spring that there is no value for the parameter&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return headerValue.replace("XXX ", "");&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public boolean supportsParameter(MethodParameter parameter) {&nbsp; &nbsp; &nbsp; &nbsp; return (parameter.hasParameterAnnotation(SomeHeader.class) &&&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !Map.class.isAssignableFrom(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameter.nestedIfOptional().getNestedParameterType()));&nbsp; &nbsp; }}我唯一不喜欢的是我正在使用为处理命名值而开发的结构,但我没有命名值。希望能帮助到你。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java