You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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与后端的字段命名,确保完全一致(包括大小写、单复数)。

具体修复步骤

  1. 修正Angular端字段命名

    • 修改UserRequest类,将地址字段名改为userAddresses,与后端保持一致:
      export class UserRequest {
        constructor(public userMaster: UserMaster, public userAddresses: UserAddress) {}
      }
      
    • 检查UserAddress类,确保fullAddress字段名与后端实体类的fullAddress一致,避免使用address等别名。
  2. 确保序列化结构正确

    • 建议用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格式完全一致。
  3. 验证请求头与枚举兼容

    • 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注解到枚举值。
  4. 调试后端接收日志

    • 在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);
          // ...后续逻辑
      }
      

内容的提问来源于stack exchange,提问作者devprakash pandey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 02:08:10