如何在Spring Boot中从Interceptor传递DTO到Controller?
首先,你的核心问题出在Interceptor的注册方式错误,导致Interceptor和Controller不在同一个Spring容器中,进而使得UserLoginInfoDTO的请求作用域实例无法共享。下面一步步拆解问题并给出修复方案:
1. 错误根源:自定义Spring容器导致实例不共享
你在addInterceptors里手动创建了AnnotationConfigApplicationContext,这会生成一个全新的Spring容器,和你的应用主容器完全独立。Interceptor里的UserLoginInfoDTO是这个新容器的实例,而Controller里的是主容器的实例,两者自然无法共享请求数据,所以Controller拿到的是空对象。
2. 修复步骤
步骤1:修正Interceptor的注册方式
直接在WebMvcConfigurer的addInterceptors方法中注入Interceptor实例,不要手动创建容器:
@Configuration public class WebConfig implements WebMvcConfigurer { // 直接注入Spring容器管理的Interceptor实例 @Autowired private Inter inter; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(inter); } }
步骤2:简化UserLoginInfoDTO的配置
你的UserLoginInfoDTO已经标注了@RequestScope和@Component,这部分是对的——它会为每个HTTP请求创建一个独立实例,刚好满足Interceptor和Controller共享同请求数据的需求。不需要在Demo类里手动创建@Bean,因为@Component已经会让Spring自动扫描创建实例了:
// 去掉Demo类里的uu()方法,保留@Component即可 @RequestScope @Component public class UserLoginInfoDTO { private int userId; private String email; private String firstName; private String lastName; // getters & setters }
步骤3:在Controller中正确注入并使用
直接在Controller中注入UserLoginInfoDTO,因为是请求作用域,同一个请求内Interceptor设置的数据会被传递过来:
@RestController @RequestMapping("/test") public class TestController { @Autowired private UserLoginInfoDTO userLoginInfoDTO; @GetMapping("/info") public ResponseEntity<UserLoginInfoDTO> getLoginInfo() { // 这里就能拿到Interceptor中设置的email了 return ResponseEntity.ok(userLoginInfoDTO); } }
3. 额外验证点
- 确保你的
Interceptor和Controller都被Spring正确扫描到(比如在启动类的@SpringBootApplication扫描范围内) - 如果是传统Spring MVC项目,要确保
<context:component-scan>配置了对应的包路径
这样修改后,同一个HTTP请求内,Interceptor设置的UserLoginInfoDTO数据就能在Controller中正常获取到了。
内容的提问来源于stack exchange,提问作者Ankit Bansal

