19

RestEasy サービスのすべての公開/利用可能なエンドポイントを簡単な方法でリストすることは可能ですか?

4

5 に答える 5

7

を公​​開する RestEasy プラグイン「stats」があり.../resteasy/registryます。

に登録する必要がありますweb.xml:

<context-param>
    <param-name>resteasy.resources</param-name>
    <param-value>org.jboss.resteasy.plugins.stats.RegistryStatsResource</param-value>
</context-param>

応答例:

<registry>
    <resource uriTemplate="/resource">
        <delete class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="delete"
                invocations="0"/>
        <head class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="head" invocations="0"/>
    </resource>
    <resource uriTemplate="/locator">
        <locator class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="getLocator"/>
    </resource>
    <resource uriTemplate="/resteasy/registry">
        <get class="org.jboss.resteasy.plugins.stats.RegistryStatsResource" method="get" invocations="2">
            <produces>application/xml</produces>
            <produces>application/json</produces>
        </get>
    </resource>
    <resource uriTemplate="/entry/{foo:.*}">
        <post class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="post" invocations="0">
            <produces>text/xml</produces>
            <consumes>application/json</consumes>
        </post>
        <put class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="put" invocations="0">
            <produces>text/xml</produces>
            <consumes>application/json</consumes>
        </put>
    </resource>
</registry>

Maven の依存関係:

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxb-provider</artifactId>
    <version>3.0.8.Final</version>
</dependency>

例を参照してください。EAP ドキュメントこの EAP 7 Jira

于 2016-09-26T10:40:46.387 に答える
6

そもそも優れていた「よりクリーンな」例を調整する必要がありました。私は RestEasy 3.07 を使用しており、各メソッドの Path アノテーション値も取得したいと考えていました。この変更が他の人の助けになることを願っています。

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.core.ResourceInvoker;
import org.jboss.resteasy.core.ResourceMethodInvoker;
import org.jboss.resteasy.core.ResourceMethodRegistry;
import org.springframework.stereotype.Component;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Component
@Path("/overview")
public class OverviewResource
{
private static final class MethodDescription
{
    private String method;
    private String fullPath;
    private String produces;
    private String consumes;

    public MethodDescription(String method, String fullPath, String produces, String consumes)
    {
        super();
        this.method = method;
        this.fullPath = fullPath;
        this.produces = produces;
        this.consumes = consumes;
    }

}

private static final class ResourceDescription
{
    private String basePath;
    private List<MethodDescription> calls;

    public ResourceDescription(String basePath)
    {
        this.basePath = basePath;
        this.calls = Lists.newArrayList();
    }

    public void addMethod(String path, ResourceMethodInvoker method)
    {
        String produces = mostPreferredOrNull(method.getProduces());
        String consumes = mostPreferredOrNull(method.getConsumes());

        for (String verb : method.getHttpMethods())
        {
            calls.add(new MethodDescription(verb, path, produces, consumes));
        }
    }

    private static String mostPreferredOrNull(MediaType[] mediaTypes)
    {
        if (mediaTypes == null || mediaTypes.length < 1)
        {
            return null;
        }
        else
        {
            return mediaTypes[0].toString();
        }
    }

    public static List<ResourceDescription> fromBoundResourceInvokers(
            Set<Map.Entry<String, List<ResourceInvoker>>> bound)
    {
        Map<String, ResourceDescription> descriptions = Maps.newHashMap();

        for (Map.Entry<String, List<ResourceInvoker>> entry : bound)
        {
            Method aMethod = ((ResourceMethodInvoker) entry.getValue().get(0)).getMethod();
            String basePath = aMethod.getDeclaringClass().getAnnotation(Path.class).value();

            if (!descriptions.containsKey(basePath))
            {
                descriptions.put(basePath, new ResourceDescription(basePath));
            }

            for (ResourceInvoker invoker : entry.getValue())
            {
                ResourceMethodInvoker method = (ResourceMethodInvoker) invoker;

                String subPath = null;
                for(Annotation annotation : method.getMethodAnnotations())
                {
                    if(annotation.annotationType().equals(Path.class))
                    {
                        subPath = ((Path) annotation).value();
                        break;
                    }
                }

                descriptions.get(basePath).addMethod(basePath + subPath, method);
            }
        }

        return Lists.newLinkedList(descriptions.values());
    }
}

@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public List<ResourceDescription> getAvailableEndpoints(@Context Dispatcher dispatcher)
{
    ResourceMethodRegistry registry = (ResourceMethodRegistry) dispatcher.getRegistry();
    return ResourceDescription.fromBoundResourceInvokers(registry.getBounded().entrySet());
}

@GET
@Path("/")
@Produces(MediaType.TEXT_HTML)
public Response getAvailableEndpointsHtml(@Context Dispatcher dispatcher)
{

    StringBuilder sb = new StringBuilder();
    ResourceMethodRegistry registry = (ResourceMethodRegistry) dispatcher.getRegistry();
    List<ResourceDescription> descriptions = ResourceDescription.fromBoundResourceInvokers(registry.getBounded()
            .entrySet());

    sb.append("<h1>").append("REST interface overview").append("</h1>");

    for (ResourceDescription resource : descriptions)
    {
        sb.append("<h2>").append(resource.basePath).append("</h2>");
        sb.append("<ul>");

        for (MethodDescription method : resource.calls)
        {
            sb.append("<li> ").append(method.method).append(" ");
            sb.append("<strong>").append(method.fullPath).append("</strong>");

            sb.append("<ul>");

            if (method.consumes != null)
            {
                sb.append("<li>").append("Consumes: ").append(method.consumes).append("</li>");
            }

            if (method.produces != null)
            {
                sb.append("<li>").append("Produces: ").append(method.produces).append("</li>");
            }

            sb.append("</ul>");
        }

        sb.append("</ul>");
    }

    return Response.ok(sb.toString()).build();

}

}

(別の注意として、ServiceStack が非常にうまく機能するリソースのリストと説明をモデル化するために、おそらく利用可能なものがあるか、私が作業を開始できます: http://mono.servicestack.net/Content/Images/MetadataIndex.png )

于 2014-09-04T02:04:02.977 に答える
-1

誰かがまだあなたのアプリで「/resteasy/registry」を探している場合は、

登録されたすべてのエンドポイント、関連するクラス/メソッドなどの XML 出力を提供します

参考までに、resteasy-jaxb-provider はこの機能を提供します

于 2014-11-07T12:22:11.923 に答える