自定义 Spring MVC Controller 方法参数处理

1,179 阅读2分钟

这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战

在 Spring MVC Controller 的方法参数,Spring 会自动为我们注入一些特殊的参数值,比如 HttpServletRequest、HttpServletResponse 等对象,或者 HTTP 请求参数。有时候,我们也可以在 Controller 中使用 @InitBinder 注解的方法,来自定义转换请求参数的逻辑。对于在整个工程的诸多地方都需要的相同的转换逻辑,我们还可以自定义一个全局的参数转换处理逻辑。

比较常见的是,很多请求方法中会需要读取当前登录的用户信息,我们以此为例,来实现一个自定义的参数处理逻辑。

最终实现的效果是,可以将保存在 Session 中的当前登录用户的 ID,注入到请求处理方法的某个参数重,这个参数使用一个注解来标记,比如这样:

@GetMapping("current")
public String right(@CurrentUserId Long userId) {
    return userId;
}

自定义注解的代码比较简单:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Documented
public @interface CurrentUserId {
}

要使Controller 中的方法能够自动获取到当前登录用户的id,我们需要写一个参数处理的类,这个类需要继承 HandlerMethodArgumentResolver 类,并实现其中的方法:

public class CurrentUserIdArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(CurrentUserId.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        Object result = nativeWebRequest.getAttribute("currentUserId", NativeWebRequest.SCOPE_SESSION);
        return object;
    }
}

以上的方法当中,第一个方法,用来判断这个参数处理器支持哪些参数,方法返回 true/false 表示是否支持,这里的判断逻辑就是参数是不是有 CurrentUserId 注解。

第二个方法是具体的处理逻辑,我们这里的示例代码比较简单,直接从 Session 中读取到相应的内容,作为返回值返回。在真实的项目当中,要根据具体的业务逻辑来指定 Session key 并作必要的判断。

最后,需要将我们自定义的参数处理器配置到 Spring MVC 中。新建一个 WebMvcConfig 类,实现 WebMvcConfigurer 接口,再重写的 addArgumentResolvers 方法中添加刚刚自定义的参数处理类即可。


@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
...
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new CurrentUserIdArgumentResolver());
    }
}

大功告成,这样,我们就可以像文章开头的那样,在 Controller 方法中使用带有自定义的注解的参数,直接获取到当前登录用户的 ID。