Java 中的 Restful Web 服务教程
欢迎阅读 Java 中的 Restful Web 服务教程。REST是表述性状态转移 (REpresentational State Transfer)的缩写。REST 是一种用于开发可通过网络访问的应用程序的架构风格。REST 架构风格由 Roy Fielding 在 2000 年的博士论文中提出。
Restful Web 服务
Restful Web 服务是一种无状态的客户端-服务器架构,其中 Web 服务是资源,可以通过其 URI 进行识别。REST 客户端应用程序可以使用 HTTP GET/POST 方法调用 Restful Web 服务。REST 没有指定要使用的任何特定协议,但在几乎所有情况下它都通过 HTTP/HTTPS 使用。与 SOAP Web 服务相比,这些服务是轻量级的,不遵循任何标准。我们可以使用 XML、JSON、文本或任何其他类型的数据进行请求和响应。
Java RESTful Web 服务 API
RESTful Web 服务的 Java API (JAX-RS) 是用于创建 REST Web 服务的 Java API。JAX-RS 使用注释来简化 Web 服务的开发和部署。JAX-RS 是 JDK 的一部分,因此您无需包含任何内容即可使用它的注释。
Restful Web 服务注解
一些重要的 JAX-RS 注释是:
@Path
:用于指定类和方法的相对路径,我们可以通过扫描Path注解的值来获取某个webservice的URI。@GET
、、、和@PUT
:用于指定方法的 HTTP 请求类型。@POST
@DELETE
@HEAD
@Produces
,@Consumes
:用于指定请求和响应类型。@PathParam
:用于通过解析方法参数将其绑定到路径值。
Restful Web 服务和 SOAP
- SOAP 是一种协议,而 REST 是一种架构风格。
- SOAP 服务器和客户端应用程序紧密耦合并通过 WSDL 契约绑定,而 REST Web 服务和客户端中没有契约。
- 与 SOAP Web 服务相比,REST 的学习曲线比较容易。
- REST Web 服务请求和响应类型可以是 XML、JSON、文本等,而 SOAP 仅适用于 XML。
- JAX-RS 是用于 REST Web 服务的 Java API,而 JAX-WS 是用于 SOAP Web 服务的 Java API。
REST API 实现
JAX-RS API 有两种主要实现。
- Jersey:Jersey是 Sun 提供的参考实现。要使用 Jersey 作为我们的 JAX-RS 实现,我们需要在 web.xml 中配置其 servlet 并添加所需的依赖项。请注意,JAX-RS API 是 JDK 的一部分,而不是 Jersey,因此我们必须在应用程序中添加其依赖项 jar。
- RESTEasy:RESTEasy是提供 JAX-RS 实现的 JBoss 项目。
Java Restful Web 服务教程
让我们看看使用 Jersey 和 RESTEasy 创建 Restful Web 服务有多么容易。我们将通过 HTTP 公开以下方法并使用 Chrome Postman 扩展程序来测试这些方法。
URI | HTTP 方法 | 描述 |
---|---|---|
/人/ {id} / getDummy | 得到 | 返回一个虚拟人物对象 |
/人/添加 | 邮政 | 添加一个人 |
/人/{id}/删除 | 得到 | 删除 URI 中带有“id”的人 |
/人/获取全部 | 得到 | 获取所有人员 |
/人/{id}/获取 | 得到 | 获取 URI 中带有“id”的人 |
Jersey Restful Web 服务
创建一个动态 Web 项目,然后将其转换为 Maven 以获取 Web 服务项目的框架。下图显示了最终项目的项目结构。让我们看看 pom.xml 文件中的 Jersey 依赖项。
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>JAXRS-Example</groupId>
<artifactId>JAXRS-Example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.19</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
我们不需要添加jersey-client依赖项,但如果您正在编写 Java 程序以使用 Jersey 调用 REST Web 服务,那么这是必需的。现在让我们查看部署描述符,以了解如何配置 Jersey 来创建我们的 Web 应用程序。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>JAXRS-Example</display-name>
<!-- Jersey Servlet configurations -->
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.journaldev</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- Jersey Servlet configurations -->
</web-app>
这就是将 Jersey 插入到我们的 Web 应用程序所需的全部内容,在我们的 Java 代码中,我们将使用 JAX-RS 注释。请注意 init 参数的值,它com.sun.jersey.config.property.packages
提供将扫描 Web 服务资源和方法的包。
REST 示例模型类
首先,我们将创建两个模型 bean -Person
用于我们的应用程序数据和Response
用于向客户端系统发送响应。由于我们将发送 XML 响应,因此 bean 应该用 注释@XmlRootElement
,因此我们有这个类。
package com.journaldev.jaxrs.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement (name="person")
public class Person {
private String name;
private int age;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString(){
return id+"::"+name+"::"+age;
}
}
package com.journaldev.jaxrs.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Response {
private boolean status;
private String message;
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
REST Web 服务教程服务
基于我们的URI结构,下面是服务接口及其实现代码。
package com.journaldev.jaxrs.service;
import com.journaldev.jaxrs.model.Person;
import com.journaldev.jaxrs.model.Response;
public interface PersonService {
public Response addPerson(Person p);
public Response deletePerson(int id);
public Person getPerson(int id);
public Person[] getAllPersons();
}
package com.journaldev.jaxrs.service;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.journaldev.jaxrs.model.Person;
import com.journaldev.jaxrs.model.Response;
@Path("/person")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public class PersonServiceImpl implements PersonService {
private static Map<Integer,Person> persons = new HashMap<Integer,Person>();
@Override
@POST
@Path("/add")
public Response addPerson(Person p) {
Response response = new Response();
if(persons.get(p.getId()) != null){
response.setStatus(false);
response.setMessage("Person Already Exists");
return response;
}
persons.put(p.getId(), p);
response.setStatus(true);
response.setMessage("Person created successfully");
return response;
}
@Override
@GET
@Path("/{id}/delete")
public Response deletePerson(@PathParam("id") int id) {
Response response = new Response();
if(persons.get(id) == null){
response.setStatus(false);
response.setMessage("Person Doesn't Exists");
return response;
}
persons.remove(id);
response.setStatus(true);
response.setMessage("Person deleted successfully");
return response;
}
@Override
@GET
@Path("/{id}/get")
public Person getPerson(@PathParam("id") int id) {
return persons.get(id);
}
@GET
@Path("/{id}/getDummy")
public Person getDummyPerson(@PathParam("id") int id) {
Person p = new Person();
p.setAge(99);
p.setName("Dummy");
p.setId(id);
return p;
}
@Override
@GET
@Path("/getAll")
public Person[] getAllPersons() {
Set<Integer> ids = persons.keySet();
Person[] p = new Person[ids.size()];
int i=0;
for(Integer id : ids){
p[i] = persons.get(id);
i++;
}
return p;
}
}
大多数代码都是不言自明的,花一些时间来熟悉 JAX- RS注释@Path
、、、、和。@PathParam
@POST
@GET
@Consumes
@Produces
Restful Web 服务测试
就是这样。我们的 Web 服务已准备就绪,只需将其导出为 WAR 文件并将其放入 Tomcat webapps 目录中或部署到您选择的任何其他容器中即可。以下是使用 Postman chrome 扩展对此 Web 服务执行的一些测试。请注意,我们必须在请求标头中提供 Accept 和 Content-Type 值作为“application/xml”,如下图所示。
- 获取Dummy
- 添加
- 得到
- 获取全部
- 删除
这就是使用 Jersey JAX-RS 实现创建 Web 服务的全部内容。如您所见,大多数代码都使用 JAX-RS 注释,并且 Jersey 通过部署描述符和依赖项插入。
RESTEasy RESTful Web 服务示例
我们将使用在 Jersey 项目中开发的所有业务逻辑,但我没有对同一个项目进行更改,而是创建了一个新项目。创建一个动态 Web 项目并将其转换为 Maven 项目。然后复制所有 Java 类 - Person、Response、PersonService 和 PersonServiceImpl。以下是完成所有更改后的最终项目。在 pom.xml 文件中添加以下 RESTEasy 依赖项。
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.13.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.0.13.Final</version>
</dependency>
下面是我们配置 Resteasy servlet 的 web.xml 文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>JAXRS-Example-RestEasy</display-name>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.journaldev.jaxrs.resteasy.app.MyApp</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
注意 init-param 中提供MyApp
类作为值,这里我们扩展javax.ws.rs.core.Application
类,如下所示。
package com.journaldev.jaxrs.resteasy.app;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import com.journaldev.jaxrs.service.PersonServiceImpl;
public class MyApp extends Application {
private Set<Object> singletons = new HashSet<Object>();
public MyApp() {
singletons.add(new PersonServiceImpl());
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
RESTEasy Web 服务测试
就是这样。我们的 Web 服务已准备好 RESTEasy JAX-RS 实现。以下是 Postman chrome 扩展测试的一些输出。
- 获取Dummy
- 添加
- 得到
这就是Restful Web 服务教程的全部内容,我希望您了解 JAX-RS 注释并理解拥有标准 API 的好处,这些 API 可以帮助我们重用代码并轻松地从 Jersey 迁移到 RESTEasy。