簡體   English   中英

自定義批注從HttpServletRequest獲取具有指定的@RequestHeaders集的自定義對象

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

我正在尋找創建自定義批注以從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.of(sessionId, userId, userName)創建此UserInfo看起來很多余而且很丑陋。 那就是問題所在。

我至少知道另外兩種解決方法:

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

但事實並非如此。 我正在尋找創建像Spring這樣的UserInfo的方法:

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

您能幫我解決辦法嗎? 或者至少提供指向文檔的鏈接,其中描述了如何在Spring內部實現@RequestHeader

您需要定義自定義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")
        );
    }
}

然后讓Spring在您的Web配置類中意識到該參數解析器:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM