【问题标题】:Documenting Spring @RequestMapping annotations into one location automatically?将 Spring @RequestMapping 注释自动记录到一个位置?
【发布时间】:2011-06-17 07:37:35
【问题描述】:

Javadoc 非常适合扫描所有源文件并创建 HTML 页面来查看它。我想知道是否有一个类似的工具可以遍历您的所有 Spring 控制器并收集所有已使用 @RequestMapping 注释的方法并生成一个列出它们的 HTML 页面。有点像开发人员的伪站点地图,以确保跨控制器的唯一性和标准化。

如果这个问题已经在其他地方问过,我深表歉意。我想不出一组合适的搜索词来提供有用的结果。

【问题讨论】:

    标签: java spring spring-mvc annotations documentation-generation


    【解决方案1】:

    据我所知,没有任何东西可以做到这一点。在创建导航之前,我已经通过应用上下文检索了控制器和映射,但是 IMO 做了大量工作却收效甚微:

    @Component
    public class SiteMap implements ApplicationContextAware, InitializingBean {
    
      private ApplicationContext context;
      private List<Page> pages = new ArrayList<Page>();
    
      public List<Page> getPages() {
         return pages;
      }
    
      public void setApplicationContext(ApplicationContext applicationContext) {
         this.context = applicationContext;
      }
    
      public void afterPropertiesSet() throws Exception {
         Assert.notNull(context, "applicationContext not set");
         Map<String, Object> controllers = ctx.getBeansWithAnnotation(Controller.class);
         for(Map.Entry<String, Object> entry : controllers.entrySet()) {
            Page page = new Page();
            Class<?> controllerClass = entry.getValue();
            String controllerRoot = null;
            RequestMapping classMapping = controllerClass.getAnnotation(RequestMapping.class);
            if(classMapping != null)
                controllerRoot = classMapping.value();
            if(controllerRoot = null)
                controllerRoot = // get and parse controller name
            page.setPath(controllerRoot);
            for(Method m : controllerClass.getDeclaredMethods()) {
                RequestMapping rm = m.getAnnotation(RequestMapping.class);
                if(rm == null)
                   continue;
                Page child = new Page();
                child.setPath(rm.value());
                page.getChildren().add(child);
            }
            pages.add(page);
         }
      }
    
      public static class Page {
          private String path;
          private List<Page> children = new ArrayList<Page>();
          // other junk
      }
    
    }
    

    然后在您的站点地图页面 JSP 中访问 ${pages}。如果您执行类似的操作,可能需要使用该代码进行一些操作,我在此编辑器中徒手编写了它。

    【讨论】:

      【解决方案2】:

      这是一个很好的问题,我经常错过(并实现)这样的功能。

      使用构建工具

      我要做的是运行 Maven(或 ant)并在编译后执行一个任务

      • 读取所有类(可能带有可配置的包列表)
      • 遍历这些类的所有方法
      • 读取注释
      • 并将输出写入 HTML

      使用注解处理

      但我想这是一个场景,annotation processing 也可能是一种方法。通常,您必须使用一些内部 API 才能在 API 中完成工作,但使用 Filer.createResource(...) 实际上应该可以开箱即用。

      这是一个基本的实现:

      public class RequestMappingProcessor extends AbstractProcessor{
      
          private final Map<String, String> map =
              new TreeMap<String, String>();
      
          private Filer filer;
      
          @Override
          public Set<String> getSupportedAnnotationTypes(){
              return Collections.singleton(RequestMapping.class.getName());
          }
      
          @Override
          public synchronized void init(
              final ProcessingEnvironment processingEnv){
              super.init(processingEnv);
              filer = processingEnv.getFiler();
          }
      
          @Override
          public boolean process(
              final Set<? extends TypeElement> annotations,
              final RoundEnvironment roundEnv){
      
              for(final TypeElement annotatedElement : annotations){
                  final RequestMapping mapping =
                      annotatedElement.getAnnotation(
                          RequestMapping.class
                      );
                  if(mapping != null){
                      addMapping(mapping, annotatedElement, roundEnv);
                  }
              }
              assembleSiteMap();
              return false;
          }
      
          private void assembleSiteMap(){
              Writer writer = null;
              boolean threw = false;
              try{
                  final FileObject fileObject =
                      filer.createResource(
                          StandardLocation.CLASS_OUTPUT,
                          "html", "siteMap.html"
                      );
                  writer = fileObject.openWriter();
                  writer.append("<body>\n");
                  for(final Entry<String, String> entry : map.entrySet()){
                      writer
                          .append("<a href=\"")
                          .append(entry.getKey())
                          .append("\">")
                          .append("Path: ")
                          .append(entry.getKey())
                          .append(", method: ")
                          .append(entry.getValue())
                          .append("</a>\n");
                  }
                  writer.append("</body>\n");
      
              } catch(final IOException e){
                  threw = true;
                  throw new IllegalStateException(e);
              } finally{
      
                  // with commons/io: IOUtils.closeQuietly(writer)
                  // with Guava: Closeables.close(writer, rethrow)
                  // with plain Java this monstrosity:
                  try{
                      if(writer != null){
                          writer.close();
                      }
                  } catch(final IOException e){
                      if(!threw){
                          throw new IllegalStateException(e);
                      }
                  } finally{
                  }
              }
          }
      
          private void addMapping(final RequestMapping mapping,
              final TypeElement annotatedElement,
              final RoundEnvironment roundEnv){
              final String[] values = mapping.value();
              for(final String value : values){
                  map.put(
                      value,
                      annotatedElement.getQualifiedName().toString()
                  );
              }
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-15
        • 1970-01-01
        • 1970-01-01
        • 2017-08-03
        • 1970-01-01
        • 2018-10-25
        • 1970-01-01
        相关资源
        最近更新 更多