Пользовательская аннотация для получения пользовательского объекта с указанным набором @RequestHeaders из HttpServletRequest - PullRequest
0 голосов
/ 21 мая 2019

Я ищу способ создания пользовательской аннотации для чтения набора заголовков из HttpServletRequest

Допустим, у меня есть следующий код:

@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);
        }
    }
} 

Как видите, у меня есть информация о пользователе в заголовках запросов. Все заголовки информации пользователя начинаются с префикса "session-". В реальной системе у меня будет более 3 полей. И они будут использоваться для большого количества запросов. Итак, я должен перевести на уровень обслуживания объект с полной пользовательской информацией. И создание этого UserInfo для каждого запроса, такого как UserInfo.of(sessionId, userId, userName), выглядит избыточным и довольно уродливым. Это проблема.

Я знаю как минимум 2 других способа решения этой проблемы:

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

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

или

@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");
}

Но все же это не тот случай. Я ищу способ создать UserInfo, как это делает весна:

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

Не могли бы вы помочь мне с решением? Или хотя бы предоставьте ссылку на документацию, где описано, как @RequestHeader реализован внутри пружины

1 Ответ

1 голос
/ 21 мая 2019

Вам необходимо определить пользовательские HandlerMethodArgumentResolver:

public class UserInfoResolver implements HandlerMethodArgumentResolver {

    private static final String sessionIdParam = "session-session_id";
    private static final String userIdParam = "session-user_id";
    private static final String userNameParam = "session-user_name";

    @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(sessionIdParam)), 
            Long.parseLong(webRequest.getHeader(userIdParam)),
            webRequest.getHeader(userNameParam)
        );
    }
}

Затем сообщите Spring об этом преобразователе аргументов в вашем классе веб-конфигурации:

@Configuration
public class WebApiConfiguration extends WebMvcConfigurationSupport {
    ...

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

    ...
}

И, наконец, вы можете использовать это так:

@PostMapping(path = "/path")
public void method(UserInfo userInfo) {
    //service.handle(userInfo);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...