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