Angular向Spring后端传数据时后端接收为null问题排查
Angular向Spring后端传参为null的排查与解决
问题描述
Angular前端将UserMaster和UserAddress封装进UserRequest对象发送到Spring后端时,后端接收的userRequest内属性为null,但通过Swagger发送相同结构的数据可正常接收。
相关代码
Angular注册组件代码
addnewuser(name: any, pass: any, phnnumb: any, address: any){ const userId = 0; const registrationDate = new Date().toISOString(); const status = "ACTIVE"; const addressId = 0; this.user = new UserMaster(userId, name, pass, phnnumb, registrationDate, status); this.userAddress = new UserAddress(addressId, this.user, address); this.userrequest = new UserRequest(this.user, this.userAddress); console.log(this.user); console.log(this.userAddress); console.log(this.userrequest); this.myservice.createUser(this.userrequest).subscribe(result => {console.log(result)}); }
Angular服务类代码
constructor(private http: HttpClient) { } createUser(userrequest: UserRequest){ return this.http.post<UserRequest>("http://localhost:10003/creatUser", userrequest); }
Spring控制器代码
@RestController @CrossOrigin("*") public class FrontController { @Autowired private ProdcomService ps; @PostMapping("creatUser") public UserMaster creatUser(@Valid @RequestBody UserRequest userRequest) { try { System.out.println(userRequest); UserMaster userMaster = userRequest.getUserMaster(); UserAddresses userAddresses = userRequest.getUserAddresses(); if (userMaster == null || userAddresses == null) { System.out.println("Received null objects in the request."); return null; } System.out.println("Received uMaster: " + userMaster); System.out.println("Received userAddresses: " + userAddresses); UserMaster uMaster = ps.creatuserService(userMaster); userAddresses.setUser(uMaster); ps.createaddressService(userAddresses); return uMaster; } catch (Exception e) { e.printStackTrace(); return null; } } }
UserMaster实体类代码
@Entity @Table(name="UserMaster") public class UserMaster { public enum UserStatus { ACTIVE, INACTIVE, PENDING_APPROVAL, BLOCKED } @Id @SequenceGenerator(name = "mygenerator", sequenceName = "mysequence", allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mygenerator") @Column(name = "user_id") private Long userId; @Column(name = "user_name") private String userName; @Column(name = "user_password") @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&-+=()])(?=\\S+$).{8,20}$",message = "password should consist of uppercase,lowercase,number,special characer and minimum of 8 character and atmost 20 character long") private String userPassword; @Column(name = "phone_number") @Size(min = 10,max = 10,message = "phone number should of only 10 digit") @NotNull(message = "phone number can not be null") private String phoneNumber; @Column(name = "registration_date") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC") private Date registrationDate; @Column(name = "status") private UserStatus status; }
UserAddresses实体类代码
@Entity @Table(name="UserAddresse") public class UserAddresses { @Id @SequenceGenerator(name = "mygenerator", sequenceName = "addsequence", allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mygenerator") @Column(name = "address_id") private Long addressId; @ManyToOne @JoinColumn(name = "user_id", nullable = false) private UserMaster user; @Column(name = "full_address") private String fullAddress; public Long getAddressId() { return addressId; } public void setAddressId(Long addressId) { this.addressId = addressId; } }
Spring服务实现类代码
@Service @Transactional public class ProdcomServiceImp implements ProdcomService { @Autowired private ProdcomJpaRespository pr; @Autowired private ProdcomAddressRepository pa; @Override public UserMaster creatuserService(UserMaster uMaster) { UserMaster userMaster = pr.save(uMaster); return userMaster; } }
请求数据格式对比
Angular控制台输出的请求数据结构
{ userMaster: { phoneNumber: "9560654651", registrationDate: "2023-10-09T00:48:52.001Z", status: "ACTIVE", userId: 0, userName: "Ramit", userPassword: "Ramit@1234" }, useraddress: { addressId: 0, fullAddress: "Spr", user: { phoneNumber: "9560654651", registrationDate: "2023-10-09T00:48:52.001Z", status: "ACTIVE", userId: 0, userName: "Ramit", userPassword: "Ramit@1234" } } }
Swagger发送的请求数据格式
{ "userMaster": { "userId": 0, "userName": "string", "userPassword": "string", "phoneNumber": "string", "registrationDate": "2023-10-09T01:43:32.188Z", "status": "ACTIVE" }, "userAddresses": { "addressId": 0, "user": { "userId": 0, "userName": "string", "userPassword": "string", "phoneNumber": "string", "registrationDate": "2023-10-09T01:43:32.188Z", "status": "ACTIVE" }, "fullAddress": "string" } }
问题排查与解决方案
核心问题:字段名不匹配
从格式对比可直接看出:
- Angular的
UserRequest中地址字段名为useraddress(小写后缀),但后端UserRequest对应的属性名是userAddresses(大写A+复数后缀),Spring无法映射到正确字段,导致接收为null。 - 需同步Angular与后端的字段命名,确保完全一致(包括大小写、单复数)。
具体修复步骤
修正Angular端字段命名
- 修改
UserRequest类,将地址字段名改为userAddresses,与后端保持一致:export class UserRequest { constructor(public userMaster: UserMaster, public userAddresses: UserAddress) {} } - 检查
UserAddress类,确保fullAddress字段名与后端实体类的fullAddress一致,避免使用address等别名。
- 修改
确保序列化结构正确
- 建议用TypeScript接口定义数据结构(比类更适合序列化),避免类的原型链影响JSON序列化:
export interface UserMaster { userId: number; userName: string; userPassword: string; phoneNumber: string; registrationDate: string; status: string; } export interface UserAddress { addressId: number; user: UserMaster; fullAddress: string; } export interface UserRequest { userMaster: UserMaster; userAddresses: UserAddress; } - 在发送请求前,打印
JSON.stringify(userrequest)确认最终发送的JSON结构与Swagger格式完全一致。
- 建议用TypeScript接口定义数据结构(比类更适合序列化),避免类的原型链影响JSON序列化:
验证请求头与枚举兼容
- Angular的
HttpClient默认发送Content-Type: application/json,可显式指定确保后端正确识别:createUser(userrequest: UserRequest){ return this.http.post<UserRequest>("http://localhost:10003/creatUser", userrequest, { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) }); } - 后端
UserStatus枚举与Angular发送的"ACTIVE"字符串兼容,无需额外处理,若出现枚举反序列化失败,可添加@JsonValue注解到枚举值。
- Angular的
调试后端接收日志
- 在Spring控制器中添加请求体日志,确认实际接收的JSON内容:
@PostMapping("creatUser") public UserMaster creatUser(@Valid @RequestBody String rawRequest) { System.out.println("Raw request body: " + rawRequest); // 再将rawRequest转为UserRequest对象进行处理 ObjectMapper mapper = new ObjectMapper(); UserRequest userRequest = mapper.readValue(rawRequest, UserRequest.class); // ...后续逻辑 }
- 在Spring控制器中添加请求体日志,确认实际接收的JSON内容:
内容的提问来源于stack exchange,提问作者devprakash pandey
相关产品推荐
相关产品推荐

