Eclipse和Tomcat的RESTEasy教程
欢迎使用RESTEasy教程。
RESTEasy是JBoss项目提供的JAX-RS实现。
我们可以使用RESTEasy创建宁静的Web服务。
RESTEasy提供了与JBoss Application Server的更紧密的集成,但是我们可以将其部署在任何servlet容器上。
因此,今天我们将学习如何使用RestEasy框架创建Restful Web服务并部署在Tomcat Servlet容器中进行测试。
RESTEasy教程
RESTEasy框架的一些功能包括:
兼容JAX-RS API-因此大多数情况下,您需要将其插入JAX-RS API编码以创建其余的Web服务。
在几乎所有支持Java 6或者更高版本的servlet容器上运行
提供对使用JAX-RS 2.0客户端API编写客户端程序的支持。
我们也会研究测试程序。丰富的提供程序集-XML,JSON,YAML,Multipart,XOP,Atom等
OAuth2和带有JBoss AS7的分布式SSO
EJB,Seam,Guice,Spring和Spring MVC集成
RESTEasy示例
以下是我们将在RestEasy Web服务实现中公开的URI。
| URI | HTTP Method | Description |
|---|---|---|
| /employee/add | POST | Add an employee |
| /employee/getDummy | GET | returns a dummy employee object |
| /employee/{id}/get | GET | Get the employee with 'id' in the URI |
| /employee/getAll | GET | Get all employees |
| /employee/{id}/delete | DELETE | Delete employee with 'id' in the URI |
RESTEasy示例Eclipse项目
下图显示了我们的最终项目结构。
首先,在Eclipse中创建"动态Web应用程序",然后将其转换为Maven项目以获取Web项目框架。
让我们研究一下RestEasy网络服务项目的不同组成部分。
RESTEasy示例模型类
我们有两个模型类-" Employee"(雇员)对象和" GenericResponse"(发送状态,消息和错误代码的客户端响应对象)。
package com.theitroad.jaxrs.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "employee")
public class Employee {
private String name;
private double salary;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return id + "::" + name + "::" + salary;
}
}
package com.theitroad.jaxrs.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "response")
public class GenericResponse {
private boolean status;
private String message;
private String errorCode;
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;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
@Override
public String toString() {
return status + "|" + message + "|" + errorCode;
}
}
请注意,两个Java Bean均带有@ XmlRootElement注释。
JAXB API要求将对象转换为xml,反之亦然。
RESTEasy示例服务类
首先,我们为尝试在静态网络服务中公开的所有操作创建一个界面。
package com.theitroad.jaxrs.service;
import javax.ws.rs.core.Response;
import com.theitroad.jaxrs.model.Employee;
public interface EmployeeService {
public Response addEmployee(Employee e);
public Response deleteEmployee(int id);
public Employee getEmployee(int id);
public Employee[] getAllEmployees();
}
以下是上述员工服务接口的实现类。
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.DELETE;
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 javax.ws.rs.core.Response;
import com.theitroad.jaxrs.model.Employee;
import com.theitroad.jaxrs.model.GenericResponse;
@Path("/employee")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public class EmployeeServiceImpl implements EmployeeService {
private static Map<Integer,Employee> emps = new HashMap<Integer,Employee>();
@Override
@POST
@Path("/add")
public Response addEmployee(Employee e) {
GenericResponse response = new GenericResponse();
if(emps.get(e.getId()) != null){
response.setStatus(false);
response.setMessage("Employee Already Exists");
response.setErrorCode("EC-01");
return Response.status(422).entity(response).build();
}
emps.put(e.getId(), e);
response.setStatus(true);
response.setMessage("Employee created successfully");
return Response.ok(response).build();
}
@Override
@DELETE
@Path("/{id}/delete")
public Response deleteEmployee(@PathParam("id") int id) {
GenericResponse response = new GenericResponse();
if(emps.get(id) == null){
response.setStatus(false);
response.setMessage("Employee Doesn't Exists");
response.setErrorCode("EC-02");
return Response.status(404).entity(response).build();
}
emps.remove(id);
response.setStatus(true);
response.setMessage("Employee deleted successfully");
return Response.ok(response).build();
}
@Override
@GET
@Path("/{id}/get")
public Employee getEmployee(@PathParam("id") int id) {
return emps.get(id);
}
@GET
@Path("/{id}/getDummy")
public Employee getDummyEmployee(@PathParam("id") int id) {
Employee e = new Employee();
e.setSalary(8976.55);
e.setName("Dummy");
e.setId(id);
return e;
}
@Override
@GET
@Path("/getAll")
public Employee[] getAllEmployees() {
Set<Integer> ids = emps.keySet();
Employee[] e = new Employee[ids.size()];
int i=0;
for(Integer id : ids){
e[i] = emps.get(id);
i++;
}
return e;
}
}
我们仅使用诸如@ Path,@ PathParam,Response等的JAX-RS API批注。
请注意,在某些方法中,我将javax.ws.rs.core.Response作为响应对象。
我想发送200以外的HTTP状态代码的地方。
RESTEasy配置
到目前为止,我们还没有做过与RestEasy相关的任何事情,现在是时候将RestEasy配置为我们的宁静Web服务的JAX-RS API实现。
第一步是扩展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.EmployeeServiceImpl;
public class EmployeeApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
public EmployeeApplication() {
singletons.add(new EmployeeServiceImpl());
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
下一步是在我们的pom.xml文件中添加RESTEasy Maven依赖项,如下所示。
<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> <version>3.0.13.Final</version> </dependency> <!-- Below dependency is for JAXB integration --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxb-provider</artifactId> <version>3.0.13.Final</version> </dependency>
最后一步是将部署描述符中的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>RestEasy-Example</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.EmployeeApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
我们的网络服务已准备就绪。
您可以看到,将RestEasy插入为我们的JAX-RS实现以实现静态Web服务是多么容易。
RESTEasy Restful Web服务测试
我正在使用Chrome Postman扩展程序对我们的Web服务进行测试。
以下是一些具有响应的测试案例。
如下图所示,所有请求中的标头都是一个共同的部分。
- getDummy
- add
- get
- getAll
- delete
- 添加错误– HTTP响应422
- 删除错误-HTTP响应404
如您所见,所有测试都通过了测试,我们的其余Web服务运行正常。
RestEasy Client – ResteasyClient示例
如前所述,RestEasy还提供用于通过Java程序测试其余Web服务的API。
为此,我们需要在pom.xml文件中添加另一个依赖项。
<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> <version>3.0.13.Final</version> </dependency>
下面是简单的测试程序,其中我正在以编程方式测试我们的Web服务。
我提供了用于测试GET,POST和DELETE HTTP方法的示例。
package com.theitroad.jaxrs.resteasy.client;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
import com.theitroad.jaxrs.model.Employee;
import com.theitroad.jaxrs.model.GenericResponse;
public class RestEasyTestClient {
public static void main(String[] args) {
ResteasyClient client = new ResteasyClientBuilder().build();
//GET example
ResteasyWebTarget getDummy = client.target("https://localhost:8080/RestEasy-Example/employee/99/getDummy");
Response getDummyResponse = getDummy.request().get();
String value = getDummyResponse.readEntity(String.class);
System.out.println(value);
getDummyResponse.close();
//POST example
ResteasyWebTarget add = client.target("https://localhost:8080/RestEasy-Example/employee/add");
Employee emp = new Employee();
emp.setId(50);emp.setName("Rick");emp.setSalary(1000);
Response addResponse = add.request().post(Entity.entity(emp, MediaType.APPLICATION_XML));
System.out.println(addResponse.readEntity(GenericResponse.class));
System.out.println("HTTP Response Code:"+addResponse.getStatus());
addResponse.close();
addResponse = add.request().post(Entity.entity(emp, MediaType.APPLICATION_XML));
System.out.println(addResponse.readEntity(GenericResponse.class));
System.out.println("HTTP Response Code:"+addResponse.getStatus());
addResponse.close();
//DELETE example
ResteasyWebTarget delete = client.target("https://localhost:8080/RestEasy-Example/employee/50/delete");
Response deleteResponse = delete.request().delete();
System.out.println(deleteResponse.readEntity(GenericResponse.class));
System.out.println("HTTP Response Code:"+deleteResponse.getStatus());
deleteResponse.close();
deleteResponse = delete.request().delete();
System.out.println(deleteResponse.readEntity(GenericResponse.class));
System.out.println("HTTP Response Code:"+deleteResponse.getStatus());
deleteResponse.close();
}
}
以下是上述RESTEasy客户程序产生的输出。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <employee><id>99</id><name>Dummy</name><salary>8976.55</salary></employee> true|Employee created successfully|null HTTP Response Code:200 false|Employee Already Exists|EC-01 HTTP Response Code:422 true|Employee deleted successfully|null HTTP Response Code:200 false|Employee Doesn't Exists|EC-02 HTTP Response Code:404

