Restlet Client ::如何添加过滤器?

时间:2014-10-15 19:59:36

标签: java restlet restlet-2.0

我缺乏在客户端使用Restlet的文档。 我通过ClientResource在服务器上获取资源:

new ClientResource(url).get();

但是服务器可以返回ETag标头。为了解决这个问题,我想在返回时保存ETag,并在使用相同的url时将其发送回服务器。 目前我这样做:

ClientResource clientResource = new ClientResource(url);
addEtag(url, clientResource); // add the cached ETag to the query if any
clientResource.get();
saveEtag(url, clientResource); // cache the ETag if any

我想使用Restlet框架来做到这一点。我正在寻找没有理解缺失环节的日子。 我可以扩展一个应用程序,覆盖createOutboundRoot()方法并返回一个过滤器:

public class RestLetClient extends Application {

    private Client client;

    // instantiation of the client and other things here

    @Override
    public Restlet createOutboundRoot() {
        return new Filter(getContext(), client){

            @Override
            protected int beforeHandle(Request request, Response response) {
                addEtag(request);
                return super.doHandle(request, response);
            }

            @Override
            protected void afterHandle(Request request, Response response) {
                saveEtag(request, reponse);
                return super.afterHandle(request, response);
            }
        };
    }
}

但是如何从我的业务代码中围绕Restlet客户端使用此过滤?

修改

到目前为止我能够工作的最好的是:

Request request = new Request(Method.GET, uri);
//the filter created in original post
filter.handle(request).getEntity();

这有效,但它未集成在框架中。我要做的是在客户端,只有服务器端记录的内容。在服务器上,你会这样做:

public class ServerApplication extends Application {

    @Override
    public Restlet createInboundRoot() {
        Router router = new Router(getContext());
        router.attach(GET_URL, GetResource.class);
        return router;
    }
}

然后启动服务器。应用程序将在URL上接收GET请求时触发 客户端的等价物是什么?如何触发客户端应用程序?如果我在客户端运行了一个应用程序,我可以很好地添加它们属于REST应用程序的过滤器

编辑2

当尝试在应用程序中运行我的客户端时,我收到错误:过滤器org.restlet.engine.application.RangeFilter@f372a7a在没有附加下一个Restlet的情况下执行。

以下是我收到错误的方法。我有一个扩展Application的类,它从JUnit测试中调用:

public class RestLetClient extends Application {

    private final Client client;

    Logger logger = LoggerFactory.getLogger(getClass());

    public RestLetClient() {
        this.client = new Client(Protocol.HTTP);
    }

    public Representation get(final String uri) throws Exception {

        Request request = new Request(Method.GET, uri);
        Response response = handle(request);
        return response.getEntity();
    }

    @Override
    public Restlet createOutboundRoot() {
        return new Filter(getContext(), client) {
            @Override
            protected int beforeHandle(Request request, Response response) {
                addEtagFilter(request);
                return super.beforeHandle(request, response);
            }

            @Override
            protected void afterHandle(Request request, Response response) {
                saveEtagFilter(request, response);
                super.afterHandle(request, response);
            }
        };
    }

    private void saveEtagFilter(Request request, Response response) {
        logger.debug("saving etag");
    }

    private void addEtagFilter(Request request) {
        logger.debug("adding etag");
    }
}

和单一测试方法的单位:

public class RestLetClientTest {

    public static final String URL = "http://localhost:8123/resource";

    private RestLetClient instance;

    private Server server;

    @Before
    public void setUp() throws Exception {
        server = new Server(Protocol.HTTP, 8123, new TestApplication());

        server.start();

        instance = new RestLetClient();
        instance.start();
    }

    @After
    public void tearDown() throws Exception {
        instance.stop();
    }

    @Test
    public void testGet() throws Exception {
        Representation representation = instance.get(URL);
        System.out.println(representation.getText());
    }

    private class TestApplication extends Application {
        @Override
        public Restlet createInboundRoot() {
            return new Router().attach(RestLetClientTest.URL, GetResource.class);
        }
    }

    private class GetResource extends ServerResource {
        @Get
        public Representation getResource() {
            return new StringRepresentation("hello world");
        }
    }
}

我做错了什么?

2 个答案:

答案 0 :(得分:2)

我从一位同事那里得到了更好的回答。我在这里发布文档。

解决方案是使用ClientResource,Filter和Client。 Filter成为ClientResource的next(),Client成为Filter的next()。

public class ETagFilter extends Filter {

    @Override
    protected int beforeHandle(Request request, Response response) {
        addEtag(request);
        return super.beforeHandle(request, response);
    }

    @Override
    protected void afterHandle(Request request, Response response) {
        saveEtag(request, reponse);
        super.afterHandle(request, response);
    }
}

public class RestLetClient extends Application {

    public Representation get(final String uri) throws Exception {

        Client client = new Client(Protocol.HTTP);
        ETagFilter eTagFilter = new ETagFilter();
        clientResource = new ClientResource(uri);

        clientResource.setNext(eTagFilter);
        eTagFilter.setNext(client);

        return clientResource.get(halMediaType);
    }
}

有关信息。在我的OP中,我试图将服务器端的代码转换为客户端。这种做法是错误的。我的同事指出,这种方法更类似于使用Apache HttpClient来满足类似的需求

答案 1 :(得分:1)

要使客户端工作,您需要将应用程序从图片中删除,因为它是根据javadoc面向服务器的。

您需要的是Component,ClientRouter和自定义ClientRoute。

  • 组件管理连接器。 Restlet Client是一个连接器。
  • ClientRouter将调度到客户端连接器。
  • ClientRoute扩展了Filter,允许在您的客户端处添加过滤器。

我的解决方案:
组件

public class RestLetComponent extends Component {

    public RestLetComponent(Client client) {
        getClients().add(client);
    }
}

ClientRouter

public class RestLetClientRouter extends ClientRouter {

    public RestLetClientRouter(final Client client) {
        super(new RestLetComponent(client));
        ClientRoute clientRoute = new RestLetClientRoute(this, client);
        //forcing to use only our custom route
        getRoutes().clear();
        getRoutes().add(clientRoute);
    }

    public Representation get(final String uri) throws Exception {
        Request request = new Request(Method.GET, uri);
        Response response = handle(request);
        return response.getEntity();
    }
}

将添加过滤器的自定义ClientRoute

public class RestLetClientRoute extends ClientRoute {

    Logger logger = LoggerFactory.getLogger(getClass());

    public RestLetClientRoute(Router router, Client client) {
        super(router, client);
    }

    //the filters
    @Override
    protected int beforeHandle(Request request, Response response) {
        addEtagFilter(request);
        return super.beforeHandle(request, response);
    }

    @Override
    protected int doHandle(Request request, Response response) {
        logger.debug("handling request: " + request.getMethod() + " - " + request.getResourceRef());
        return super.doHandle(request, response);
    }

    @Override
    protected void afterHandle(Request request, Response response) {
        saveEtagFilter(request, response);
        super.afterHandle(request, response);
    }

    private void saveEtagFilter(Request request, Response response) {
        logger.debug("saving etag");
    }

    private void addEtagFilter(Request request) {
        logger.debug("adding etag");
    }
}

最后但并非最不重要的是,我向Restlet的作者道歉,文档就在那里。我正在阅读Restlet in Action一书,但答案就在于javadoc。