正则表达式 Java 端点注释

Posted

技术标签:

【中文标题】正则表达式 Java 端点注释【英文标题】:Regex Java Endpoint Annotations 【发布时间】:2013-02-19 02:45:56 【问题描述】:

我有一个项目来记录一个非常大的项目中的所有端点。我只有源文件,所以我不能在上面运行某种文档工具。我唯一的资源(据我所知)是使用 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 注释。它可能是也可能不是第一个注释。方法可以有任何签名。

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

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

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

【问题讨论】:

【参考方案1】:

您对正则表达式作为唯一解决方案的准备程度如何? 假设你已经编译了代码(或可以编译它),并且你的注释是零售的,你可以编写一个遍历所有类的 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 代码并遍历语法树的库,例如 this

【讨论】:

我也许能够获得一个*.war 文件,这将使这成为可能。我以前用reflection 做过类似的事情,但我不熟悉ZipInputStream 或者一堆*.class 文件如何让我的工作更轻松。你能详细说明一下吗? @kentcdodds - 我用模拟代码和另一种选择扩展了我的答案 感谢您的帮助。我在 Class.forName() 上收到了 ClassNotFound。我的类路径中有*.war 文件。我不确定它有什么问题...... @kentcdodds - 战争/耳朵可能有一个更复杂的结构,这会阻止 java 类加载器正确查看它们的内容。也许您的 *.war 在 /lib 下包含更多 *.jars 或里面的东西?如果是这样,您将需要提取所有这些并处理它们(将所有内容放在类路径中并检查它们的所有内容)【参考方案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;
  

【讨论】:

以上是关于正则表达式 Java 端点注释的主要内容,如果未能解决你的问题,请参考以下文章

Java正则表达式忽略/注释掉正则表达式的一部分[重复]

在 Java 正则表达式中包含注释

什么是用于查找未注释 Java 代码行的正则表达式?

Java:使用正则表达式从块注释中去除斜线和星号

SQL 注释中的 Java 正则表达式查找/替换模式

正则表达式检测代码中的注释[重复]