Это очень хороший вопрос, я часто пропускаю (и внедряю) такую функциональность.
Используйте инструмент сборки
Что бы я сделал, это запустил 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()
);
}
}
}