【问题标题】:Need to write a RESTful JSON service in Java需要用 Java 写一个 RESTful JSON 服务
【发布时间】:2011-10-01 19:46:33
【问题描述】:

这是我的要求:

  1. 我在 mysql 中有一个简单的表(考虑任何有几个字段的表)
  2. 我需要用 Java 编写一个简单的 RESTFUL JSON Web 服务,用于对这个表执行 CRUD 操作。

我尝试在网上搜索一些全面的示例,但找不到。 有人可以帮忙吗?

【问题讨论】:

  • 您是否考虑过结合使用 Spring Web Services 和 Hibernate 进行 CRUD 操作?

标签: java json rest


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    我会看看 Spring 提供了什么。有RestTemplateSpring MVC,应该都能帮到你。

    另一件有用的事情是某种 JSON 映射库。我会推荐Jackson Object Mapper。查看他们的教程,了解其工作原理。

    【讨论】:

      【解决方案3】:

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

      • IDE:面向 Jave EE 开发人员 (Kepler) 的 Eclipse IDE,内置 Maven
      • 数据库:MySQL(也使用 MySQL Workbench)
      • 应用服务器:GlassFish 4.0
      • Java EE 7(JAX-RS、JPA、JAXB 等)
      • 任何用于测试的 REST 客户端:(例如 Postman)

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

      持久层

      • 使用 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。
        • 使用浏览器登录到 GlassFish 管理区域(默认位于 http://localhost:4848)。
        • Resources > JDBC > Connection Pools 下,使用 java.sql.Driver 的“资源类型”创建一个新的连接池。
        • 在“新建 JDBC 连接池(第 1 步,共 2 步)”屏幕上。
          • 输入“池名称”(例如 SmallBizPool)。
          • 选择“资源类型”(java.sql.Driver)。
          • 选择“数据库驱动程序供应商”(MySQL)。
          • 下一个
        • 附加属性中以下屏幕的底部。
          • 网址: jdbc:mysql://localhost:3306/smallbiz
          • 用户: yourUser(我的设置中的根用户)
          • 密码:你的密码
          • 完成
          • Ping 在以下屏幕上测试连接。
        • Resources > JDBC > JDBC Resources 的连接池创建 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”

      为了映射到数据库,使用了 JPA 实体。 JPA 实体是一个简单的 POJO(普通旧 Java 对象),使用 JPA 注释进行注释。如果数据库已经存在,Eclipse 可以从数据库中生成 JPA Entity。

      • 在 Eclipse 中使用 SQLscrapbook 使用以下 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。

      由于此示例使用 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;
          }
      
      }
      
      • 创建文件夹 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>
        

      RESTful 服务层

      • 将 Maven 编译器设置为 1.7
        • 右键单击 pom.xml 文件并选择 Open With > Maven POM Editor。在结束标记之前添加以下内容。

      xml sn-p

          <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>
      
      • 使用 m2e 添加依赖项:
        • Servlet 3.1(JAX-RS 2.0 需要这个)“javax.servlet javax.servlet.api”
        • 球衣(用于 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:删除

      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();
          }
      
      }
      
      • 创建一个定义基本 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)进行测试。

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

      • 弄清楚如何从 Eclipse 连接到它。
      • 将 Jersey 和 EclipseLink 的 Maven 依赖项从提供更改为编译(因为这些是 GlassFish 中的实现,在其他容器中可能不同)。

      希望对你有帮助。

      【讨论】:

        【解决方案4】:

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

        免责声明: 我从未使用过它——只是记得最近在一篇新闻文章中看到过它。

        【讨论】:

          猜你喜欢
          • 2012-03-29
          • 2016-12-08
          • 1970-01-01
          • 2023-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-13
          相关资源
          最近更新 更多