Java REST-ful服务器+ Angular 5客户端POST PUT语法

时间:2018-01-25 08:04:06

标签: java angular rest crud

我正在尝试使用Java RESTful servlet和Angular5客户端进行通信的测试中学习HTTP REST / CRUD协议。我设法使GET和DELETE正常工作,但是尽管有很多搜索无法通过POST在数据库中添加或编辑记录,PUT调用。我猜我没有通过我的客户端请求将数据传递给服务器。我得到的错误是:

[HTTP/1.1 415 Unsupported Media Type]

这是应用的代码。 servlet是一个非常简单的Java应用程序。使用以下命令在Netbeans中自动生成:

"RESTful Web Services From Database" 

在GlassFish服务器上实现。 (无需编码,只需点击几下即可在Netbeans中复制此servlet - 请参阅:this)。

以下是我的servlet PlayerFacadeREST类的相关摘要:

@GET
@Path("{id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<Player> find(@PathParam("id") Integer id) {
    List<Player> list = new ArrayList<>();
    list.add(super.find(id));
    return list;
}

@GET
@Override
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<Player> findAll() {
    return super.findAll();
}

@POST
@Override
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public void create(Player entity) {
    super.create(entity);
}

@PUT
@Path("{id}")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public void edit(@PathParam("id") Integer id, Player entity){
    super.edit(entity);
}

玩家类:

@Entity
@Table(name = "PLAYER")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Player.findAll", query = "SELECT p FROM Player p")
    , @NamedQuery(name = "Player.findById", query = "SELECT p FROM Player p WHERE p.id = :id")
    , @NamedQuery(name = "Player.findByFirstname", query = "SELECT p FROM Player p WHERE p.firstname = :firstname")
    , @NamedQuery(name = "Player.findByLastname", query = "SELECT p FROM Player p WHERE p.lastname = :lastname")
    , @NamedQuery(name = "Player.findByJerseynumber", query = "SELECT p FROM Player p WHERE p.jerseynumber = :jerseynumber")
    , @NamedQuery(name = "Player.findByLastspokenwords", query = "SELECT p FROM Player p WHERE p.lastspokenwords = :lastspokenwords")})
public class Player implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "ID")
    private Integer id;
    @Size(max = 64)
    @Column(name = "FIRSTNAME")
    private String firstname;
    @Size(max = 64)
    @Column(name = "LASTNAME")
    private String lastname;
    @Column(name = "JERSEYNUMBER")
    private Integer jerseynumber;
    @Size(max = 255)
    @Column(name = "LASTSPOKENWORDS")
    private String lastspokenwords;

    public Player() {
    }

    public Player(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

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

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    etc. - other: Getters/Setters of relevant fields

这是我的Angular客户 - 相关部分:

数据对象的类:

    export class PlayerRecord {
        id: number;
        firstname: string;
        lastname: string;
        jerseynumber: number;
        spokenwords: string;
    }
  • GET的工作部分:

    this.http.get<PlayerRecord[]>(url)
        .subscribe(data => this.onDataSuccess(data), 
                    err => console.log(err));  
    

    和DELETE - 也有效:

    this.http.delete(url + '/' + id)
        .subscribe(data => this.onDataSuccess(data), 
                    err => console.log(err));  
    

以下是PUT尝试不起作用:

     this.http.put(url + '/' + id, JSON.stringify(player))
        .subscribe(result => console.log('Http Success; ' + result), 
                      err => console.log(err));  

请您解释一下我做错了什么,并提供正确的语法,说明'播放器'需要如何呈现给服务器,以便编辑数据库中的记录?

谢谢。

以下是浏览器的日志输出:

回复标题:

Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Content-Language:
Content-Length: 1207
Content-Type: text/html
Server: GlassFish Server Open Source Edition  5.0x-powered-byServlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition  5.0  Java/Oracle Corporation/1.8)

请求标题:

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Content-Length: 70
Content-Type: text/plain
Host: localhost:8080
Origin: http://localhost:4200
Referer: http://localhost:4200/
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0

根据皮埃尔的建议,我试过这个:

     this.http.put(url + '/' + id, player)
        .subscribe(result => console.log('Http Success; ' + result), 
                      err => console.log(err));  

但得到错误:

[HTTP/1.1 500 Internal Server Error ]

这些是使用过的标题:

    Host: localhost:8080
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
    Accept: application/json, text/plain, */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Content-Type: application/json
    Referer: http://localhost:4200/
    Content-Length: 106
    Origin: http://localhost:4200
    Connection: keep-alive

2 个答案:

答案 0 :(得分:1)

我认为问题是您的请求的内容类型。

  

Content-Type:text / plain

我认为问题就在这里:

this.http.put(url + '/' + id, JSON.stringify(player))
        .subscribe(result => console.log('Http Success; ' + result), 
                      err => console.log(err));  

你不必将你的身体变成一根绳子。因此,删除JSON.stringify验证您的请求的内容类型是application / json(您的PUT路由消耗)并且一切都应该没问题

(如果你使用新的HttpClientModule,内容类型应该是application / json)

答案 1 :(得分:0)

以下是我在经过数天的HTTP,REST,CORS等研究后解决这个问题的方法。

现在看来,上述步骤中使用的某些库/版本存在问题(在Netbeans中生成Java Web应用程序和“RESTful Web Services From Database”)与新的GlassFish服务器相关。

我从头开始重试相同的过程,但这次是从Maven Web应用程序(而不是Java Web应用程序)开始。似乎Maven提供了正确/更新的依赖项,并且所有依赖项都开始工作。

注意:不要忘记包括以下步骤:“跨源资源共享过滤器”。

通过Maven生成具有REST服务和CORS的服务器应用程序之后,在Angular客户端Web应用程序中,使用所有基本动词:GET,PUT,POST和DELETE对服务器的调用开始正常工作:< / p>

获取(接收数据):

 this.http.get<PlayerRecord[]>(url)
     .subscribe(data => this.onDataSuccess(data), 
                 err => console.log(err));  

 onDataSuccess(data: PlayerRecord[]) {
     // work with your data here
 }

PUT(编辑):

 this.http.put(url + '/' + id, player)
    .subscribe(result => console.log('Http Success; ' + result), 
                  err => console.log(err));  

POST(添加):

 this.http.post(url, player)
     .subscribe(result => console.log('Http Success; ' + result), 
                  err => console.log(err)); 

我甚至可以在Firefox浏览器中禁用CORS插件,许多人建议安装它。这不是必需的,因为我们的servlet端CORS Filter负责在Angular中开发并在端口4200上从Angular访问我们的Web服务器端口8080时处理跨域问题。 快乐的编码。