自定义 Spring 参数解析器

自定义 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();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_49137820/article/details/128505428