问题
Consider the next code.
Filter:
public class InputFilter extends Filter {
@Override
protected int beforeHandle(Request request, Response response) {
int result = CONTINUE;
InputStream inputStream = request.getEntity().getStream();
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");
String theString = writer.toString();
JsonRepresentation jRep = new JsonRepresentation(theString);
String token = jRep.getJsonObject().getString("token");
.
.
.
return result;
}
}
Resource:
public class inputResource extends GsServerResource {
@Post
public JsonRepresentation getInput(JsonRepresentation jRep) {
String token = jRep.getJsonObject().getString("token");
.
.
.
}
}
jRep is NULL.
I use the stream once in the filter and it is closed for later use due to the fact that it is not transient
.
My current fix:
in the filter (after retrieving the Stream):
request.getAttributes().putIfAbsent("token", token);
in the resource:
String token = (String) getRequest().getAttributes().get("token");
Is there any other solution than putting the data in to the context
in the filter
and later retrieving it in the resource
?
回答1:
In fact, you can set again within the filter the entity for the request based on a StringRepresentation
based on the entity text you extracted from the request, as described below:
// Get entity text
Representation repr = request.getEntity();
String content = repr.getText();
// Use entity text
InputStream inputStream = request.getEntity().getStream();
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");
String theString = writer.toString();
JsonRepresentation jRep = new JsonRepresentation(theString);
String token = jRep.getJsonObject().getString("token");
// Set again the entity for the request
StringRepresentation sRepr = new StringRepresentation(
content, repr.getMediaType());
request.setEntity(sRepr);
Using this approach, you can read again the request entity within the resource behind the filter.
Hope it helps you, Thierry
回答2:
There is a simpler approach to write the filter:
Filter filter = new Filter(getContext()) {
@Override
protected int beforeHandle(Request request, Response response) {
try {
JsonRepresentation jrep = new JsonRepresentation(request.getEntity());
JSONObject jo = jrep.getJsonObject();
String token = jo.getString("token");
System.out.println(token);
request.setEntity(new JsonRepresentation(jo));
} catch (JSONException | IOException e) {
throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
}
return super.beforeHandle(request, response);
}
};
And actually, it would even be easier if the JsonRepresentation class persists the parsed object. I've entered an issue for this topic (https://github.com/restlet/restlet-framework-java/issues/1067). In that case, we could simply write:
Filter filter = new Filter(getContext()) {
@Override
protected int beforeHandle(Request request, Response response) {
try {
JsonRepresentation jrep = new JsonRepresentation(request.getEntity());
String token = jrep.getJsonObject().getString("token");
System.out.println(token);
request.setEntity(jrep);
} catch (JSONException | IOException e) {
throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
}
return super.beforeHandle(request, response);
}
};
来源:https://stackoverflow.com/questions/30012863/restlet-reuse-inputstream