我有以下Spring控制器:
@RestController
@RequestMapping(value = "my-rest-endpoint")
public class MyController {
@GetMapping
public List<MyStuff> defaultGet() {
...
}
@GetMapping(params = {"param1=value1", "param2=value2"})
public MySpecificStuff getSpecific() {
...
}
@GetMapping(params = {"param1=value1", "param2=value3"})
public MySpecificStuff getSpecific2() {
return uiSchemas.getRelatedPartyUi();
}
}我需要的是使用自定义注释使它更加通用:
@RestController
@RequestMapping(value = "my-rest-endpoint")
public class MyController {
@GetMapping
public List<MyStuff> defaultGet() {
...
}
@MySpecificMapping(param2 = "value2")
public MySpecificStuff getSpecific() {
...
}
@MySpecificMapping(param2 = "value3")
public MySpecificStuff getSpecific2() {
return uiSchemas.getRelatedPartyUi();
}
}我知道Spring 元注释可以帮助我做到这一点。
因此,我定义了注释:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@RequestMapping(method = RequestMethod.GET, params = {"param1=value1"})
public @interface MySpecificMapping {
String param2() default "";
}光靠这个是不行的。
因此,我添加了一个拦截器来处理"param2":
public class MyInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// get annotation of the method
MySpecificMapping mySpecificMapping = handlerMethod.getMethodAnnotation(MySpecificMapping.class);
if (mySpecificMapping != null) {
// get the param2 value from the annotation
String param2 = mySpecificMapping.param2();
if (StringUtils.isNotEmpty(param2)) {
// match the query string with annotation
String actualParam2 = request.getParameter("param2");
return param2 .equals(actualParam2);
}
}
}
return true;
}
}当然,将其包含到Spring配置中。
这很好,但前提是每个控制器都有一个这样的自定义映射。
如果我添加了两个带有@MySpecificMapping注释的方法,甚至具有不同的"param2“值,那么我就会得到应用程序启动的”模糊映射“错误:
java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'myController' method
public com.nailgun.MySpecificStuff com.nailgun.MyController.getSpecific2()
to {[/my-rest-endpoint],methods=[GET],params=[param1=value1]}: There is already 'myController' bean method
public com.nailgun.MySpecificStuff com.nailgun.MyController.getSpecific() mapped.
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.assertUniqueMethodMapping(AbstractHandlerMethodMapping.java:576)
- Application startup failed我明白为什么会发生这种事。
,但你能帮我暗示一下这是两个不同的映射吗?
我在SpringWeb4.3.5中使用SpringBoot1.4.3
发布于 2018-06-02 10:14:14
@AliasFor是用于这样做的注释。下面是一个使用@RequestMapping进行自定义注释的示例
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @interface JsonGetMapping {
@AliasFor(annotation = RequestMapping.class, attribute = "value")
String value() default "";
}也是使用的例子
@JsonGetMapping("/category/{categoryName}/books")
public List<Book> getBooksByCategory(@PathVariable("categoryName") String categoryName){
return bookRepository.getBooksByCategory(categoryName);
}发布于 2017-04-20 13:35:28
不能将堆栈中的注释绑定到它们的params中,Spring会将这两个方法视为具有相同@RequestMapping的方法。
但是您可以尝试一个技巧:在映射生成器之前以某种方式嵌入您的自定义注释增强器,然后执行注释替换:
@MySpecificMapping获取所有方法:
MySpecificMapping myMapping =.@RequestMapping注释,假设它将是
RequestMapping oldMapping =.@RequestMapping类的新实例:
RequestMapping newMapping = new RequestMapping() { // ... rest methods @Override public String[] params() { // here merge params from old and MySpecificMapping: String[] params = new String[oldMapping.params().length + 1]; // todo: copy old one // ... params[params.length-1] = myMapping.param2(); return params; } }newMapping相应地分配给每个方法,而不是oldMapping。这是相当棘手和复杂的,但这只是实现你想要的一种方式,我相信。
发布于 2017-04-20 13:25:56
我认为最好的方法是将@RequestMapping注释移到方法级别,而不是类级别。
Spring给您带来的错误是因为Spring在一个路径上绑定了多个处理程序,这是无效的。也许给我们一个您想要公开的URL的例子,这样我们就可以更好地了解您想要构建的内容。
https://stackoverflow.com/questions/43520174
复制相似问题