1

我有一个项目来记录一个非常大的项目中的所有端点。我只有源文件,所以我不能在上面运行某种文档工具。我唯一的资源(据我所知)是带有 perl 或 python 或类似东西的正则表达式。

以下是方法上的注释示例:

/**
 * Method Javadoc
 */
@Endpoint
@POST
@Path("path/{objectid}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@TypeHint(SomeObject.class)
public Response deleteObject(@PathParam("objectid") Integer objectid) {
  //method code
}

我相信我唯一可以信任的是一致的是每个端点方法都会有@Endpoint注释。它可能是也可能不是第一个注释。这些方法可以有任何签名。

对于像这样的正则表达式的任何帮助都会很棒。我希望匹配所有这些信息不仅仅需要一个正则表达式,所以一些甚至也会有所帮助!

只是为了让你知道我要做什么(我不希望你为我做这项工作,我主要是在寻求正则表达式的帮助),我想要的是一个具有以下结构的 csv:

SourceFile.java  |  MethodName  |      Path       | Method  |  QueryParams  |  FormParams  |  Consumes                  |  Produces                                                |  ReturnedObject
ClassName.java   | deleteObject | path/{objectid} |  POST   |  objectid,    |              | MediaType.APPLICATION_JSON |  {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML} | SomeObject.class
4

2 回答 2

3

您对 regexp 作为唯一解决方案的态度如何?假设您已经编译了代码(或可以编译它),并且您的注释是零售的,您可以编写一个遍历所有类的 java 方法,使用 class.forName() 加载它们,然后你有一个多种反射 API 供您使用,以检查类、方法、字段等的注释。

如果类被 jarred 了,您只需在运行时将 jar 添加到类路径中,然后使用 ZipInputStream 打开它,检查条目,然后使用 class.forName() 将它们一一加载。如果它“爆炸”(只是一堆 *.class 文件)你的工作就更容易了。

浏览一个 zip(其中 *.jar、*.ear、*.war 是)类似于:

ZipInputStream zis = new ZipInputStream(new FileInputStream("fileName"));
ZipEntry entry;
while ((entry = zis.getNextEntry())!=null) {
    if (entry.isDirectory()) {
        continue;
    }
    if (!entry.getName().endsWith(".class")) {
        continue;
    }
    Class theClass = Class.forName(entry.getName());
    Endpoint targetAnnotation = theClass.getAnnotation(Endpoint.class);
    if (targetAnnotation == null) {
        continue;
    }
    //probably what youre looking for
}

当然,您的程序需要在执行的 lasspath 上使用目标 *.war/jar/ear 执行,才能使Class.forName()调用生效。如果编译后的代码没有震动,那么您可以简单地以非常相似的方式遍历文件系统。

如果您之后的注释在编译后没有保留,您可以考虑引入一个可以读取 java 代码并遍历语法树的库,例如这个

于 2013-03-04T21:20:50.350 回答
2

像这样的东西可能在 Perl 中起作用,例如,

my $found_method;
my $found_endpoint;

# Iterate over each line of the input .java file
while (<>) {
  $found_method = 0;
  $found_endpoint = 0;

  # Look for an @endpoint annotation, and capture what's between the
  # parenthesees.  Do the same for each annotation.
  if (/\@endpoint/i) {
    $found_endpoint = 1;
  } elsif (/\@path\(([^\)]+)\)/i) {
    $path = $+;
  } elsif (/\@consumes\(([^\)]+)\)/i) {
    $consumes = $+;
  } elsif (/\@produces\(([^\)]+)\)/i) {
    $produces = $+;
  } elsif (/\@typehint\(([^\)]+)\)/i) {
    $typehint = $+;

  # Look for a method definition (all on one line)
  } elsif (/\w+\s+\w+\(.*{/i) {
    $open_brackets = 1;

    # Skip over the bracketed method definition
    while ($open_brackets) {
      $found_method = 1;
      if (/{/) {
        $open_brackets++;
      } elsif (/{/) {
        $open_brackets--;
      }
    }
  }

  # If we just finished passing over an annotated method, output what we
  # found
  if ($found_method and  $found_endpoint) {
    print "\npath = " . $path;
    print "\nconsumes = " . $consumes;
    print "\nproduces = " . $produces;
    print "\ntypehint = " . $typehint;
  }
}
于 2013-03-04T21:46:27.933 回答