这是我参与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。