Java的Restful Web Services教程

时间:2020-02-23 14:35:33  来源:igfitidea点击:

欢迎使用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扩展程序进行测试。

URIHTTP MethodDescription
/person/{id}/getDummyGETReturns a dummy person object
/person/addPOSTAdds a person
/person/{id}/deleteGETDelete the person with 'id' in the URI
/person/getAllGETGet all persons
/person/{id}/getGETGet 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