如何让Spring从Spring Security认证自动注入User实体至RequestMapping
解决方案:自定义Spring MVC参数解析器
你可以通过实现HandlerMethodArgumentResolver来实现直接在控制器方法中注入MyUserEntity,彻底消除重复代码。这个接口允许你自定义Spring MVC如何解析控制器方法的参数。
步骤1:实现自定义参数解析器
创建一个解析器类,负责从SecurityContext中获取用户UUID、查询完整实体并返回:
@Component public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver { private final UserService userService; // 构造注入UserService public CurrentUserArgumentResolver(UserService userService) { this.userService = userService; } // 判断是否需要处理当前参数 @Override public boolean supportsParameter(MethodParameter parameter) { // 匹配MyUserEntity类型的参数 return MyUserEntity.class.isAssignableFrom(parameter.getParameterType()); } // 执行参数解析逻辑 @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { // 从SecurityContext获取已认证的用户信息 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null || !(authentication.getPrincipal() instanceof CustomUserDetails)) { throw new UnauthorizedException("用户未登录或认证信息无效"); } CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal(); // 根据UUID查询完整用户实体 return userService.findByUuid(userDetails.getUuid()); } }
步骤2:注册参数解析器到Spring MVC
创建WebMvc配置类,将自定义解析器加入Spring MVC的参数解析器列表:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { private final CurrentUserArgumentResolver currentUserArgumentResolver; public WebMvcConfig(CurrentUserArgumentResolver currentUserArgumentResolver) { this.currentUserArgumentResolver = currentUserArgumentResolver; } @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(currentUserArgumentResolver); } }
步骤3:在控制器中直接使用
现在你可以在任意控制器方法中直接注入MyUserEntity,无需任何额外代码:
@GetMapping("/some") public SomeResponse someMethod(MyUserEntity user) { // 直接使用完整的User实体 // ... }
可选优化:添加自定义注解(更清晰)
如果希望明确标记需要注入用户的参数,可以自定义一个注解,避免误注入:
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface CurrentUser { }
修改解析器的supportsParameter方法:
@Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(CurrentUser.class) && MyUserEntity.class.isAssignableFrom(parameter.getParameterType()); }
控制器使用方式变为:
@GetMapping("/some") public SomeResponse someMethod(@CurrentUser MyUserEntity user) { // ... }
注意事项
- 确保
UserService.findByUuid方法的性能,建议添加缓存避免重复查询数据库 - 未登录或认证无效的场景,可根据业务需求抛出对应异常(如
AccessDeniedException),配合全局异常处理器返回标准响应
内容的提问来源于stack exchange,提问作者entropy177
相关产品推荐
相关产品推荐

