为什么@RequestBody获取具有空属性的对象 [英] Why is the @RequestBody getting an object with null attributes

查看:134
本文介绍了为什么@RequestBody获取具有空属性的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个springboot REST控制器,具有所示的PATCH和PUT的请求方法.由于某些原因,@ RequestBody"company"的字段/属性以空值形式出现.我想念什么?

I have a springboot REST controller with the request method for a PATCH and PUT as indicated. For some reason, the fields/attributes for @RequestBody "company" are coming in as null values. What am I missing?

我在前端使用angular8,并且正在执行PATCH调用.

I am using angular8 on the front end and it is performing a PATCH call.

我尝试了其他一些建议,但没有运气.如果这是一个重复的问题,请指出答案.

I have tried some of the other posts suggestions, but no luck. If this is a repeated question, please point me to the answer.

Spring Tool Suite 4 

版本:4.1.0.RELEASE建立编号:201812201347

Version: 4.1.0.RELEASE Build Id: 201812201347

版权所有(c)2007-2018 Pivotal,Inc.版权所有.访问 http://spring.io/tools4

Copyright (c) 2007 - 2018 Pivotal, Inc. All rights reserved. Visit http://spring.io/tools4

我正在将pgAdmin 4.12用于Postgres.

I am using pgAdmin 4.12 for postgres.

这是我从Angular拨打的电话:

This is the call I am making from Angular:

    this.companyService.patch$(this.currentId, this.appMenu.currentObject).subscribe(selectedCompany => {this.appMenu.currentObject = selectedCompany});

这是如上所示被调用的角度服务:

This is the angular service that is called as indicated above:

    import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';
import { Company } from '../models/company.model';

@Injectable({
  providedIn: 'root'
})
export class CompanyService {
  private url: string;

  constructor(private http: HttpClient) {
    this.url = "http://localhost:8080/niche/company";
  }

  getOne$ = (companyId: number): Observable<Company> => this.http.get<Company>(`${this.url}/${companyId}`);

  get$ = (): Observable<Company[]> => this.http.get<Company[]>(this.url);

  post$ = (company: Company): Observable<Company> => this.http.post<Company>(this.url, { company });

  patch$ = (companyId: number, company: Company): Observable<Company> => this.http.patch<Company>(`${this.url}/${companyId}`, { company });

  delete$ = (companyId: number): Observable<Company> => this.http.delete<Company>(`${this.url}/${companyId}`);
}

从Angular前端请求有效载荷:

Request Payload from Angular front end:

    {company: {createdBy: "denis", createdDate: "2019-04-14T04:00:00.000+0000", updatedBy: "denis",…}}
company: {createdBy: "denis", createdDate: "2019-04-14T04:00:00.000+0000", updatedBy: "denis",…}
companyName: "Bull Winkle"
createdBy: "denis"
createdDate: "2019-04-14T04:00:00.000+0000"
email: "bullwinkle@mail.com"
id: 2
notes: "test"
phone: "999999999"
products: []
updatedBy: "denis"
updatedDate: "2019-05-14T04:00:00.000+0000"
webSite: "bullwilkle.com"

这是实际的JSON:

{"company":{"createdBy":"denis","createdDate":"2019-04-14T04:00:00.000+0000","updatedBy":"denis","updatedDate":"2019-05-14T04:00:00.000+0000","id":2,"email":"bullwinkle@mail.com","companyName":"Bull Winkle","webSite":"bullwilkle.com","phone":"999999999","notes":"test","products":[]}}

springboot后端控制器:

The springboot backend controller:

    /**
 * 
 */
package com.ebusiness.niche.controller;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;

import com.ebusiness.niche.entity.Company;
import com.ebusiness.niche.service.CompanyService;
//import com.sun.istack.internal.logging.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author denisputnam
 *
 */
@RestController
@RequestMapping( value = "/niche" )
public class CompanyController {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private CompanyService companyService;

    @ResponseBody
    @RequestMapping(value = {"/company"}, method = { RequestMethod.GET })
    @CrossOrigin(origins = "http://localhost:4200")
    public ResponseEntity<List<Company>> getCompanys() {
        log.info("getCompanys(): Called...");

        List<Company> companyList = null;

        companyList = this.companyService.findAll();

        if( companyList == null || companyList.isEmpty() ) {
            log.info("getCompanys(): returned a null or empty list.");
            ResponseEntity<List<Company>> rVal = new ResponseEntity<List<Company>>(companyList, HttpStatus.NO_CONTENT);
            return rVal;
        }
        return new ResponseEntity<List<Company>>(companyList, HttpStatus.OK);       
    }

    @ResponseBody
    @RequestMapping(value = {"/company/{id}"}, method = { RequestMethod.GET })
    @CrossOrigin(origins = "http://localhost:4200")
    public ResponseEntity<Company> getCompany(@PathVariable("id") Long id) {
        log.info("getCompany(): Called...");
        log.info("id=" + id);

//      List<Company> companyList = null;
        Optional<Company> optcompany = null;
        Company company = null;

        optcompany = this.companyService.findById(id);

        if( optcompany == null  ) {
            log.info("getCompany(): returned a null.");
            ResponseEntity<Company> rVal = new ResponseEntity<Company>(company, HttpStatus.NO_CONTENT);
            return rVal;
        } else {
            company = optcompany.get();
        }
        return new ResponseEntity<Company>(company, HttpStatus.OK);     
    }

    @ResponseBody
//  @RequestMapping(value = {"/company/{id}"}, headers = {
//    "content-type=application/json" }, consumes = MediaType.APPLICATION_JSON_VALUE, method = { RequestMethod.PATCH, RequestMethod.PUT, RequestMethod.POST })
    @RequestMapping(value = {"/company/{id}"}, method = { RequestMethod.PATCH, RequestMethod.PUT })
    @CrossOrigin(origins = {"http://localhost:4200"})
    public ResponseEntity<Company> updateCompany(@PathVariable("id") Long id, @RequestBody Company company) {
        log.info("updateCompany(): Called...");
        log.info("id=" + id);

        Optional<Company> currentCompany = this.companyService.findById(id);
        Company dbCompany = null;

        if( currentCompany == null ) {
            log.error("Unable to update.  The company with id {} not found.", id);
            ResponseEntity<Company> rVal = new ResponseEntity<Company>(company, HttpStatus.NO_CONTENT);
            return rVal;
        }

        dbCompany = currentCompany.get();
        dbCompany.setCompanyName(company.getCompanyName());
        dbCompany.setEmail(company.getEmail());
        dbCompany.setNotes(company.getNotes());
        dbCompany.setPhone(company.getPhone());
        dbCompany.setWebSite(company.getWebSite());

        this.companyService.update(dbCompany);

        return new ResponseEntity<Company>(dbCompany, HttpStatus.OK);       
    }

}

springboot后端实体bean:

The springboot backend entity bean:

    /**
 * 
 */
package com.ebusiness.niche.entity;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;

/**
 * @author denisputnam
 *
 */
@Entity
@Table(
        uniqueConstraints = {
                @UniqueConstraint(columnNames = {"email"})
        }
)
public class Company extends History implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 1329304564033025946L;

    @Id
    @GeneratedValue
    private Long id;

    @Column
    @NotNull
    private String email;

    @Column
    @NotNull
    private String companyName;

    @Column
    @NotNull
    private String webSite;

    @Column
    @NotNull
    private String phone;

    @Column(length=4096)
    private String notes;

    @ManyToMany(mappedBy="companys")
    Set<Product> products;

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    public String getWebSite() {
        return webSite;
    }

    public void setWebSite(String webSite) {
        this.webSite = webSite;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Set<Product> getProducts() {
        return products;
    }

    public void setProducts(Set<Product> products) {
        this.products = products;
    }

}

此History基类实体bean:

This History base class entity bean:

    /**
 * 
 */
package com.ebusiness.niche.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.validation.constraints.NotNull;

/**
 * @author denisputnam
 *
 */
//@Entity
@MappedSuperclass
public class History implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = -1136283585074348099L;
    private String createdBy;
    @Column(nullable = false)
    @NotNull
    private Date createdDate = new Date();
    private String updatedBy;
    private Date updatedDate;
    /**
     * @return the createdBy
     */
    public String getCreatedBy() {
        return createdBy;
    }
    /**
     * @param createdBy the createdBy to set
     */
    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }
    /**
     * @return the createdDate
     */
    public Date getCreatedDate() {
        return createdDate;
    }
    /**
     * @param createdDate the createdDate to set
     */
    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }
    /**
     * @return the updatedBy
     */
    public String getUpdatedBy() {
        return updatedBy;
    }
    /**
     * @param updatedBy the updatedBy to set
     */
    public void setUpdatedBy(String updatedBy) {
        this.updatedBy = updatedBy;
    }
    /**
     * @return the updatedDate
     */
    public Date getUpdatedDate() {
        return updatedDate;
    }
    /**
     * @param updatedDate the updatedDate to set
     */
    public void setUpdatedDate(Date updatedDate) {
        this.updatedDate = updatedDate;
    }


}

我对此进行了编辑,以添加控制台日志中的TRACE输出.我还简化了Company实体,使其不包含任何日期或与其他实体的任何其他关系,因此现在仅传递字符串.

I edited this to add the TRACE output from the console log. I also simplified the Company entity to not contain any dates or any other relationships to other entities, so now only strings are passed.

这是TRACE输出:

   2019-09-18 15:52:19.591 TRACE 47732 --- [nio-8080-exec-1] o.h.r.j.i.ResourceRegistryStandardImpl   : Releasing JDBC resources
2019-09-18 15:52:19.591 TRACE 47732 --- [nio-8080-exec-1] cResourceLocalTransactionCoordinatorImpl : ResourceLocalTransactionCoordinatorImpl#afterCompletionCallback(true)
2019-09-18 15:52:19.591 TRACE 47732 --- [nio-8080-exec-1] .t.i.SynchronizationRegistryStandardImpl : SynchronizationRegistryStandardImpl.notifySynchronizationsAfterTransactionCompletion(3)
2019-09-18 15:52:19.591 TRACE 47732 --- [nio-8080-exec-1] org.hibernate.internal.SessionImpl       : SessionImpl#afterTransactionCompletion(successful=true, delayed=false)
2019-09-18 15:52:19.594 DEBUG 47732 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/json, application/*+json]
2019-09-18 15:52:19.594 TRACE 47732 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [[com.ebusiness.niche.entity.Company@ddb52f3, com.ebusiness.niche.entity.Company@73d5674e]]
2019-09-18 15:52:19.619 TRACE 47732 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : No view rendering, null ModelAndView returned.
2019-09-18 15:52:19.619 TRACE 47732 --- [nio-8080-exec-1] org.hibernate.internal.SessionImpl       : Closing session [f1652eeb-71a2-4776-8d94-9573336d60f3]
2019-09-18 15:52:19.619 TRACE 47732 --- [nio-8080-exec-1] o.h.e.jdbc.internal.JdbcCoordinatorImpl  : Closing JDBC container [org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl@6effa4c8]
2019-09-18 15:52:19.619 TRACE 47732 --- [nio-8080-exec-1] o.h.r.j.i.ResourceRegistryStandardImpl   : Releasing JDBC resources
2019-09-18 15:52:19.619 TRACE 47732 --- [nio-8080-exec-1] o.h.r.j.i.LogicalConnectionManagedImpl   : Closing logical connection
2019-09-18 15:52:19.620 TRACE 47732 --- [nio-8080-exec-1] o.h.r.j.i.ResourceRegistryStandardImpl   : Releasing JDBC resources
2019-09-18 15:52:19.620 TRACE 47732 --- [nio-8080-exec-1] o.h.r.j.i.LogicalConnectionManagedImpl   : Logical connection closed
2019-09-18 15:52:19.620 DEBUG 47732 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed 200 OK, headers={masked}
2019-09-18 15:52:31.192 TRACE 47732 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.http.ResponseEntity<com.ebusiness.niche.entity.Company> com.ebusiness.niche.controller.CompanyController.updateCompany(java.lang.Long,com.ebusiness.niche.entity.Company)
2019-09-18 15:52:31.264 TRACE 47732 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.http.ResponseEntity<com.ebusiness.niche.entity.Company> com.ebusiness.niche.controller.CompanyController.updateCompany(java.lang.Long,com.ebusiness.niche.entity.Company)
2019-09-18 15:52:31.266 TRACE 47732 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : PUT "/niche/company/2", parameters={}, headers={masked} in DispatcherServlet 'dispatcherServlet'
2019-09-18 15:52:31.267 TRACE 47732 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.http.ResponseEntity<com.ebusiness.niche.entity.Company> com.ebusiness.niche.controller.CompanyController.updateCompany(java.lang.Long,com.ebusiness.niche.entity.Company)
2019-09-18 15:52:31.268 TRACE 47732 --- [nio-8080-exec-3] .i.SessionFactoryImpl$SessionBuilderImpl : Opening Hibernate Session.  tenant=null, owner=null
2019-09-18 15:52:31.268 TRACE 47732 --- [nio-8080-exec-3] org.hibernate.internal.SessionImpl       : Opened Session [740dabea-2970-4491-8ff7-d373afc649f6] at timestamp: 1568836351268
2019-09-18 15:52:31.268 TRACE 47732 --- [nio-8080-exec-3] o.s.web.cors.DefaultCorsProcessor        : Skip: response already contains "Access-Control-Allow-Origin"
2019-09-18 15:52:31.312 TRACE 47732 --- [nio-8080-exec-3] m.m.a.RequestResponseBodyMethodProcessor : Read "application/json;charset=UTF-8" to [com.ebusiness.niche.entity.Company@46388186]
2019-09-18 15:52:31.320 TRACE 47732 --- [nio-8080-exec-3] .w.s.m.m.a.ServletInvocableHandlerMethod : Arguments: [2, com.ebusiness.niche.entity.Company@46388186]

推荐答案

好,此问题是因为从前端应用程序发送了JSON正文作为嵌套了公司的JSON对象. {公司}

OK, this issue was because from Front End application was being sent a the JSON body as an JSON object that had nested a company. { company }

patch$ = (companyId: number, company: Company): Observable<Company> 
          => this.http.patch<Company>(`${this.url}/${companyId}`, { company });

然后,当请求到达后端应用程序时,字段值是 null ,因为它是 company 中的JSON对象.通过移除方括号 {} 可以解决此问题,以使 company 作为对象.

Then when the request was coming to Back End application the fields values were null since that it was a JSON object within company. This was fixed by removing the brackets {} in order to have company as object.

patch$ = (companyId: number, company: Company): Observable<Company> 
          => this.http.patch<Company>(`${this.url}/${companyId}`, company);

这篇关于为什么@RequestBody获取具有空属性的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆