Jersey 1.x和Tomcat:如何以编程方式(即没有web.xml的方式)注册ContainerRequestFilter?

时间:2019-08-28 16:45:40

标签: java jersey jax-rs jersey-1.0

我的应用程序

在运行于Tomcat的JAX-RS / Jersey应用程序中,我需要运行一个在每个资源方法之前实现ContainerRequestFilter的过滤器类。筛选器确定该服务现在是否可用 1 。如果我在web.xml中注册过滤器,则可以轻松完成此操作:

DataResource.java

package thepackage;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@Path("/data")
public class DataResource {

  @GET
  @Produces("application/json")
  public String getData() {
    return "{\"data\": [{\"id\": 1},{\"id\": 2}]}";
  }

}

ServiceAvailabilityFilter.java

package thepackage;

import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;
import java.util.Random;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

public class ServiceAvailabilityFilter implements ContainerRequestFilter {

  private static final Random RANDOM = new Random();

  private boolean isServiceAvailable(ContainerRequest request) {
    // Actual logic goes here; for this sample, just flip a coin
    return RANDOM.nextBoolean();
  }

  @Override
  public ContainerRequest filter(ContainerRequest request) {
    if (isServiceAvailable(request)) {
      return request;
    } else {
      throw new WebApplicationException(
          Response.serverError().type(MediaType.APPLICATION_JSON_TYPE)
              .entity("{\"error\":\"Service not available\"}").build()
      );
    }
  }

}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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/web-app_3_1.xsd"
         version="3.1">
  <servlet>
    <servlet-name>jersey</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>io.github.garysheppardjr.jersey1xfiltertest</param-value>
    </init-param>
    <init-param>
      <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
      <param-value>io.github.garysheppardjr.jersey1xfiltertest.ServiceAvailabilityFilter</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>jersey</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

我的问题

但是,我不想在XML中声明ServiceAvailabilityFilter。我想用Java代码注册它。我该怎么办?

我不想做的事

  • 在web.xml中声明过滤器。 为什么不呢?如果我以本地软件的形式提供此应用程序,则要确保有人无法通过编辑web.xml禁用我的过滤器。
  • 检查DataResource类中的服务可用性。 为什么不呢?我不想在所有资源类中编写和维护新代码。这是过滤器可以避免的一件事。
  • 从Jersey 1.x更改为Jersey2.x。 为什么不呢?我有依赖关系和截止日期,这将使迁移到Jersey 2.x非常困难。

1 您可能会问,为什么该服务不可用?没关系动用你的想象力。该逻辑与该问题无关,因此我已将其替换为Random.nextBoolean()

1 个答案:

答案 0 :(得分:1)

从web.xml中删除<servlet>元素(如果您所拥有的全部,并且至少使用Servlet API 3.0,则甚至完全删除web.xml)。要代替<servlet>元素,请创建一个扩展javax.ws.rs.core.Application的类。对于此问题,扩展com.sun.jersey.api.core.PackagesResourceConfig可能是最简单的。用javax.ws.rs.ApplicationPath注释新班级。在此类的构造函数中进行<init-param>设置。

DataResource.java :不变。

ServiceAvailabilityFilter.java :不变。

MyApplication.java (或任何您想调用的名称):

package thepackage;

import com.sun.jersey.api.core.PackagesResourceConfig;
import javax.ws.rs.ApplicationPath;

@ApplicationPath("/")
public class MyApplication extends PackagesResourceConfig {

  public MyApplication() {
    // "com.sun.jersey.config.property.packages" init-param
    super(DataResource.class.getPackageName());
    // "com.sun.jersey.spi.container.ContainerRequestFilters" init-param
    getContainerRequestFilters().add(ServiceAvailabilityFilter.class);
  }

}

web.xml :至少删除<servlet>元素,或者您可以完全删除文件。