Автоматически документировать аннотации Spring @RequestMapping в одном месте? - PullRequest
6 голосов
/ 28 января 2011

Javadoc отлично подходит для сканирования всех исходных файлов и создания HTML-страниц для их просмотра.Мне было интересно, есть ли подобный инструмент, который бы проходил через все ваши контроллеры Spring, собирал все методы, аннотированные @RequestMapping, и создавал бы одну HTML-страницу с их списком.Вроде как псевдо-карта сайта для разработчиков, чтобы обеспечить уникальность и стандартизацию для всех контроллеров.

Я прошу прощения, если этот вопрос уже задавался в другом месте.Я не смог придумать подходящий набор поисковых терминов, который бы дал полезный результат.

Ответы [ 2 ]

4 голосов
/ 28 января 2011

Это очень хороший вопрос, я часто пропускаю (и внедряю) такую ​​функциональность.

Используйте инструмент сборки

Что бы я сделал, это запустил Maven (или ant) ​​ивыполнить задачу после компиляции, чтобы

  • считывал все классы (возможно, с настраиваемым списком пакетов)
  • перебирает все методы этих классов
  • читает аннотации
  • и записывает вывод в HTML

Использовать обработку аннотаций

Но я предполагаю, что это сценарий, где обработка аннотаций также может бытьспособ сделать это.Обычно вам нужно использовать некоторые внутренние 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()
            );
        }
    }

}
0 голосов
/ 29 января 2011

Я не знаю ничего такого, что могло бы сделать это.Я получил контроллеры и сопоставления через контекст приложения, прежде чем создавать навигацию, но это было много работы для небольшого увеличения 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
  }

}

Затем доступ к ${pages} на странице карты вашего сайта JSP.Возможно, вам придется поиграть с этим кодом, если вы делаете что-то подобное, я сделал это бесплатно в этом редакторе.

...