我正在使用Spring MVC创建一个可视化编辑器Web应用程序。
可视化具有一些属性:
public class VisualizationProperties {
double strokeWidth = 1;
Rectangle selectedArea;
}
每个浏览器会话都应该有一个,因此我将其定义为会话范围的bean:
@Component
@Scope("session")
public class VisualizationProperties {
...
因为我想从服务中访问它...
@Service
public class VisualizationService {
@Resource
private VisualizationProperties properties;
public void createVisualization () {
//create visualization using properties
...
}
}
...我通过代理定义访问权限:
@Component
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class VisualizationProperties {
...
将成员设为私有,并为其添加getters + setter。
到目前为止完美。
现在我希望客户端能够读取和更新属性。
所以我将bean更改为控制器并添加访问自身的方法:
@Controller
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class VisualizationProperties {
private double strokeWidth = 1;
private Rectangle selectedArea;
... //getters + setters
@RequestMapping(value="/properties", method=RequestMethod.GET)
public @ResponseBody VisualizationProperties getProperties () {
return this;
}
@RequestMapping(value="/properties", method=RequestMethod.POST)
public @ResponseBody void setProperties (@RequestBody VisualizationProperties newProperties) {
this.strokeWidth = newProperties.strokeWidth;
this.selectedArea = newProperties.selectedArea;
}
}
启动时导致以下异常:
IllegalStateException: Ambiguous mapping found.
Cannot map 'visualizationProperties' bean method getProperties() to {[/properties],methods=[GET],...}:
There is already 'scopedTarget.visualizationProperties' bean method.
为什么?
答案 0 :(得分:3)
这里的问题是双重的。首先,您要注释已使用@Controller
注释的类。
@Controller
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class VisualizationProperties {
其次,您正在使用范围代理。在这种情况下,Spring将注册两个bean定义。一个名称为visualizationProperties
用于实际bean,另一个名称为scopedTarget.visualizationProperties
,用作创建代理的FactoryBean
。
处理程序方法注册过程(对于@Controller
bean和@RequestMapping
方法)通过在上下文中查找所有bean 名称,找到它们的类型,扫描其方法来工作。如果用@RequestMapping
注释,则键入并注册这些方法。
由于Spring将visualizationProperties
和scopedTarget.visualizationProperties
bean名称解析为具有VisualizationProperties
注释方法的类型@RequestMapping
的bean,它将尝试注册两者,在第二个时失败因为映射冲突(你不能将两个处理程序映射到同一个请求)。
我建议的解决方案是重构并创建一个委托给会话作用域@Controller
bean的专用VisualizationProperties
类(未代理)。
答案 1 :(得分:0)
有效的替代方案:
proxyMode=ScopedProxyMode.INTERFACES
,将可爱的小属性POJO移至VisualizationProperties
Impl
并为其引入界面.. overhead duh!< / em>的其他想法?