ZetCode

Jersey 应用程序中的 Web URL

最后修改于 2020 年 7 月 13 日

在本教程中,我们将创建一个检查传入 URL 的 RESTful Java Web 应用程序。该应用程序使用 Jersey。

统一资源定位符 (URL) 是对 Web 资源的引用,它指定了其在计算机网络上的位置以及检索它的机制。Web 资源是通过 Web 可获得的任何数据,例如 HTML 文档、PDF 文件、PNG 图像、JSON 数据或纯文本。

通用 URL 的形式如下:

scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]

方括号表示该部分是可选的。Scheme 是寻址资源的方式,例如 http、ftp、mailto 或 file。

两个斜杠后面的部分称为 authority 部分。authority 部分包含 1) 一个可选的身份验证部分,包含用户名和密码,用冒号分隔,后跟一个 at 符号 (@);2) 一个主机,即主机名或 IP 地址;3) 一个可选的端口号,用冒号与主机分隔。

Path 是主机上资源的路径。它可能看起来像文件系统路径,也可能与文件系统路径完全不匹配。Query string 用于为资源请求添加一些条件。它通常是一系列的键/值对。最后一部分是可选的 fragment,它指向一个二级资源,例如标题。它用哈希符号 (#) 与查询字符串分隔。

使用 Jersey 的 RESTful 应用程序

在下面的 RESTful 应用程序中,我们将检索 URL 的各个部分并将其返回给客户端。我们使用 Jersey,这是一个用于在 Java 中开发 RESTful Web 服务的开源框架。它是 RESTful Web Services Java API (JAX-RS) 规范的参考实现。

$ tree
.
├── nb-configuration.xml
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── app
    │   │           │   └── ApplicationConfig.java
    │   │           └── restex
    │   │               └── MyInfo.java
    │   ├── resources
    │   └── webapp
    │       ├── index.html
    │       ├── META-INF
    │       │   └── context.xml
    │       └── WEB-INF
    └── test
        └── java

这是项目结构。

pom.xml
<?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>RestEx</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>RestEx</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>

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>2.25</version>
        </dependency>
        
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>2.25</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins> 
    </build>
</project>

这是 Maven POM 文件。它包含 Jersey 所需的依赖项。

context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/RestEx"/>

在 Tomcat 的 context.xml 配置文件中,我们定义了应用的上下文路径。

com/zetcode/ApplicationConfig.java
package com.zetcode.app;

import com.zetcode.restex.MyInfo;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("rest")
public class ApplicationConfig extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> set = new HashSet<>();
        set.add(MyInfo.class);
        return set;
    }
}

这是应用程序配置类。自 Servlet 3.0 起,无需 web.xml 文件即可部署应用程序 — 在 Jersey 中,我们创建一个扩展抽象 Application 的配置类,并使用 @ApplicationPath 注解。Application 定义了 JAX-RS 应用程序的组件并提供其他元数据。在这里,我们注册应用程序所需的资源类、提供程序或属性。

@ApplicationPath("rest")

使用 @ApplicationPath 注解,我们设置了 REST Web 服务的路径。

@Override
public Set<Class<?>> getClasses() {
    Set<Class<?>> set = new HashSet<>();
    set.add(MyInfo.class);
    return set;
}

getClasses 方法中,我们添加了资源类。在本例中,我们有一个 MyInfo 类。

com/zetcode/MyInfo.java
package com.zetcode.restex;

import java.net.URI;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;

@Path("mypath")
public class MyInfo {

    @Context
    private UriInfo info;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getInfo() {
        
        URI uri = info.getRequestUri();
        
        int port = uri.getPort();
        String path = uri.getPath();
        String query = uri.getQuery();
        String host = uri.getHost();
        String scheme = uri.getScheme();
        
        String fmt = "Scheme: %s%nHost: %s%nPort: %s%nPath: %s%nQuery: %s%n";
        
        String out = String.format(fmt, scheme, host, port, 
                path, query);

        return out;
    }
}

这是资源类。

@Path("mypath")
public class MyInfo {

@Path 注解指定了资源响应的 URL 路径。

@Context
private UriInfo info;

使用 @Context 注解,我们注入了 UrlInfo 对象。它提供了对应用程序和请求 URL 信息的访问。

@GET
@Produces(MediaType.TEXT_PLAIN)

@GET 注解表示该方法响应 HTTP GET 请求。@Produces 注解定义了资源类的方法可以生成的媒体类型。在本例中,getInfo 方法返回纯文本。

URI uri = info.getRequestUri();

我们使用 getRequestUri 方法获取 URI。

int port = uri.getPort();
String path = uri.getPath();
String query = uri.getQuery();
String host = uri.getHost();
String scheme = uri.getScheme();

我们检索 URL 的端口、路径、查询、主机和 scheme 部分。

$ curl https://:8084/RestEx/rest/mypath?name=Jan
Scheme: http
Host: localhost
Port: 8084
Path: /RestEx/rest/mypath
Query: name=Jan

我们使用 curl 工具测试应用程序。

在本教程中,我们更深入地研究了 URL。我们使用 Jersey 创建了一个 Java RESTful 应用程序,并识别了传入 URL 的各个部分。