Java的Restful Web Services教程
欢迎使用Java的Restful Web服务教程。
REST是代表状态转移的首字母缩写。
REST是一种体系结构样式,用于开发可通过网络访问的应用程序。
REST建筑风格是由Roy Fielding在2000年的博士论文中提出的。
Restful Web服务
Restful Web Services是一种无状态的客户端-服务器体系结构,其中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:用于指定类和方法的相对路径。
我们可以通过扫描路径注释值来获取Web服务的URI。@ GET,@ PUT,@ POST,@ DELETE和@HEAD:用于指定方法的HTTP请求类型。
@ 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有两种主要实现。
泽西岛:泽西岛是Sun提供的参考实现。
为了使用Jersey作为我们的JAX-RS实现,我们需要在web.xml中配置其servlet并添加所需的依赖项。
请注意,JAX-RS API是JDK而不是Jersey的一部分,因此我们必须在应用程序中添加其依赖项jar。RESTEasy:RESTEasy是提供JAX-RS实现的JBoss项目。
Java Restful Web服务教程
让我们看看使用Jersey和RESTEasy创建Restful网络服务有多么容易。
我们将通过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依赖关系,但是如果您正在编写Java程序以使用Jersey调用REST网络服务,则需要这样做。
现在,让我们看一下部署描述符,以了解如何配置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.theitroad</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响应,因此应使用@ XmlRootElement
来标注Bean,因此我们拥有此类。
package com.theitroad.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.theitroad.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.theitroad.jaxrs.service; import com.theitroad.jaxrs.model.Person; import com.theitroad.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.theitroad.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.theitroad.jaxrs.model.Person; import com.theitroad.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目录中或者部署到您选择的任何其他容器中即可。
以下是针对此Web服务使用Postman chrome扩展程序执行的一些测试。
请注意,我们必须在请求标头中提供Accept和Content-Type值作为" application/xml",如下图所示。
- getDummy
- add
- get
- getAll
- delete
这就是使用Jersey JAX-RS实施创建网络服务的全部过程。
如您所见,大多数代码都使用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.theitroad.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.theitroad.jaxrs.resteasy.app; import java.util.HashSet; import java.util.Set; import javax.ws.rs.core.Application; import com.theitroad.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实现已准备好我们的Web服务。
以下是Postman chrome扩展测试的一些输出。
- getDummy
- add
- get