自定義Controller方法參數解析器

  • 2019 年 12 月 19 日
  • 筆記

自定義Controller方法參數注入,比如主動注入當前用戶等等

核心類:HandlerMethodArgumentResolver

package org.springframework.web.method.support;    import org.springframework.core.MethodParameter;  import org.springframework.lang.Nullable;  import org.springframework.web.bind.WebDataBinder;  import org.springframework.web.bind.support.WebDataBinderFactory;  import org.springframework.web.context.request.NativeWebRequest;    /**   * Strategy interface for resolving method parameters into argument values in   * the context of a given request.   *   * @author Arjen Poutsma   * @since 3.1   * @see HandlerMethodReturnValueHandler   */  public interface HandlerMethodArgumentResolver {       /**      * Whether the given {@linkplain MethodParameter method parameter} is      * supported by this resolver.      * @param parameter the method parameter to check      * @return {@code true} if this resolver supports the supplied parameter;      * {@code false} otherwise      */     boolean supportsParameter(MethodParameter parameter);       /**      * Resolves a method parameter into an argument value from a given request.      * A {@link ModelAndViewContainer} provides access to the model for the      * request. A {@link WebDataBinderFactory} provides a way to create      * a {@link WebDataBinder} instance when needed for data binding and      * type conversion purposes.      * @param parameter the method parameter to resolve. This parameter must      * have previously been passed to {@link #supportsParameter} which must      * have returned {@code true}.      * @param mavContainer the ModelAndViewContainer for the current request      * @param webRequest the current request      * @param binderFactory a factory for creating {@link WebDataBinder} instances      * @return the resolved argument value, or {@code null} if not resolvable      * @throws Exception in case of errors with the preparation of argument values      */     @Nullable     Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,           NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;    }

這個介面中有兩個方法,supportsParameter用於判斷是否通過本解析器解析該參數,resolveArgument用於編寫解析的邏輯,返回的對象賦值給方法的相對應的參數。

舉個例子

import lombok.Data;    /**   * @author donghaibin   */  @Data  public class User {        private String name;        private String age;  }

一個User對象,現在需要在Controller的一個介面中獲取當前請求的User,最直接的方法是在方法體中編寫邏輯獲取,但這樣寫不是那麼的優雅。另一種方法就是通過HandlerMethodArgumentResolver實現。

import org.springframework.core.MethodParameter;  import org.springframework.web.bind.support.WebDataBinderFactory;  import org.springframework.web.context.request.NativeWebRequest;  import org.springframework.web.method.support.HandlerMethodArgumentResolver;  import org.springframework.web.method.support.ModelAndViewContainer;    /**   * @author donghaibin   */  public class UserArgumentResolver implements HandlerMethodArgumentResolver {        @Override      public boolean supportsParameter(MethodParameter methodParameter) {          // isAssignableFrom方法判斷類型是否為本身或者子類          return methodParameter.getParameterType().isAssignableFrom(User.class);      }        @Override      public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {          // 這裡測試直接構建一個對象返回          User user = new User();          user.setAge("18");          user.setName("DHB");          return user;      }    }
import org.springframework.context.annotation.Configuration;  import org.springframework.web.method.support.HandlerMethodArgumentResolver;  import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;    import java.util.List;    /**   * @author donghaibin   */  @Configuration  public class WebMvcConfig implements WebMvcConfigurer {        @Override      public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {          // 添加進參數解析器集合          resolvers.add(new UserArgumentResolver());      }  }

測試

import cn.dhbin.test.config.User;  import cn.dhbin.test.config.UserFlag;  import lombok.extern.slf4j.Slf4j;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RestController;    /**   * @author donghaibin   */  @RestController  @Slf4j  public class TestController {        @RequestMapping("/test")      public String test(String a, User user) {          log.info(user.toString());          return a;      }  }

結果

2019-07-18 23:47:14.535  INFO 44852 --- [nio-8080-exec-1] cn.dhbin.test.controller.TestController  : User(name=DHB, age=11)

總結

通過這個demo大概明白自定義參數解析只需兩步

  1. 繼承HandlerMethodArgumentResolver編寫解析邏輯
  2. 重寫WebMvcConfigurer的addArgumentResolvers方法,添加自定義的解析器到參數解析器集合中