jsf初步使用
一、新建一个web项目MyJSF
直接把生成index.jsp和web.xml勾选上生成对应的文件。
在web项目跟目录下(一般是web或者是WebRoot,也可以自己指定,本人用的是WebRoot)。
二、在项目中加入jar包
加入jsf需要jar包(javaee.jar、jsf-api.jar、jsf-impl.jar、jstl-1.2.jar),当然jresystem lib必须要有
三、引入jsf插件
1. 在在WebRoot下的WEB-INF文件夹下新建一个faces-config.xml文件(此文件为jsf配置文件)。
2. 在web.xml中加入jsf相关的配置信息
<!-- 指定JSF配置文件的保存位置-->
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
<listener>
<!--指定JS配置监听与上面的jsf配置文件位置配置任取一个即可 -->
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<!—定义jsfServlet -->
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 指定JSF过滤请求的后缀-->
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- JSF采用 xhtml 前缀,定义这个参数让Facelet渲染器能够解释这个前缀-->
默认为.jsp,它自于javax.faces.application.ViewHandler
类中的常量. 常量的名字是 DEFAULT_SUFFIX 值相当于 ".jsp" -->
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jsp</param-value>
</context-param>
四、新建一个java对象并且在jsf注册
1. 新建一个名字为com.myjsf.UserBean的java文件。
2. 修改jsf的配置文件faces-config.xml注册UserBean对象。具体配置为
<managed-bean>
<managed-bean-name>userBean</managed-bean-name>
<managed-bean-class>com.myjsf.UserBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
五、项目结构图
六、指定程序的欢迎页面
在web.xml中加入
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
此页面只作为一个入口,直接跳转到登录界面
Index.xml的内容为<html><head></head><body> <jsp:forward page="page/login.faces"/></body></html>直接跳转到login.jsp页面(此处许注意在forward标签中只能使用.faces后缀,之前在web.xml配置的jsf只过滤.faces结尾的请求)
七、登录功能(action请求类似于strust2的form提交点击按钮后访问对应的方法)
1. 在UserBean中加入两个私有的属性userName、passWord并提供相应的get、set方法。
2. 在UserBean.java中添加一个方法login具体代码如下。
/**
*〈简述〉用户登录方法(点击登录触发此方法)
*〈详细描述〉
* @author zhongjun
* @return
*/
public String login(){
if(null == userName ||"".equals(userName)){
return "failure";
}else{
return "success";
}
}
3. 在faces-config.xml注册登录action方法返回后的跳转具体代码如下:
<navigation-rule>
<!--定义从哪个页面发出的请求,只有此页面的请求才会执行下面的配置此处定义为登录界面请求-->
<from-view-id>/page/login.jsp</from-view-id>
<--登录成功-->
<navigation-case>
<!--定义请求的哪个方法,只有请求此此方法才会执行下面的配置此处定义为登录方法-->
<from-action>#{userBean.login}</from-action>
<--请求方法的返回值,返回的结果会与from-outcome的值对比如果一致就会执行此navigation中的to-view-id跳转到指定的页面,此处定义为跳转到welcome.jsp -->
<from-outcome>success</from-outcome>
<to-view-id>/welcome.jsp</to-view-id>
</navigation-case>
<--登录失败-->
<navigation-case>
<from-action>#{userBean.login}</from-action>
<from-outcome>failure</from-outcome>
<to-view-id>/failure.jsp</to-view-id>
</navigation-case>
</navigation-rule>
4. 在login.jsp登录界面添加一个姓名输入框
<tr>
<td>用户名:</td>
<!—userBean为在faces-config.xml注册UserBean使用的名称,此处在这个输入框里标定这个用户名字段-->
<td>
<h:inputTextid="userNameValue"
value="#{userBean.userName}"></h:inputText>
</td>
</tr>
5. 在login.jsp登录界面添加一个密码输入框
<tr>
<td>密码:</td>
<td>
<!—用法同上-->
<h:inputSecret id="passWordValue" value="#{userBean.passWord}">
</h:inputSecret>
</td>
</tr>
6. 在login.jsp登录界面添加一个登录按钮并且绑定登录请求
<tr>
<!—userBean为在faces-config.xml注册UserBean使用的名称,此处的action就对应UserBean里的login方法,点击此按钮就会直接请求UserBean里的login方法-->
<td colspan="2">
<h:commandButton action="#{userBean.login}"
value="登录"></h:commandButton>
</td>
</tr>
八、验证事件绑定(都在login.jsp里添加相应的html代码)
1. 绑定自带的长度验证
<tr>
<td>密码:</td>
<td>
<!—用法同上-->
<h:inputSecretid="passWordValue" value="#{userBean.passWord}">
<!—长度验证一定要有下面的错误信息提示框<h:message 并且这个提示框要根据密码输入框的id绑定密码输入框-->
<f:validateLengthminimum="0" maximum="12" ></f:validateLength>
</h:inputSecret>
<h:message for="passWordValue"></h:message>
</td>
</tr>
2. 创建自定义验证组件(本人已登录名长度验证为例)
a) 新增自定义验证java类com.myjsf. UserValidator.java这个一定要实现jsf的javax.faces.validator.Validator接口,重写validate方法,代码如下:
package com.myjsf;
importjavax.faces.application.FacesMessage;
importjavax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
importjavax.faces.validator.Validator;
importjavax.faces.validator.ValidatorException;
public class UserValidatorimplements Validator {
@Override
public void validate(FacesContext context, UIComponent component,Object obj)
throws ValidatorException {
String name = (String) obj;
if (name.length() < 2) {
//异常信息
FacesMessage message =
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"名字长度小于2", "名字长度不得小于2");
//抛出异常信息,这个会在页面对应的<h:message中显示
throw newValidatorException(message);
}else if(name.length() > 10 ){
FacesMessage message =
newFacesMessage(FacesMessage.SEVERITY_ERROR,
"名字长度大于10","名字长度不得大于10");
throw newValidatorException(message);
}
}
}
b) 注册自定义验证组件
在faces-config.xml加入以下配置
<!-- 注册自定义验证组件-->
<validator>
<!-- 注册的验证组件引用名称 -->
<validator-id>userValidator</validator-id>
<!-- 要注册的验证组件全路径 -->
<validator-class>com.myjsf.UserValidator</validator-class>
</validator>
c) 在输入框上绑定自定义验证
<tr>
<td>用户名:</td>
<!—userBean为在faces-config.xml注册UserBean使用的名称,此处在这个输入框里标定这个用户名字段-->
<td>
<h:inputTextid="userNameValue" value="#{userBean.userName}">
<!—绑定自定义验证组件validatorId就是自己在
faces-config.xml注册的对应自定义验证组件的引用名 ->
<f:validator validatorId="userValidator" />
</h:inputText>
<!--异常信息提示与自带验证一样-->
<h:message for="userNameValue"></h:message>
</td>
</tr>
九、ValueChangeEvent值变更事件(现以所在城市和所在城市下的区级联下拉框为例)
1. 在UserBean添加几个私有的属性
/**
* 城市(只是为了赋值个可选城市)
*/
private static List<SelectItem>staticCitys;
static{
staticCitys = newArrayList<SelectItem>();
staticCitys.add(newSelectItem("sz", "苏州"));
staticCitys.add(newSelectItem("wx", "无锡"));
}
/**
* 可选所在城市
*/
private List<SelectItem> citys =staticCitys;
/**
* 用户所在城市
*/
private String city;
/**
* 可选城市对应的所在县区
*/
private List<SelectItem> zones = newArrayList<SelectItem>();
/**
* 用户所在县区
*/
private String zone;
并添加对应的get、set方法(staticCitys属性除外,这个不是业务里要用到的,只是为了赋值使用,实际的程序一般都是去数据库里取的)
2. 添加ValueChangeEvent事件
在UserBean里添加方法cityChangeListener
/**
*〈简述〉用户选择城市时的值变更事件(城市值变更时触发此事件)
*〈详细描述〉
* @author zhongjun
* @param cityChangeEvent
*/
public void cityChangeListener(ValueChangeEventcityChangeEvent){
FacesContextcontext = FacesContext.getCurrentInstance();
String newCity =(String)cityChangeEvent.getNewValue();
if("sz".equals(newCity)){
zones = new ArrayList<SelectItem>();
zones.add(newSelectItem("xcq", "相城区"));
zones.add(newSelectItem("yq", "园区"));
zones.add(newSelectItem("xq", "新区"));
}elseif("wx".equals(newCity)){
zones = newArrayList<SelectItem>();
zones.add(newSelectItem("sq", "市区"));
zones.add(newSelectItem("xq", "新区"));
}else{
zones = newArrayList<SelectItem>();
}
context.renderResponse();
}
3. 绑定ValueChangeEvent值变更事件(都在login.jsp里添加相应的html代码)
添加
<tr>
<td>城市:</td>
<td>
<!-- userBean.cityChangeListener为 绑定的ValueChangeEvent值改变事件名οnchange="submit();"这个必须写,当只改变时直接递交此下拉框的值并触发绑定的cityChangeListener的ValueChangeEvent事件-->
<h:selectOneMenu value="#{userBean.city}"
οnchange="submit();"valueChangeListener=
"#{userBean.cityChangeListener}"immediate="true">
<f:selectItemsvalue="#{userBean.citys}" />
</h:selectOneMenu>
</td>
</tr>
<tr>
<td>区域:</td>
<td>
<h:selectOneMenuvalue="#{userBean.zone}">
<f:selectItemsvalue="#{userBean.zones}" />
</h:selectOneMenu>
</td>
</tr>