Spring迁移Spring Boot后Tomcat启动但端点401错误排查求助
迁移Spring到Spring Boot的问题解决指南
1. 健康端点访问失败的核心原因
你没添加@ComponentScan,且主类包和API端点包不同,导致健康检查相关的Controller/Jersey资源类根本没被Spring容器加载,请求找不到对应映射,才会抛出“This application has no explicit mapping for /error”的提示。至于401,大概率是Spring Boot默认引入的Spring Security拦截了未授权请求,但核心问题还是端点未注册。
2. 解决@ComponentScan引发的Bean重复冲突
出现expecting a single bean but found 2,是因为applicationContext.xml已经手动定义了某些Bean,而@ComponentScan又扫描到了同一个类上的@Component/@Service/@Controller等注解,导致容器中出现同类型/同名的重复Bean。给你三个解决方向:
- 排除扫描重复类:在
@ComponentScan中指定排除xml已定义的Bean对应的类,示例:@SpringBootApplication @ImportResource("classpath:applicationContext.xml") @ComponentScan( basePackages = "com.your.api.package", excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = {DuplicateBean1.class, DuplicateBean2.class} ) ) public class YourBootApplication { public static void main(String[] args) { SpringApplication.run(YourBootApplication.class, args); } } - 统一Bean管理方式:要么删掉xml中重复定义的Bean,改用注解管理(适合长期迁移);要么去掉对应类上的注解,保留xml配置。
- 指定注入Bean:如果是同类型不同名的Bean冲突,在注入时用
@Qualifier("beanName")指定要注入的Bean名称。
3. 用Java配置替代原有web.xml的Jersey Servlet映射
Spring Boot无需web.xml,你需要用Java配置来迁移原来的Jersey Servlet设置:
- 确保依赖中包含Jersey Spring Boot Starter(没有就加进pom.xml):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jersey</artifactId> </dependency> - 创建Jersey配置类,注册资源包:
import org.glassfish.jersey.server.ResourceConfig; import org.springframework.stereotype.Component; @Component public class JerseyConfig extends ResourceConfig { public JerseyConfig() { // 扫描你的Jersey资源类所在包 packages("com.your.jersey.resource.package"); } } - 在
application.properties里配置Jersey的根路径(对应原来web.xml的url-pattern):spring.jersey.application-path=/rest-api-web/api
这样Jersey就能处理对应路径下的请求,和原来web.xml的配置效果一致。
4. 额外补充
如果你的健康检查是Spring Boot Actuator的端点,需要确保添加了Actuator依赖,并配置允许访问:
# 暴露健康端点 management.endpoints.web.exposure.include=health # 显示健康详情 management.endpoint.health.show-details=always # 若有Spring Security,允许匿名访问健康端点 spring.security.authorization.request-matchers.management.endpoints.web.path=/actuator/health.permitAll()
如果是自定义的Jersey健康资源类,只要确保该类被Jersey的包扫描覆盖到即可。
内容的提问来源于stack exchange,提问作者Suraj
相关产品推荐
相关产品推荐

