如何在Java API方法执行前验证@HeaderParam参数
验证请求头参数"key"的几种方案(类似请求体自定义反序列化验证的思路)
当然可以!完全能用类似自定义JSON反序列化器验证请求体的思路来处理请求头"key"的验证,下面给你几种贴合这种思路的实现方式:
方式一:自定义HandlerMethodArgumentResolver(最贴近自定义反序列化器的思路)
这种方式就像你自定义JSON反序列化器处理请求体那样,自己接管"key"参数的解析和验证逻辑:
- 先写一个自定义的解析器类,实现
HandlerMethodArgumentResolver:
public class KeyHeaderArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { // 判断参数是否是我们要处理的String类型,且带有@HeaderParam("key")注解 return parameter.getParameterType().equals(String.class) && parameter.hasParameterAnnotation(HeaderParam.class) && "key".equals(parameter.getParameterAnnotation(HeaderParam.class).value()); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { String key = webRequest.getHeader("key"); // 这里写你的验证逻辑,比如格式校验、合法性校验 if (key == null || key.isEmpty()) { throw new IllegalArgumentException("请求头key不能为空"); } if (!key.matches("[A-Za-z0-9]{16}")) { // 示例:校验key必须是16位字母数字 throw new IllegalArgumentException("请求头key格式非法,必须是16位字母数字"); } return key; } }
- 然后把这个解析器注册到Spring容器里(如果是Spring Boot的话):
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new KeyHeaderArgumentResolver()); } }
- 之后你的接口方法不用改,直接用就行:
@RequestMapping(value = "/update") public ResponseEntity<Response> update( @ApiParam(required=true) @Valid @RequestBody Request request, @RequestHeader @HeaderParam("key") String key ){ // 这里的key已经是经过验证的合法值了 return null; }
方式二:结合@Validated和自定义校验注解
如果你想更贴合Spring的校验体系,也可以用自定义校验注解来实现,和@Valid验证请求体的逻辑一致:
- 先定义一个自定义校验注解:
@Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = KeyValidator.class) public @interface ValidKey { String message() default "请求头key格式非法"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
- 然后写对应的校验器:
public class KeyValidator implements ConstraintValidator<ValidKey, String> { @Override public boolean isValid(String key, ConstraintValidatorContext context) { if (key == null || key.isEmpty()) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("请求头key不能为空").addConstraintViolation(); return false; } return key.matches("[A-Za-z0-9]{16}"); } }
- 然后在接口方法上加上
@Validated和自定义注解:
@RestController @Validated // 必须加这个注解,开启方法参数校验 public class YourController { @RequestMapping(value = "/update") public ResponseEntity<Response> update( @ApiParam(required=true) @Valid @RequestBody Request request, @RequestHeader @HeaderParam("key") @ValidKey String key ){ // 验证不通过的话会抛出ConstraintViolationException,你可以全局捕获处理 return null; } }
方式三:自定义Converter(适合简单类型转换+验证)
如果你的验证逻辑是和类型转换绑定的(比如把key字符串转换成某个自定义对象的同时验证),可以用自定义Converter:
public class KeyConverter implements Converter<String, String> { @Override public String convert(String source) { if (source == null || source.isEmpty()) { throw new IllegalArgumentException("请求头key不能为空"); } if (!source.matches("[A-Za-z0-9]{16}")) { throw new IllegalArgumentException("请求头key格式非法"); } return source; } }
注册到容器:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new KeyConverter()); } }
这样当Spring解析请求头的key参数时,会自动调用这个Converter完成验证。
总结一下,第一种方式最贴近你用自定义JSON反序列化器验证请求体的思路——自己接管参数的解析和验证流程;第二种方式更贴合Spring的校验生态,和@Valid验证请求体的风格统一;第三种适合简单的转换+验证场景。你可以根据自己的需求选择~
内容的提问来源于stack exchange,提问作者adbar
相关产品推荐
相关产品推荐

