spring.svg

【Spring Boot】カスタムデータバインド

SpringBoot

はじめに

例えば認証トークンなど、Controller 以下でリクエストヘッダーの情報を取得したい場合、以下のようにHttpServletRequestを使用します。

@GetMapping
public String getToken(HttpServletRequest request) {
  return getToken.orElse("");
}

private Optional<String> getToken(HttpServletRequest request) {
  String authorization = request.getHeader("Authorization");
  if (authorization == null || authorization.isEmty()) {
    return Optional.empty();
  }
  try {
    String identifier = authorization.substring(0, 6);
    if (!"Bearer".equals(identifier)) {
      return Optional.empty();
    }
    String token = authorization.substring(7);
    return Optional.of(token);
  } catch (StringIndexOutofBoundsException e) {
    return Optional.empty();
  }
}

正直、上記のgetTokenのようにメソッドを用意してもよいのですが、以下のようにアノテーションを利用し、Controller のパラメーターとして取得することを考えていきます。

@GetMapping
public String getToken(@AuthToken String token) {
  return token;
}

アノテーションの作成

以下のようにアノテーションを作成します。 今回はパラメーター用にしたいため、@TargetにはElementType.PARAMETERを指定します。

AuthToken.java
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthToken {
}

パラメーターの設定処理

@AuthTokenの指定があるパラメーターに対し、リクエストヘッダーのAuthorizationの内容を設定する処理を実装していきます。

これを実現するためには、HandlerMethodArgumentResolverを implements したクラスを作成します。

AuthTokenResolver.java
public class AuthTokenResolver implements HandlerMethodArgumentResolver {

  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    return parameter.hasParameter(AuthToken.class);
  }

  @Override
  public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();

    //トークンの取得処理(省略...)
    String token = getToken(request).orElse(null);
    return token;
  }
}

HandlerMethodArgumentResolverでは、supportsParameter()resolveArgument()の 2 つのメソッドを実装します。 supportsParameter()で作成したアノテーションの紐付けを行い、resolveArgument()で具体的なパラメーターの設定処理を定義します。

あとはこの処理が実行されるように、WebMvcConfigureで登録をします。

WebMvcConfig.java
@Configuration
public class WebMvcConfig implements WebMvcConfigure {

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

おわりに

上記では説明していませんが、リクエストヘッダーを取得する場合は@RequestHeaderを使用します。

@GetMapping
public String getToken(@RequestHeader("Authorization") String authorization) {
  //...
}

なのでただ単にリクエストヘッダーの情報を読み込む場合は必要ありません。 今回のようにリクエストヘッダーの内容を分解して…、みたいなことを行う場合は有効かもしれませんので是非ご参考までに。