Javadoc非常适合扫描所有源文件并创建HTML页面来查看它。我想知道是否有一个类似的工具可以通过所有的Spring控制器并收集所有已经使用@RequestMapping注释的方法并生成一个列出它们的HTML页面。有点类似于伪站点地图,供开发人员确保控制器的唯一性和标准化。
如果已经在别处问过这个问题,我道歉。我无法想出一套能够提供有用结果的适当搜索词。
答案 0 :(得分:4)
这是一个非常好的问题,我经常会错过(并实现)这样的功能。
我要做的是运行Maven(或ant)并在编译后执行任务
但我想这是一个场景,其中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()
);
}
}
}
答案 1 :(得分:0)
我知道没有什么可以做到的。在创建导航之前,我已经通过应用程序上下文检索了控制器和映射,但是为了获得微小的收益,我做了很多工作:
@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}
。如果你做了类似的事情,我可能需要使用那些代码,我在这个编辑器中对它进行了解释。