在REST API设计教程中,我们学会了将REST原则放在网络应用程序的设计过程中。在本文中,我们将学习使用JAX-RS 2.0(用于RESTful服务的Java API)创建REST API 。
目录
JAX-RS 2.0规范
JAX-RS 2.0批注
创建Maven应用程序
包括JAX-RS依赖关系到应用程序
创建资源表示
在运行时创建REST资源
寄存器资源
演示
googletag.cmd.push(function() { googletag.display('waldo-tag-4084'); });
JAX-RS提供了可移植的API,用于开发,公开和访问符合REST架构风格原则设计和实现的Web应用程序。
Java EE 6版本通过引入用于RESTful Web服务的Java API(JAX-RS) [ JSR 311 ],迈出了标准化RESTful Web服务API的第一步。JAX-RS确保跨所有符合Java EE的应用程序服务器的REST API代码的可移植性。最新版本是JAX-RS 2.0 [ JSR 339 ],它是作为Java EE 7平台的一部分发布的。
JAX-RS专注于将Java注释应用于普通Java对象。JAX-RS具有将特定URI模式和HTTP操作绑定到Java类的各个方法的注释。它还有注释,可以帮助您处理输入/输出参数。
正如我们已经说过JAX-RS是规范; 这意味着我们需要让它的实现来运行REST API代码。目前可用的一些流行的JAX-RS实现是:
让我们来看看JAX-RS 2.0提供的一些重要注释。
@Path( 'resourcePath')
它用于匹配相对于基URI的URI路径。它可以在资源类或方法上指定。
@Path("/configurations")
public class ConfigurationResource
{
@Path("/{id}")
@GET
public Response getConfigurationById(@PathParam("id") Integer id){
...
}
}
设置路径base URL + /resourcePath
。基本URL基于应用程序名称,servlet和web.xml
配置文件中的URL模式。
@POST
带注释的方法将处理HTTP POST
匹配资源路径上的请求。
@POST
@Consumes("application/xml")
public Response createConfiguration(Configuration config) {
...
}
@PUT
带注释的方法将处理HTTP PUT
匹配资源路径上的请求。
@PUT
@Consumes("application/xml")
public Response updateConfiguration(@PathParam("id") Integer id, Configuration config){
...
}
@GET
带注释的方法将处理HTTP GET
匹配资源路径上的请求。
@GET
@Path("/{id}")
public Response getConfigurationById(@PathParam("id") Integer id){
...
}
@DELETE
带注释的方法将处理HTTP DELETE
匹配资源路径上的请求。
@DELETE
@Path("/{id}")
public Response deleteConfiguration(@PathParam("id") Integer id){
...
}
@PathParam(“parameterName”)
它用于将URL中的值(资源标识符)注入方法参数。
@DELETE
@Path("/{id}")
public Response deleteConfiguration(@PathParam("id") Integer id){
...
}
在上面的例子中,id
from 的值/{id}
将匹配@PathParam("id") Integer id
。例如,URI HTTP DELETE /configurations/22312
将映射到上面的方法,id
并将使用值填充22312
。
@Produces
它定义了带注释的资源方法传递的MIME类型。它可以在类级别和方法级别定义。如果在类级别定义,则资源类内的所有方法都将返回相同的MIME类型,如果不在任何方法中重写。
@Path("/configurations")
@Produces("application/xml")
public class ConfigurationResource {
...
}
@Consumes
它定义了带注释的资源方法使用的MIME类型。
@POST
@Consumes("application/xml")
public Response createConfiguration(Configuration config) {
...
}
@Context
为了构建HATEOAS链接,JAX-RS 2.0提供了UriInfo
可以使用@Context
注释获得的类。
@Context
UriInfo uriInfo;
默认情况下,如果未明确实现,JAX-RS运行时将自动支持HEAD和OPTIONS方法。对于HEAD,运行时将调用实现的GET方法(如果存在)并忽略响应实体(如果设置)。OPTIONS方法可以在“允许”标题中返回带有一组受支持的资源方法的响应。
Maven是一个软件项目管理和理解工具,包括项目构建,报告和来自中心信息的文档,即pom.xml
。
要在eclipse中使用maven创建应用程序,请按照下列步骤操作:
创建Maven应用程序 - 步骤1
创建Maven应用程序 - 步骤2
创建Maven应用程序 - 步骤3
创建Maven应用程序 - 步骤4
JAX-RS 2.0与JDK 1.7捆绑在一起,因此如果你有JDK 1.7或更高版本,[JAVA_HOME](https://docs.oracle.com/cd/E19182-01/820-7851/inst_cli_jdk_javahome_t/)
则不需要单独包含JAX-RS。但是,您需要包含上面列出的其中一个实现。
在这个例子中,我使用的是RESTEasy 3.1.2.Final。
<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.restfulapi.app</groupId>
<artifactId>NetworkManagement</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>NetworkManagement</name>
<url>http://maven.apache.org</url>
<repositories>
<repository>
<id>jboss</id>
<name>jboss repo</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<finalName>NetworkManagement</finalName>
</build>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.1.2.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.1.2.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-servlet-initializer</artifactId>
<version>3.1.2.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
resteasy-servlet-initializer
artifact可以自动扫描Servlet 3.0容器中的资源和提供程序。
在JAX-RS,资源表示是带有加注解的POJO类JAXB注解,即@XmlRootElement
,@XmlAttribute
和@XmlElement
等。
在这个例子中,我们暴露了两个表示。让我们为它们创建java类。
package net.restfulapi.app.rest.domain;
import java.util.List;
import javax.ws.rs.core.Link;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "configurations")
@XmlAccessorType(XmlAccessType.FIELD)
public class Configurations
{
@XmlAttribute
private Integer size;
@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
@XmlElement
private Link link;
@XmlElement
private List<Configuration> configurations;
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public Link getLink() {
return link;
}
public void setLink(Link link) {
this.link = link;
}
public List<Configuration> getConfigurations() {
return configurations;
}
public void setConfigurations(List<Configuration> configurations) {
this.configurations = configurations;
}
}
package net.restfulapi.app.rest.domain;
import javax.ws.rs.core.Link;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.restfulapi.app.rest.domain.common.Status;
@XmlRootElement(name="configuration")
@XmlAccessorType(XmlAccessType.FIELD)
public class Configuration
{
@XmlAttribute
private Integer id;
@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
@XmlElement
private Link link;
@XmlElement
private String content;
@XmlElement
private Status status;
public Link getLink() {
return link;
}
public void setLink(Link link) {
this.link = link;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
}
package net.restfulapi.app.rest.domain.common;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "message")
public class Message {
public Message() {
super();
}
public Message(String content) {
super();
this.content = content;
}
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
此外,我们使用ConfigurationDB
类模拟了数据库功能。它为配置资源集合和单个配置资源中的CRUD操作公开静态实用程序方法。
package net.restfulapi.app.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import net.restfulapi.app.rest.domain.Configuration;
import net.restfulapi.app.rest.domain.common.Status;
public class ConfigurationDB {
private static Map<Integer, Configuration> configurationDB = new ConcurrentHashMap<Integer, Configuration>();
private static AtomicInteger idCounter = new AtomicInteger();
public static Integer createConfiguration(String content, Status status){
Configuration c = new Configuration();
c.setId(idCounter.incrementAndGet());
c.setContent(content);
c.setStatus(status);
configurationDB.put(c.getId(), c);
return c.getId();
}
public static Configuration getConfiguration(Integer id){
return configurationDB.get(id);
}
public static List<Configuration> getAllConfigurations(){
return new ArrayList<Configuration>(configurationDB.values());
}
public static Configuration removeConfiguration(Integer id){
return configurationDB.remove(id);
}
public static Configuration updateConfiguration(Integer id, Configuration c){
return configurationDB.put(id, c);
}
}
我们已经在第二部分中了解了JAX-RS注释。让我们将它们应用于REST资源,并在REST资源上的操作上映射HTTP方法。
我在每个方法上面添加了自解释代码注释来解释它。
package net.restfulapi.app.rest.service;
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.Context;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import net.restfulapi.app.dao.ConfigurationDB;
import net.restfulapi.app.rest.domain.Configuration;
import net.restfulapi.app.rest.domain.Configurations;
import net.restfulapi.app.rest.domain.common.Message;
import net.restfulapi.app.rest.domain.common.Status;
/**
* This REST resource has common path "/configurations" and
* represents configurations collection resource as well as individual collection resources.
*
* Default MIME type for this resource is "application/XML"
* */
@Path("/configurations")
@Produces("application/xml")
public class ConfigurationResource
{
/**
* Use uriInfo to get current context path and to build HATEOAS links
* */
@Context
UriInfo uriInfo;
/**
* Get configurations collection resource mapped at path "HTTP GET /configurations"
* */
@GET
public Configurations getConfigurations() {
List<Configuration> list = ConfigurationDB.getAllConfigurations();
Configurations configurations = new Configurations();
configurations.setConfigurations(list);
configurations.setSize(list.size());
//Set link for primary collection
Link link = Link.fromUri(uriInfo.getPath()).rel("uri").build();
configurations.setLink(link);
//Set links in configuration items
for(Configuration c: list){
Link lnk = Link.fromUri(uriInfo.getPath() + "/" + c.getId()).rel("self").build();
c.setLink(lnk);
}
return configurations;
}
/**
* Get individual configuration resource mapped at path "HTTP GET /configurations/{id}"
* */
@GET
@Path("/{id}")
public Response getConfigurationById(@PathParam("id") Integer id){
Configuration config = ConfigurationDB.getConfiguration(id);
if(config == null) {
return Response.status(javax.ws.rs.core.Response.Status.NOT_FOUND).build();
}
if(config != null){
UriBuilder builder = UriBuilder.fromResource(ConfigurationResource.class)
.path(ConfigurationResource.class, "getConfigurationById");
Link link = Link.fromUri(builder.build(id)).rel("self").build();
config.setLink(link);
}
return Response.status(javax.ws.rs.core.Response.Status.OK).entity(config).build();
}
/**
* Create NEW configuration resource in configurations collection resource
* */
@POST
@Consumes("application/xml")
public Response createConfiguration(Configuration config){
if(config.getContent() == null) {
return Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.entity(new Message("Config content not found"))
.build();
}
Integer id = ConfigurationDB.createConfiguration(config.getContent(), config.getStatus());
Link lnk = Link.fromUri(uriInfo.getPath() + "/" + id).rel("self").build();
return Response.status(javax.ws.rs.core.Response.Status.CREATED).location(lnk.getUri()).build();
}
/**
* Modify EXISTING configuration resource by it's "id" at path "/configurations/{id}"
* */
@PUT
@Path("/{id}")
@Consumes("application/xml")
public Response updateConfiguration(@PathParam("id") Integer id, Configuration config){
Configuration origConfig = ConfigurationDB.getConfiguration(id);
if(origConfig == null) {
return Response.status(javax.ws.rs.core.Response.Status.NOT_FOUND).build();
}
if(config.getContent() == null) {
return Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.entity(new Message("Config content not found"))
.build();
}
ConfigurationDB.updateConfiguration(id, config);
return Response.status(javax.ws.rs.core.Response.Status.OK).entity(new Message("Config Updated Successfully")).build();
}
/**
* Delete configuration resource by it's "id" at path "/configurations/{id}"
* */
@DELETE
@Path("/{id}")
public Response deleteConfiguration(@PathParam("id") Integer id){
Configuration origConfig = ConfigurationDB.getConfiguration(id);
if(origConfig == null) {
return Response.status(javax.ws.rs.core.Response.Status.NOT_FOUND).build();
}
ConfigurationDB.removeConfiguration(id);
return Response.status(javax.ws.rs.core.Response.Status.OK).build();
}
/**
* Initialize the application with these two default configurations
* */
static {
ConfigurationDB.createConfiguration("Some Content", Status.ACTIVE);
ConfigurationDB.createConfiguration("Some More Content", Status.INACTIVE);
}
}
要使用服务器的运行时注册JAX-RS REST资源,您需要扩展javax.ws.rs.core.Application
类并将其放在应用程序的类路径中。
package net.restfulapi.app.rest;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import net.restfulapi.app.rest.service.ConfigurationResource;
@ApplicationPath("/network-management")
public class NetworkApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> empty = new HashSet<Class<?>>();
public NetworkApplication() {
singletons.add(new ConfigurationResource());
}
@Override
public Set<Class<?>> getClasses() {
return empty;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
这里的@ApplicationPath
注释将此类标识为servlet 3.0容器中自动扫描过程的REST应用程序。它有助于使web.xml
文件几乎为空 - 根本没有特定于REST的配置。
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
</web-app>
构建此项目并将其部署到任何Web服务器并启动服务器。现在通过在任何浏览器客户端上调用上面的URI来测试REST API。
获取配置集合。
HTTP GET - 配置集合资源
获取单个配置。
HTTP GET - 单个配置资源
创建新的配置资源。
HTTP POST - 创建新资源
更新配置资源。
HTTP PUT - 更新单个配置资源
删除配置资源。
HTTP DELETE - 单个配置资源
单击给定的下载链接以下载此应用程序的源代码。
Powered by RESTful API 中文网 + with by 全栈开发网. 网站地图 按Ctrl+D试试 .