Java Servlet RESTful 客户端
最后修改于 2023 年 8 月 24 日
在 Java Servlet RESTful 客户端教程中,我们使用 JAX-RS 在 Java Servlet 中创建了一个 RESTful 客户端。
Java API for RESTful Web Services (JAX-RS) 是一个 Java API 规范,它支持根据 Representational State Transfer (REST) 架构模式创建 Web 服务。
RESTEasy 是一个 Java RESTful Web Services 框架,也是 JBoss 的 JAX-RS 实现。
Servlet 是一个 Java 类,它响应特定类型的网络请求——最常见的是 HTTP 请求。Java Servlets 用于创建 Web 应用程序。它们运行在 Tomcat 或 Jetty 等 Servlet 容器中。现代 Java Web 开发使用构建在 Servlet 之上的框架。
Java Servlet 应用程序
以下 Web 应用程序向 api.randomuser.me
(一个随机用户生成器)站点发送请求。
Java Servlet 使用 ClientBuilder
创建 Client
,这是用于构建和执行客户端请求以处理返回响应的流畅 API 的主要入口点。
pom.xml src ├── main │ ├── java │ │ └── com │ │ └── zetcode │ │ ├── model │ │ │ ├── Location.java │ │ │ ├── Name.java │ │ │ ├── Person.java │ │ │ └── PersonsList.java │ │ ├── service │ │ │ └── PersonService.java │ │ └── web │ │ └── MyServlet.java │ ├── resources │ └── webapp │ ├── index.html │ └── show.jsp └── test └── java
这是项目结构。
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zetcode</groupId> <artifactId>JavaServletRestClient</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>14</maven.compiler.source> <maven.compiler.target>14</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-servlet-initializer</artifactId> <version>4.5.5.Final</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> <version>4.5.5.Final</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jackson2-provider</artifactId> <version>4.5.5.Final</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.0</version> </plugin> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.4.30.v20200611</version> </plugin> </plugins> </build> </project>
这是 Maven POM 文件。我们有以下工件:javax.servlet-api
用于 Servlet,jstl
用于标准 JSP 标签库,resteasy-servlet-initializer
用于将 RESTEasy 与 Servlet 集成,resteasy-client
用于 RESTful 核心客户端实现,resteasy-jackson2-provider
用于 JSON/Java 模型数据绑定。
在应用程序中,我们有三个模型类;这些模型将用响应中的数据填充。
package com.zetcode.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class Location { private String city; private String state; private String postcode; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getPostcode() { return postcode; } public void setPostcode(String postcode) { this.postcode = postcode; } @Override public String toString() { final StringBuilder sb = new StringBuilder("Location{"); sb.append("city='").append(city).append('\''); sb.append(", state='").append(state).append('\''); sb.append(", postcode='").append(postcode).append('\''); sb.append('}'); return sb.toString(); } }
Location
存储用户的地址。
@JsonIgnoreProperties(ignoreUnknown = true)
使用 @JsonIgnoreProperties
注释,我们告诉 Jackson 忽略 Person
中未列出的属性。
package com.zetcode.model; public class Name { private String first; private String last; private String title; public String getFirst() { return first; } public void setFirst(String firstName) { first = firstName; } public String getLast() { return last; } public void setLast(String lastName) { last = lastName; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(title).append(" ").append(first) .append(" ").append(last); return sb.toString(); } }
Name
存储用户名详细信息。
package com.zetcode.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class Person { private Name name; private Location location; private String email; private String gender; public void setName(Name name) { this.name = name; } public Name getName() { return name; } public Location getLocation() { return location; } public void setLocation(Location location) { this.location = location; } public void setEmail(String email) { this.email = email; } public String getEmail() { return email; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Name: ").append(name) .append("Address: ").append(location) .append("Email ").append(email) .append("Gender: ").append(gender); return sb.toString(); } }
Person
类存储用户数据,包括姓名、地址、电子邮件和性别。
package com.zetcode.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) public class PersonsList { private List<Person> results; public List<Person> getResults() { return results; } public void setResults(List<Person> result) { results = result; } }
这是 Person
对象的列表。Web 服务使用此列表填充数据。
package com.zetcode.web; import com.zetcode.model.Person; import com.zetcode.service.PersonService; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; @WebServlet(name = "MyServlet", urlPatterns = {"/MyServlet"}) public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); List<Person> people = PersonService.fetchPeople(0, 50); request.setAttribute("people", people); request.getRequestDispatcher("show.jsp").forward(request, response); } }
MyServlet
Servlet 调用 PersonService.fetchPeople()
,它返回一个 Person
对象列表。该列表存储为一个属性,然后将处理转发到 show.jsp
页面。JSP 页面渲染 Person
对象列表。
package com.zetcode.service; import com.zetcode.model.Person; import com.zetcode.model.PersonsList; import java.util.List; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; public class PersonService { private static WebTarget resource = ClientBuilder.newBuilder() .build().target("https://api.randomuser.me/"); public static List<Person> fetchPeople(int offset, int num) { PersonsList res = resource.queryParam("seed", 1) .queryParam("results", num).queryParam("page", 1) .request(MediaType.APPLICATION_JSON).get(PersonsList.class); return res.getResults(); } }
PersonService
包含一个 fetchPeople()
方法,用于在 api.randomuser.me
Web 服务上执行查询。该服务返回随机用户对象。
private static WebTarget resource = ClientBuilder.newBuilder() .build().target("https://api.randomuser.me/");
使用 ClientBuilder
,我们创建一个 Web 资源目标。api.randomuser.me
网站随机返回用户列表。
public static List<Person> fetchPeople(int offset, int num) { PersonsList res = resource.queryParam("seed", 1) .queryParam("results", num).queryParam("page", 1) .request(MediaType.APPLICATION_JSON).get(PersonsList.class); return res.getResults(); }
我们向 Web 资源发送一个查询;数据存储在 PersonsList
中。
<!DOCTYPE html> <html> <head> <title>Home Page</title> <meta charset="UTF-8"> </head> <body> <a href="MyServlet">List people</a> </body> </html>
这是主页。它包含一个调用 MyServlet
的链接。
<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Show people</title> </head> <body> <table> <thead> <tr> <th>Title</th> <th>First name</th> <th>Last name</th> <th>City</th> <th>State</th> <th>Postcode</th> <th>Email</th> <th>Gender</th> </tr> </thead> <tbody> <c:forEach var="per" items="${people}"> <tr> <td><c:out value="${per.name.title}"/></td> <td><c:out value="${per.name.first}"/></td> <td><c:out value="${per.name.last}"/></td> <td><c:out value="${per.location.city}"/></td> <td><c:out value="${per.location.state}"/></td> <td><c:out value="${per.location.postcode}"/></td> <td><c:out value="${per.email}"/></td> <td><c:out value="${per.gender}"/></td> </tr> </c:forEach> </tbody> </table> </body> </html>
show.jsp
页面使用 JSTL 库中的 c:forEach
和 c:out
标签以 HTML 表格的形式显示数据。
$ mvn jetty:run
我们启动应用程序并访问 localhost:8080
。
在本文中,我们创建了一个 RESTEasy 客户端请求到生成随机用户的 Web 服务。该请求是从 Java Servlet 发送的。