jsf + spring + hibernate 开发示例
以下是用例图,用户可以进行以下操作:登录、浏览、注册、修改、删除、退出
创建 user 工程
添加 jsf 框架、spring 框架、hibernate 框架
这里的JSF框架在MyEclipse中使用MyFaces1.0.9,并且在弹出是否增加j2ee包的对话框时,请选择No,如果选择了Yes的话会发现jsp页面无法在Tomcat中显示的问题,不过换了resin3就可以了,请不要使用Sun JSF,因为后面的集成部份必需使用MyFaces,当然,如果有朋友会集成Sun JSF的话也不勉强,并请你教我怎么集成!
在添加spring框架时,选中所有的可选项,具体应该使用哪一个我也分不清,创建完成后需要对 web.xml 文件进行配置,加入以下内容:
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
在添加完Hibernate时,记得把jdbc文件拷贝到lib目录
使用三层结构: WEB 层、MODEL 层和 DATA 层
启动mysql并创建USERS表
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(100) NOT NULL default '',
`password` varchar(100) NOT NULL default '',
PRIMARY KEY (`id`)
)
新建三个包,分别为:com.web、com.model、com.data
其中 com.web 包中包含以下包:
com.web.bo、com.web.vo
其中 com.model 包中包含以下包:
com.model.service、com.model.service.impl、com.model.exception
其中 com.data 包中包含以下几个包:
com.data.dao、com.data.dao.impl
包 com.web.bo ,用来存放映射后的BO(业务)层的对像
包 com.web.vo ,用来存放映射后的VO(业务)层的对像
包 com.model.service , 用来存放 service(服务)层的对像的接口
包 com.model.service.impl , 用来存放 service(服务)层的对像接口的实例
包 com.model.exception ,用来存放自定义的异常处理类
包 com.data.dao ,用来存放DAO(数据访问)层的对像的接口
包 com.data.dao.impl ,用来存放DAO(数据访问)层的对像接口的实例
配置完成 hibernate 后对表进行映射操作,将映射文件保存到com.web.bo包内
创建一个异常处理类 UserException.java,内容如下:
public class UserException extends Exception {
public UserException(){
super();
}
public UserException(String msg){
super(msg);
}
public UserException(String msg, Throwable cause) {
super(msg, cause);
}
}
使用 数据浏览工具 创建 User 对像
创建 JSF 绑定类 UserBaseBean 和 UserBean ,UserBaseBean 是 UserBean 的基类
UserBaseBean 的内容如下:
package com.web.vo;
public class UserBaseBean {
}
UserBean 的内容如下:
package com.web.vo;
import com.model.exception.UserException;
import com.web.bo.User;
public class UserBean extends UserBaseBean {
private User user=new User();
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
// 登录事件
public String loginAction(){
return null;
}
// 退出事件
public String logoutAction(){
return null;
}
// 注册事件
public String registerAction(){
return null;
}
// 删除事件
public String deleteAction(){
return null;
}
// 编辑事件
public String editAction(){
return null;
}
// 浏览事件
public String browseAction(){
return null;
}
}
创建 IUserService 接口,内容如下:
此接口的作用是由 UI 层来调用她,她再调用 data 层来访问数据库处理数据。
package com.model.service;
import java.util.List;
import com.web.bo.User;
import com.model.exception.UserException;
public interface IUserService {
public User login(String username,String password) throws UserException;
public boolean logout() throws UserException;
public boolean register(User user) throws UserException;
public boolean delete(Integer uid) throws UserException;
public boolean edit(User user) throws UserException;
public List browse() throws UserException;
}
以上方法都是业务逻辑,从单词中应该可以看出是做什么用的
创建 IUserService 接口的实现 UserServiceImpl 类,内容如下:
package com.model.service.impl;
import java.util.List;
import com.model.exception.IUserService;
import com.model.exception.UserException;
import com.web.bo.User;
public class UserServiceImpl implements IUserService {
public User login(String username, String password) throws UserException {
// TODO Auto-generated method stub
return null;
}
public boolean logout() throws UserException {
// TODO Auto-generated method stub
return false;
}
public boolean register(User user) throws UserException {
// TODO Auto-generated method stub
return false;
}
public boolean delete(Integer uid) throws UserException {
// TODO Auto-generated method stub
return false;
}
public boolean edit(User user) throws UserException {
// TODO Auto-generated method stub
return false;
}
public List browse() throws UserException {
// TODO Auto-generated method stub
return null;
}
}
修改 UserBaseBean ,这个类只有一个属性为 IUserService 对像,内容如下:
import com.model.service.IUserService;
public class UserBaseBean {
private IUserService userService;
public IUserService getUserService() {
return userService;
}
public void setUserService(IUserService userService) {
this.userService = userService;
}
}
配置 UserService,此类将由 Spring 来管理,内容如下:
在spring配置文件 applicationContext.xml 文件中配置 userService 对像,配置内容如下:
<bean id="userService" class="com.model.service.impl.UserServiceImpl"></bean>
为了让 JSF 能够获得 Spring 的配置信息,需要使用 Spring 提供的 DelegatingVariableResolver 类来进行集成
这时只需要增加 JSF 的配置信息即可
打开 faces-config.xml 文件
按下 Ctrl + N 键,选择 Application 向导
点击 下一步 ,在对话框中填入以下值:
Variable Resolver:org.springframework.web.jsf.DelegatingVariableResolver
点击 完成 生成以下配置信息:
<application>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
</application>
这段配置信息的功能为使用Spring的变量解析器来替换JSF的变量解析器
按下 Ctrl + N 键,使用向导来配置 JSF 的 Managed Bean
在弹出的对话框中填入以下值:
Name:userBean 因为 UserBean 类是继承于 UserBaseBean 类,所以注入时实际上却是要注入到 UserBean 而不是 UserBaseBean
Class:com.web.vo.UserBean
Scope:session 这个很重要,Bean中的对像将会自动保存在session中,这样页面跳转之后也可以使用getter方法来获取数据
点击 Add 按钮,创建一个属性
Name:userService 这里的值对应 UserBaseBean 类中的 userService 对像,名称不能弄错
点击下一步
Name:#{userService} 这里的值将会读取 spring 配置文件并创建一个 userService 对像并注入到 UserBean 对像中
点击完成后生成以下配置信息:
<managed-bean>
<managed-bean-name>userBean</managed-bean-name>
<managed-bean-class>com.web.vo.UserBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>userService</property-name>
<value>#{userService}</value>
</managed-property>
</managed-bean>
创建 IUserDao 接口,内容如下:
package com.data.dao;
import java.util.List;
import com.web.bo.User;
public interface IUserDao {
public User getUser(String username);
public boolean addUser(User user);
public boolean delUser(Integer uid);
public boolean updateUser(User user);
public List getAllUser();
}
以上全部是数据库操作的方法,具体操作由下面的类来负责
创建 IUsersDao 接口的实现 UserDaoImpl 类,因为要使用到 Hibernate 所在得继承 HibernateDaoSupport
只有继承了这个类才可以注入 sessionFactory 对像(注意版本),内容如下:
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.data.dao.IUserDao;
import com.web.bo.User;
public class UserDaoImpl extends HibernateDaoSupport implements IUserDao {
public User getUser(String username) {
// TODO Auto-generated method stub
return null;
}
public boolean addUser(User user) {
// TODO Auto-generated method stub
return false;
}
public boolean delUser(Integer uid) {
// TODO Auto-generated method stub
return false;
}
public boolean updateUser(User user) {
// TODO Auto-generated method stub
return false;
}
public List getAllUser() {
// TODO Auto-generated method stub
return null;
}
}
现在修改 UserServiceImpl.java 文件,增一个 IUserDao 对像的属性,并添加 getter 、 setter 方法
private IUserDao userDao;
public IUserDao getUserDao() {
return userDao;
}
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
修改 Spring 配置文件,增加数据库相关部份的配置信息,内容如下:
<!-- 配置 dataSource 使用Hibernate2的话要修改下面的第一行 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/test</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>root</value>
</property>
</bean>
<!-- 配置sessionFactory, 注意这里引入的包的不同 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="mappingResources">
<list>
<value>com/web/bo/User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
增加 userDao对像 注入到 userService 对像,修改后的配置文件内容如下:
<bean id="userDao" class="com.data.dao.impl.UserDaoImpl">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<bean id="userService" class="com.model.service.impl.UserServiceImpl">
<property name="userDao">
<ref bean="userDao" />
</property>
</bean>
现在整个模型已经搭建完毕了,后面仅仅是修改代码的问题了
*****************************************************************************************
下面是页面设计部份
以下是页面导航图例
导航内容如下:
<navigation-rule>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<to-view-id>/login.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/browse.jsp</from-view-id>
<navigation-case>
<from-outcome>Delete</from-outcome>
<to-view-id>/browse.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>Logout</from-outcome>
<to-view-id>/index.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>Edit</from-outcome>
<to-view-id>/edit.jsp</to-view-id>
<redirect></redirect>
</navigation-case>
<navigation-case>
<from-outcome>Register</from-outcome>
<to-view-id>/register.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>Find:success</from-outcome>
<to-view-id>/browse.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/error.jsp</from-view-id>
</navigation-rule>
<navigation-rule>
<from-view-id>/login.jsp</from-view-id>
<navigation-case>
<from-outcome>Login:failure</from-outcome>
<to-view-id>/error.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>Login:success</from-outcome>
<to-view-id>/browse.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/edit.jsp</from-view-id>
<navigation-case>
<from-outcome>Edit:success</from-outcome>
<to-view-id>/browse.jsp</to-view-id>
<redirect /></navigation-case>
<navigation-case>
<from-outcome>Edit:failure</from-outcome>
<to-view-id>/edit.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/register.jsp</from-view-id>
<navigation-case>
<from-outcome>Register:success</from-outcome>
<to-view-id>/browse.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>Register:failure</from-outcome>
<to-view-id>/register.jsp</to-view-id>
</navigation-case>
</navigation-rule>
现然先用熟悉的 登录(login) 来做一下测试
首先打开 index.jsp 文件,修改后文件内容如下:
<html>
<head>
<title>Index</title>
</head>
<body>
<a href="login.faces">Login</a>
</body>
</html>
修改 login.jsp 文件,内容如下:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<html>
<head>
<title>Login</title>
</head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="username" value="User Name:" />
<h:inputText id="username" value="#{userBean.user.username}" required="true" />
<h:message for="username" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret id="password" value="#{userBean.user.password}" required="true" />
<h:message for="password" />
</h:panelGrid>
<h:panelGrid>
<h:panelGroup>
<h:commandButton value="Login" action="#{userBean.loginAction}" />
</h:panelGroup>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
其中绑定 UserBean 的内容有三处,两个属性:#{userBean.user.username}、#{userBean.user.password} 一个事件 #{userBean.loginAction}
修改 error.jsp 文件,内容如下:
<html>
<head>
<title>Error!!!</title>
</head>
<body>
Error!!!<br>
</body>
</html>
修改 UserBean 的 loginAction 事件内容,代码如下:
public String loginAction() throws UserException{
User user=this.getUserService().login(this.user.getUsername(),this.user.getPassword());
if(user==null)
return "Login:failure";
return "Login:success";
}
注意返回的字符串要和页面设计时所定义的字符串一至
这个事件为点击页面中的 Login 按钮后执行 UserServiceImpl 对像中的 login() 方法,并返回一个 User 对像
现在修改 UserServiceImpl 对像中的 login() 方法,代码如下:
public User login(String username, String password) throws UserException {
// 调用 UserDao 成功后得到一个 User 对像
try {
User user=userDao.getUser(username);
if(user==null)
return null;
// 判断密码是否正确
if(!password.equals(user.getPassword()))
return null;
return user;
} catch (HibernateObjectRetrievalFailureException he) {
throw new UserException(username);
}
}
现在轮到 UserDaoImpl 对像的 getUser() 方法了,代码如下:
public User getUser(String username) {
// 根据用户名得到 User 对像
String hql="from User u where username=?";
List users=this.getHibernateTemplate().find(hql,username);
if(users.size()==1)
return (User)users.get(0);
return null;
}
好了,登录过程已经OK了!!!,手动在数据库 User 表中插入一条记录,以作为初始管理员。
现在做 浏览页
修改 browse.jsp 文件,内容如下:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<html>
<head>
<title>
Browse User
</title>
</head>
<body>
<f:view>
<h:form id="allUser">
<h:dataTable id="table" value="#{userBean.users}" var="u" border="1" width="80%">
<h:column>
<f:facet name="header">
<f:verbatim escape="true">ID</f:verbatim>
</f:facet>
<h:outputText value="#{u.id}" />
</h:column>
<h:column>
<f:facet name="header">
<f:verbatim escape="true">User Name</f:verbatim>
</f:facet>
<h:commandLink id="username" action="#{userBean.editAction}" value="#{u.username}">
</h:commandLink>
</h:column>
<h:column>
<f:facet name="header">
<f:verbatim escape="true">Password</f:verbatim>
</f:facet>
<h:outputText value="#{u.password}" />
</h:column>
</h:dataTable>
</h:form>
</f:view>
</body>
</html>
这个页面中使用了一个新值,#{userBean.users},这是一个数据集,是一个 DataModel 接口的实现对像(ListDataModel),也可以是 List
还有一个事件 #{userBean.editAction} 这个事件出现在用户名上,点击用户名称后就会跳转到编辑页面
页面中使用了 JSF 的 dataTable 组件来呈现数据集,点击 Find 链接后将查询所有用户并显示
现在需要在 UserBean 中增加一个 users 的属性
private DataModel users=new ListDataModel();
public DataModel getUsers() throws UserException {
// 此方法是在页面获取users前从数据库中查询得到users
// 此方法只有放到这里,Table中的链接才可以实现userBean中的方法
// 查询方法只能在这里,而原来设定的browseAction()方法已经不需要了。
users.setWrappedData(this.getUserService().browse());
return users;
}
public void setUsers(DataModel users) {
this.users = users;
}
接下来修改 UserServiceImpl 的 browse() 方法
public List browse() throws UserException {
// 得到所有用户
try {
List users=userDao.getAllUser();
return users;
} catch (HibernateObjectRetrievalFailureException he) {
throw new UserException("Browse Users");
}
}
最后修改 UserDaoImpl 的 getAllUser() 方法
public List getAllUser() {
// 查询所有用户记录
String hql="from User u";
List users=this.getHibernateTemplate().find(hql);
return users;
}
好了,浏览已经完成了
现在做注册新用户
修改 register.jsp 文件,内容如下
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<html>
<head>
<title>Register</title>
</head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="username" value="User Name:" />
<h:inputText id="username" value="#{userBean.user.username}" required="true" />
<h:message for="username" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret id="password" value="#{userBean.user.password}" required="true" />
<h:message for="password" />
</h:panelGrid>
<h:panelGrid>
<h:panelGroup>
<h:commandButton value="Register" action="#{userBean.registerAction}" />
</h:panelGroup>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
修改 browse.jsp 文件,内容如下
<f:view>
<h:outputLink id="register" value="register.faces">
<h:outputText value="Register User"></h:outputText>
</h:outputLink>
<h:form id="allUser">
修改 UserBean.java 文件的 registerAction() 方法
// 注册事件
public String registerAction() throws UserException {
User newuser=new User();
newuser.setUsername(user.getUsername());
newuser.setPassword(user.getPassword());
if(this.getUserService().register(user))
return "Register:success";
else
return "Register:failure";
}
打开 UserServiceImpl.java 文件,修改 register() 方法
public boolean register(User user) throws UserException {
// 注册新用户
return userDao.addUser(user);
}
打开 UserDaoImpl.java 文件,修改 addUser() 方法
public boolean addUser(User user) {
// 增加新用户
this.getHibernateTemplate().save(user);
return true;
}
好了,注册用户完成!
现在做修改 ,edit.jsp 文件内容如下:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<html>
<head>
<title>Edit</title>
</head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="username" value="User Name:" />
<h:inputText id="username" value="#{userBean.user.username}" required="true" />
<h:message for="username" />
<h:outputLabel for="password" value="Password:" />
<h:inputText id="password" value="#{userBean.user.password}" required="true" />
<h:message for="password" />
</h:panelGrid>
<h:panelGrid>
<h:panelGroup>
<h:commandButton value="UpDate" action="#{userBean.updateAction}" />
</h:panelGroup>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
修改 UserBean 的 editAction 方法
// 编辑事件,现用来做为导航事件
public String editAction() {
// 此方法可以从 users 对像中得到点击后的 user 对像
this.setUser((User)users.getRowData());
return "Edit";
}
在 UserBean 中增加 updateAction 方法
// 修改事件
public String updateAction() throws UserException{
if(this.getUserService().edit(user)){
users.setWrappedData(this.getUserService().browse());
return "Edit:success";
}
else
return "Edit:failure";
}
修改 UserServiceImpl 中的 edit() 方法
public boolean edit(User user) throws UserException {
// 修改用户密码
try {
// 先读取 User 对像
return userDao.updateUser(user);
} catch (HibernateObjectRetrievalFailureException he) {
throw new UserException("Update user");
}
}
修改 UserDaoImpl 的 updateUser() 方法
public boolean updateUser(User user) {
// 修改User
this.getHibernateTemplate().update(user);
return true;
}
好了,修改也已经完成了。
以下是注意的地方:
配置文件中 UserBean 的配置信息中
<managed-bean-scope>session</managed-bean-scope>
这里一定要使用 session,如果使用的是 request 的话会造成 User 对像中的 ID 值变为 null ,这时就不能进行 UpDate 操作了
现在开始做 删除
打开 browse.jsp 文件,增加以下内容
...
<h:column>
<f:facet name="header">
<f:verbatim escape="true">Operation</f:verbatim>
</f:facet>
<h:commandLink id="operation" action="#{userBean.deleteAction}">
<h:outputText value="Delete" />
</h:commandLink>
</h:column>
</h:dataTable>
...
这里是面 Table 中增加一列,此列的作用是增加一个链接,点击此链接后将执行 UserBean 中的 deleteAction() 方法
打开 UserBean.java 文件,修改 deleteAction() 事件
// 删除事件
public String deleteAction() throws UserException {
this.setUser((User)users.getRowData());
this.getUserService().delete(user.getId());
return null;
}
打开 UserServiceImpl.java 文件,修改 delete() 方法
public boolean delete(Integer uid) throws UserException {
// 删除用户
return userDao.delUser(uid);
}
打开 UserDaoImpl.java 文件,修改 delUser() 方法
public boolean delUser(Integer uid) {
// 删除一个用户
User user=(User) this.getHibernateTemplate().load(User.class,uid);
this.getHibernateTemplate().delete(user);
return true;
}
删除事件已经完成!
现在做最后一个事件,注销事件
修改 browse.jsp 文件,内容如下
</h:form>
<br>
<h:commandLink id="logout" action="#{userBean.logoutAction}" value="Logout">
</h:commandLink>
</f:view>
修改 UserBean.java 文件的 logoutAction() 方法
// 退出事件
public String logoutAction() {
this.setUser(null);
return "Logout";
}
好了,注销已经完成了!
现在所有的代码编写都已经完成,可以进行完整的测试了!