使用Java进行的Restful Web服务教程
欢迎来到Java中的Restful Web服务教程。REST代表表现层状态转移。REST是一种用于开发可以通过网络访问的应用程序的架构风格。REST架构风格在2000年由罗伊·菲尔丁在其博士论文中提出的。
RESTful Web Services (简称RESTful Web服务)
RESTful Web Services 是一种无状态的客户机-服务器架构,其中 Web 服务是资源,并且可以通过其 URI 进行标识。REST 客户端应用程序可以使用 HTTP GET/POST 方法来调用 RESTful Web 服务。REST 不指定要使用的任何特定协议,但几乎在所有情况下都使用 HTTP/HTTPS。与 SOAP Web 服务相比,这些 Web 服务比较轻量级,并且不遵循任何标准。我们可以使用 XML、JSON、文本或任何其他类型的数据进行请求和响应。
Java RESTful Web Services API 的意思是使用 Java 编写的一种接口,可以用来开发和管理 RESTful Web 服务。
Java API for RESTful Web Services (JAX-RS) 是用于创建 RESTful 网络服务的 Java API。JAX-RS 使用注解来简化网络服务的开发和部署。JAX-RS 是 JDK 的一部分,所以您无需包含任何内容就可以使用它的注解。
RESTful web服务注解
一些重要的JAX-RS注解包括:
- @Path: used to specify the relative path of class and methods. We can get the URI of a webservice by scanning the Path annotation value.
- @GET, @PUT, @POST, @DELETE and @HEAD: used to specify the HTTP request type for a method.
- @Produces, @Consumes: used to specify the request and response types.
- @PathParam: used to bind the method parameter to path value by parsing it.
Restful 网络服务和 SOAP
-
- SOAP是一个协议,而REST是一种架构风格。
-
- SOAP服务器和客户端应用程序紧密耦合,并与WSDL合同绑定,而在REST网络服务和客户端中没有合同。
-
- 与SOAP网络服务相比,REST的学习曲线更容易。
-
- REST网络服务的请求和响应类型可以是XML,JSON,文本等,而SOAP仅使用XML。
- JAX-RS是用于REST网络服务的Java API,而JAX-WS是用于SOAP网络服务的Java API。
REST API 实现
JAX-RS API有两种主要的实现方式。
-
- Jersey: Jersey是由Sun提供的参考实现。要将Jersey作为我们的JAX-RS实现使用,我们只需要在web.xml中配置它的servlet并添加所需的依赖项。请注意,JAX-RS API是JDK的一部分,而不是Jersey,所以我们必须在我们的应用程序中添加它的依赖jar包。
- RESTEasy: RESTEasy是JBoss项目提供的JAX-RS实现。
Java的Restful Web服务教程
让我们看看使用Jersey和RESTEasy创建Restful Web服务有多么简单。我们将通过HTTP暴露以下方法,并使用Chrome Postman扩展来测试这些方法。
URI | HTTP Method | Description |
---|---|---|
/person/{id}/getDummy | GET | Returns a dummy person object |
/person/add | POST | Adds a person |
/person/{id}/delete | GET | Delete the person with ‘id’ in the URI |
/person/getAll | GET | Get all persons |
/person/{id}/get | GET | Get the person with ‘id’ in the URI |
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的依赖,但如果您使用Jersey编写Java程序来调用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.Olivia</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.Olivia.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.Olivia.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.Olivia.jaxrs.service;
import com.Olivia.jaxrs.model.Person;
import com.Olivia.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.Olivia.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.Olivia.jaxrs.model.Person;
import com.Olivia.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服务执行的一些测试。请注意,我们必须在请求头中提供“application/xml”作为接受和内容类型的值,如下图所示。
- getDummy
- add
- get
- getAll
- delete
使用Jersey JAX-RS实现创建Web服务就是这些。如您所见,大多数代码都使用JAX-RS注解,而Jersey则通过部署描述符和依赖项进行插入。
RESTEasy 是一个 RESTful Web Services 示例。
我们将使用在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>
以下是web.xml文件,我们在其中配置Resteasy servlet。
<?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.Olivia.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.Olivia.jaxrs.resteasy.app;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import com.Olivia.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 服务测试
就这些了。我们的网络服务使用RESTEasy JAX-RS实现已经准备就绪。以下是Postman Chrome扩展测试的一些输出。
- getDummy
- add
- get
对于“Restful Web Services教程”就讲到这里,希望你学到了JAX-RS注解,并理解了拥有标准API的好处,它帮助我们重复使用代码,并轻松地从Jersey迁移到RESTEasy。