预检请求成功却返回404:Spring Rest Controller故障排查求助
问题描述
我正在开发搭配Angular客户端的Spring应用,新增了两个Rest Controller,其中一个正常工作,另一个(PriceConfigRestController)的所有端点均出现问题:调用时预检请求成功,但后续返回404错误。已确认请求URL正确,用Postman测试也得到相同的404响应。怀疑该Controller未被Spring扫描注册,但不知道如何验证,且两个新Controller目录结构一致,目前陷入困境。
附上该Controller代码:
@RestController @Validated public class PriceConfigRestController implements ApiRestController { public static final String URI_PRICECONFIG_BY_ID_INTERNAL = URI_PRICECONFIGS_INTERNAL + "{priceConfigId}"; public static final String URI_DELETE_PRICECONFIG_BY_ID_INTERNAL = URI_PRICECONFIGS_INTERNAL + "{priceConfigId}"; public static final String URI_PRICECONFIGS_BY_ORGANIZER_ID = URI_ORGANIZERS_INTERNAL + "{organizerId}/priceconfigs"; private static final Logger LOGGER = LoggerFactory.getLogger(PriceConfigRestController.class); private final PriceConfigService priceConfigService; public PriceConfigRestController(PriceConfigService priceConfigService) { this.priceConfigService = priceConfigService; } @RequestMapping(value = URI_PRICECONFIGS_INTERNAL, method = RequestMethod.POST, consumes = APPLICATION_JSON) public ResponseEntity<PriceConfigDto> createPriceConfig(@RequestBody @Valid @NotNull PriceConfigDto priceConfigDto){ PriceConfigDto resultDto = priceConfigService.createPriceConfig(priceConfigDto); LOGGER.debug("PriceConfig with ID : " + resultDto.getId() + " created: Response: " + HttpStatus.OK); return new ResponseEntity<>(priceConfigDto, HttpStatus.OK); } @RequestMapping(value = URI_DELETE_PRICECONFIG_BY_ID_INTERNAL, method = RequestMethod.DELETE) public ResponseEntity<Boolean> deletePriceConfigById(@PathVariable Long priceConfigId) throws ResourceNotFoundException { priceConfigService.deletePriceConfigById(priceConfigId); LOGGER.debug("Removed priceConfig with ID: " + priceConfigId + " Response: " + HttpStatus.OK); return new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK); } @RequestMapping(value = URI_PRICECONFIG_BY_ID_INTERNAL, method = RequestMethod.GET) public ResponseEntity<PriceConfigDto> getPriceConfigById(@PathVariable Long priceConfigId) throws ResourceNotFoundException { PriceConfigDto priceConfigDto = priceConfigService.getPriceConfigById(priceConfigId); LOGGER.debug("PriceConfig ID: " + priceConfigId + " Response: " + HttpStatus.OK); return new ResponseEntity<>(priceConfigDto, HttpStatus.OK); } @RequestMapping(value = URI_PRICECONFIGS_BY_ORGANIZER_ID, method = RequestMethod.GET) public ResponseEntity<List<PriceConfigDto>> getPriceConfigsByOrganizerId(@PathVariable Long organizerId) { List<PriceConfigDto> priceConfigDtos = priceConfigService.getPriceConfigsByOrganizerId(organizerId); LOGGER.debug("PriceConfigsByOrganizerId ID: " + organizerId + " Response: " + HttpStatus.OK); return new ResponseEntity<>(priceConfigDtos, HttpStatus.OK); } }
排查与解决步骤
一、验证Controller是否被Spring注册
- 启用Spring Boot Actuator的
beans端点:在application.properties中添加management.endpoints.web.exposure.include=beans,启动应用后访问/actuator/beans,搜索priceConfigRestController,能找到则说明已注册,否则未被扫描。 - 添加构造方法日志:在
PriceConfigRestController的构造方法中加入LOGGER.info("PriceConfigRestController initialized"),启动应用时查看日志是否有该输出,有则说明Controller已被实例化。 - 检查扫描范围:确认启动类上的
@SpringBootApplication或@ComponentScan注解的扫描路径包含该Controller所在包。若启动类与Controller不在同一父包下,需显式指定,比如@SpringBootApplication(scanBasePackages = {"com.your.project.package"})。
二、检查URI常量定义
代码中使用的URI_PRICECONFIGS_INTERNAL、URI_ORGANIZERS_INTERNAL未在当前代码中定义,需确认:
- 常量是否以
/开头?比如URI_PRICECONFIGS_INTERNAL若为priceconfigs而非/priceconfigs,拼接后的路径会缺少前缀斜杠,导致匹配失败。 - 常量值是否存在拼写错误,或与其他Controller的路径冲突?
三、打印所有注册端点
添加配置类打印Spring已注册的所有端点,确认PriceConfigRestController的路径是否正确:
@Component public class EndpointPrinter implements ApplicationListener<ApplicationReadyEvent> { private final RequestMappingHandlerMapping handlerMapping; public EndpointPrinter(RequestMappingHandlerMapping handlerMapping) { this.handlerMapping = handlerMapping; } @Override public void onApplicationEvent(ApplicationReadyEvent event) { handlerMapping.getHandlerMethods().forEach((key, value) -> { System.out.println("Endpoint: " + key.getPatternsCondition() + " -> " + value.getBean()); }); } }
启动应用后查看控制台输出,确认目标Controller的端点是否存在,以及路径是否与你请求的一致。
四、其他排查点
- 检查拦截器/过滤器是否修改了请求路径,导致无法匹配到Controller。
- 确认
@Validated依赖是否完整:需引入spring-boot-starter-validation依赖,缺失可能导致Controller初始化失败。 - 检查
PriceConfigService是否正常注入:若该Service存在初始化异常,会导致Controller无法正常注册。
内容的提问来源于stack exchange,提问作者FJ97
相关产品推荐
相关产品推荐

