【IT168 专稿】
摘要:在一个系统中,用户登录功能是最常见的功能之一。本文演示了如何使用JSF+Hibernate+Spring组合实现简单的用户登录功能。
本文使用的开发包为:jsf 1.2_04+hibernate 3.2.2.ga+spring 2.0.5,开发环境为jdk 1.5+myeclipse 6.0+mysql 5.0。
一、三层设计
本文实现的功能虽然简单,但是仍然采用了三层的设计:
1)数据访问层:本文使用Hibernate实现数据访问。
2)业务逻辑层:本文使用Spring组织业务逻辑。
3)表示层,本文使用JSF进行前台显示。
分层的好处在于:有利于系统的扩展性、伸缩性和维护性。
下面让我们演示每一层具体是如何做的,在开始之前,首先看一下我们的数据库设计:
实现登录功能,需要一张userinfo表,包含id, username和password字段。
1. logon.sql:
# # Database structure for database 'logon' # CREATE DATABASE /*!32312 IF NOT EXISTS*/ `logon` /*!40100 DEFAULT CHARACTER SET latin1 */; USE logon; # # Table structure for table 'userinfo' # CREATE TABLE /*!32312 IF NOT EXISTS*/ `userinfo` ( `id` int(11) NOT NULL auto_increment, `username` varchar(100) NOT NULL default '', `password` varchar(100) NOT NULL default '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # # Dumping data for table 'userinfo' # /*!40000 ALTER TABLE userinfo DISABLE KEYS;*/ LOCK TABLES userinfo WRITE; REPLACE INTO userinfo (id, username, password) VALUES (1,'admin','admin'); UNLOCK TABLES; /*!40000 ALTER TABLE userinfo ENABLE KEYS;*/
好了,让我们开始吧!
package com.it168.logon.model.dao; import com.it168.logon.model.businessobject.Userinfo; public interface IUserDAO { public Userinfo getUser(String username); }
接着,UserDAO类实现了IUserDAO接口:
3. com.it168.logon.model.dao.impl.UserDAO.java:
4. com.it168.logon.model.businessobject.Userinfo.java:
package com.it168.logon.model.service; import com.it168.logon.model.businessobject.Userinfo; public interface IUserService { public Userinfo login(String username, String password); }
package com.it168.logon.model.service.impl; import com.it168.logon.model.businessobject.Userinfo; import com.it168.logon.model.dao.impl.UserDAO; import com.it168.logon.model.service.IUserService; public class UserService implements IUserService { private UserDAO userDAO; public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } public Userinfo login(String username, String password) { Userinfo user = this.userDAO.getUser(username); if (user != null) { if (!user.getPassword().equals(password)) { user = null; } } return user; } }
大家或许注意到了这样一句:
private UserDAO userDAO;
这里的UserDAO正是数据访问层中的UserDAO。在UserService类中,我们没有看到UserDAO的实例化过程,既然没有实例化,Userinfo user = this.userDAO.getUser(username);这行代码,又是如何发挥作用的呢?
9. applicationContext.xml代码片断二:
这也正是Spring的强大所在!它将类的实例化过程交给了Spring容器,从而实现了控制反转(IoC)。
public String verify() { Userinfo user = serviceLocator.getUserService().login(this.username, this.password); if (user == null) { this.errorMessage = "登录失败"; this.loggedIn = false; return "failure"; } else { this.loggedIn = true; return "success"; } }
大家可能注意到了这段代码:
package com.it168.logon.view.bean; import javax.faces.context.FacesContext; import javax.servlet.ServletContext; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import com.it168.logon.model.service.IUserService; import com.it168.logon.model.service.impl.UserService; import com.it168.logon.view.servicelocator.IServiceLocator; public class ServiceLocatorBean implements IServiceLocator { private static final String USER_SERVICE_BEAN_NAME = "userService"; private ApplicationContext appContext; private UserService userService; public ServiceLocatorBean() { ServletContext context = (ServletContext) FacesContext .getCurrentInstance().getExternalContext().getContext(); this.appContext = WebApplicationContextUtils .getRequiredWebApplicationContext(context); this.userService = (UserService) this .lookupService(USER_SERVICE_BEAN_NAME); } public IUserService getUserService() { return this.userService; } public Object lookupService(String serviceBeanName) { return appContext.getBean(serviceBeanName); } }
<f:view> <h:form rendered="true"> <div align="center"> <h:outputText escape="false" rendered="true" value="#{userBean.errorMessage}"></h:outputText> </div> <div align="center"> <h:outputText value="用户名: " /> <h:inputText id="username" required="true" value="#{userBean.username}"> </h:inputText> <h:message for="username" /> <br> </div> <div align="center"> <h:outputText value="密 码: " /> <h:inputSecret id="password" required="true" rendered="true" value="#{userBean.password}" style="width: 154px"> </h:inputSecret> <h:message for="password" /> <br> </div> <br> <div align="center"> <h:commandButton rendered="true" value="登录" action="#{userBean.verify}"></h:commandButton> </div> </h:form> </f:view>
<managed-bean> <managed-bean-name>userBean</managed-bean-name> <managed-bean-class> com.it168.logon.view.bean.UserBean </managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>serviceLocator</property-name> <value>#{serviceLocatorBean}</value> </managed-property> </managed-bean>
<navigation-rule> <from-view-id>/pages/login.jsp</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/pages/welcome.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/pages/login.jsp</to-view-id> </navigation-case> </navigation-rule>
在faces-config.xml文件中的<navigation-rule>节点中,我们定义了页面导航规则。