Java 在'中动态绑定过滤器;我不为次级资源工作
我创建了一个Jersey过滤器,需要将其分配给一些资源(不是全部)。因此,我使用动态绑定来实现这一点Java 在'中动态绑定过滤器;我不为次级资源工作,java,rest,jax-rs,jersey-2.0,Java,Rest,Jax Rs,Jersey 2.0,我创建了一个Jersey过滤器,需要将其分配给一些资源(不是全部)。因此,我使用动态绑定来实现这一点 public class MyDynamicFeature implements DynamicFeature { @Override public void configure(ResourceInfo resourceInfo, FeatureContext featureContext) { Path resourcePath = resourceInfo
public class MyDynamicFeature implements DynamicFeature {
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext featureContext) {
Path resourcePath = resourceInfo.getResourceClass().getAnnotation(Path.class);
if (resourcePath != null && resourcePath.value().contains("/v2/"))
{
featureContext.register(MyFilter.class);
}
}
}
所以我希望这个过滤器应用于那些资源中的所有方法,这些方法的路径中包含特定的字符串。其中一些资源使用子资源定位器来定义子资源。例如:
@Path("/v2/resource_path")
@Consumes({ ... })
@Produces({ ... })
class MyResource
{
@Path("/subresource_path")
public MySubResource getSubResource(@Context ResourceContext rc)
{
return rc.getResource(MySubResource.class);
}
}
即使泽西岛的文件声称
对于应用程序中定义的每个资源方法,configure方法将执行一次
上面显示的MyDynamicFeature
中的configure
方法根本没有被MyResource
类的getSubResource
方法调用。但是,MyResource
类中的所有其余方法都会调用它(我在示例中省略了它)
有没有一种方法可以让次级资源发挥作用?我还需要将我的筛选器应用于MySubResource
我们使用Jersey 2.21。退房。我不确定目前是否可行。如果您在特性中添加一些日志来记录方法和类,您将看到子资源方法永远不会被遍历。正如Marek在本期文章中所解释的,这是因为为了处理这个问题,需要调用子资源定位器方法,而这从来都不是
唯一的解决办法是改用。我已经测试过了,它可以工作(见下文)。其思想是制作一个自定义注释,并注释要过滤的过滤器、资源类和子资源类。比如说
@NameBinding
@Target({METHOD, TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeAnno {}
@SomeAnno
public class Filter implements ContainerRequestFilter {}
@SomeAnno
@Path("v2")
public class V2Resource {
@Path("sub")
public V2SubResource get() {
return new V2SubResource();
}
@SomeAnno
public static class V2SubResource {
@GET
public String get() { return "get"; }
}
}
上面将绑定V2Resource
以及V2SubResource
中的所有资源方法
下面是一个使用的完整示例。像其他JUnit测试一样运行它
更新:请注意,对于以下测试,对于Jersey的当前(2.26)版本,由于筛选器中返回了1000状态代码,版本2资源的测试将挂起。我想泽西不喜欢这个。要解决这个问题,只需将过滤器中的状态代码更改为500,并相应地修复测试断言以测试500状态代码
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.logging.Logger;
import javax.ws.rs.GET;
import javax.ws.rs.NameBinding;
import javax.ws.rs.Path;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* Stack Overflow question http://stackoverflow.com/q/36878817/2587435
*
* Run this like any other JUnit test. Only one required test dependency
*
* <dependency>
* <groupId>org.glassfish.jersey.test-framework.providers</groupId>
* <artifactId>jersey-test-framework-provider-inmemory</artifactId>
* <version>${jersey2.version}</version>
* </dependency>
*
* @author Paul Samsotha
*/
public class DynamicSubresourceTest extends JerseyTest {
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public static @interface Status1000 {}
@Provider
@Status1000
public static class Status1000Filter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext context) throws IOException {
context.abortWith(Response.status(500).build());
}
}
@Path("v1")
public static class V1Resource {
@GET
public String get() {
return "v1";
}
@Path("sub")
public V1SubResource getSub() {
return new V1SubResource();
}
public static class V1SubResource {
@GET
public String get() {
return "v1subresource";
}
}
}
@Path("v2")
@Status1000
public static class V2Resource {
@GET
public String get() {
return "v2";
}
@Path("sub")
public V2SubResource getSub() {
return new V2SubResource();
}
@Status1000
public static class V2SubResource {
@GET
public String get() {
return "v2subresource";
}
}
}
@Override
public ResourceConfig configure() {
return new ResourceConfig(V1Resource.class, V2Resource.class)
.property(ServerProperties.WADL_FEATURE_DISABLE, true)
.register(Status1000Filter.class)
.register(new LoggingFilter(Logger.getAnonymousLogger(), true));
}
@Test
public void should_return_1000_for_v2_resource_method() {
final Response response = target("v2").request().get();
assertThat(response.getStatus(), is(500));
}
@Test
public void should_return_1000_for_v2_subresource_locator() {
final Response response = target("v2/sub").request().get();
assertThat(response.getStatus(), is(500));
}
@Test
public void should_return_data_for_v1_resource_method() {
final Response response = target("v1").request().get();
assertThat(response.getStatus(), is(200));
assertThat(response.readEntity(String.class), is("v1"));
}
@Test
public void should_return_data_for_v1_subresource_locator() {
final Response response = target("v1/sub").request().get();
assertThat(response.getStatus(), is(200));
assertThat(response.readEntity(String.class), is("v1subresource"));
}
}
import java.io.IOException;
导入java.lang.annotation.ElementType;
导入java.lang.annotation.Retention;
导入java.lang.annotation.RetentionPolicy;
导入java.lang.annotation.Target;
导入java.util.logging.Logger;
导入javax.ws.rs.GET;
导入javax.ws.rs.NameBinding;
导入javax.ws.rs.Path;
导入javax.ws.rs.container.ContainerRequestContext;
导入javax.ws.rs.container.ContainerRequestFilter;
导入javax.ws.rs.core.Response;
导入javax.ws.rs.ext.Provider;
导入org.glassfish.jersey.filter.LoggingFilter;
导入org.glassfish.jersey.server.ResourceConfig;
导入org.glassfish.jersey.server.ServerProperties;
导入org.glassfish.jersey.test.JerseyTest;
导入org.junit.Test;
导入静态org.hamcrest.CoreMatchers.is;
导入静态org.junit.Assert.assertThat;
/**
*堆栈溢出问题http://stackoverflow.com/q/36878817/2587435
*
*像其他JUnit测试一样运行此测试。只有一个必需的测试依赖项
*
*
*org.glassfish.jersey.test-framework.providers
*jersey测试框架提供程序inmemory
*${jersey2.version}
*
*
*@作者保罗·桑索塔
*/
公共类DynamicSubresourceTest扩展了JerseyTest{
@姓名绑定
@保留(RetentionPolicy.RUNTIME)
@目标({ElementType.METHOD,ElementType.TYPE})
公共静态@interface Status1000{}
@提供者
@状态1000
公共静态类Status1000Filter实现ContainerRequestFilter{
@凌驾
公共无效筛选器(ContainerRequestContext上下文)引发IOException{
abortWith(Response.status(500.build());
}
}
@路径(“v1”)
公共静态类资源{
@得到
公共字符串get(){
返回“v1”;
}
@路径(“sub”)
公共V1SubResource getSub(){
返回新的V1SubResource();
}
公共静态类v1子资源{
@得到
公共字符串get(){
返回“v1subresource”;
}
}
}
@路径(“v2”)
@状态1000
公共静态类V2Resource{
@得到
公共字符串get(){
返回“v2”;
}
@路径(“sub”)
公共V2SubResource getSub(){
返回新的V2SubResource();
}
@状态1000
公共静态类V2SubResource{
@得到
公共字符串get(){
返回“v2subresource”;
}
}
}
@凌驾
公共资源配置(){
返回新的ResourceConfig(V1Resource.class、V2Resource.class)
.property(ServerProperties.WADL\u功能禁用,true)
.寄存器(Status1000Filter.class)
.register(新的LoggingFilter(Logger.getAnonymousLogger(),true));
}
@试验
public void应返回\u 1000\u,用于\u v2\u资源\u方法(){
最终响应=目标(“v2”).request().get();
断言(response.getStatus(),为(500));
}
@试验
public void应该返回\u 1000\u,用于\u v2\u子资源\u定位器(){
最终响应=目标(“v2/sub”).request().get();
断言(response.getStatus(),为(500));
}
@试验
public void应该返回资源方法()的数据{
最终响应=目标(“v1”).request().get();
断言(response.getStatus(),为(200));
断言(response.readEntity(String.class)为(“v1”);
}
@试验
public void应返回\u v1\u子资源\u定位器()的\u数据{
最终响应=目标(“v1/sub”).request().get();
断言(response.getStatus(),为(200));
资产(response.readEntity(String.class)为(“v1subresource”);
}
}
退房。我不确定目前是否可行。如果你加些日志