最近,項目組的里的同事遇到一個問題,他自己負責的模塊,SpringMVC的Controller與其他模塊的Controller 類名重名了,導致整個工程都起不來了。
后臺報的錯誤是這樣的:
[java] view plain copy××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 中,使用重名名就可以了
如 下例子:[java] view plain copytest.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[java] view plain copypackage 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 啟動的時候,后臺會報錯:
[java] view plain copySEVERE: 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中
[java] view plain copypackage 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中,使用:[java] view plain copypackage 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。
新聞熱點
疑難解答