我缺乏在客户端使用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");
}
}
}
我做错了什么?
答案 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。
我的解决方案:
组件
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。