Мое приложение
В моем приложении JAX-RS/Jersey, работающем в Tomcat, мне нужно запустить класс фильтра, который реализует 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>
Мой вопрос
Однако я не хочу объявлять ServiceAvailabilityFilter
в XML. Я хочу зарегистрировать его в коде Java. Как бы я это сделал?
Вещи, которые я бы предпочел не делать
- Объявите фильтр в файле web.xml. Почему бы и нет? Если я поставлю это приложение как локальное программное обеспечение, я хочу убедиться, что кто-то не сможет отключить мой фильтр, отредактировав файл web.xml.
- Проверить наличие услуги в классе
DataResource
. Почему бы и нет? Я не хочу писать и поддерживать новый код во всех своих классах ресурсов. Этого можно избежать с помощью фильтров. - Переход с Джерси 1.x на Джерси 2.x. Почему бы и нет? У меня есть зависимости и крайние сроки, которые сделают переход на Jersey 2.x очень сложным.
1 Вы можете спросить, почему служба может быть недоступна? Это не имеет значения. Использовать ваше воображение. Эта логика не имеет отношения к этому вопросу, поэтому я заменил ее на Random.nextBoolean()
.