我们正在构建某种自动描述REST服务(实时文档生成)。为此我们有一个控制器方法,它查找所有控制器bean,并提取请求映射信息,以便在友好的友好html页面中显示它们。
为此,我们使用MetadataReader(通过CachingMetadataReaderFactory创建)来获取类的元数据。 当我们获取公共方法的MethodMetaData时,我们找到RequestMapping注释以及produce和value参数,但是方法字段总是一个空数组,尽管我们在源代码中配置它并且映射有效。所以信息应该在某个地方。这真是令人费解! : - )
编辑:方法字段为空=> RequestMapping Annotation有一个方法字段,它是RequestMethod对象的数组。如果您尝试从MethodMetaData实例中读取它,那么它是一个空数组。示例:metadata.getAnnotationAttributes(RequestMapping.class.getName())。get(“method”)
我试图在spring框架源代码中找到原因,但到目前为止还没有找到原因......
有什么想法吗?
仅供参考:我们正在使用Spring 3.1
答案 0 :(得分:1)
我出于自己的好奇心创建了一个小样本项目,并使用Spring提供的MetadataReader进行了一些调整。对于演示,我创建了一个非常简单的控制器,如下所示:
@Controller
public class SomeAnnotatedController {
@RequestMapping(method = {RequestMethod.GET}, value = "/someUrl")
public void someMethod() {
// do something later
}
}
我无法使用Spring MetadataReader从注释中提取正确的信息。
@Test
public void shouldReturnMethodArrayWithSpringMetadataReader() throws Exception {
MetadataReader metadataReader = new CachingMetadataReaderFactory().getMetadataReader(SomeAnnotatedController.class.getName());
Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata().getAnnotatedMethods(RequestMapping.class.getName());
assertEquals(1, annotatedMethods.size());
MethodMetadata methodMetadata = annotatedMethods.iterator().next();
assertEquals("someMethod", methodMetadata.getMethodName());
Map<String, Object> annotationAttributes = methodMetadata.getAnnotationAttributes(RequestMapping.class.getName());
assertTrue(annotationAttributes.containsKey("method"));
RequestMethod[] methodAttribute = (RequestMethod[]) annotationAttributes.get("method");
assertEquals(1, methodAttribute.length);
}
在最后一行运行此测试失败并告诉您这是一个空数组...
java.lang.AssertionError:
Expected :1
Actual :0
使用本机Java执行相同操作会感觉更容易并返回正确的信息。
@Test
public void shouldReturnMethodArrayWithPlainJava() throws Exception {
Method method = SomeAnnotatedController.class.getDeclaredMethod("someMethod");
RequestMapping annotation = method.getAnnotation(RequestMapping.class);
assertEquals(1, annotation.method().length);
assertEquals(RequestMethod.GET, annotation.method()[0]);
}
所以我很遗憾地告诉你,我没有找到问题的解决方案,但是样本项目或基于普通java的文档替代方案可能有所帮助。
答案 1 :(得分:1)
这不是您所要求的直接答案,而是一种非常好的方式来自行记录REST API。使用Rossen Stoyanchev描述的端点文档控制器在他的github位置:https://github.com/rstoyanchev/spring-mvc-31-demo.git
总结一下,你的控制器看起来像这样:
@Controller
public class EndpointDocController {
private final RequestMappingHandlerMapping handlerMapping;
@Autowired
public EndpointDocController(RequestMappingHandlerMapping handlerMapping) {
this.handlerMapping = handlerMapping;
}
@RequestMapping(value="/endpointdoc", method=RequestMethod.GET)
public void show(Model model) {
model.addAttribute("handlerMethods", this.handlerMapping.getHandlerMethods());
}
}
你的jsp会以这种方式引用方法,产生,消耗,方法签名的属性,假设hm是一个处理程序方法:
Patterns:${hm.key.patternsCondition.patterns}
Method: ${hm.key.methodsCondition.methods}
Method signature: ${hm.value}
Consumes: ${hm.key.consumesCondition.expressions}
Produces: ${hm.key.producesCondition.expressions}