在本教程中,我们将学习如何使用Tomcat和 Jersey 创建 JAX-RS Get、POST、PUT 和 DELETE Rest Web 服务。
我们将建造什么?
我们正在构建一个简单的 用户管理应用程序,它具有以下 CRUD Rest API。
为用户 资源 创建了以下五个 REST API(控制器处理程序方法) 。
在开始之前,我想给你一个 JAX-RS Java API 的概述。
什么是 JAX-RS?
JAX-RS(用于 RESTful Web 服务的 Java API) 是一组 Java API,为创建 REST API 提供支持。并且该框架很好地利用了 JAX-RS 注解来简化这些 API 的开发和部署。
JAX-RS 2.0 (JSR-339) 和 JAX-RS 2.1 (JSR-370) 是 JCP(Java 社区进程)规范,它们通过 HTTP 协议为 RESTful Web 服务提供 Java API。
一些比较知名的 JAX-RS API 实现是 RESTEasy 和 Jersey。
JAX-RS HTTP 注释
JAX-RS 具有响应 HTTP 请求的注释。
- @GET - 表示注解的方法响应 HTTP GET 请求
- @POST - 表示被注解的方法响应一个 HTTP POST 请求
- @DELETE - 表示注解的方法响应 HTTP DELETE 请求
- @PUT - 表示注解的方法响应 HTTP PUT 请求
什么是 Tomcat?
它是一个开源 Java servlet 容器,它实现了许多 Java 企业规范,例如网站 API、Java-Server Pages 以及最后但并非最不重要的 Java Servlet。Tomcat 的全称是“Apache Tomcat”,它是在一个开放的、参与式的环境中开发的,并于 1998 年首次发布。它最初是作为第一个 Java-Server Pages 和Java Servlet API 的参考实现。但是,它不再作为这两种技术的参考实现,但即使在此之后,它仍被认为是用户的首选。由于具有良好的可扩展性、经过验证的核心引擎以及经过良好测试和耐用等多种功能,它仍然是使用最广泛的 java-sever 之一。
什么是 Jersey ?
Jersey RESTful Web Services,前身为Glassfish Jersey,目前 Eclipse Jersey框架是一个开源框架,用于在 Java 中开发 RESTful Web Services。它提供对 JAX-RS API 的支持并用作 JAX-RS(JSR 311 & JSR 339 & JSR 370)参考实现。
在本教程中,我们使用 Jetty服务器来部署 Jersey Web 应用程序。
使用的工具和技术
- JDK 1.8 或更高版本
- Maven 3.5+
- NetBeans IDE
- JAX-RS 2.0 +
- Jersey
- Tomcat 8.5+
开发步骤
- 在 IDE 中创建一个 Maven 项目
- 添加 Maven 依赖项
- 项目结构
- 创建用户模型类
- 创建一个用户服务类
- 创建一个 UserResource 类
- 创建应用程序类
- REST API 的客户端
- 结论
1.在IDE中创建一个Maven 项目
2.添加maven依赖
这是完整的 Maven pom.xml 文件。它包含依赖项。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zetcode</groupId>
<artifactId>JerseyTomcatEmbedded</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>JerseyTomcatEmbedded</name>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<tomcat.version>8.0.53</tomcat.version>
<jersey.version>2.10.1</jersey.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
</dependencies>
<build>
<finalName>JerseyTomcatEmbedded</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.example.jaxrs.app.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
3、项目结构
有关项目结构和打包结构,请参阅下面的屏幕截图:
4.创建用户模型类
这是一个 用户 模型类。它包含三个属性: id、 name和 email。
package com.example.jaxrs.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class User {
private Long id;
private String name;
private String email;
public User() {
}
public User(Long id, String name, String email) {
super();
this.id = id;
this.name = name;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", email=" + email + "]";
}
}
5.创建一个UserService类
让我们创建 为用户对象提供内存存储 的UserService 。UserService 包含 CRUD 合约方法。我们有查找用户、保存用户、更新使用和删除用户的方法。
package com.example.jaxrs.service;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.NotFoundException;
import com.example.jaxrs.model.User;
public class UserService {
private List< User> users = new ArrayList< User>();
public List< User> findAll() {
users.add(new User(100L,
"Ramesh", "ramesh@gmail.com"));
users.add(new User(101L,
"Tny", "tony@gmail.com"));
users.add(new User(102L,
"Tom", "tom@gmail.com"));
return users;
}
public User fetchBy(long id) throws NotFoundException {
for (User user : findAll()) {
if (id == user.getId()) {
return user;
} else {
throw new NotFoundException("Resource not found with Id :: " + id);
}
}
return null;
}
public boolean create(User user) {
return users.add(user);
}
public boolean update(User user) {
for (User updateUser : users) {
if (user.getId().equals(updateUser.getId())) {
users.remove(updateUser);
users.add(user);
return true;
}
}
return false;
}
public boolean delete(Long id) throws NotFoundException {
for (User user : users) {
if (user.getId().equals(id)) {
users.remove(user);
return true;
}
}
return false;
}
}
6.创建UserResource类
最后,让我们在这里查看一个实际的 CRUD API 定义:
package com.example.jaxrs.resource;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
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.example.jaxrs.model.User;
import com.example.jaxrs.service.UserService;
/**
* CRUD Rest APIs for User Resource
*
* @author Ramesh Fadatare
*
*/
@Path("users")
public class UserResource {
private UserService userService = new UserService();
@GET
@Produces(MediaType.APPLICATION_JSON)
// @Produces(MediaType.TEXT_PLAIN)
public Response getUsers() {
List< User> users = userService.findAll();
if (!users.isEmpty()) {
return Response.ok(users).build();
} else {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getUserById(@PathParam("id") Long id) {
User user = userService.fetchBy(id);
if (user.getId() != null) {
return Response.ok(user).build();
} else {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response createUser(User user) {
boolean result = userService.create(user);
if (result) {
return Response.ok().status(Response.Status.CREATED).build();
} else {
return Response.notModified().build();
}
}
@PUT
@Path("/{id}")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateUser(@PathParam("id") long id, User user) {
boolean result = userService.update(user);
if (result) {
return Response.ok().status(Response.Status.NO_CONTENT).build();
} else {
return Response.notModified().build();
}
}
@Path("/{id}")
@DELETE
@Produces(MediaType.APPLICATION_JSON)
public Response deleteUser(@PathParam("id") Long id) {
boolean result = userService.delete(id);
if (result) {
return Response.ok().status(Response.Status.NO_CONTENT).build();
} else {
return Response.notModified().build();
}
}
}
让我们从上面的代码中理解 JAX-RS 注解:
- @Path 注释指定资源响应的 URL 。
- @GET 注解表示被注解的方法响应 HTTP GET 请求。
- @Produces 注释用于指定资源可以生成并发送回客户端的 MIME 媒体类型。
- 创建新资源时,我们使用 @POST 注解。
- @Consumes 注释用于指定资源可以从客户端接受或使用的表示的 MIME 媒体类型。
7. 创建应用类
让我们创建一个应用程序类。
package com.example.jaxrs.app;
import com.example.jaxrs.config.RestConfig;
import java.io.File;
import javax.servlet.ServletException;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import org.glassfish.jersey.servlet.ServletContainer;
public class Application {
public static void main(String[] args) throws LifecycleException, ServletException {
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
Context context = tomcat.addWebapp("", new File(".").getAbsolutePath());
ServletContainer servletContainer = new ServletContainer(new RestConfig());
tomcat.addServlet("", "restConfig", servletContainer);
context.addServletMappingDecoded("/restapi/*", "restConfig");
tomcat.start();
tomcat.getServer().await();
}
}
package com.example.jaxrs.config;
import org.glassfish.jersey.server.ResourceConfig;
public class RestConfig extends ResourceConfig {
public RestConfig() {
packages("com.example.jaxrs");
}
}
8. REST API 客户端
这是完整的 Maven pom.xml 文件。它包含依赖项。
Jersey:
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.javaguides</groupId>
<artifactId>JerseyClientRESTAPI</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>JerseyClientRESTAPI</name>
<url>http://maven.apache.org</url>
<properties>
<resteasy.version>3.9.3.Final</resteasy.version>
</properties>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.35</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.35</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.35</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<finalName>resteasy-crud-example-tutorial</finalName>
</build>
</project>
import com.example.jaxrs.model.User;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
public class UserResourceMain {
private static final String FULL_PATH = "http://localhost:8080/restapi/users";
public static void main(String[] args) {
UserResourceMain urm = new UserResourceMain();
urm.testListAllUsers();
urm.testGetUser();
urm.testCreateUser();
urm.testUpdateUser();
urm.testDeleteUser();
}
public void testListAllUsers() {
Client client = ClientBuilder.newClient();
final WebTarget target = client
.target(FULL_PATH);
String response = target.request().get(String.class);
System.out.println(response);
}
public void testGetUser() {
Client client = ClientBuilder.newClient();
final WebTarget target = client
.target(FULL_PATH + "/100");
Response response = target.request().get();
User user = response.readEntity(User.class);
System.out.println(user.toString());
response.close();
}
public void testCreateUser() {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(FULL_PATH);
Response response = target.request()
.post(Entity.entity(new User(100L,
"Amir", "amir@gmail.com"), "application/json"));
System.out.println(response.getStatus());
response.close();
}
public void testUpdateUser() {
User user = new User();
user.setName("Ram");
user.setEmail("ram@gmail.com");
Client client = ClientBuilder.newClient();
WebTarget target = client.target(FULL_PATH + "/100");
Response response = target.request()
.put(Entity.entity(user, "application/json"));
System.out.println(response.getStatus());
response.close();
}
public void testDeleteUser() {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(FULL_PATH + "/101");
Response response = target.request()
.delete();
System.out.println(response.getStatus());
response.close();
final WebTarget target1 = client
.target(FULL_PATH);
String response1 = target1.request().get(String.class);
System.out.println(response1);
}
}
结论
在本教程中,我们使用 jetty和 Jersey创建了一个 CRUD RESTFul 应用程序。