I have a SpringBoot project and in an every endpoint's the first call is parsing a request header into a POJO object. making sure required headers are set. Is it possible "to teach" SpringBoot to be able to provide custom object in endpoints?
class CommonHeader {
private String callerId;
private String systemId;
....
public static CommonHeader parseCommonHeader(Map<String, String> map) {
CommonHeader header = new CommonHeader();
header.setCallerId(map.get("x-caller-id"));
.....
return header;
}
}
@Path("/columnConfigs")
Response getColumnConfig(@RequestHeader Map<String, String> headers) {
CommonHeader commonHeader = parseCommonHeader(headers);
....
}
@Path("/other")
Response getColumnConfig(@RequestHeader Map<String, String> headers) {
CommonHeader commonHeader = parseCommonHeader(headers);
....
}
I would like to be able to simplify the following code into:
@Path("/columnConfigs")
Response getColumnConfig(CommonHeader commonHeader) {
....
}
@Path("/other")
Response getColumnConfig(CommonHeader commonHeader) {
....
}
CodePudding user response:
Define CommonHeader
to extend Map<String, String>
:
@RequestHeader
public interface CommonHeader extends Map<String, String> {
}
CodePudding user response:
I was looking for some solution for this, that is, bind headers to an object of our definition. I found a good technique here: Using Custom Data Binders in SpringMVC
What you have to do in a nutshell are these, apart from the already created CommonHeader
class:
- Define an annotation, say
@MyHeaders
(with@Retention( RUNTIME )
and@Target( PARAMETER )
)
@Retention( RUNTIME )
@Target( PARAMETER )
public @interface MyHeaders {}
- Create an implementation of
HandlerMethodArgumentResolver
, sayMyHeadersResolver
. This will map the headers from the request into an instance ofCommonHeader
and return it.
@Override
public boolean supportsParameter( MethodParameter methodParameter ){
return methodParameter.getParameterAnnotation( MyHeaders.class ) != null;
}
@Override
public Object resolveArgument( MethodParameter methodParameter, ModelAndViewContainer mavc, NativeWebRequest req, WebDataBinderFactory wdbf ) throws Exception{
HttpServletRequest request = (HttpServletRequest) req.getNativeRequest();
CommonHeader h = new CommonHeader();
Collections.list( request.getHeaderNames() ).forEach( header -> {
switch( header.toLowerCase() ) {
//Set values into CommonHeader instance
}
});
return h;
}
- Declare this to SpringMVC as an argument resolver in a class that implements
WebMvcConfigurer
, like this:
@Override
public void addArgumentResolvers( List<HandlerMethodArgumentResolver> resolvers ) {
resolvers.add( new MyHeadersResolver() );
}
- Your controller method signature will now look like this:
Response getColumnConfig( @MyHeaders CommonHeader commonHeader )