我刚开始使用JSF,我不明白为什么我的服务没有被注入到我的控制器中。
@ManagedBean
@ApplicationScoped
public class MyController {
@ManagedProperty(value = "#{service}")
private MyService service;
public void setService(MyService service) {
this.service = service;
}
public MyService getService() {
return service;
}
public void callToService(AjaxBehaviorEvent event) {
System.out.println(service);
}
}
Q: @ManagedProperty
中值的目的是什么?
@ManagedBean
@ApplicationScoped
public class MyService {
}
点击按钮,方法为callToService
,业务为null
。
<h:form>
<h:commandButton value="Call Service">
<f:ajax listener="#{myController.callToService}"/>
</h:commandButton>
</h:form>
当#{service}
实际解析为null
时就会发生这种情况。
当您使用@ManagedBean
而不使用name
属性时,托管bean名称将默认解析为第一个字符小写的类名(至少,符合Javabeans规范),因此您的MyService
bean将有效地获得myService
的托管bean名称。
基本上有两种方法来解决这个问题,
-
用
#{myService}
代替@ManagedProperty("#{myService}") private MyService service;
-
您自己指定托管bean名称,以便它作为
#{service}
可用。@ManagedBean(name="service") @ApplicationScoped public class MyService { }
与具体问题无关,因为您似乎对ajax事件不感兴趣,而是对动作事件感兴趣,那么您还可以简化<f:ajax>
的使用,如下所示:
<h:commandButton value="Call Service" action="#{myController.callToService}">
<f:ajax />
</h:commandButton>
public void callToService() {
System.out.println(service);
}
,这样当最终用户没有启用JS时,它仍然可以工作。
最后,业务服务通常被设计为@Stateless
EJB,而不是JSF托管bean,因为它应该与JSF视图没有直接关系。你可以直接使用
@EJB
private MyService service;