Последние пару дней я играл с Джерси, и я хотел создать одну точку входа или индекс, в котором перечислены все мои ресурсы, доступные пути и глаголы, которые они приняли.
Гвидо Симоне объяснил изящный способ поиска путей и глаголов для конкретного ресурса, используя Джерси IntrospectionModeller :
AbstractResource resource = IntrospectionModeller.createResource(JacksonResource.class);
System.out.println("Path is " + resource.getPath().getValue());
String uriPrefix = resource.getPath().getValue();
for (AbstractSubResourceMethod srm :resource.getSubResourceMethods())
{
String uri = uriPrefix + "/" + srm.getPath().getValue();
System.out.println(srm.getHttpMethod() + " at the path " + uri + " return " + srm.getReturnType().getName());
}
Если мы запустим , что против Д4-минимального «s JacksonResource класса мы получаем следующий результат:
Path is /jackson
GET at the path /jackson/{who} return com.g414.j4.minimal.JacksonResource$Greeting
GET at the path /jackson/awesome/{who} return javax.ws.rs.core.Response
Это довольно здорово, но я не хотел вручную перечислять все свои ресурсы, так как я уже сделал это с помощью Guice.
Мне нужен был способ получить их программно, и я частично нашел способ сделать это из этого поста, который предлагает использовать Application.getSingletons () .
Я на самом деле в конечном итоге с помощью Application.getClasses () и я в конечном итоге с ResourceListingResource :
@Path("/")
public class ResourceListingResource
{
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response showAll( @Context Application application,
@Context HttpServletRequest request)
{
String basePath = request.getRequestURL().toString();
ObjectNode root = JsonNodeFactory.instance.objectNode();
ArrayNode resources = JsonNodeFactory.instance.arrayNode();
root.put( "resources", resources );
for ( Class<?> aClass : application.getClasses() )
{
if ( isAnnotatedResourceClass( aClass ) )
{
AbstractResource resource = IntrospectionModeller.createResource( aClass );
ObjectNode resourceNode = JsonNodeFactory.instance.objectNode();
String uriPrefix = resource.getPath().getValue();
for ( AbstractSubResourceMethod srm : resource.getSubResourceMethods() )
{
String uri = uriPrefix + "/" + srm.getPath().getValue();
addTo( resourceNode, uri, srm, joinUri(basePath, uri) );
}
for ( AbstractResourceMethod srm : resource.getResourceMethods() )
{
addTo( resourceNode, uriPrefix, srm, joinUri( basePath, uriPrefix ) );
}
resources.add( resourceNode );
}
}
return Response.ok().entity( root ).build();
}
private void addTo( ObjectNode resourceNode, String uriPrefix, AbstractResourceMethod srm, String path )
{
if ( resourceNode.get( uriPrefix ) == null )
{
ObjectNode inner = JsonNodeFactory.instance.objectNode();
inner.put("path", path);
inner.put("verbs", JsonNodeFactory.instance.arrayNode());
resourceNode.put( uriPrefix, inner );
}
((ArrayNode) resourceNode.get( uriPrefix ).get("verbs")).add( srm.getHttpMethod() );
}
private boolean isAnnotatedResourceClass( Class rc )
{
if ( rc.isAnnotationPresent( Path.class ) )
{
return true;
}
for ( Class i : rc.getInterfaces() )
{
if ( i.isAnnotationPresent( Path.class ) )
{
return true;
}
}
return false;
}
}
Единственное изменение, которое я сделал из решения Гвидо Симона, это то, что я также вызываю resource.getResourceMethods (), потому что resource.getSubResourceMethods () возвращает только те методы, которые имеют аннотацию @Path .
Поскольку мы иногда определяем наш путь на уровне класса, а затем определяем различные глаголы, которые оперируют с этим ресурсом, он пропускает некоторые методы.
Если мы запустим команду cURL ( пропущенную через python, чтобы она выглядела хорошо ) против корня, мы получим следующий вывод:
$ curl http://localhost:8080/ -w "\n" 2>/dev/null | python -mjson.tool
{
"resources": [
{
"/bench": {
"path": "http://localhost:8080/bench",
"verbs": [
"GET",
"POST",
"PUT",
"DELETE"
]
}
},
{
"/sample/{who}": {
"path": "http://localhost:8080/sample/{who}",
"verbs": [
"GET"
]
}
},
{
"/jackson/awesome/{who}": {
"path": "http://localhost:8080/jackson/awesome/{who}",
"verbs": [
"GET"
]
},
"/jackson/{who}": {
"path": "http://localhost:8080/jackson/{who}",
"verbs": [
"GET"
]
}
},
{
"/": {
"path": "http://localhost:8080/",
"verbs": [
"GET"
]
}
}
]
}