Фильтры запроса Dropwizard с шаблоном URI
Я создаю RESTful-приложение в Dropwizard. При подключении к базе данных, я хочу настроить UserNotFoundFilter
который реализует ContainerRequestFilter
так что входящие запросы сначала проходят через этот фильтр.
Идея состоит в том, что я хотел бы, чтобы этот конкретный фильтр отображался только на определенные шаблоны URI. Например, я хочу, чтобы фильтр применялся только к /users/*
и ничего больше. Есть ли способ сделать это, не прибегая к пользовательским аннотациям и реализации с DynamicFeature
?
@Provider
public class UserNotFoundFilter implements ContainerRequestFilter {
@Context
UriInfo uriInfo;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
MultivaluedMap pathParams = uriInfo.getPathParameters(); // Should contain (uid: 1) pair for /users/1
boolean userExists = // check against the database using above pathparam pair to see if user exists
if (!userExists)
throw new WebApplicationException("User does not exist", Status.NOT_FOUND);
// let the request through as user exists
}
}
Мой класс UserResource
public class UserResource {
@GET
@Path("/users/{uid}")
@Produces(MediaType.APPLICATION_JSON)
public User getUser(@PathParam("uid") String uid) {
// Now I don't need to do the check here !
// boolean userExists = check against database using uid path param
// if (!userExists)
// throw new WebApplicationException("User does not exist", Status.NOT_FOUND);
return database.getUser(uid);
}
}
Мой класс ItemResource
public class ItemResource {
@GET
@Path("/items/{uid}")
@Produces(MediaType.APPLICATION_JSON)
public Item getItem(@PathParam("uid") String uid) {
return database.getItem(uid);
}
}
Что я пытаюсь сделать
public class MyApplication extends Application<MyConfiguration> {
// ...
@Override
public void run(MyConfiguration config, Environment environment) throws Exception {
// ... do other things, register resources
// this pseudocode, the UserNotFoundFilter only applies to URIs of the kind /users/*
environment.jersey().register(new UserNotFoundFilter()).forUriPattern("/users/*");
Я ценю любые примеры кода.
2 ответа
За Servlet
фильтр -
Вероятно, вы ищете addMappingForUrlPatterns
от javax.servlet.FilterRegistration
интерфейс, который будет использоваться в вашем run()
как -
environment.servlets().addFilter("FilterName", UserNotFoundFilter.class)
.addMappingForUrlPatterns(EnumSet
.allOf(DispatcherType.class), true, "/users/*");
Подпись использованного выше способа -
public void addMappingForUrlPatterns(
EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter,
String... urlPatterns);
Редактировать - для динамического связывания:
Попробуйте и используйте DynamicFeature
как
@Provider
public class UserNotFoundDynamicFilter implements DynamicFeature {
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext featureContext) {
if (resourceInfo.getResourceMethod().getAnnotation(UserRequired.class) != null) {
featureContext.register(UserNotFoundFilter.class);
}
}
}
где вы можете определить UserRequired
аннотация как -
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserRequired {
}
и в пределах ваших ресурсов отметьте все /users/*
API с той же аннотацией, что и -
@GET
@Path("/users/{uid}")
@Produces(MediaType.APPLICATION_JSON)
@UserRequired
public User getUser(@PathParam("uid") String uid) {
// Now I don't need to do the check here !
// boolean userExists = check against database using uid path param
// if (!userExists)
// throw new WebApplicationException("User does not exist", Status.NOT_FOUND);
return database.getUser(uid);
}
Источник - трикотажные фильтры
Вы получите кучу полезных вещей в ((ContainerRequest) requestContext).getUriInfo()
например, для соответствия /users/*
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String uriTemplate = ((ContainerRequest) requestContext).getUriInfo().getMatchedTemplates().stream().map(o -> o.getTemplate()).reduce("", (acc, template) -> template + acc);
if (uriTemplate == "/users/{id}") {
// matched!
}
String path = ((ContainerRequest) requestContext).getUriInfo().getPath();
if (path.startsWith("users/")) {
// matched!
}
}
Получить фактического пользователя id
аналогичным образом для поиска вашей БД.