SpringMVC conflicts with existing, non-compatible bean definition of same name and class 的解決辦法


問題起因

最近,項目組的里的同事遇到一個問題,他自己負責的模塊,SpringMVC的Controller與其他模塊的Controller 類名重名了,導致整個工程都起不來了。

后台報的錯誤是這樣的:

××Controller' for bean class [××ontroller] conflicts with existing, non-compatible bean definition of same name and class 

午飯時,他一直和我抱怨這個問題,還說找不到辦法。

后面我想了一下,SpringMVC的Controller 應該是采用類似鍵值對(key/value)的映射方式處理的。而當中的鍵,默認是用cotroller的類名(非全類名)作為鍵。這樣,如果不同包下面的兩個Contoller 重名的話,就會導致SpringMVC的容器管理中的controller map中的key重復了。

解決這個問題也比較簡單。

在@Controller 中,使用重名名就可以了

如 下例子:

test.controller.bill.BillSaveController
package test.controller.bill;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by liuch on 5/27/15.
 */
@Controller
@RequestMapping("/billsave")
public class BillSaveController {

    @RequestMapping("/dosave")
    public String saveBill(){

        return "billsave";
    }

}

及 test.controller.bill.BillSaveController

package test.controller.billsave;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by liuch on 5/27/15.
 */
@Controller
@RequestMapping("/billsave_test")
public class BillSaveController {

    @RequestMapping("/test")
    public String test(){
        return "test";
    }

}

上面這兩個代碼雖然在不同的包下面,即全類名不同,但是類名卻是相同。

這樣,在Tomcat 啟動的時候,后台會報錯:

SEVERE: Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: 

Unexpected exception parsing XML document from ServletContext resource
[/WEB-INF/dispatcher-servlet.xml]; 

nested exception is java.lang.IllegalStateException: 

Annotation-specified bean name 'billSaveController' for 
bean class [test.controller.billsave.BillSaveController] 
conflicts with existing, non-compatible bean definition of same name 
and class [test.controller.bill.BillSaveController]

問題原因:

因為如果在使用注解 @Controller 時候,如果不使用命名,而SpringMVC會默認把類名的頭一個字母小寫,然后放到一個map中。

比如上面的例子,盡管上面兩個類全類名不同,但是他們使用了@Controller 注解的時候,都沒有使用命名。在SpringMVC在掃描Controller的時候,會把他們都默認解析為 billSaveController.然后以這個billSaveController為鍵(key), 放到一個全局的map中。

這樣,就會出現兩個鍵完全一樣的Controller。由於SpringMVC不使用覆蓋的方式處理具有相同鍵的不同全類名的Controller,、掃描的時候就會包上面的錯誤。

解決的辦法:

在@Controller上使用名稱

如:test.controller.bill.BillSaveController中

package test.controller.bill;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by liuch on 5/27/15.
 */
@Controller("testbillsave")
@RequestMapping("/billsave")
public class BillSaveController {

    @RequestMapping("/dosave")
    public String saveBill(){

        return "billsave";
    }

}
test.controller.billsave.BillSaveController中,使用:
package test.controller.billsave;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
 * Created by liuch on 5/27/15.
 */
@Controller("realbillsave")
@RequestMapping("/billsave_test")
public class BillSaveController {

    @RequestMapping("/test")
    public String test(){
        return "test";
    }

}

上面兩個Controller中,只要保證一個有命名即可,但是最好兩個都使用上。

這是一種良好的編程方式,因為你無法保證其他人不會使用和你一樣的類名的Controller。

后記:

下午讓同事試了一下,果然可以了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM