方法参数转换器
HandlerMethodArgumentResolver
介绍
使用方法参数转化器[HandlerMethodArgumentResolver]给controller的自定义参数赋值.
使用场景
例:从请求头获取用户信息
现在的方案:获取"SCRM-BASICS"请求头中的数据,然后转换后再获取企业id,自己手动转换,我们可以使用方法参数转换器,自动封装到一个参数中.
@PostMapping("/friends/create")
@ApiOperation(value = "好友助力-创建好友助力活动", notes = "创建好友助力活动")
public BaseResult createFriends(
@RequestHeader("SCRM-BASICS") String scrm,
@Valid @RequestBody CreateFriendsReqVO req) throws FriendsHelpException {
log.info("好友助力-创建好友助力活动请求头信息,userInfo:{},入参:{}", scrm, JSONUtil.toJsonStr(req));
if (StringUtils.isEmpty(scrm)) {
throw new FriendsHelpException(NO_LOGIN_ERROR);
}
return helpService.createFriends(new ScrmBasics(scrm).getCorpId(), new ScrmBasics(scrm).getAccountId(), req);
}
替代方案
使用HandlerMethodArgumentResolver
@ApiOperation("新增菜单")
@PostMapping("/add")
public R addMenu(
@ApiIgnore @CurrentUser CU cu,//我们需要用代码实现,把用户id,自动注入到添加了@CurrentUser注解的CU 类型的cu中
@Validated(value = {BaseInsert.class}) @RequestBody MenuReqVO req
) {
log.info("新增菜单,参数:{}", JSONUtil.toJsonStr(req));
return menuService.add(cu, req);
}
实现步骤
创建一个实体
创建一个实体,用于接收数据
@Data
@AllArgsConstructor
public class CU {
/**
* 用户id
*/
private Long userId;
}
创建一个注解
创建一个注解用于精确定位
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentUser {
}
创建一个转换器
/**
*该类会在controller的每个方法执行前调用,执行supportsParameter()判断是否转换,调用resolveArgument()转换参数
*/
@Component
@Slf4j
public class CurrentUserResolver implements HandlerMethodArgumentResolver {
//判断是否进行转化
@Override
public boolean supportsParameter(MethodParameter parameter) {
//判断这个方法参数列表中是否具有CU这个类,是否有CurrentUser这个注解
return parameter.getParameterType().isAssignableFrom(CU.class)
&& parameter.hasParameterAnnotation(CurrentUser.class);
}
//具体转换逻辑
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) {
//获取请求头的信息,解析出请求信息
String accessToken = nativeWebRequest.getHeader("accessToken");
try {
Claims claims = JwtUtil.parseJWT(accessToken);
String subject = claims.getSubject();
LoginUserInfo info = JSONUtil.toBean(subject, LoginUserInfo.class);
Long userId = info.getUserId();
//返回要注入的对象
return new CU(userId);
} catch (Exception e) {
log.warn("token解析异常");
}
return null;
}
}
把转换器注册到spring中
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Autowired
private CurrentUserResolver currentUserResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(currentUserResolver);
}
}