简体   繁体   中英

Custom annotation to get custom object with specified set of @RequestHeaders from HttpServletRequest

I'm looking for the way to create custom annotation to read set of headers from HttpServletRequest

Let's say I have a following code:

@RestController
public class ExampleController {

    @PostMapping(path = "/path")
    public void method(@RequestHeader("session-session_id") long sessionId,
                       @RequestHeader("session-user_id") long userId,
                       @RequestHeader("session-user_name") String userName) {
        UserInfo userInfo = UserInfo.of(sessionId, userId, userName);
        //service.handle(userInfo);
    }

    public static final class UserInfo {
        private final long sessionId;
        private final long userId;
        private final String userName;

        private UserInfo(long sessionId, long userId, String userName) {
            this.sessionId = sessionId;
            this.userId = userId;
            this.userName = userName;
        }

        public static UserInfo of(long sessionId, long userId, String userName) {
            return new UserInfo(sessionId, userId, userName);
        }
    }
} 

As you can see I have user info in request headers. All user info headers will start with "session-" prefix. On the real system I will have more than 3 fields. And they will be used for a lot of requests. So, I have to transfer to service level an object with full user info. And creation of this UserInfo for each request like UserInfo.of(sessionId, userId, userName) looks redundant and pretty ugly. Thats is the problem.

I know at least 2 another ways to solve this:

@PostMapping(path = "/path")
public void method(HttpServletRequest request) {
    UserInfo userInfo = UserInfo.of(request);
}

public static UserInfo of(HttpServletRequest request) {
    //request.getHeader("header name");
}

or

@PostMapping(path = "/path")
public void method(@RequestHeader Map<String, String> request) {
    UserInfo userInfo = UserInfo.of(request);
}

public static UserInfo of(Map<String, String> request) {
    //map.get("header name");
}

But still it isn't the case. I'm looking for the way to create UserInfo like spring does it:

@PostMapping(path = "/path")
public void method(@UserInfo UserInfo request) {
    UserInfo userInfo = UserInfo.of(request);
}

Could you help me with a solution? Or at least provide a link to documentation where described how @RequestHeader implemented inside the spring

You need to define custom HandlerMethodArgumentResolver :

public class UserInfoResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().equals(UserInfo.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {
        // There are no null-checks here for simplicity, 
        // so don't forget to add them in production code
        return UserInfo(
            Long.parseLong(webRequest.getHeader("session-session_id")), 
            Long.parseLong(webRequest.getHeader("session-user_id")),
            webRequest.getHeader("session-user_name")
        );
    }
}

Then make Spring aware of that argument resolver in your web configuration class:

@Configuration
public class WebApiConfiguration extends WebMvcConfigurationSupport {
    ...

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new UserInfoResolver());
    }

    ...
}

And finally you can use it this way:

@PostMapping(path = "/path")
public void method(UserInfo userInfo) {
    //service.handle(userInfo);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM