SpringMVC conflicts with existing,non-compatible bean definition of same name and classの解決方法
7160 ワード
問題の原因
最近、プロジェクトチームの同僚が問題に遭遇しました.彼自身が担当しているモジュール、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のクラス名(全クラス名ではない)をキーとして使用します.このように,異なるパッケージの下にある2つの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";
}
}
上の2つのコードは、異なるパッケージの下、すなわち全クラス名が異なるが、クラス名は同じである.
これにより、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に配置します.
たとえば、上記の例では、上記の2つのクラスの全クラス名が異なるにもかかわらず、@Controller注釈を使用した場合、名前は使用されません.SpringMVCがControllerをスキャンすると、デフォルトでbillSaveControllerとして解析されます.そしてこのbillSaveControllerをキーとして、グローバルなmapに配置します.
すると、2つのキーがまったく同じ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";
}
}
上の2つのControllerでは、1つに名前が付けられていることを保証すればよいが、両方とも使用することが望ましい.
これは、他の人があなたと同じクラス名のControllerを使用しないことを保証できないため、良いプログラミング方法です.
後記:
午後は同僚にやってもらったが、やはりよかった.