Spring mvc Обнаружено неоднозначное отображение. Не удается сопоставить метод bean-компонента контроллера

Я пытаюсь создать приложение, которое может отображать некоторые значения из базы данных и изменять, добавлять, удалять при необходимости с помощью Spring 4, и я получаю следующую ошибку (только если аннотация «@Controller» присутствует в обоих моих файлах контроллера, если я удаляю аннотацию из одного из файлов, она работает, но я получаю сообщение в консоли «сопоставление не найдено... в диспетчерском сервлете с именем...):

    INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/edit/{id}],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.bookReview.app.BookController.editBook(int,org.springframework.ui.Model)
WARN : org.springframework.web.context.support.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'reviewController' bean method 
public java.lang.String com.bookReview.app.ReviewController.editReview(int,org.springframework.ui.Model)
to {[/edit/{id}],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'bookController' bean method
public java.lang.String com.bookReview.app.BookController.editBook(int,org.springframework.ui.Model) mapped.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4728)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'reviewController' bean method 
public java.lang.String com.bookReview.app.ReviewController.editReview(int,org.springframework.ui.Model)
to {[/edit/{id}],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'bookController' bean method
public java.lang.String com.bookReview.app.BookController.editBook(int,org.springframework.ui.Model) mapped.
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:212)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:184)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:144)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:123)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.java:126)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
    ... 21 more

Это мой файл pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.bookReview.app</groupId>
  <artifactId>BookReviewApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <name>BookReviewApp</name>
  <description>review app</description>

   <!--   <properties>

        Generic properties
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        Spring
        <spring-framework.version>4.0.3.RELEASE</spring-framework.version>

        Hibernate / JPA
        <hibernate.version>4.3.5.Final</hibernate.version>
        <hibernate.version>3.6.9.Final</hibernate.version>

        Logging
        <logback.version>1.0.13</logback.version>
        <slf4j.version>1.7.5</slf4j.version>

    </properties> -->

  <dependencies>
  <!-- Spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.1.6.RELEASE</version>
        <!-- Exclude Commons Logging in favor of SLF4j -->
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                 </exclusion>
            </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.1.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>4.1.6.RELEASE</version>
    </dependency>
    <!-- Hibernate -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.3.9.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>4.3.9.Final</version>
    </dependency>
    <!-- Apache Commons DBCP -->
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>
    <!-- Spring ORM -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>4.1.6.RELEASE</version>
    </dependency>
    <!-- AspectJ -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.8.5</version>
    </dependency>
    <!-- Logging -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.12</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.7.12</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.mail</groupId>
                    <artifactId>mail</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>
        <!-- @Inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2.1-b03</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- Test -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.1.6.RELEASE</version>
        </dependency>
  </dependencies>
</project>

Это мой файл web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app/root-context.xml</param-value>
    </context-param>

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Processes application requests -->
    <servlet>
        <servlet-name>servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/app/servlet/sevlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>servlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

Это мой файл sevlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing 
        infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving 
        up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources 
        in the /WEB-INF/views directory -->
    <beans:bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <beans:property name="url"
            value="jdbc:mysql://localhost:3306/test" />
        <beans:property name="username" value="serban" />
        <beans:property name="password" value="serban" />
    </beans:bean>

    <!-- Hibernate 4 SessionFactory Bean definition -->
    <beans:bean id="hibernate4AnnotatedSessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource" />
        <beans:property name="annotatedClasses">
            <beans:list>
                <beans:value>com.bookReview.app.model.book</beans:value>
                <beans:value>com.bookReview.app.model.review</beans:value>
            </beans:list>
        </beans:property>
        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
                </beans:prop>
                <beans:prop key="hibernate.show_sql">true</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>

    <beans:bean id="bookDAO" class="com.bookReview.app.dao.bookDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
    </beans:bean>
    <beans:bean id="bookService" class="com.bookReview.app.service.BookServiceImpl">
        <beans:property name="bookDAO" ref="bookDAO"></beans:property>
    </beans:bean>

    <beans:bean id="reviewDAO" class="com.bookReview.app.dao.reviewDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
    </beans:bean>
    <beans:bean id="reviewService" class="com.bookReview.app.service.ReviewServiceImpl">
        <beans:property name="reviewDAO" ref="reviewDAO"></beans:property>
    </beans:bean>

    <!-- <default-servlet-handler/> -->

    <context:component-scan base-package="com.bookReview.app" />

    <tx:annotation-driven transaction-manager="transactionManager"/>

        <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
    </beans:bean>

    </beans:beans>

Это мой файл BookController.java

package com.bookReview.app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.bookReview.app.model.book;
import com.bookReview.app.service.BookService;


@Controller
public class BookController {

    private BookService  bookService;

    @Autowired(required=true)
    @Qualifier(value="bookService")
    public void setBookService(BookService bs){
        this.bookService = bs;
    }

    @RequestMapping(value = "/books", method = RequestMethod.GET)
    public String listBooks(Model model) {
        model.addAttribute("book", new book());
        model.addAttribute("listBooks", this.bookService.listBooks());
        return "book";
    }

    //For add and update book both
        @RequestMapping(value= "/book/add", method = RequestMethod.POST)
        public String addBook(@ModelAttribute("book") book b){

            if(b.getBookid() == 0){
                //new book, add it
                this.bookService.addBook(b);
            }else{
                //existing book, call update
                this.bookService.updateBook(b);
            }

            return "redirect:/books";

        }

        @RequestMapping("/remove/{id}")
        public String removeBook(@PathVariable("id") int id){

            this.bookService.removeBook(id);
            return "redirect:/books";
        }

         @RequestMapping("/edit/{id}")
            public String editBook(@PathVariable("id") int id, Model model){
                model.addAttribute("book", this.bookService.getBookById(id));
                model.addAttribute("listBooks", this.bookService.listBooks());
                return "book";
            }


}

А это мой файл ReviewController.java

package com.bookReview.app;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.bookReview.app.model.review;
import com.bookReview.app.service.ReviewService;


@Controller
public class ReviewController {

    private ReviewService  reviewService;

    @Autowired(required=true)
    @Qualifier(value="reviewService")
    public void setReviewService(ReviewService rs){
        this.reviewService = rs;
    }

    @RequestMapping(value = "/reviews", method = RequestMethod.GET)
    public String listReviews(Model model) {
        model.addAttribute("book", new review());
        model.addAttribute("listReviews", this.reviewService.listReviews());
        return "review";
    }

    //For add and update review both
    @RequestMapping(value= "/review/add", method = RequestMethod.POST)
    public String addReview(@ModelAttribute("review") review r){

        if(r.getId() == 0){
            //new review, add it
            this.reviewService.addReview(r);
        }else{
            //existing review, call update
            this.reviewService.updateReview(r);
        }

        return "redirect:/reviews";

    }

    @RequestMapping("/remove/{id}")
    public String removeReview(@PathVariable("id") int id){

        this.reviewService.removeReview(id);
        return "redirect:/reviews";
    }

     @RequestMapping("/edit/{id}")
        public String editReview(@PathVariable("id") int id, Model model){
            model.addAttribute("review", this.reviewService.getReviewById(id));
            model.addAttribute("listReviews", this.reviewService.listReviews());
            return "review";
        }


}

Спасибо


person Serban Gorcea    schedule 29.04.2015    source источник
comment
Ух ты. Это много кода. Вы уверены, что это минимальный полный проверяемый пример, акцент на минимальном? Создание минимального примера поможет другим быстрее определить вашу ошибку, а также может помочь вам найти проблему самостоятельно.   -  person Cecilia    schedule 29.04.2015
comment
Извините, я пытался дать как можно больше информации, чтобы проблему было легче отследить. Если вы обратите внимание, xml-файлы контекста pom, web и servlet необходимы, потому что может быть ошибка, кроме этого, вы можете найти журнал ошибок, который также важен, и два файла классов, с которыми все было в порядке, я поместил их в полный формат, потому что проблема была в нижней части этих двух файлов. все равно спасибо   -  person Serban Gorcea    schedule 29.04.2015
comment
Когда я получил эту ошибку, это произошло потому, что я обновлял Spring Boot до более новой версии. Мне пришлось удалить уже существующий @Bean для контроллера, потому что аннотация @RestController заставила Spring создать его уже!   -  person Will Newton    schedule 30.08.2018


Ответы (4)


Вы должны написать

@Controller("/review")
public class ReviewController {

а также

@Controller("/book")
public class BookController {

потому что в вашем коде у вас есть два метода без явного/уникального пути для сопоставления (например, если у нас есть вызов /edit/1 , невозможно четко определить метод контроллера из вашего editBook BookController или ReviewController editReview)

person Alexey Semenyuk    schedule 29.04.2015
comment
Большое спасибо, это была проблема, во-первых, я изменил имя редактирования и удаления ReviewController на редактирование обзора и удаление обзора, и я не мог изменить @Controller на @Controller(/book), поэтому я использовал @Controller (значение=книга), я надеюсь, что это правильно. возможно, это другая весенняя версия. Теперь у меня есть только консольное сообщение: Не найдено сопоставление для HTTP-запроса с URI [/BookReviewApp/] в DispatcherServlet с именем «сервлет». Я не знаю, связано ли это с этой проблемой или нет. - person Serban Gorcea; 29.04.2015

Если проблема связана с неоднозначным методом, вероятно, проблема должна быть в @RequestMapping. Измените @RequestMapping(name =...) на @RequestMapping(value =...)

@RequestMapping(name = "xxx.htm", method = RequestMethod.GET)

to

@RequestMapping(value = "xxx.htm", method = RequestMethod.GET)
person gilberto Nd    schedule 24.01.2017
comment
Этот ответ был моим решением проблемы, описанной выше, при использовании среды загрузки Spring. Спасибо! - person Fratt; 13.01.2018

Для меня добавление атрибута «params» в @RequestMapping работало, как показано

  @ResponseBody
  @RequestMapping(method = RequestMethod.GET, params = {"id"})
  public User getUserById(final @RequestParam(name="id", required = true) String Id)
    throws InvalidArgumentException {

    return userService.getUserById(UUID.fromString(Id));
  }

  /**
   * REST service endpoint.
   * @param name Unique name for the user in the system.
   * @return Object of type {@link User} if exists otherwise null.
   */
  @ResponseBody
  @RequestMapping(method = RequestMethod.GET, params = {"name"})
  public User getUserByName(final @RequestParam(name="name", required = true) String name)
    throws InvalidArgumentException {

    return userService.getUserByName(name);
  }

Однако добавление обоих параметров одновременно в строку запроса приведет к ошибке 500 с сообщением:

Неоднозначные методы обработчика, сопоставленные для пути HTTP

В этом случае у вас может быть другой метод контроллера, принимающий оба параметра, но использующий только один из них, который, как мне кажется, не нужен.

person Shrikant Prabhu    schedule 24.01.2019

В моем случае у меня было два метода в двух разных контроллерах в загрузочном приложении Spring, оба с одним и тем же @DeleteMapping("/detailbonadelete/{id}") // delete, я изменил один из них на @DeleteMapping("/bonadelete/{id}") // delete, и он работает.

То же самое, если у вас:

@PutMapping("/detailbonaupdate/{id}") // update

@PostMapping("/detailbonainsert") // insert

@GetMapping("/detailbonaidbon/{idBona}") // selectByBonaId

Убедитесь, что он уникален для каждого контроллера.

person SourceCode    schedule 27.02.2019