8

我们正在使用 Jersey 实现 RESTful API,利用其自动 WADL 生成的酷特性。

举个例子,我们有方法

@GET
@Path("/{id}/{attribute}")
@Produces(MediaType.APPLICATION_JSON)
public Object getAttributeByID(@PathParam("id") long id, @PathParam("attribute") String attribute) {
....
}

这会在 WADL 中生成以下片段:

<param type="xs:string" style="template" name="attribute:.*"/>

属性可以是name, typesize我们不仅要在运行时验证值,还要在生成的 wadl 中显示它 根据这个文档,应该通过<option>在 内部生成几个标签来支持这样的功能<param>,即我期待如下内容:

<param type="aws:Attributes" style="template" name="attribute">
  <option value="name"/> 
  <option value="type"/> 
  <option value="size"/> 
</param>

我的问题是用泽西岛启用它。如果找不到相关文档并假设如果我将参数类型从String更改enum为此功能将自动工作,因此我将方法签名更改为:

@Path("/{id}/{attribute}")
@Produces(MediaType.APPLICATION_JSON)
public Object getAttributeByID(@PathParam("id") long id, @PathParam("attribute") Attribute attribute) {
....
}

在哪里

public enum Attribute {
    name, type, size
}

但是 Jersey 仍然会生成<param>不带选项的标签,并且参数的类型仍然是xs:string.

我试图在 Jersey 的代码中找到它并找到com.sun.research.ws.wadl.Option带有相关 JAXB 注释的类,所以它似乎是相关的,但我不知道如何使它工作。我想问题出在WadlGeneratorConfig.

这是我们的泽西定义的相关部分web.xml

<filter>
<filter-name>REST-API</filter-name>
<filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class>
    ................
<init-param>
    <param-name>com.sun.jersey.config.property.WadlGeneratorConfig</param-name>
    <param-value>com.mycompany.resource.OurWADLGenerator</param-value>
</init-param>
<init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>com.mycompany</param-value>
</init-param>
</filter>

其中OurWADLGenerator代码是:

public class OurWADLGenerator extends WadlGeneratorConfig {
    @Override
    public List<WadlGeneratorDescription> configure() {
        return generator(WadlGeneratorApplicationDoc.class)
                .prop("applicationDocsStream", "application-doc.xml")
            .generator(WadlGeneratorResourceDocSupport.class)
                .prop("resourceDocStream", "resourcedoc.xml").descriptions();
    }
}

我在这里想念什么?提前致谢。

4

2 回答 2

3

快速搜索com.sun.research.ws.wadl.Param.getOption()(参见此处的结果)的用法表明它实际上从未从库中调用过。我猜它之所以存在,是因为这些类是由 xjc 从 wadl.xsd 生成的。尽管 Jersey 似乎基本上忽略了 wadl 文件中的这条信息,并且同样不关心将其包含在它生成的 wadl 文件中。

几年前,我们最终编写了自己的代码来生成 wadl,因为可用的工具太差了。从那时起这可能已经改变,但上述问题表明对 wadl 的适当支持仍然不完全存在。:(

于 2013-02-21T17:49:42.883 回答
2

经过几次调查,我没有在填充选项列表的球衣中找到任何代码。(可能还不支持的东西)

因此,您可以实现自己的 WadlGenerator 并将其插入生成器链。

OptionsWadlGenerator这是一个为类型参数添加<option>元素的示例Enum

package com.mycompany;

import com.sun.jersey.api.model.AbstractMethod;
import com.sun.jersey.api.model.AbstractResource;
import com.sun.jersey.api.model.AbstractResourceMethod;
import com.sun.jersey.api.model.Parameter;
import com.sun.jersey.server.wadl.WadlGenerator;
import com.sun.research.ws.wadl.Application;
import com.sun.research.ws.wadl.Method;
import com.sun.research.ws.wadl.ObjectFactory;
import com.sun.research.ws.wadl.Option;
import com.sun.research.ws.wadl.Param;
import com.sun.research.ws.wadl.RepresentationType;
import com.sun.research.ws.wadl.Request;
import com.sun.research.ws.wadl.Resource;
import com.sun.research.ws.wadl.Resources;
import com.sun.research.ws.wadl.Response;

import javax.ws.rs.core.MediaType;

public class OptionsWadlGenerator implements WadlGenerator {

    private WadlGenerator _delegate;

    private ObjectFactory objectFactory = new ObjectFactory();

    @Override
    public Param createParam(AbstractResource r, AbstractMethod m, Parameter p) {
        Param param = _delegate.createParam(r, m, p);
        if(((Parameter)p).getParameterClass().isEnum()){
            Object[] values = p.getParameterClass().getEnumConstants();
            for(Object enumItem:values){
                Option option = objectFactory.createOption();
                option.setValue(((Enum)enumItem).name());
                param.getOption().add(option);
            }
        }
        return param;
    }

    @Override
    public void setWadlGeneratorDelegate(WadlGenerator delegate) {
        this._delegate = delegate;
    }

    @Override
    public Application createApplication() {
        return _delegate.createApplication();
    }

    ... all other methods also simply call the _delegate equivalent method    
}

当然,要将其插入您的链中,请执行以下操作:

public class OurWADLGenerator extends WadlGeneratorConfig {
    @Override
    public List<WadlGeneratorDescription> configure() {
        return generator(WadlGeneratorApplicationDoc.class)
                .prop("applicationDocsStream", "application-doc.xml")
            .generator(WadlGeneratorResourceDocSupport.class)
                .prop("resourceDocStream", "resourcedoc.xml")
            .generator(OptionsWadlGenerator.class).descriptions();
    }
}
于 2013-03-02T16:14:11.653 回答