簡體   English   中英

Restlet Client ::如何添加過濾器?

[英]Restlet Client :: how to add filters?

我缺乏在客戶端使用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");
        }
    }
}

我究竟做錯了什么?

我從一位同事那里得到了更好的回答。 我在這里發布文檔。

解決方案是使用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來滿足類似的需求

要讓客戶端工作,您需要將應用程序從圖片中取出,因為它是根據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中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM