自定义 Spring 参数解析器
1、自定义一个参数解析器类去实现 Spring 的拓展接口 HandlerMethodArgumentResolver
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private UserTokenService userTokenService;
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
// 获取 handler 方法签名中参数的类型
Class<?> parameterType = methodParameter.getParameterType();
// 获取指定的注解
RequestUser annotation = methodParameter.getParameterAnnotation(RequestUser.class);
// 判断当前参数贴了 RequestUser 注解 并且是 UserInfo 对象
// 字节码在 JVM 中始终只有一份
return annotation != null && UserInfo.class == parameterType;
}
@Override
public Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest,
WebDataBinderFactory webDataBinderFactory) throws Exception {
// 只有 supportsParameter 方法返回 true 才会执行这里的参数解析方法
/**e
* nativeWebRequest.getNativeRequest() 实际获取的就是 HttpServletRequest 对象
*/
UserInfo userInfo = userTokenService.getLoginUser(nativeWebRequest.getNativeRequest());
RequestUser annotation = methodParameter.getParameterAnnotation(RequestUser.class);
// 通过 RequestUser 中的 required 属性来决定是否抛异常
if ((annotation != null && annotation.required()) && userInfo == null) {
throw new AuthException("用户未认证");
}
return userInfo;
}
}
2、将自定义的参数解析对象交给 Spring MVC 进行管理(类似于登录拦截器)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private UserArgumentResolver userArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
// 将自定义的参数解析器交给 Spring MVC 进行管理
resolvers.add(userArgumentResolver);
}
}
3、为了区分模型对象和参数解析对象采用自定义注解来实现
@Target(ElementType.PARAMETER) // 指明当前注解只能贴在 parameter 参数上
@Retention(RetentionPolicy.RUNTIME) // 当前注解存在于运行时期
public @interface RequestUser {
// required 卜传值默认就是 true, 如果指明为 false 就会报错
boolean required() default true;
}
4、如何使用?
@RestController
@RequestMapping("/strategies/comments")
public class StrategyCommentController {
@Autowired
private IStrategyCommentService strategyCommentService;
@PostMapping("/test1")
public AjaxResult<?> test1(@RequestUser(required = false) UserInfo userInfo) {
System.out.print("userInfo 对象找不到 但又不想报错, 此时指明 required = false 返回 null, required 属性默认为true")
return AjaxResult.success();
}
@PostMapping("/test2")
public AjaxResult<?> test2(@RequestUser UserInfo userInfo) {
System.out.print("userInfo 对象找不到直接报错")
return AjaxResult.success();
}
@PostMapping("/thumb")
public AjaxResult<?> thumb(String cid, @RequestUser UserInfo userInfo) {
strategyCommentService.update(cid, userInfo);
return AjaxResult.success();
}
}