RESTful MySQL / 术语 / 传递参数 / 返回整数和双精度数

Posted

技术标签:

【中文标题】RESTful MySQL / 术语 / 传递参数 / 返回整数和双精度数【英文标题】:RESTful MySQL / Terminology / Passing Parameters / Returning Ints & Doubles 【发布时间】:2011-07-09 15:04:16 【问题描述】:

所以,为了尝试为 mysql 数据库创建 RESTful 前端,我简要地查看了 phprestql(简单且简单,但只是 简单),现在我正在尝试构建它到NetBeans' tutorial。我已经完成了基本教程,并且可以很好地使用我的数据库。但是,我正在尝试弄清楚如何对其进行一些自定义。

    JSON 中的所有结果似乎都是字符串,尽管 MySQL 表中的属性是 Big Ints、Ints 和 Doubles。这些类型似乎也在 netbeans 源中正确设置。但是,JSON 将所有内容都作为字符串返回。有什么想法可以解决这个问题吗? (同样,我只是从上面的教程开始工作,尽管使用的是我的数据库。)

    我还试图弄清楚如何在 URI 中实现其他参数,以进一步细化 DB 结果。 (http://localhost/the_db/people_table/?gender_property=male&updated_property=2011-01-18) ... 将返回符合这些条件的所有人员行。我的部分问题是我什至不确定此类功能的正确术语,因此很难找到有关它的示例和教程。

    这可能与上一项有关,但我还想使用 URI “向下钻取”到表/行/属性中以返回单个值(在 JSON 中)...( http://localhost/the_db/people_table/42/lastname) ... 会返回 "Jones"

部分问题是我几乎从 Python 和 Ruby 中了解 Java。不过,我非常熟悉在 Objective-C、PHP 和 Perl 中破坏事物。然而,关于那些快速简单的 Restful MySQL 服务的教程似乎并不流行或流行。

[编辑]

在这有助于回答问题 #1 的范围内,我附上了一些 java 方法来指示如何设置/检索数字属性...据我所知,实际的 JSON 生成是由某个库自动生成的.我在这里看不到它:

/** in the MySQL CommitteeObj table, the committeeId is set as follows */
/* `committeeId` bigint(11) NOT NULL auto_increment */

/** in committee.java */
public class committee implements Serializable 
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "committeeId")
    private BigInteger committeeId;
//.....


public committee(BigInteger committeeId) 
    this.committeeId = committeeId;


@Override
    public String toString() 
        return "texlege.committee[committeeId=" + committeeId + "]";
    

/** in committeeConverter.java */

@XmlElement
public BigInteger getCommitteeId() 
    return (expandLevel > 0) ? entity.getCommitteeId() : null;


public void setCommitteeId(BigInteger value) 
    entity.setCommitteeId(value);


/** in committeeResource.java */

@GET
    @Produces("application/json")
    public committeeConverter get(@QueryParam("expandLevel")
                                  @DefaultValue("1")
    int expandLevel) 
        return new committeeConverter(getEntity(), uriInfo.getAbsolutePath(), expandLevel);
    

protected committee getEntity() 
        try 
            return (committee) em.createQuery("SELECT e FROM committee e where e.committeeId = :committeeId").setParameter("committeeId", id).getSingleResult();
         catch (NoResultException ex) 
            throw new WebApplicationException(new Throwable("Resource for " + uriInfo.getAbsolutePath() + " does not exist."), 404);
        
    

以下是特定委员会的查询结果。请注意,committeeId、committeeType 和 parentId 属性明显缺少 JSON 编号:


    "@uri":"http://localhost:8080/TexLegeRest/rest/committees/2735/",
    "clerk":"Amy Peterson",
    "committeeId":"2735",
    "committeeName":"Appropriations",
    "committeeType":"1",
    "parentId":"-1",
    "updated":"2011-02-20T00:00:00-06:00",

【问题讨论】:

@Greg 需要 24 小时才能获得赏金。如果你愿意,那就联系我吧,我觉得这是一个非常有趣的问题,可以节省一些分数 您想区分 JSON 中的不同数字类型吗?因为 JSON 只有一种原生数字类型:双精度浮点数。 不,只是一个普通的 json 数字输出就可以了。我刚刚提到了后端的类型,因为我认为 netbeans 业务会利用数字性质并自动吐出非字符串。 我应该补充一点,我绝不会嫁给 netbeans。这似乎是寻找简单/快速解决方案的下一步,因为它在 gui 中快速配置 我真的因为这个 +100 的赏金而破产了,所以我希望我们能得到一些好的答案。 【参考方案1】:

简而言之,这个答案可能根本不是您想要的,因为它与 NetBeans 无关。但是,它确实提供了一种不同的方式来执行您想要为 MySQL 数据库提供 RESTful 接口的方式。

我有uploaded a zip file 有 4 个 Java 文件、2 个 XML 文件和 1 个文本文件来支持这个解决方案,否则答案会很长。

简而言之,这是一个 Maven/Java/Spring/Hibernate/MySQL 解决方案,原因是我最近一直在使用这种架构,并且发现它非常简单而强大,可以做真正只是转换 SQL ↔ JSON 的事情!

此解决方案还使用 Maven 等其他一些工具进行编译/打包/部署,而不是使用 IDE,在我看来,这消除了一定程度的复杂性,但可能会让一些喜欢 IDE 的人望而却步。

系统配置

因此,如果您还没有 Java 和 Maven,首先需要下载并解压缩/安装它们。我还将假设 Windows,主要是因为这是我目前使用的。我在以下位置安装了上述应用程序:

c:\apps\java\jdk1.6.0_24
c:\apps\apache-maven-3.0.3

由于此解决方案中没有 IDE,因此应用程序是从命令行构建和运行的。这里的配置很少,所以只需执行以下设置一些环境变量:

set JAVA_HOME=c:\apps\java\jdk1.6.0_24 回车

set M2_HOME=c:\apps\apache-maven-3.0.3 回车

set PATH=%PATH%;%M2_HOME%\bin;%JAVA_HOME%\bin 输入

然后可以使用输入 mvn --version 来验证 Java 和 Maven 是否已正确安装和找到。

项目创建

为您的源创建一个目录,让我们使用c:\src\project1

再次在命令行上,导航到该目录并执行:

mvn archetype:generate -DgroupId=my.group -DartifactId=project1 -DarchetypeArtifactId=maven-archetype-quickstart

Maven 将下载一些标准库并最终提示您“定义属性'版本'的值:” - 只需 Enter 继续。然后 Maven 会要求您确认项目设置,因此只需再次按 Enter 进行确认。您最终会得到一个目录结构,您将在其中找到一个pom.xml 文件和两个Java 文件。项目对象模型 (POM) 文件告诉 Maven 如何构建/测试/打包/部署(以及更多)您的项目。您需要向该文件添加一些库,以便我们可以使用 Spring、JSON、Jetty 和其他功能。因此编辑pom.xml,将以下内容添加到 XML 结构中:

<project> 元素下(即作为<url> 元素的兄弟)添加:

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <spring.version>3.0.5.RELEASE</spring.version>
</properties>
<repositories>
  <repository>
    <id>JBoss</id>
    <url>https://repository.jboss.org/nexus/content/groups/public/</url>
    <releases>
      <enabled>true</enabled>
      <updatePolicy>always</updatePolicy>
      <checksumPolicy>warn</checksumPolicy>
    </releases>
  </repository>
</repositories>

&lt;dependencies&gt; 元素下,从上面链接的 zip 文件中添加 dependencies.txt 文件的内容。这些更改将允许 Maven 找到最新的 Hibernate 和 Spring 库,这些库并不总是存在于默认 Maven 存储库以及其他库中,例如 HSQLDB - 用于测试此示例和 JSON ↔ 的内存数据库Java 转换。

还在&lt;project> 元素下(我在&lt;/dependencies&gt; 元素之后添加了这个)添加以下内容:

<build>
  <plugins>
    <plugin>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>maven-jetty-plugin</artifactId>
      <version>6.1.26</version>
      <configuration>
        <contextPath>/$project.artifactId</contextPath>
        <scanIntervalSeconds>10</scanIntervalSeconds>
        <webXml>$project.build.directory/$project.build.finalName/WEB-INF/web.xml</webXml>
      </configuration>
    </plugin>
  </plugins>
</build>

这是我们将用来运行您将要构建的.war 文件的嵌入式网络服务器,这导致我们对pom.xml 的最终更改...靠近文件顶部的&lt;packaging&gt; 元素需要改为war而不是jar

再次在命令行上,导航到您刚刚创建的 pom.xml 所在的项目目录(可能是cd project1)并输入mvn compile。 Maven 应该下载我们刚刚添加到 POM 中的所有新库,并希望编译时不会出错。现在我们只需要配置 Spring 来连接所有 RESTful URL 和 bean 并配置 Web 应用程序本身。

在 /src/main 下创建 2 个名为 resourceswebapp/WEB-INF 的新目录。您的目录结构现在应该如下所示:

src
src/main
src/main/java
src/main/resources
src/main/webapp/WEB-INF

resources 中添加压缩文件中名为applicationContext.xml 的文件。 ApplicationContext 是应用程序的配置。

WEB-INF 目录中,从压缩文件中添加名为web.xml 的文件。 web.xml 描述了 Web 容器(例如 Tomcat 或在我们的例子中为 Jetty)应如何部署应用程序。

现在我们需要添加一些代码! zip 文件没有在此处添加代码并使此答案比现在更长,而是包含 4 个类。只需将它们复制到src/main/java/my/group 目录中,在此过程中覆盖App.java

编译与执行

这是您应该交叉手指的地方……因为您应该能够使用mvn compile 编译类,然后如果成功mvn jetty:run-war 使用应用程序war 文件运行Web 服务器。如果启动应用程序没有错误,则在 Jetty 初始化完成时应该有一些类似于 INFO: Mapped URL path [/people] onto handler 'app' 的日志记录。

测试 REST 接口

现在我们可以测试 RESTful URL。我建议为 Firefox 使用 Poster addon(虽然与 Firefox 4 不兼容),所以安装它,我们可以使用它在 project1 网络应用程序上执行 PUT 和 GET 请求。安装后,选择工具 → 海报或 Ctrl+Alt+P

首先,由于我们使用的是Spring content negotiation(向下滚动到Content Negotiation 部分),您需要配置海报以添加正确的内容类型。只需将application/json 添加到此字段即可。要将添加到我们的数据库中,只需添加

"firstName" : "foo", "lastName" : "bar"

到正文(这是海报插件中的大区域)并使用 PUT 按钮。您应该从 web-app 获得响应并在命令窗口中查看日志记录。响应应该是:

"name":"foo bar","id":1,"height":1.8

这是有效的 JSON,您可以看到整数和双精度数显示得很好。如果您查看 zip 文件中的 Person.java 类,您可以看到 firstNamelastName 是实际类成员的名称,它们与 PUT 的 JSON 键的名称相匹配。我已经添加了一个@JsonIgnoreannotation 并创建了一个不同的@JsonProperty 来返回全名。实际上,您可能不会这样做,否则很难仅更新名字或姓氏,但在此示例中,我只是使用它来表明您可以完全控制返回的 JSON 实体及其名称/值。另请注意,Person 类有一个硬编码的 Double(height 成员)来证明数字已正确序列化为 JSON。

然后,您可以通过将 URL 更改为 http://localhost:8080/project1/people/1 并使用 GET 按钮来检索 person 1,该按钮仅返回相同的 JSON。

为 MySQL 交换 HSQLDB

您可能已经注意到到目前为止还没有 MySQL 数据库。您将需要更改一些配置以指向 MySQL 数据库,而不是之前使用的内存 HSQL 数据库。 “dataSource” bean 属性应该像这样更新:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
  p:driverClassName="com.mysql.jdbc.Driver"
  p:url="jdbc:mysql://localhost:3306/name_of_your_database_instance"
  p:username="your_database_username"
  p:password="your_database_password"/>

您需要在其中指定数据库的连接详细信息。

最后,休眠方言需要更新为 MySQL 方言,所以将 org.hibernate.dialect.HSQLDialect 替换为

<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>

applicationContext.xml 文件中。

请注意,当 Hibernate 配置了以下属性 &lt;prop key="hibernate.hbm2ddl.auto"&gt;create&lt;/prop&gt; 时,它将在 Web 应用程序启动时破坏数据库,因为 Hibernate 正在扫描 Person 类并从@Table、@Entity 和 @Column(和其他)注释。

请注意,很遗憾我没有测试最后一部分,因为我没有安装 MySQL,但希望它应该可以工作。

回答您的问题(或不回答)

1) 不知道,抱歉。它看起来只是一个转换/序列化问题,可以通过查看教程中使用的 bean 并检查它们的文档来解决。

2) 和 3) 使用上述解决方案,您可以根据需要添加任意数量的路径变量,例如

@RequestMapping(value = "/people/gender/gender/updated/lastUpdated", method = RequestMethod.GET)
@ResponseBody
public Person findByGenderAndUpdated(@PathVariable String gender, @PathVariable String lastUpdated) 

创建一个 API 来公开各个属性可能不切实际。通过 URL 返回完整资源更实用,然后让下游组件从 Person JSON 对象中挑选出 lastName (如果这就是它所需要的)。但是,如果有大量数据,我可以看到需要对 Person 进行缩减的 JSON 表示。即,从带宽的角度来看,排除某些大数据属性会更有效。

您必须自己为每种组合实现这些方法。这有效地构成了您的 RESTful API。如果您需要创建一个文档来描述您的 API,那么 Atlassian guidelines 写得非常好。

总结

这个解决方案有很多变化,实际上你应该把类放在一个更好的目录结构(模型、视图、控制器)中,并创建一些 Java 类模板来处理持久性,因为所有模型都可能需要一个“保存",例如 "find" 方法。

我希望这个解决方案对某人有用:-)

【讨论】:

神圣的地狱。这真是太棒了。就我个人而言,我最终得到了一个 PHP servlet,它非常适合我所追求的,但是它并不像这个解决方案那么完整。干得好。【参考方案2】:

JSON 中的所有结果似乎都是字符串,即使在 MySQL 中 表属性是 Big Ints、Ints、 和双打。这些类型似乎也是 在 netbeans 中正确设置 来源也是如此。但是,JSON 返回 一切都是字符串。任何想法 解决这个问题? (再一次,我只是 根据上面的教程工作, 虽然是我的数据库。)

JSON 中的数字将不带引号。例如 "person": "name":"Fred", "age":24 。因此 JSON 解析器应该能够将其作为数字处理。

我也在想办法 可以实现附加参数 URI,进一步细化数据库 结果。 (http://localhost/the_db/people_table/?gender_property=male&updated_property=2011-01-18) ...将返回所有人员行 符合这些标准。我的部分问题 我什至不确定是否正确 此类功能的术语, 所以这有点困难 查找有关它的示例和教程。

这些被称为查询参数。它们非常有用,尤其是当您的请求中有很多可选参数时

这可能与上一个有关 项目,但我也想使用 URI “深入”到 要返回的表/行/属性 单个值(在 JSON 中)... (http://localhost/the_db/people_table/42/lastname) ... 会返回 "Jones"

这里可以使用查询参数。如果通过 url 传递特定参数,那么它将被设置或为空。检查每个查询参数的空条件,并根据不为空的参数构造where子句。这将给出所需的结果。

更新:如果将数字作为字符串返回是您面临的唯一问题,请将以下内容添加到 web.xml。这将使 pojo 支持。这会将数字作为数字返回。

 <init-param>
   <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
   <param-value>true</param-value>
 </init-param>

【讨论】:

谢谢。如果我正确阅读了您的回复,我有一些后续措施。 JSON 解析器 不是问题,因为它是从 netbeans 教程设置中输出的 JSON,即使 MySQL 数据库中的数据使用数字类型,它也不会输出数字。它将所有数字数据输出为 JSON 中的字符串,这就是问题所在(至少对于问题 1) 如果教程输出在 json 中有数字作为字符串,那么它不是输出纯 json。有关示例,请参阅json.org/example.html。将这些示例与教程输出进行比较。如果两者都不匹配,则教程输出错误。 正是..感觉教程中自动生成的代码是错误的,所以我的部分问题是我在哪里/如何找到问题的根源?我即将聘请某人为我做这个网络服务编程......我知道这很可耻,但我从来没有成功地让我的头脑围绕 Java(或 Python)。跨度> 基于编辑,我可以看到您正在使用基于 JAXB 的 JSON。尝试删除 @XmlElement 注释并运行。这将使它成为基于 pojo 的 JSON。 Xml 将数字视为字符串。您使用的是哪个 JSON 提供程序,它是 jersey 还是 jackson 还是 jettison? 顺便说一句,还有一个示例示例将 db 值公开为 web 服务。这是球衣样品download.java.net/maven/2/com/sun/jersey/samples/bookmark-em/…

以上是关于RESTful MySQL / 术语 / 传递参数 / 返回整数和双精度数的主要内容,如果未能解决你的问题,请参考以下文章

调用spring restful接口怎样传递字符数组参数

在 RESTful api 中传递超过 1000 个参数

Ajax中Put和Delete请求传递参数无效的解决方法(Restful风格)

RestFul结构

如何通过类对象作为方法参数的RESTful服务吗

这种接口怎么调用?怎么传递参数?