我正在使用Sping Boot 1.5.15开发一个REST API,我实现了一个客户HandlerMethodArgumentResolver
来Map一个HTTP header,具体来说,我将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());
}
}
型
现在,我可以在任何需要的控制器中使用以下Map。
@PostMapping("/some/paath")
public void someMethod(@SomeHeader String someHeaderValue) {
// Method body...
}
型
然而,Some-Header
信息对我来说是强制性的。我希望如果它不存在,Spring向调用者返回400 Bad Request响应。这与我可以使用@RequestHeader("Some-Header")
annotation获得的行为相同。
我可以复制同样的行为吗?可能,我不想使用专用的 * 控制器建议 *。
4条答案
按热度按时间ilmyapht1#
如果您看到用于
@RequestHeader
的RequestHeaderMethodArgumentResolver
的实现,您将看到AbstractNamedValueMethodArgumentResolver
抽象类的handleMissingValue
方法的重写实现,如下所示:字符串
这个
handleMissingValue
方法在AbstractNamedValueMethodArgumentResolver
的resolveArgument
方法中使用,RequestHeaderMethodArgumentResolver
基于某些条件扩展了AbstractNamedValueMethodArgumentResolver
。所以当header不存在并且抛出ServletRequestBindingException
时,Spring的DefaultHandlerExceptionResolver
将处理它并发送400响应。所以这就是
@RequestHeader
的验证工作方式。所以你可以在SomeHeaderArgumentResolver
类的resolveArgument
方法中实现类似的东西,如下所示:型
qfe3c7zg2#
您可以为任何情况声明您自己的异常,并在控制器中设置ExceptionException以返回正确的http-status。
字符串
所以如果header不存在,你可以抛出这个异常:
型
fnatzsnv3#
感谢@madhu-bhat的建议,我明白了哪个类是正确的扩展,让Spring发挥魔力。
Spring使用类
RequestHeaderMethodArgumentResolver
来解析Java对象内部的HTTP header值,它扩展了抽象类AbstractNamedValueMethodArgumentResolver
。这个类允许您使用createNamedValueInfo
方法指定header值是否具有某些默认值。它遵循代码。
字符串
我唯一不喜欢的是,我正在使用开发的结构来处理 * 命名值 *,但我没有一个 * 命名值 *。
希望对你有帮助。
nuypyhwy4#
我基于这里的想法创建了一个Sping Boot 2.7.17示例。该示例使用了一个**@RequestHeaderEmail**自定义参数annotation。当此annotation出现时,它会将“X-EMAIL”请求头的值放入其中。如果没有这样的头或者它是null或空的,则REST方法将返回Bad Request。
使用方法:
字符串
注解:
型
解析器:
型
设置:
型
下面是一个带有单元测试的github repo:https://github.com/peterborkuti/request_param_custom_annotation/tree/main