I. briefly
Have you ever thought about how annotations like @ RequestParam and @ RequestBody work? Why can form forms and application/json parameters be directly encapsulated in Bean objects? This is about HandlerMethodArgumentResolver - Method Parameter resolver, which has two methods:
public interface HandlerMethodArgumentResolver { boolean supportsParameter(MethodParameter parameter); Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception; }
The supportsiparameter method returns the boolean value, which indicates whether the parser is enabled, true indicates enabled, and false indicates not enabled; the resolveArgument method indicates the parsing process of method parameters, which is the process of converting HTTP request parameters to method parameters, and returns the Object object Object, which is the conversion result of parameters.
@The parameter resolver corresponding to RequestParam is RequestParamMethodArgumentResolver; @ the parameter resolver corresponding to RequestBody is RequestResponseBodyMethodProcessor; readers can read these parsers by themselves.
2. User defined parameter resolver
I want to get the login information of the current user in the controller method parameter, which is about the following effect. As long as the @ CurrentUser annotation is added, the login information of the current user will be in the UserParam parameter.
@RequestMapping(value = "/list", method = RequestMethod.POST) public ResponseData<List<SysWayDto>> list(@CurrentUser UserParam userParam) { Map<String, Object> objectMap = MapUtils.convertObjToMap(userParam); return sysWayService.findWithOriginDest(objectMap); }
How to achieve it? First, we need to have an @ CurrentUser annotation:
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface CurrentUser { }
So the rest of the work is about HandlerMethodArgumentResolver:
@Slf4j public class CurrentUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { /** * It is used to determine whether the parameter decomposition needs to be handled. If true is returned, the following method resolveArgument will be called. */ @Override public boolean supportsParameter(MethodParameter methodParameter) { return methodParameter.getParameterType().isAssignableFrom(UserParam.class) && methodParameter.hasParameterAnnotation(CurrentUser.class); } /** * The real method used to handle parameter decomposition, the returned Object is the parameter Object on the controller method. */ @Override public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { String accessToken = nativeWebRequest.getHeader(GatewayHeader.accessToken); try { UserParam userParam = JsonUtils.readValue(JwtHelper.parseJWT(accessToken), UserParam.class); return userParam ; } catch (IOException e) { log.error("CurrentUserHandlerMethodArgumentResolver resolveArgument readValue error.accessToken:{}", accessToken, e); } catch (Exception e) { log.error("CurrentUserHandlerMethodArgumentResolver resolveArgument error.accessToken:{}", accessToken, e); } return null; } }
Finally, don't forget to register a custom parameter parser!
@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(new CurrentUserHandlerMethodArgumentResolver()); } }