首页 > 解决方案 > 如何将注入/自动装配的对象从 Spring 传递到 ManagedBean?

问题描述

我正在使用 Spring 和 EJB/Primefaces 开发一个项目,我想将值从 spring 上下文传递到托管 bean。我将使用示例代码进行演示以进一步澄清。

假设我们有以下域类(为了更好的可读性,我保持简单):

public class Store {
    @JsonProperty("store_name")
    private String storeName;

    //constructors, getters and setters...
}

@JsonProperty 的原因是因为我从另一个将 Json 发布到以下控制器的应用程序中获取此值:

@Controller
@RequestMapping("/store")
public class StoreController {
    @Autowired
    private Store store;

    @RequestMapping(method = RequestMethod.POST)
    public String getStoreResponse(@RequestBody String store) throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper mapper = new ObjectMapper();
        LOGGER.info("Store Before Post: " + store.getName());
        store = mapper.readValue(request, Store.class);
        LOGGER.info("Store After Post: " + store.getName());
        return "store";
    }

}

我已经在 BeanConfig 类中配置了 store bean:

@Configuration
public class BeanConfig {

    @Bean(name = "store")
    @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public Store store() {
        Store store = new Store();
        store.setName("Test Store Name");
        return store;
    }
}

这是我的托管 bean:

@ManagedBean
@SessionScoped
public class StoreView extends SpringBeanAutowiringSupport {

    private static final Logger LOGGER = LoggerFactory.getLogger(Store.class);

    //@ManagedProperty("#{store}")
    @Autowired
    private Store store;

    public void test() {
        LOGGER.info("TEST " + store.getName());
    }

    //getters and setters
}

最后是我的 xhtml:

<h:panelGrid columns="3">
    <p:outputLabel for="j_store" value="#{messages['storeview.name']}" />
    <p:inputText id="j_store" value="#{storeView.store.name}" />
    <p:message for="j_store" />
    <h:panelGroup />
    <p:commandButton value="#{messages['storeview.test']}" action="#{storeView.test}" update="@form" ajax="false" />                                                                        
</h:panelGrid>

当我第一次使用邮递员发布示例数据时,记录器输出:

10:35:57,433 INFO  [com.store.test.controllers.StoreController] (default task-2) Store Before Post: Test Store Name
10:35:57,488 INFO  [com.store.test.controllers.StoreController] (default task-2) Store After Post: posted store name

如果我继续调用控制器,我会不断获得“发布的商店名称”,因此它保留了该值。

但是当我去 store.xhtml 并点击测试按钮提交表单时,它仍然具有在 bean 配置文件中设置的值(“测试商店名称”),并且从那时起它保留了我提交的值在输入文本中。

我怀疑它与 Spring 和 Faces 上下文有关,我不知道我想做的是否可行。如果是,请指出我应该更改什么才能使其正常工作,否则,请为我提供替代解决方案。

提前致谢。

标签: springejb

解决方案


您正在混合@Autowired@ManagedBean注释。 @Autowired由 Spring 管理,而@ManagedBean由 JSF 管理。这意味着您可能会有 2 个 Store 实例,由控制器修改的那个与托管 bean 使用的实例不同。

您应该在托管 bean 中注释为@ManagedProperty("#{store}")您的商店属性并定义 getter 和 setter。要让它工作,您还必须在 faces-config.xml 中定义 spring 表达式语言解析器

<application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>

由于 jsf session 与 mvc session 不同,因此您还必须在 Store 对象的定义中使用单例范围。

@Scope(value = "singleton"........

推荐阅读