看了《 使用JSF 构建数据库驱动的应用程序》 一文后,动手做了练习。这是一个 订阅时事通讯的示例 Web 应用程序。订户通过提供他们的电子邮件地址、姓名和首选项进行注册。他们还必须选择一个口令,
以便以后可以更改他们的配置文件。 收获不少。
1、
这个没有什么可说的。
2、
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<head>
</body>
典型的jstl加jsf,看来要好好学习jsp2.0了,赶上不形势啊!
点击链接
Subscribe可进入subscribe.jsp(如图一),填订单页面。
命令按钮的"action"绑定到了视图loginInfo Bean的loginAction()方法,
loginAction() 方法会根据登录用户的角色(订户或管理员)返回 profile 或 list(导航法则在faces-config.xml文件中定义) ,
请求转向订户修改配置文件页面 profile.jsp(图二) 或订户列表页面 list.jsp(图三)。先看看LoginInfoBean.java源码:
package jsfdb.view;
import jsfdb.model.LoginInfo;
import jsfdb.model.Subscriber;
import jsfdb.model.ModelUtils;
import jsfdb.model.err.LoginException;
import jsfdb.model.err.IncorrectPasswordException;
import jsfdb.model.err.UnknownSubscriberException;
public class LoginInfoBean extends LoginInfo {
public String loginAction() {
//初始化一个SubscriberBean对象
SubscriberBean subscriber= (SubscriberBean) ViewUtils.eval("#{subscriber}");
//获取管理员的邮件地址,管理员的邮件在web.xml文件中配置
String adminEmail= (String) ViewUtils.eval("#{initParam.adminEmail}");
try {
Subscriber selectedSubscriber
= ModelUtils.getSubscriberDAO().select(this);//通过数据库验证口令与email
ModelUtils.copy(selectedSubscriber, subscriber);//订户数据复制进视图bean
subscriber.setLoggedIn(true);//登录标志设为true
if (subscriber.getEmail().equals(adminEmail))
return "list";//如果是超级管理员,转向list.jsp
else
return "profile";//如果是订户,转向profile.jsp
} catch (LoginException x) {
ViewUtils.addExceptionMessage(x);
return null;
} catch (UnknownSubscriberException x) {
ViewUtils.addExceptionMessage(x);
return null;
} catch (IncorrectPasswordException x) {
ViewUtils.addExceptionMessage(x);
return null;
}
}
}
图一(填订单)
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<head>
</body>
这是SubscriberBean.java源码
package jsfdb.view;
import jsfdb.model.Subscriber;
import jsfdb.model.ModelUtils;
import jsfdb.model.err.ProfileException;
import jsfdb.model.err.SubscribeException;
import jsfdb.model.err.UnsubscribeException;
import javax.faces.component.UIComponent;
import javax.faces.component.EditableValueHolder;
import javax.faces.context.FacesContext;
public class SubscriberBean extends Subscriber {
public final static String INVALID_EMAIL_ID
= "jsfdb.view.SubscriberBean.INVALID_EMAIL";
public final static String SELECT_NEWSLETTER_ID
= "jsfdb.view.SubscriberBean.SELECT_NEWSLETTER";
private transient boolean loggedIn = false;
public boolean isLoggedIn() {
return loggedIn;
}
public void setLoggedIn(boolean loggedIn) {
this.loggedIn = loggedIn;
}
public void emailValidator(FacesContext context, UIComponent comp, Object value) {
String email = (String) value;
if (email.indexOf("@") == -1) {
String compId = comp.getClientId(context);
ViewUtils.addErrorMessage(context, compId, INVALID_EMAIL_ID);
((EditableValueHolder) comp).setValid(false);
}
}
public String subscribeAction() {
if (countNewsletters() == 0) {
ViewUtils.addErrorMessage(
FacesContext.getCurrentInstance(),
null, SELECT_NEWSLETTER_ID);
return null;
}
try {
ModelUtils.getSubscriberDAO().insert(this);
setLoggedIn(true);
return "subscribed";
} catch (SubscribeException x) {
ViewUtils.addExceptionMessage(x);
return null;
}
}
public String profileAction() {
if (!loggedIn)
return "login";
if (countNewsletters() == 0) {
ViewUtils.addErrorMessage(
FacesContext.getCurrentInstance(),
null, SELECT_NEWSLETTER_ID);
return null;
}
try {
ModelUtils.getSubscriberDAO().update(this);
return null;
} catch (ProfileException x) {
ViewUtils.addExceptionMessage(x);
return null;
}
}
public String unsubscribeAction() {
if (!loggedIn)
return "login";
try {
ModelUtils.getSubscriberDAO().delete(this);
return "unsubscribed";
} catch (UnsubscribeException x) {
ViewUtils.addExceptionMessage(x);
return null;
}
}
public String cancelAction() {
if (!loggedIn)
return "login";
else
return "cancel";
}
public int getDailyConst() {
return TYPE_DAILY;
}
public int getWeeklyConst() {
return TYPE_WEEKLY;
}
public int getMonthlyConst() {
return TYPE_MONTHLY;
}
}
这是修改配置的页面:
图二
再看看list.jsp
图三
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
SELECT * FROM subscribers ORDER BY subscriberEmail
<head>
</body>
这个页面用jstl标记访问数据库!
数据适配层和数据访问对象DAO
这个应用通过ModelUtils类访问后端数据源,
提供了 SubscriberDAO 接口的两个实现,一个(JDBCSubscriberDAO.java)基于 JDBC API,另一个(TopLinkSubscriberDAO.java)使用 Oracle TopLink。下面是ModelUtils类的源码:
package jsfdb.model;
import jsfdb.model.dao.SubscriberDAO;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.beans.IntrospectionException;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.ResourceBundle;
import java.util.MissingResourceException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ModelUtils {
public static final String RESOURCES
= ModelUtils.class.getPackage().getName() + ".res.ModelResources";
private static ResourceBundle resources;
private static SubscriberDAO subscriberDAO;
public static void log(Throwable x) {
Logger.global.log(Level.SEVERE, x.getMessage(), x);
}
public static synchronized ResourceBundle getResources() {
if (resources == null)
try {
resources = ResourceBundle.getBundle(RESOURCES);
} catch (MissingResourceException x) {
log(x);
throw new InternalError(x.getMessage());
}
return resources;
}
public static String getResource(String key) {
return getResources().getString(key);
}
public synchronized static SubscriberDAO getSubscriberDAO() {
if (subscriberDAO == null)
try {
Class daoClass = Class.forName(getResource("DAO"));
subscriberDAO
= (SubscriberDAO) daoClass.newInstance();
} catch (ClassNotFoundException x) {
log(x);
throw new InternalError(x.getMessage());
} catch (IllegalAccessException x) {
log(x);
throw new InternalError(x.getMessage());
} catch (InstantiationException x) {
log(x);
throw new InternalError(x.getMessage());
}
return subscriberDAO;
}
public static void copy(Object source, Object dest) {
try {
Class sourceClass = source.getClass();
Class destClass = dest.getClass();
BeanInfo info = Introspector.getBeanInfo(sourceClass);
PropertyDescriptor props[]
= info.getPropertyDescriptors();
Object noParams[] = new Object[0];
Object oneParam[] = new Object[1];
for (int i = 0; i < props.length; i++) {
Method getter = props[i].getReadMethod();
if (getter == null)
continue;
Object value = getter.invoke(source, noParams);
Method setter = props[i].getWriteMethod();
if (setter != null && sourceClass != destClass)
try {
setter = destClass.getMethod(
setter.getName(),
setter.getParameterTypes());
} catch (NoSuchMethodException x) {
setter = null;
}
if (setter != null) {
oneParam[0] = value;
setter.invoke(dest, oneParam);
}
}
} catch (IntrospectionException x) {
log(x);
throw new InternalError(x.getMessage());
} catch (IllegalAccessException x) {
log(x);
throw new InternalError(x.getMessage());
} catch (IllegalArgumentException x) {
log(x);
throw new InternalError(x.getMessage());
} catch (SecurityException x) {
log(x);
throw new InternalError(x.getMessage());
} catch (InvocationTargetException x) {
log(x.getTargetException());
throw new InternalError(
x.getTargetException().getMessage());
}
}
}
此类的getSubscriberDAO()方法返回 SubscriberDAO 接口的一个实例,该接口定义了在关系数据库中选择、删除、插入、更新 Subscriber 对象的方法。 你的应用中具体使用哪一个后端数据源,在 ModelResources资源包有一个 DAO 参数,用于指定要使用的 DAO 实现.
这是ModelResources.properties文件:
DAO=jsfdb.model.dao.JDBCSubscriberDAO
# DAO=jsfdb.model.dao.TopLinkSubscriberDAO
TopLinkSession=JSFDBSession
JavaCompEnv=java:comp/env
DataSource=jdbc/OracleDS
SelectStatement=SELECT \
subscriberPassword, \
subscriberName, \
managerFlag, \
developerFlag, \
administratorFlag, \
subscriptionType \
FROM subscribers \
WHERE subscriberEmail=?
InsertStatement=INSERT INTO subscribers ( \
subscriberEmail, \
subscriberPassword, \
subscriberName, \
managerFlag, \
developerFlag, \
administratorFlag, \
subscriptionType ) \
VALUES (?, ?, ?, ?, ?, ?, ?)
UpdateStatement=UPDATE subscribers SET \
subscriberPassword=?, \
subscriberName=?, \
managerFlag=?, \
developerFlag=?, \
administratorFlag=?, \
subscriptionType=? \
WHERE subscriberEmail=?
DeleteStatement=DELETE FROM subscribers \
WHERE subscriberEmail=?
SubscribeException=Subscription failed. \
Please try another email address.
ProfileException=Couln't update your profile. \
Please contact the Webmaster.
UnsubscribeException=Unsubscription failed. \
Please contact the Webmaster.
LoginException=Login failed. \
Please contact the Webmaster.
UnknownSubscriberException=Unknown subscriber. \
Please subscribe.
IncorrectPasswordException=Incorrect password. \
Please try to login again.
我做这个例子时用了Access数据库
package jsfdb.model.dao; import jsfdb.model.LoginInfo; import jsfdb.model.Subscriber; import jsfdb.model.ModelUtils; import jsfdb.model.err.IncorrectPasswordException; import jsfdb.model.err.LoginException; import jsfdb.model.err.ProfileException; import jsfdb.model.err.SubscribeException; import jsfdb.model.err.UnknownSubscriberException; import jsfdb.model.err.UnsubscribeException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException;
public class JDBCSubscriberDAO implements SubscriberDAO { // private DataSource dataSource; public JDBCSubscriberDAO() { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); } private void close(Connection conn, PreparedStatement ps) throws SQLException { if (ps != null) ps.close(); if (conn != null) conn.close(); } public Subscriber select(LoginInfo loginInfo) throws LoginException, UnknownSubscriberException, IncorrectPasswordException { Connection conn = DriverManager.getConnection("jdbc:odbc:jsfdb"); PreparedStatement ps = null; try { conn = dataSource.getConnection(); ps = conn.prepareStatement( ModelUtils.getResource("SelectStatement")); ps.setString(1, loginInfo.getEmail()); ResultSet rs = ps.executeQuery(); if (!rs.next()) throw new UnknownSubscriberException(); String password = rs.getString(1); if (!loginInfo.getPassword().equals(password)) throw new IncorrectPasswordException(); Subscriber subscriber = new Subscriber(); subscriber.setEmail(loginInfo.getEmail()); subscriber.setPassword(loginInfo.getPassword()); subscriber.setName(rs.getString(2)); subscriber.setManager(rs.getBoolean(3)); subscriber.setDeveloper(rs.getBoolean(4)); subscriber.setAdministrator(rs.getBoolean(5)); subscriber.setSubscriptionType(rs.getInt(6)); return subscriber; } catch (SQLException x) { ModelUtils.log(x); throw new LoginException(); } finally { try { close(conn, ps); } catch (SQLException x) { ModelUtils.log(x); throw new LoginException(); } } } public void insert(Subscriber subscriber) throws SubscribeException { Connection conn = DriverManager.getConnection("jdbc:odbc:jsfdb"); PreparedStatement ps = null; try { conn = dataSource.getConnection(); ps = conn.prepareStatement( ModelUtils.getResource("InsertStatement")); ps.setString(1, subscriber.getEmail()); ps.setString(2, subscriber.getPassword()); ps.setString(3, subscriber.getName()); ps.setBoolean(4, subscriber.isManager()); ps.setBoolean(5, subscriber.isDeveloper()); ps.setBoolean(6, subscriber.isAdministrator()); ps.setInt(7, subscriber.getSubscriptionType()); int rowCount = ps.executeUpdate(); if (rowCount != 1) throw new SubscribeException(); } catch (SQLException x) { ModelUtils.log(x); throw new SubscribeException(); } finally { try { close(conn, ps); } catch (SQLException x) { ModelUtils.log(x); throw new SubscribeException(); } } } public void update(Subscriber subscriber) throws ProfileException { Connection conn = DriverManager.getConnection("jdbc:odbc:jsfdb"); PreparedStatement ps = null; try { conn = dataSource.getConnection(); ps = conn.prepareStatement( ModelUtils.getResource("UpdateStatement")); ps.setString(1, subscriber.getPassword()); ps.setString(2, subscriber.getName()); ps.setBoolean(3, subscriber.isManager()); ps.setBoolean(4, subscriber.isDeveloper()); ps.setBoolean(5, subscriber.isAdministrator()); ps.setInt(6, subscriber.getSubscriptionType()); ps.setString(7, subscriber.getEmail()); int rowCount = ps.executeUpdate(); if (rowCount != 1) throw new ProfileException(); } catch (SQLException x) { ModelUtils.log(x); throw new ProfileException(); } finally { try { close(conn, ps); } catch (SQLException x) { ModelUtils.log(x); throw new ProfileException(); } } } public void delete(Subscriber subscriber) throws UnsubscribeException { Connection conn = DriverManager.getConnection("jdbc:odbc:jsfdb"); PreparedStatement ps = null; try { conn = dataSource.getConnection(); ps = conn.prepareStatement( ModelUtils.getResource("DeleteStatement")); ps.setString(1, subscriber.getEmail()); int rowCount = ps.executeUpdate(); if (rowCount != 1) throw new UnsubscribeException(); } catch (SQLException x) { ModelUtils.log(x); throw new UnsubscribeException(); } finally { try { close(conn, ps); } catch (SQLException x) { ModelUtils.log(x); throw new UnsubscribeException(); } } } }
↑返回目录
前一篇: JSF实例学习--JSF Weekly 电子报订阅
后一篇: 面向对象的类设计原则