需要用 Java 编写一个 RESTful JSON 服务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7622521/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 20:44:18  来源:igfitidea点击:

Need to write a RESTful JSON service in Java

javajsonrest

提问by wantobegeek

Here is my requirement:

这是我的要求:

  1. I have a simple table in mysql(Consider any table with a few fields)
  2. I need to write a simple RESTFUL JSON webservice in Java that performs CRUD operations on this table.
  1. 我在 mysql 中有一个简单的表(考虑任何带有几个字段的表)
  2. 我需要用 Java 编写一个简单的 RESTFUL JSON web 服务,该服务在该表上执行 CRUD 操作。

I tried searching on the net for some comprehensive example for this but could not find any. Can anyone help?

我尝试在网上搜索一些综合示例,但找不到任何示例。任何人都可以帮忙吗?

回答by Brian Roach

Jerseyis a JAX-RS implementation for building RESTful webservices.

Jersey是用于构建 RESTful Web 服务的 JAX-RS 实现。

Start with their tutorial. It's pretty easy.

从他们的教程开始。这很容易。

http://jersey.java.net/nonav/documentation/latest/getting-started.html

http://jersey.java.net/nonav/documentation/latest/getting-started.html

Edit:Also, there's a great O'Riley book on the subject (shocking, I know); RESTful Java with JAX-RS

编辑:另外,关于这个主题有一本很棒的 O'Riley 书(我知道令人震惊); 带有 JAX-RS 的 RESTful Java

回答by ZanGOlie

I will outline the essential parts of my blog post Building a RESTful Web Service in Java, which shows the steps you can take to connect to the database and create a RESTful Web Service using the following.

我将概述我的博客文章用 Java 构建 RESTful Web 服务的基本部分,其中显示了您可以使用以下步骤连接到数据库并创建 RESTful Web 服务的步骤。

  • IDE: Eclipse IDE for Jave EE Developers (Kepler), comes with Maven built in
  • Database: MySQL (also makes use of MySQL Workbench)
  • Application Server: GlassFish 4.0
  • Java EE 7 (JAX-RS, JPA, JAXB, etc)
  • Any REST Client for testing: (eg Postman)
  • IDE:面向 Jave EE 开发人员 (Kepler) 的 Eclipse IDE,内置 Maven
  • 数据库:MySQL(也使用 MySQL Workbench)
  • 应用服务器:GlassFish 4.0
  • Java EE 7(JAX-RS、JPA、JAXB 等)
  • 任何用于测试的 REST 客户端:(例如 Postman)

The following description assumes you have already installed the technology listed above. The service is for a database table 'item' that stores items with the fields id, itemName, itemDescription, itemPrice.

以下描述假设您已经安装了上面列出的技术。该服务用于存储具有字段id、itemName、itemDescription、itemPrice的项目的数据库表“item” 。

The Persistence Layer

持久层

  • Create a MySQL database schema using MySQL Workbench's ‘create a new schema in connected server‘ icon. In this example the schema is called 'smallbiz'.
  • Connect Eclipse to MySQL
    • Download the MySQL JDBC driver and save in a convenient location.
    • In Eclipse, create a new Database Connectionin the Data Source Explorertab. During this process you will need to browse to the MySQL JDBC driver.
  • Create a MySQL JDBC Connection Pool and Resource in GlassFish (this is required for the application to be able to connect the database once deployed on the server).
    • Copy the MySQL JDBC driver to the extdirectory in GlassFish i.e. $glassfish_install_folder\glassfish\lib\ext. Then restart GlassFish.
    • Loggin into the GlassFish admin area using a browser (located at http://localhost:4848by default).
    • Under Resources > JDBC > Connection Pools, create a new connection pool with a 'Resource Type' of java.sql.Driver.
    • On the 'New JDBC Connection Pool (Step 1 of 2)' screen.
      • Enter a 'Pool Name' (eg SmallBizPool).
      • Select the 'Resource Type' (java.sql.Driver).
      • Select the 'Database Driver Vendor' (MySQL).
      • Next.
    • On the bottom section of the following screen in Additional Properties.
      • URL:jdbc:mysql://localhost:3306/smallbiz
      • user:yourUser (root in my set-up)
      • password:yourPassword
      • Finish
      • Pingon the following screen to test the connection.
    • Create a JDBC Resource from the connection pool at Resources > JDBC > JDBC Resources:
      • Enter a 'JNDI Name' (eg jdbc/SmallBiz). We use this in the persistence.xml file so the application knows how to connect to the database.
      • Select the connection pool previously created from the 'Pool Name' drop down list.
    • For more Information on JDBC Connection Pool and Resource
  • Connect Eclipse to GlassFish.
    • Add GlassFish Tools to Eclipse by searching Help > Eclipse Marketplace.
    • Connect GlassFish to Eclipse by creating a new server using the Serverstab.
      • Select GlassFish 4.0 on the Define a New Serverscreen.
      • Ensure 'jdk7' i selected and the JDKin the New GlasssFish 4.0 Runtimescreen.
      • On the screen that follows, ensure the correct domain directory is selected (the default is domain1, eg. $glassfish_install_folder\glassfish\domains\domain1), then enter the admin credential for GlassFish.
      • You can now interact with GlassFish (start, stop, restart, run on, etc) from in Eclipse.
  • Create a new Maven Project in Eclipse and add dependencies using m2e (which is built in) for:
    • EclipseLink (for JPA) “org.eclipse.persistence eclipselink”
  • 使用 MySQL Workbench 的“在连接的服务器中创建新架构”图标创建 MySQL 数据库架构。在这个例子中,模式被称为“smallbiz”。
  • 将 Eclipse 连接到 MySQL
    • 下载 MySQL JDBC 驱动程序并保存在方便的位置。
    • 在 Eclipse 中,在Data Source Explorer选项卡中创建一个新的Database Connection。在此过程中,您需要浏览到 MySQL JDBC 驱动程序。
  • 在 GlassFish 中创建 MySQL JDBC 连接池和资源(这是应用程序在服务器上部署后能够连接数据库所必需的)。
    • 将 MySQL JDBC 驱动程序复制到GlassFish 中的ext目录,即$glassfish_install_folder\glassfish\lib\ext。然后重新启动 GlassFish。
    • 使用浏览器(http://localhost:4848默认位于)登录 GlassFish 管理区域。
    • Resources > JDBC > Connection Pools 下,创建一个“资源类型”为 java.sql.Driver 的新连接池。
    • 在“新建 JDBC 连接池(第 1 步,共 2 步)”屏幕上。
      • 输入“池名称”(例如 SmallBizPool)。
      • 选择“资源类型”(java.sql.Driver)。
      • 选择“数据库驱动程序供应商”(MySQL)。
      • 接下来
    • 在以下屏幕的底部附加属性中
      • 网址:jdbc:mysql://localhost:3306/smallbiz
      • 用户:yourUser (在我的设置中根)
      • 密码:你的密码
      • 结束
      • 在以下屏幕上Ping以测试连接。
    • 资源 > JDBC > JDBC 资源的连接池创建一个JDBC 资源
      • 输入“JNDI 名称”(例如 jdbc/SmallBiz)。我们在persistence.xml 文件中使用它,以便应用程序知道如何连接到数据库。
      • 从“池名称”下拉列表中选择先前创建的连接池。
    • 有关 JDBC 连接池和资源的更多信息
  • 将 Eclipse 连接到 GlassFish。
    • 通过搜索Help > Eclipse Marketplace将 GlassFish 工具添加到 Eclipse 。
    • 通过使用Servers选项卡创建新服务器,将 GlassFish 连接到 Eclipse 。
      • 定义新服务器屏幕上选择 GlassFish 4.0 。
      • 确保在New GlasssFish 4.0 Runtime屏幕中选择了“jdk7”和JDK
      • 在接下来的屏幕上,确保选择了正确的域目录(默认为 domain1,例如$glassfish_install_folder\glassfish\domains\domain1),然后输入 GlassFish 的管理员凭据。
      • 您现在可以在 Eclipse 中与 GlassFish 交互(启动、停止、重新启动、继续运行等)。
  • 在 Eclipse 中创建一个新的 Maven 项目并使用 m2e(内置)添加依赖项:
    • EclipseLink(用于 JPA)“org.eclipse.persistence eclipselink”

To map to the database, a JPA Entity is used. A JPA Entity is simple a POJO (Plain Old Java Object) annotated with JPA annotations. If the database already exists, Eclipse can generate the JPA Entity from the database.

为了映射到数据库,使用了 JPA 实体。JPA 实体是一个简单的 POJO(Plain Old Java Object),带有 JPA 注释。如果数据库已经存在,Eclipse 可以从数据库生成 JPA 实体。

  • Create a database table using the SQL scrapbookin Eclipse with the following SQL

    CREATE TABLE item (
         id VARCHAR(36) NOT NULL,
         itemName TEXT NOT NULL,
         itemDescription TEXT,
         itemPrice DOUBLE,
         PRIMARY KEY (id)
     )
    
  • Create a JPA entity from the database table by right clicking a package created in Eclipse and selecting New > JPA Entities from Table.

  • Annotate the JPA entity with JAXB annotation in order to be able to marshal it to and from xml or json.
  • 在 Eclipse中使用 SQL剪贴簿创建一个数据库表,使用以下 SQL

    CREATE TABLE item (
         id VARCHAR(36) NOT NULL,
         itemName TEXT NOT NULL,
         itemDescription TEXT,
         itemPrice DOUBLE,
         PRIMARY KEY (id)
     )
    
  • 通过右键单击在 Eclipse 中创建的包并选择New > JPA Entities from Table从数据库表创建JPA 实体

  • 使用 JAXB 注释对 JPA 实体进行注释,以便能够在 xml 或 json 之间进行编组。

Since this example uses UUID's for the primary key, there are also annotations (@UuidGenerator and @GeneratedValue) that are specific to EclipseLink to take care of creating them. It is not necessary to use UUID's as the primary keys but one of the reasons I use it is so that I can create a model on the client complete with a UUID and then PUT that new model to the server (eg in offline mode, new models created and stored locally are PUT to the server when cell signal returns). If the server created the UUID then new model is sent to the server without an id using POST.

由于此示例使用 UUID 作为主键,因此还有特定于 EclipseLink 的注释(@UuidGenerator 和 @GeneratedValue)来负责创建它们。没有必要使用 UUID 作为主键,但我使用它的原因之一是我可以在客户端上创建一个带有 UUID 的模型,然后将该新模型放入服务器(例如,在离线模式下,新的当单元信号返回时,在本地创建和存储的模型将 PUT 到服务器)。如果服务器创建了 UUID,则使用 POST 将没有 id 的新模型发送到服务器。

package com.zangolie.smallbiz.entities;

import java.io.Serializable;

import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;

import org.eclipse.persistence.annotations.UuidGenerator;


/**
 * The persistent class for the item database table.
 * 
 */
@UuidGenerator(name="UUID")
@XmlRootElement
@Entity
@NamedQuery(name="Item.findAll", query="SELECT i FROM Item i")
public class Item implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(generator="UUID")
    @Column(length=36)
    private String id;

    private String itemDescription;

    @Lob
    private String itemName;

    private double itemPrice;

    public Item() {
    }

    public String getId() {
        return this.id;
    }

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

    public String getItemDescription() {
        return this.itemDescription;
    }

    public void setItemDescription(String itemDescription) {
        this.itemDescription = itemDescription;
    }

    public String getItemName() {
        return this.itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public double getItemPrice() {
        return this.itemPrice;
    }

    public void setItemPrice(double itemPrice) {
        this.itemPrice = itemPrice;
    }

}
  • Create folder src\main\webapp\WEB-INF\classes\META-INF and create a persistence.xml file.

    <?xml version="1.0" encoding="UTF-8"?>
    
    <persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
        <persistence-unit name="testPU" transaction-type="JTA">
            <jta-data-source>jdbc/SmallBiz</jta-data-source>
        </persistence-unit>
    </persistence>
    
  • 创建文件夹 src\main\webapp\WEB-INF\classes\META-INF 并创建一个 persistence.xml 文件。

    <?xml version="1.0" encoding="UTF-8"?>
    
    <persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
        <persistence-unit name="testPU" transaction-type="JTA">
            <jta-data-source>jdbc/SmallBiz</jta-data-source>
        </persistence-unit>
    </persistence>
    

The RESTful Service Layer

RESTful 服务层

  • Set the Maven Compiler to 1.7
    • Right click the pom.xml file and select Open With > Maven POM Editor. Add the following just before the closing tag.
  • 将 Maven 编译器设置为 1.7
    • 右键单击 pom.xml 文件并选择Open With > Maven POM Editor。在结束标记之前添加以下内容。

xml snippet

xml 片段

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
  • Add dependencies using m2e for:
    • Servlet 3.1 (JAX-RS 2.0 requires this) "javax.servlet javax.servlet.api"
    • Jersey (for JAX-RS) "org.glassfish.jersey.core jersey-sever"
    • EJB (required to use the @Stateless annotation) "javax.ejb javax.ejb.api"
  • Create a POJO (plain old java object) and annotate it with JAX-RS annotations to create an endpoint.
    • @Path("/your-app-api-uri"): To indicate the path, relative to your server base uri, that a resource is located
    • @Produces ({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}): The representation produced can be json or xml.
    • @Consumes ({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}): The representation consumed can be json or xml
    • @Stateless: There server does not store state between interactions (this is one of the principles of the RESTful architecture).
  • Annotate methods that map to CRUD operations
    • @POST: Create
    • @GET: Read
    • @PUT: Update
    • @DELETE: Delete
  • 使用 m2e 添加依赖项:
    • Servlet 3.1(JAX-RS 2.0 需要这个)“javax.servlet javax.servlet.api”
    • Jersey(用于 JAX-RS)“org.glassfish.jersey.core jersey-sever”
    • EJB(需要使用@Stateless 注释)“javax.ejb javax.ejb.api”
  • 创建一个 POJO(普通的旧 java 对象)并使用 JAX-RS 批注对其进行批注以创建端点。
    • @Path("/your-app-api-uri"):指示资源所在的相对于服务器基础 uri 的路径
    • @Produces ({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}):生成的表示可以是 json 或 xml。
    • @Consumes ({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}):消费的表示可以是 json 或 xml
    • @Stateless:服务器不存储交互之间的状态(这是 RESTful 架构的原则之一)。
  • 注释映射到 CRUD 操作的方法
    • @POST:创建
    • @GET:阅读
    • @PUT:更新
    • @DELETE: 删除

The JAX-RS Service

JAX-RS 服务

package com.zangolie.smallbiz.services.rest;

import java.net.URI;
import java.util.Collection;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import com.zangolie.smallbiz.entities.Item;

@Path("/item")
@Produces ({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes ({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Stateless
public class ItemRestService {
    //the PersistenceContext annotation is a shortcut that hides the fact
    //that, an entity manager is always obtained from an EntityManagerFactory.
    //The peristitence.xml file defines persistence units which is supplied by name
    //to the EntityManagerFactory, thus  dictating settings and classes used by the
    //entity manager
    @PersistenceContext(unitName = "testPU")
    private EntityManager em;

    //Inject UriInfo to build the uri used in the POST response
    @Context
    private UriInfo uriInfo;

    @POST
    public Response createItem(Item item){
        if(item == null){
            throw new BadRequestException();
        }
        em.persist(item);

        //Build a uri with the Item id appended to the absolute path
        //This is so the client gets the Item id and also has the path to the resource created
        URI itemUri = uriInfo.getAbsolutePathBuilder().path(item.getId()).build();

        //The created response will not have a body. The itemUri will be in the Header
        return Response.created(itemUri).build();
    }

    @GET
    @Path("{id}")
    public Response getItem(@PathParam("id") String id){
        Item item = em.find(Item.class, id);

        if(item == null){
            throw new NotFoundException();
        }

        return Response.ok(item).build();
    }

    //Response.ok() does not accept collections
    //But we return a collection and JAX-RS will generate header 200 OK and
    //will handle converting the collection to xml or json as the body
    @GET
    public Collection<Item> getItems(){
        TypedQuery<Item> query = em.createNamedQuery("Item.findAll", Item.class);
        return query.getResultList();
    }

    @PUT
    @Path("{id}")
    public Response updateItem(Item item, @PathParam("id") String id){
        if(id == null){
            throw new BadRequestException();
        }

        //Ideally we should check the id is a valid UUID. Not implementing for now
        item.setId(id);
        em.merge(item);

        return Response.ok().build();
    }

    @DELETE
    @Path("{id}")
    public Response deleteItem(@PathParam("id") String id){
        Item item = em.find(Item.class, id);
        if(item == null){
            throw new NotFoundException();
        }
        em.remove(item);
        return Response.noContent().build();
    }

}
  • Create an Application Class that defines the base uri. eg for http://localhost:8080/smallbiz/rest

    package com.zangolie.smallbiz.services.rest;
    
    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;
    
    @ApplicationPath("rest")
    public class ApplicationConfig extends Application {
    
    }
    
  • Deploying to GlassFish from within Eclipse.

    • Right click the project Run As > Run on Server
    • Select the connected GlassFish server.
  • Test with any HTTP client (such as Postman which works in chrome).
  • 创建一个定义基本 uri 的应用程序类。例如对于http://localhost:8080/smallbiz/rest

    package com.zangolie.smallbiz.services.rest;
    
    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;
    
    @ApplicationPath("rest")
    public class ApplicationConfig extends Application {
    
    }
    
  • 从 Eclipse 内部署到 GlassFish。

    • 右键单击项目运行方式 > 在服务器上运行
    • 选择连接的 GlassFish 服务器。
  • 使用任何 HTTP 客户端进行测试(例如在 chrome 中工作的 Postman)。

Though the example uses GlassFish, any Java EE 7 compliant container will work. If you do use a different container (and assuming you use the same EclipseLink for JPA and Jersey for JAX-RS implementations), you will have to:

尽管该示例使用 GlassFish,但任何符合 Java EE 7 的容器都可以使用。如果您确实使用了不同的容器(并假设您对 JPA 使用相同的 EclipseLink,对 JAX-RS 实现使用相同的 Jersey),您将必须:

  • Sort out how to connect to it from Eclipse.
  • Change the Maven dependencies for Jersey and EclipseLink from provided to compile (since those are the implementations in GlassFish and may be different in other containers).
  • 整理出如何从 Eclipse 连接到它。
  • 将 Jersey 和 EclipseLink 的 Maven 依赖项从提供更改为编译(因为这些是 GlassFish 中的实现,在其他容器中可能有所不同)。

Hope it is helpful.

希望它有帮助。

回答by nicholas.hauschild

I would take a look at what Spring has to offer. There are RestTemplate's, and Spring MVC, Both of which should be able to help you out.

我会看看 Spring 提供了什么。有RestTemplate's 和Spring MVC,两者都应该能够帮助你。

Another thing which will be helpful is some sort of JSON-Mapping library. I will recommend Hymanson Object Mapper. Take a look at their tutorials for an idea of how it will work.

另一件有用的事情是某种 JSON-Mapping 库。我会推荐Hymanson Object Mapper。看看他们的教程,了解它是如何工作的。

回答by Eike D

this might be doing exactly what you are looking for: http://restsql.org/doc/Overview.html

这可能正是您正在寻找的:http: //restsql.org/doc/Overview.html

DISCLAIMER: I have never used it - just remembered seeing it recently in a news post.

免责声明:我从未使用过它 - 只是记得最近在新闻帖子中看到过它。