WADL REST API的描述语言

简介

WADL(Web Application Description Language)是一种用于描述web应用对外提供接口语言,它使用XML来表示。其中主要包括每个资源的定位(URI)、请求类型(GET、POST等)、请求参数类型(路径参数、query参数等)、响应值和响应类型等一系列内容。根据这个XML,可以直接读取到系统提供的所有REST API,并能够进行调用。

由于WADL使用XML描述,对于开发者来说,可以通过标准的xslt进行转换,将机器读取的XML转换成便于人读取的HTML,进而行程API文档。关于WADL具体格式,参见w3c的Web Application Description Language

实现

对于使用springboot的微服务应用来说,会使用两种框架实现REST服务,一种是jersey,一种是spring MVC。这里不进行二者实现的比较和使用方式介绍,仅对于WADL相关内容做出描述。

jersey

jersey是一个完整实现JAX-RS API,并对其进行了扩展的REST API库,springboot对其有对应的starter,引入和使用都非常方便。jersey本身已经自带了WADL生成,因此如果使用jersey作为REST API框架,不需要任何修改,系统已经自带了WADL文件的生成。其默认地址是/application.wadl,访问系统对应的URL即可。

spring MVC

spring MVC默认没有提供生成WADL相关的功能,但是可以通过注入RequestMappingHandlerMapping对象来获取spring MVC中的映射关系,进而获取到生成WADL所需要的所有内容。

public class WadlEndpoint extends AbstractMvcEndpoint {

    private static String xs_namespace="http://www.w3.org/2001/XMLSchema" ;

    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @Autowired
    private WebApplicationContext webApplicationContext;

    public WadlEndpoint() {
        super("/application.wadl", false);
    }

    @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_XML_VALUE)
    public @ResponseBody Application generateWadl(HttpServletRequest request) {
        Application application = new Application();

        Doc doc = new Doc();
        doc.setTitle(webApplicationContext.getId() + " WADL");
        application.getDoc().add(doc);

        Resources wadlResources = new Resources();
        wadlResources.setBase(getBaseUrl(request));

        Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
            HandlerMethod handlerMethod = entry.getValue();
            Class<?> beanType = handlerMethod.getBeanType();
            if (!beanType.isAnnotationPresent(RestController.class)) {
                // not a rest controller,skip
                continue;
            }

            RequestMappingInfo mappingInfo = entry.getKey();
            Set<String> patterns = mappingInfo.getPatternsCondition().getPatterns();
            for (String uri : patterns) {
                Resource wadlResource = genResource(uri, mappingInfo, handlerMethod);
                wadlResources.getResource().add(wadlResource);
            }
        }

        application.getResources().add(wadlResources);


        return application;
    }
    ...
}

首先按照springboot endpoint的方式,定义一个生成WADL的endpoint,并将当前endpoint处理的URL绑定为/application.wadl,以便和jersey生成的路径保持一致,方便后面的xslt转换操作。

然后这个类需要注入的是RequestMappingHandlerMappingWebApplicationContext这两个对象,前者可以获取到spring MVC中的绑定情况(通过@RequestMapping注解标注的方法),后者获取到对应的类,用以解析方法的入参、出参等数据。

接着就可以从RequestMappingHandlerMapping对象中,通过getHandlerMethods方法获取到当前spring容器中所有url的绑定情况。返回值是一个Map类型,key是RequestMappingInfo对象,其中包括了@RequestMapping注解中的所有字段;HandlerMethod是处理方法的描述,可以获取到对应的类和方法。

最后就是根据这些数据,拼装生成最终的WADL XML了。这里首先有个简单的过滤,如果处理类不是@RestController注解修饰的,直接跳过。因此这个WADL文件,仅针对@RestController注解修饰的类,不包括@Controller注解修饰的类。

最后,除了标准的注解之外,为了增加可读性,还新建了一个@ApiDescribe注解,该注解可以用于绑定方法上,更加详细的描述方法的作用。通常情况下,通过绑定方法的名称,基本上可以知道这个方法的具体业务场景和大致业务逻辑,这个注解只是作为补充,在生成Method的时候,加上对应的文档。

生成HTML

前面介绍了jersey和spring MVC框架下如何生成WADL文件。该文件是XML类型,如果知道每个标签的大致含义,基本上是可以看懂的。为了能够更加直观和美观的查看API文档,找到了https://github.com/ehearty/Swadl 工程,它通过xslt,将WADL的XML文档转换成类似Swagger的界面,可读性大大增强。

生成方式比较简单,该工程直接将转换代码放在了js中,也就是将xslt过程放在了浏览器中进行。因此,只需要修改下初始载入的链接,改成/application.wadl,js会完成加载对应的XML,并通过工程中的stylesheet来进行转换和美化。

相关静态资源也已经放置到工程中,因此只要工程使用了spring MVC,即可通过/wadl.html来展示当前工程的API文档。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.