Spring Boot CRUD应用POST请求返回404错误问题求助
Spring Boot CRUD应用PostMapping 404错误排查与解决
问题概述
开发基于PostgreSQL的Spring Boot CRUD应用时,@GetMapping请求可正常返回空对象数组,但@PostMapping请求返回404错误。此前使用@RequestMapping("api/v1/customers")时收到405错误,修改为@RequestMapping(name = "api/v1/customers" ,method = RequestMethod.POST)后变为404错误。同时customerRepository.save(customer)不允许将依赖注入设为final,IDEA建议设为static但无效。
代码问题分析
1. 请求映射配置错误
- 类级别
@RequestMapping误用name属性:name仅作为路径别名,不会实际映射请求路径;同时指定method = RequestMethod.POST会限制整个类的请求只能是POST,导致原本正常的@GetMapping请求出现405(方法不允许)。 @PostMapping注解位置错误:放在了内部record类NewCustomerRequest中,Spring无法识别该类中的控制器方法,因为record未被标记为控制器组件。
2. 依赖注入错误
使用static修饰CustomerRepository,Spring容器管理的Bean实例不应为静态,静态成员会脱离容器的生命周期管理,导致依赖注入失效。
修复后的代码
SpringRecapApplication.java
package com.example.SpringRecap; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @SpringBootApplication(exclude = SecurityAutoConfiguration.class) @RequestMapping("api/v1/customers") // 正确使用value属性映射基础路径 public class SpringRecapApplication { // 使用final修饰,依赖注入由Spring容器管理 private final CustomerRepository customerRepository; // 构造注入,无需static public SpringRecapApplication(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } public static void main(String[] args) { SpringApplication.run(SpringRecapApplication.class, args); } @GetMapping public List<Customer> getCustomer() { return customerRepository.findAll(); } // 将PostMapping方法移到类级别,作为控制器方法 @PostMapping public void addCustomer(@RequestBody NewCustomerRequest newCustomerRequest) { Customer customer = new Customer(); customer.setAge(newCustomerRequest.age()); customer.setName(newCustomerRequest.name()); customer.setEmail(newCustomerRequest.email()); customerRepository.save(customer); } // 仅作为DTO的record,无需注解 record NewCustomerRequest( String name, String email, Integer age ) {} }
CustomerRepository.java(无需修改)
package com.example.SpringRecap; import org.springframework.data.jpa.repository.JpaRepository; public interface CustomerRepository extends JpaRepository<Customer,Integer> { }
Customer.java(无需修改)
package com.example.SpringRecap; import jakarta.persistence.*; import java.util.Objects; @Entity public class Customer { @Id @SequenceGenerator( name = "customer_id_sequence", sequenceName = "customer_id_sequence", allocationSize = 1 ) @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "customer_id_sequence" ) private Integer id; private String name; private String email; private Integer age; public Customer(Integer id, String name, String email, Integer age) { this.id = id; this.name = name; this.email = email; this.age = age; } public Customer() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Customer customer = (Customer) o; return Objects.equals(id, customer.id) && Objects.equals(name, customer.name) && Objects.equals(email, customer.email) && Objects.equals(age, customer.age); } @Override public int hashCode() { return Objects.hash(id, name, email, age); } @Override public String toString() { return "Customer{" + "id=" + id + ", name='" + name + '\'' + ", email='" + email + '\'' + ", age=" + age + '}'; } }
测试验证
修复后,使用Postman发送POST请求到http://localhost:8080/api/v1/customers,请求体使用JSON格式:
{ "name": "Test User", "email": "test@example.com", "age": 25 }
此时请求应返回200状态码,数据成功存入PostgreSQL数据库;@GetMapping请求http://localhost:8080/api/v1/customers可返回新增的用户数据。
内容的提问来源于stack exchange,提问作者Nimasha Madhushani
相关产品推荐
相关产品推荐

