Jersey JSON
最后修改于 2023 年 1 月 10 日
Jersey JSON 教程展示了如何在 Jersey 中从 RESTful 应用程序提供 JSON。该应用程序部署在 Tomcat 上。
Jersey
Jersey 是一个用于在 Java 中开发 RESTful Web 服务的框架。它是 Java API for RESTful Web Services (JAX-RS) 规范的参考实现。另一个流行的 JAX-RS 实现是 JBoss 的 RESTEasy。
JSON
JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。它易于人类阅读和编写,也易于机器解析和生成。JSON 的官方 Internet 媒体类型是 application/json
。JSON 文件扩展名是 .json
。
Jersey JSON 示例
下面的示例是一个简单的 RESTful 应用程序,它向客户端返回 JSON 数据。
├── pom.xml └── src ├── main │ ├── java │ │ └── com │ │ └── zetcode │ │ ├── conf │ │ │ └── AppResConfig.java │ │ ├── model │ │ │ └── City.java │ │ ├── service │ │ │ ├── CityService.java │ │ │ └── ICityService.java │ │ └── ws │ │ └── MyResource.java │ ├── resources │ └── webapp │ ├── META-INF │ │ └── context.xml │ └── WEB-INF │ └── beans.xml └── 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>JerseyJsonTomcat</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>JerseyJsonTomcat</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey</groupId> <artifactId>jersey-bom</artifactId> <version>2.26</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.ext.cdi</groupId> <artifactId>jersey-cdi1x-servlet</artifactId> </dependency> <dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <version>2.0-EDR1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> </dependency> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-shaded</artifactId> <version>3.0.2.Final</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> </project>
这是 Maven POM 文件。它包含启用 Jersey、将 Java 类转换为 JSON 和依赖注入的依赖项。
<?xml version="1.0" encoding="UTF-8"?> <Context path="/JerseyJsonTomcat"> <Resource auth="Container" factory="org.jboss.weld.resources.ManagerObjectFactory" name="BeanManager" type="javax.enterprise.inject.spi.BeanManager"/> </Context>
在 Tomcat 的 context.xml
配置文件中,我们定义了应用程序上下文路径。我们还注册了 Weld 的 BeanManager 工厂。
<?xml version="1.0"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" version="1.1" bean-discovery-mode="all"> </beans>
在 WEB-INF
目录中,我们有一个空的 beans.xml
文件。它是 CDI 的部署描述符。它可用于配置拦截器、装饰器和其他内容。即使我们不做任何配置,也需要添加一个空的 beans.xml
来注册 CDI。
package com.zetcode.model; import java.util.Objects; public class City { private Long id; private String name; private int population; public City() { } public City(Long id, String name, int population) { this.id = id; this.name = name; this.population = population; } 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 int getPopulation() { return population; } public void setPopulation(int population) { this.population = population; } @Override public int hashCode() { int hash = 3; hash = 71 * hash + Objects.hashCode(this.id); hash = 71 * hash + Objects.hashCode(this.name); hash = 71 * hash + this.population; return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final City other = (City) obj; if (this.population != other.population) { return false; } if (!Objects.equals(this.name, other.name)) { return false; } return Objects.equals(this.id, other.id); } @Override public String toString() { return "City{" + "id=" + id + ", name=" + name + ", population=" + population + '}'; } }
这是一个 City
类。
package com.zetcode.conf; import javax.ws.rs.ApplicationPath; import org.glassfish.jersey.server.ResourceConfig; @ApplicationPath("rest") public class AppResConfig extends ResourceConfig { public AppResConfig() { packages(true, "com.zetcode"); } }
ResourceConfig
是用于配置 Web 应用程序的资源配置。通过 packages
方法,我们指定要搜索组件的包。
@ApplicationPath("rest")
使用 @ApplicationPath
注解,我们设置了 RESTful Web 服务的路径。
package com.zetcode.service; import com.zetcode.model.City; import java.util.List; public interface ICityService { public List<City> findAll(); }
ICityService
包含一个 findAll
合约方法。
package com.zetcode.service; import com.zetcode.model.City; import java.util.ArrayList; import java.util.List; public class CityService implements ICityService { @Override public List<City> findAll() { List<City> cities = new ArrayList<>(); cities.add(new City(1L, "Bratislava", 432000)); cities.add(new City(2L, "Budapest", 1759000)); cities.add(new City(3L, "Prague", 1280000)); cities.add(new City(4L, "Warsaw", 1748000)); cities.add(new City(5L, "Los Angeles", 3971000)); cities.add(new City(6L, "New York", 8550000)); cities.add(new City(7L, "Edinburgh", 464000)); cities.add(new City(8L, "Berlin", 3671000)); return cities; } }
CityService
包含 findAll
方法的实现。它返回一个城市列表。
package com.zetcode.ws; import com.zetcode.model.City; import com.zetcode.service.ICityService; import java.util.List; import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.GenericEntity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @Path("cities") public class MyResource { @Inject private ICityService cityService; @GET @Produces(MediaType.APPLICATION_JSON) public Response message() { List<City> cities = cityService.findAll(); GenericEntity<List<City>> myEntity = new GenericEntity<List<City>>(cities) {}; return Response.status(200).entity(myEntity).build(); } }
这是 MyResource
类。
@Path("cities") public class MyResource {
@Path
指定资源响应的 URL。
@Inject private ICityService cityService;
使用 @Inject
注解,我们将城市服务注入到 cityService
字段中。
@GET @Produces(MediaType.APPLICATION_JSON) public Response message() {
@GET
注解表示带注解的方法响应 HTTP GET 请求。通过 @Produces
注解,我们定义该方法生成 JSON 数据。
List<City> cities = cityService.findAll(); GenericEntity<List<City>> myEntity = new GenericEntity<List<City>>(cities) {};
我们调用城市服务,并从返回的城市列表中创建一个 GenericEntity
。
return Response.status(200).entity(myEntity).build();
我们将包含 JSON 数据的响应发送给客户端。消息正文写入器将城市列表转换为 JSON。
$ curl localhost:8084/JerseyJsonTomcat/rest/cities [{"id":1,"name":"Bratislava","population":432000},{"id":2,"name":"Budapest","population":1759000}, {"id":3,"name":"Prague","population":1280000},{"id":4,"name":"Warsaw","population":1748000}, {"id":5,"name":"Los Angeles","population":3971000},{"id":6,"name":"New York","population":8550000}, {"id":7,"name":"Edinburgh","population":464000},{"id":8,"name":"Berlin","population":3671000}]
应用程序部署在 Tomcat 上后,我们使用 curl
向应用程序发送 GET 请求。
在此教程中,我们创建了一个将 JSON 数据发送给客户端的 RESTful 应用程序。我们使用了 Tomcat Web 服务器和 Jersey 框架。