我第一次尝试使用带有Eclipse的JSF 2.0模板,但我遇到了问题。
原始index.xhtml
页面正常工作,当我点击按钮时,一切正常。但是,如果我更改索引页面以使其使用模板文件,它将无法正常工作。修改后的index.xhtml
页面位于:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="/templates/main-template.xhtml">
<ui:define name="title">
Simulator using JSF 2.0 - Test Version 2
</ui:define>
<ui:define name="header">
Home Page of the Simulator using JSF 2.0 - Test Version 2
</ui:define>
<ui:define name="body">
Click on the button to select the required option
<h:outputText value="and login" rendered="#{!login.loggedIn}"/>
<h:form prependId="false">
<h:commandButton value="Option 1" action="#{login.option1}"/>
<h:commandButton value="Option 2" action="#{login.option2}"/>
<h:commandButton value="Option 3" action="#{login.option3}"/>
<h:commandButton value="Logout" disabled="#{!login.loggedIn}" action="#{login.logout}"/>
</h:form>
</ui:define>
</ui:composition>
,模板文件main.template.xhtml
位于子文件夹模板中,位于:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>
<ui:insert name="title">Title</ui:insert>
</title>
</h:head>
<h:body>
<ui:insert name="header">Header</ui:insert>
<br/>
We are in template.xhtml
<br/>
<ui:insert name="body">Body</ui:insert>
</h:body>
</html>
如果我使用index.xhtml中的“h”标记删除所有代码,则该文件会正确获取templates / main-template.xhtml中的代码,因此路径正确。但是,如果我包含带有“h”标签的代码,就像在这里一样,Eclipse会抱怨标签无法识别且页面失败。
如果我在顶部包含行xmlns:h="http://java.sun.com/jsf/html"
,那么Eclipse识别出“h”标记并且页面被正确呈现,但是当我单击按钮时应用程序失败,并返回错误:
javax.servlet.ServletException:javax.el.PropertyNotFoundException: /index.xhtml @ 15,68 action =“#{login.option1}”:目标无法访问, 标识符'login'已解析为null
也许某种程度上模板文件中的行xmlns:h="http://java.sun.com/jsf/html"
搞砸了,但模板的整个想法是在模板文件中包含尽可能多的公共代码。
有没有人知道发生了什么,以及解决方案是什么?
web.xml
和faces-config.xml
是标准配置,并且不认为必须对它们进行任何操作。
答案 0 :(得分:1)
您对模板应如何工作的想法似乎是正确的,但我们应该澄清一些要点。也许这会对你有所帮助:
<强>命名空间强>
关于命名空间,无论何时在页面中使用标记库,都应声明它的命名空间。即使您使用的是模板,也已在模板中声明了它们。如果它有帮助,您可以认为名称空间声明不会被继承。
在这种情况下,我看到您index.xhtml
页面正在使用h:commandButton
,但尚未声明其名称空间。
<强>豆强>
对于EL
找到的bean,您应该具有以下内容:
使用@ManagedBean
从javax.faces.bean.ManagedBean
包导入注释的类,如下所示:
import javax.faces.bean.ManagedBean;
@ManagedBean
@ViewScoped
public class Login
{
// ...
}
在这种情况下,按照惯例,EL
的名称login
应该找到您的bean。 (给你的班级名字的第一个字母取消资本)
或者你可以给它一个名字:
import javax.faces.bean.ManagedBean;
@ManagedBean(name="login")
@ViewScoped
public class MyLoginBean
{
// ...
}
在这种情况下,按惯例,它会被称为myLoginBean
,但我们给它命名,在这种情况下为login
,因此EL
应该通过名称login
找到它}。
如果您想使用CDI而不是普通的JSF,您可以使用@Named
注释来定义EL
如何根据相同的命名约定找到您的bean。
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
@Named(value="login")
@RequestScoped
public class MyLoginBean
{
// ...
}
请记住,您希望EL
查找和更改的数据必须具有正确的getter和setter。
<强>提示强>
我建议您创建更简单的代码以测试功能。在这种情况下,您可以先测试模板,然后测试bean,操作等......
我希望它有所帮助。