HandlerMethodArgumentResolver详解
一、前言
最近在项目中看到的一个接口,之前没见过这个写法,记录一下。
二、源码
源码不长,直接拷贝吧。
/**
* 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;
}
通过官方的讲解,我们可以知道,这个接口就是将请求参数解析成特定类型的策略接口。
需要实现两个方法:
1、supportsParameter: 判断请求参数是否支持此解析器
2、resolveArgument: 做参数解析的具体实现方法
参数说明:
MethodParameter parameter:要解析的方法参数,这个参数必须是支持该解析器的
ModelAndViewContainer mavContainer: 当前请求的 ModelAndViewContainer 容器
NativeWebRequest webRequest:当前的 请求实体
WebDataBinderFactory binderFactory:实例创建工厂
返回值: 具体的需要解析的对象
三、实现
简单看看该策略接口都有哪些具体的实现吧。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1sTlCnXP-1637808887888)(C:\Users\lurious\AppData\Roaming\Typora\typora-user-images\image-20211125095956664.png)]
简单看了下,有几个我们比较常用的参数
PathVariableMethodArgumentResolver // @PathParam 注解解析器
RequestHeaderMethodArgumentResolver // @RequestHeader 注解解析器
RequestParamMethodArgumentResolver // @RequestParam 注解解析器
四、应用
在开发中常常需要获取登录用户的信息,如果每次都去写解析方法的话 可能会有点麻烦,
这个时候就可以直接自定义一个参数解析器,专门用来解析登录用户的信息。
这里拷贝人人开源里的一个例子来做示例
@Component
public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private UserService userService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(UserEntity.class) && parameter.hasParameterAnnotation(LoginUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
NativeWebRequest request, WebDataBinderFactory factory) throws Exception {
//获取用户ID
Object object = request.getAttribute(AuthorizationInterceptor.USER_KEY, RequestAttributes.SCOPE_REQUEST);
if(object == null){
return null;
}
//获取用户信息
UserEntity user = userService.getById((Long)object);
return user;
}
}
逻辑比较简单,判断注解是否合法,然后从注解中拿到用户ID信息,再从数据库拿数据就可以。对于比较复杂的场景,这可能是有用的。
最后别忘了再webMvcConfig中添加解析器
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;
@Override
public void addInterceptors(InterceptorRegistry registry) {
........
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
}
}