如何配置Spring Boot使其支持在endpoint中直接注入自定义请求头解析对象
实现方案
完全可以实现,以下是两种适配不同场景的落地方案:
方案1:Spring MVC 场景(推荐,适配绝大多数Spring Web项目)
通过自定义HandlerMethodArgumentResolver参数解析器完成自动注入,步骤如下:
- 实现参数解析器
import org.springframework.core.MethodParameter; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import java.util.Collections; import java.util.Map; import java.util.stream.Collectors; public class CommonHeaderArgumentResolver implements HandlerMethodArgumentResolver { // 匹配需要解析的CommonHeader类型参数 @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterType().equals(CommonHeader.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { // 提取所有请求头转为Map Map<String, String> headerMap = Collections.list(webRequest.getHeaderNames()) .stream() .collect(Collectors.toMap(h -> h, webRequest::getHeader)); // 调用已有的解析逻辑 CommonHeader commonHeader = CommonHeader.parseCommonHeader(headerMap); // 在此处添加必填字段校验逻辑,校验不通过直接抛出异常即可 if (commonHeader.getCallerId() == null || commonHeader.getCallerId().isBlank()) { throw new IllegalArgumentException("请求头x-caller-id不能为空"); } // 其他字段校验逻辑同理 return commonHeader; } }
- 注册解析器到Spring MVC配置
import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new CommonHeaderArgumentResolver()); } }
配置完成后即可直接使用你期望的接口写法,Spring会自动完成请求头解析、校验、对象注入。
方案2:Jersey(JAX-RS)场景
如果项目使用Jersey作为REST框架(原生支持@Path注解),可通过自定义Factory实现:
- 实现CommonHeader生成工厂
import org.glassfish.hk2.api.Factory; import javax.servlet.http.HttpServletRequest; import javax.inject.Inject; import java.util.Collections; import java.util.Map; import java.util.stream.Collectors; public class CommonHeaderFactory implements Factory<CommonHeader> { private final HttpServletRequest request; @Inject public CommonHeaderFactory(HttpServletRequest request) { this.request = request; } @Override public CommonHeader provide() { Map<String, String> headerMap = Collections.list(request.getHeaderNames()) .stream() .collect(Collectors.toMap(h -> h, request::getHeader)); CommonHeader commonHeader = CommonHeader.parseCommonHeader(headerMap); // 在此处添加必填字段校验逻辑 return commonHeader; } @Override public void dispose(CommonHeader instance) { // 无清理需求可留空 } }
- 注册到Jersey配置
import org.glassfish.hk2.utilities.binding.AbstractBinder; import org.glassfish.jersey.process.internal.RequestScoped; import org.glassfish.jersey.server.ResourceConfig; import org.springframework.context.annotation.Configuration; @Configuration public class JerseyConfig extends ResourceConfig { public JerseyConfig() { packages("你的接口类所在包路径"); register(new AbstractBinder() { @Override protected void configure() { bindFactory(CommonHeaderFactory.class) .to(CommonHeader.class) .in(RequestScoped.class); } }); } }
使用时在参数前加@Context注解即可:
@Path("/columnConfigs") Response getColumnConfig(@Context CommonHeader commonHeader) { // 直接使用解析好的对象即可 }
内容的提问来源于stack exchange,提问作者yurii.pitomets
相关产品推荐
相关产品推荐

