Spring Boot微服务访问localhost端点出现404错误求助
404错误排查:Spring Cloud Gateway访问产品微服务失败
我用Maven构建Spring Boot微服务项目,包含products(产品服务)和config-server(配置中心),本地PostgreSQL有一个product数据库,表结构和数据都已就绪。但通过网关地址http://localhost:8222/api/v1/products访问时,返回404错误,响应内容如下:
{ "timestamp": 1436442596410, "status": 404, "error": "Not Found", "message": "No message available", "path": "/api/v1/products" }
相关代码文件
产品服务核心代码
ProductController.java
@RestController @RequestMapping("/api/v1/products") @RequiredArgsConstructor public class ProductController { private final ProductService service; @PostMapping public ResponseEntity<Integer> createProduct( @RequestBody @Valid ProductRequest request ) { return ResponseEntity.ok(service.createProduct(request)); } @PostMapping("/purchase") public ResponseEntity<List<ProductPurchaseResponse>> purchaseProducts( @RequestBody List<ProductPurchaseRequest> request ) { return ResponseEntity.ok(service.purchaseProducts(request)); } @GetMapping("/{product-id}") public ResponseEntity<ProductResponse> findById( @PathVariable("product-id") Integer productId ) { return ResponseEntity.ok(service.findById(productId)); } @GetMapping public ResponseEntity<List<ProductResponse>> findAll() { return ResponseEntity.ok(service.findAll()); } }
ProductService.java
@Service @RequiredArgsConstructor public class ProductService { private final ProductRepository repository; private final ProductMapper mapper; public Integer createProduct( ProductRequest request ) { var product = mapper.toProduct(request); return repository.save(product).getId(); } public ProductResponse findById(Integer id) { return repository.findById(id) .map(mapper::toProductResponse) .orElseThrow(() -> new EntityNotFoundException("Product not found with ID:: " + id)); } public List<ProductResponse> findAll() { return repository.findAll() .stream() .map(mapper::toProductResponse) .collect(Collectors.toList()); } @Transactional(rollbackFor = ProductPurchaseException.class) public List<ProductPurchaseResponse> purchaseProducts( List<ProductPurchaseRequest> request ) { var productIds = request .stream() .map(ProductPurchaseRequest::productId) .toList(); var storedProducts = repository.findAllByIdInOrderById(productIds); if (productIds.size() != storedProducts.size()) { throw new ProductPurchaseException("One or more products does not exist"); } var sortedRequest = request .stream() .sorted(Comparator.comparing(ProductPurchaseRequest::productId)) .toList(); var purchasedProducts = new ArrayList<ProductPurchaseResponse>(); for (int i = 0; i < storedProducts.size(); i++) { var product = storedProducts.get(i); var productRequest = sortedRequest.get(i); if (product.getAvailableQuantity() < productRequest.quantity()) { throw new ProductPurchaseException("Insufficient stock quantity for product with ID:: " + productRequest.productId()); } var newAvailableQuantity = product.getAvailableQuantity() - productRequest.quantity(); product.setAvailableQuantity(newAvailableQuantity); repository.save(product); purchasedProducts.add(mapper.toproductPurchaseResponse(product, productRequest.quantity())); } return purchasedProducts; } }
ProductApplication.java
@SpringBootApplication public class ProductApplication { public static void main(String[] args) { SpringApplication.run(ProductApplication.class, args); } }
配置中心的服务配置
gateway-service.yml
server: port: 8222 spring: cloud: gateway: discovery: locator: enabled: true routes: - id: product-service uri: lb:http://PRODUCT-SERVICE predicates: - Path=/api/v1/products/**
product-service.yml
server: port: 8050 spring: datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://localhost:5432/product username: XXX password: XXX jpa: hibernate: ddl-auto: validate database: postgresql database-platform: org.hibernate.dialect.PostgreSQLDialect flyway: baseline-on-migrate: true enabled: true baseline-description: "init" baseline-version: 0 user: ${spring.datasource.username} password: ${spring.datasource.password}
Eureka客户端配置(application.yml)
eureka: instance: hostname: localhost client: service-url: defaultZone: http://localhost:8761/eureka name: value: XXX spring: cloud: config: override-system-properties: false management: tracing: sampling: probability: 1.0
已验证操作
- 所有微服务已成功注册到Eureka(地址
http://localhost:8761) - 项目文件结构及pom.xml配置无错误
- Flyway已成功连接PostgreSQL并完成数据初始化
排查方向
- 验证产品服务自身可用性:直接访问
http://localhost:8050/api/v1/products,确认是否能正常返回数据。若直接访问也404,检查:- 控制器类是否在
ProductApplication所在包或子包下,确保被Spring扫描到 - 产品服务是否配置了
server.servlet.context-path,导致路径前缀变化
- 控制器类是否在
- 检查网关路由配置:
- 确认Eureka中产品服务的注册名称是否为
PRODUCT-SERVICE(Eureka服务名称大小写敏感) - 网关路由断言
Path=/api/v1/products/**是否匹配请求路径,可调整为Path=/api/v1/products或Path=/api/v1/products/**测试 - 开启网关日志,查看请求转发详情,确认请求是否正确路由到产品服务
- 确认Eureka中产品服务的注册名称是否为
- 检查负载依赖:确保网关项目依赖中包含
spring-cloud-starter-loadbalancer,否则lb://协议无法生效 - 检查端口通信:确认本地防火墙或安全策略未阻止网关(8222)与产品服务(8050)之间的通信
内容的提问来源于stack exchange,提问作者dqdq dqsss
相关产品推荐
相关产品推荐

