引自免费微信小程序:皆我百晓生
在Java Spring MVC中,当@RequestMapping注解的指定方法存在两个以上相同的方法时(即@RequestMapping(value = "/customer/list", method = RequestMethod.GET)),Spring会抛出一个AmbiguityException,并导致org.springframework.beans.factory.BeanCreationException异常。
原因在于,Spring Web框架在初始化@RequestMapping方法时,会根据注入的上下文对象进行匹配,如果存在多个具有相同名称的@RequestMapping方法,它们都会被对应的注册处理器寻找匹配的位置,并执行对应的方法。如果找不到合适的匹配位置,就会抛出AmbiguityException。
具体来说,@RequestMapping方法声明了一个路由,其映射为URL Ov"/customer/list",这意味着Spring将这个方法作为用户访问/customer路径的默认处理逻辑。然而,当Spring发现包含该路径的其他方法存在与这个默认方法相同的名称(即@RequestMapping(value = "/customer/list", method = RequestMethod.GET))时,它将首先检查这些@RequestMapping方法是否在同一个父类中,以及是否存在父类中定义的同一个名字的切面(带有@Controller注解的方法)。如果满足这两个条件,则表示存在名为@RequestMapping(value = "/customer/list", method = RequestMethod.GET)的公共接口或方法。
下面是在Spring框架中解析并解决这个问题的一种可能方案:
- 在实体类(如
Customer、CaseInfo等)上添加相应的@RestController注解,并在控制器方法上调用@GetMapping注解获取路由的URL映射配置信息,如value属性:
@RestController
@RequestMapping("/customer")
public class CustomerController {
@GetMapping("/list")
public String list() {
// Get the URL value from a properties file or environment variable
String urlValue = "customer.list";
// Initialize the URL mapping and any other necessary configuration
Map urlMap = new HashMap<>();
urlMap.put("url", urlValue);
// Register the mapping as a default route
RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping(urlMap);
handlerMapping.setDefaultTargetPath("/customer");
// Return the list method's result
return "This is the list method for customers";
}
}
- 使用
@Autowired注解注入一个或多个需要映射到@RequestMapping方法的资源类(如@Autowired注入了CustomerMapper和CustomerEvaluator对象):
@Service
public class CustomerService {
private final CustomerMapper customerMapper;
private final CustomerEvaluator evaluator;
@Autowired
public CustomerService(CustomerMapper customerMapper, CustomerEvaluator evaluator) {
this.customerMapper = customerMapper;
this.evaluator = evaluator;
}
public List list() {
// Use the provided resource classes to find the corresponding methods
List methods = new ArrayList<>();
for (Object resource : resources) {
if (resource instanceof CustomerMethod) {
methods.add((CustomerMethod) resource);
}
}
// Map the available methods to their respective URLs
Map mappings = new HashMap<>();
for (CustomerMethod method : methods) {
mappings.put(method.getName(), method.getUrl());
}
// Use the `DefaultRouteHandler` to register the URL mapping and ensure it has a matching target path
RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping(mappings);
handlerMapping.setDefaultTargetPath("/customer");
// Execute the specified methods to retrieve the requested data
for (CustomerMethod method : methods) {
List results = method.execute();
return results;
}
}
}
// Configure your application dependencies
@Configuration
public class AppConfig {
// Your other configuration settings here...
@Bean
public CustomerMapper customerMapper() {
return new CustomerMapper();
}
@Bean
public CustomerEvaluator evaluator() {
return new CustomerEvaluator();
}
}
- 使用
@ControllerAdvice注解在相应的方法上创建一个统一的日志拦截器,如ExceptionAdvice,并在其中捕获并处理AmbiguityException异常:
@ControllerAdvice
public class ExceptionHandlingAdvice {
@ExceptionHandler(AmbiguityException.class)
public ResponseEntity
上述代码示例中,我们首先通过@RestController注解标注实体类,并设置@GetMapping方法作为URL的默认处理逻辑。然后,我们在SpringConfiguraiton配置类中注入CustomerMapper和CustomerEvaluator对象,并在其中创建了多个CustomerMethod对象用于从不同的资源类获取数据。接着,在@Autowired注解中为这些资源类指定了相应的属性和方法,以便在编译时自动选择最适合的映射方式。
接下来,我们创建了一个全局日志拦截器ExceptionHandlingAdvice,在其中对AmbiguityException异常进行处理。在handleAmbiguityException方法中,我们从异常对象中提取错误信息,并创建一个新的响应体,包含错误信息和HTTP状态码。同时,我们打印出错误消息和HTTP状态码,以便于后续跟踪和调试。
在实际应用中,将上述代码整合到业务逻辑层,确保所有的URL映射配置都是合法且正确的,从而保证了系统的正常工作。如果在某些特定场景下,可能需要重写CustomerController及其子类的某些方法,使其更具灵活性,例如根据业务需求提供不同类型的列表方法,或者支持其他元数据(如id,name等)的引用替换。
需要注意的是,这个解决方案只是一个基本示例,具体的实现可能会根据你的项目需求和具体情况有所调整,包括但不限于URL的正则表达式匹配、路由的动态规划、错误处理策略等。此外,如果你的系统中还包含了其他依赖库,例如Spring Boot或Spring Security,可能需要进一步扩展和完善代码,以适应新的版本和特性。
