J'ai utilisé jersey pour créer des services Web. J'ai créé un filtre de requête à l'aide de ContainerRequestFilter
. J'ai traversé Jersey Request Filter uniquement sur certaines URI question mais je souhaite exclure le filtre pour certaines URL uniquement.
@Provider
public class AuthFilter implements ContainerRequestFilter{
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// business logic
}
}
Au lieu d'exclure les URI d'un filtre global, vous pouvez envisager d'utiliser un filtre de liaison de noms pour sélectionner les points d'extrémité auxquels votre filtre sera lié.
Vérifiez également cette réponse pour quelques exemples avec des filtres de liaison de noms.
Si vous êtes toujours satisfait de l'approche du filtre global, vous pouvez envisager d'utiliser l'interface UriInfo
pour obtenir des détails sur l'URI demandé. Utilisez l’une des approches suivantes pour obtenir une instance de UriInfo
:
Utilisation de @Context
annotation:
@Provider
public class AuthFilter implements ContainerRequestFilter {
@Context
private UriInfo info;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
...
}
}
Obtenir de la ContainerRequestContext
:
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
UriInfo info = requestContext.getUriInfo();
...
}
Une fois que vous avez l'instance UriInfo
, vous aurez accès à un tas de méthodes qui peuvent être utiles:
getAbsolutePath()
: Obtenir le chemin absolu de la demande.getBaseUri()
: Obtenir l'URI de base de l'application.getMatchedResources()
: Obtenir une liste en lecture seule des instances de la classe de ressources actuellement correspondantes.getMatchedURIs()
: Obtenir une liste en lecture seule des adresses URI des ressources correspondantes.getPath()
: Récupère le chemin de la requête en cours par rapport à l'URI de base sous forme de chaîne.getPathSegments()
: Obtenir le chemin de la requête en cours par rapport à l'URI de base sous la forme d'une liste de PathSegment
.getRequestUri()
: Extrait l'URI de la demande absolue, y compris les paramètres de la requête.relativize(URI)
: Relativise un URI par rapport à l'URI de la demande actuelle.resolve(URI)
: Résout un URI relatif par rapport à l'URI de base de l'application.Pour plus de détails, consultez la documentation UriInfo
.
Si l'URI demandé ne correspond pas à l'URI auquel vous souhaitez appliquer le filtre, utilisez simplement une instruction return
:
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
UriInfo info = requestContext.getUriInfo();
if (!info.getPath().contains("secured")) {
return;
}
}
Une autre approche est liaison dynamique. Il vous permet d'affecter des filtres et des intercepteurs aux méthodes de ressource de manière dynamique. La liaison de noms, mentionnée ci-dessus, utilise une approche statique et les modifications de liaison nécessitent une modification et une recompilation du code source. Avec la liaison dynamique, vous pouvez implémenter un code qui définit les liaisons lors de l’initialisation de l’application.
L'exemple suivant extrait de la documentation Jersey montre comment implémenter une liaison dynamique:
@Path("helloworld")
public class HelloWorldResource {
@GET
@Produces("text/plain")
public String getHello() {
return "Hello World!";
}
@GET
@Path("too-much-data")
public String getVeryLongString() {
String str = ... // very long string
return str;
}
}
// This dynamic binding provider registers GZIPWriterInterceptor
// only for HelloWorldResource and methods that contain
// "VeryLongString" in their name. It will be executed during
// application initialization phase.
public class CompressionDynamicBinding implements DynamicFeature {
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
if (HelloWorldResource.class.equals(resourceInfo.getResourceClass())
&& resourceInfo.getResourceMethod().getName().contains("VeryLongString")) {
context.register(GZIPWriterInterceptor.class);
}
}
}
La liaison est effectuée à l'aide du fournisseur qui implémente l'interface DynamicFeature
. L'interface définit une méthode configure
avec deux arguments, ResourceInfo
et FeatureContext
.
ResourceInfo
contient des informations sur la ressource et la méthode avec lesquelles la liaison peut être effectuée. La méthode configure sera exécutée une fois pour chaque méthode de ressource définie dans l'application. Dans l'exemple ci-dessus, le fournisseur sera exécuté deux fois, une fois pour la méthode getHello()
et une fois pour getVeryLongString()
(une fois que resourceInfo
contiendra des informations sur la méthode getHello()
et une fois qu'il pointera sur getVeryLongString()
).
Si un fournisseur de liaison dynamique souhaite inscrire un fournisseur pour la méthode de ressource réelle, il le fera à l'aide de FeatureContext
qui étend l'API configurable JAX-RS. Toutes les méthodes d'enregistrement de classes ou d'instances de filtre ou d'intercepteur peuvent être utilisées. Ces filtres ou intercepteurs enregistrés dynamiquement ne seront liés qu'à la méthode de ressource réelle. Dans l'exemple ci-dessus, la GZIPWriterInterceptor
sera liée uniquement à la méthode getVeryLongString()
, ce qui entraînera la compression des données uniquement pour cette méthode et non pour la méthode getHello()
.
Notez que les filtres et les intercepteurs enregistrés à l'aide de la liaison dynamique ne sont que des filtres supplémentaires exécutés pour la méthode de ressource. S'il existe des fournisseurs liés par un nom ou des fournisseurs globaux, ils seront toujours exécutés.
Pour plus de détails, consultez la documentation Jersey sur les filtres et les intercepteurs .
Utiliser @NameBinding peut être l'approche la plus élégante, mais si vous souhaitez simplement exclure une ressource unique et appliquer le filtre sur toutes les autres, vous devez vous rappeler de mettre l'annotation de liaison sur toutes les ressources. Dans ce cas, vous pouvez utiliser ContainerRequestContext.getUriInfo().getMatchedResources()
pour vérifier si la ressource cible a été mise en correspondance. C'est mieux que de coder en dur un chemin qui pourrait changer.
L'exemple ci-dessous appliquera la logique de filtrage à toutes les ressources sauf StatusResource:
public class CorsContainerRequestFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext req) {
if (!matchesStatusResource(req)) {
// filter logic
}
}
private boolean matchesStatusResource(ContainerRequestContext req) {
List<Object> matchedResources = req.getUriInfo().getMatchedResources();
for (Object matchedResource : matchedResources) {
if (matchedResource instanceof StatusResource) {
return true;
}
}
return false;
}
}
Comme mentionné par d'autres, les liaisons dynamiques peuvent être utilisées à la place, mais c'est assez moche, car il n'est pas évident que le filtre ne soit pas appliqué à toutes les ressources.