系统登陆页面为login.jsp,如图
一、实现数据访问层DAO
1.首先在com.netbank.dao包中创建UserDAO接口,然后再UserDAO接口中添加GetAccount(String username)方法,根据客户名获取账户对象。代码如下
package com.netbank.dao;
import com.netbank.entity.Account;
public interface UserDAO {
//根据客户名获取账号对象
public Account getAccount(String username);
}
2.在com.netbank.dao.impl包中创建UserDAO接口的实现类UserDAOImpl,实现getAccount(String username)方法
public class UserDAOImpl implements UserDAO {
SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/*
* 根据客户名获取账号对象
*/
@Override
public Account getAccount(String username) {
// TODO Auto-generated method stub
Session session=sessionFactory.getCurrentSession();
String hql="from Account where username='"+username+"'";
Query query=session.createQuery(hql);
return (Account) query.uniqueResult();
}
}
3.在Spring配置文件中定义UserDAOImpl,并给类中的sessionFactory属性注入实例
<!--定义UserDAOImpl,并给类中的sessionFactory属性注入实例 -->
<bean id="userDao" class="com.netbank.dao.impl.UserDAOImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
二、实现业务逻辑层
1.在com.netbank.biz包中创建UserBiz接口,在UserBiz接口中添加getAccount(String username)方法,根据客户名获取账号对象:
package com.netbank.biz;
import com.netbank.entity.Account;
public interface UserBiz {
//根据客户名获取账号对象
public Account getAccount(String username);
}
2.在com.netbank.biz.impl包中创建UserBiz接口的实现类UserBizImpl,实现getAccount(String username)方法:
//使用@Transaction注解实现事务管理
@Transactional
public class UserBizImpl implements UserBiz {
//使用UserDao接口声明对象,并添加set方法,用于依赖注入
UserDAO userDao;
public void setUserDao(UserDAO userDao) {
this.userDao = userDao;
}
@Override
public Account getAccount(String username) {
// TODO Auto-generated method stub
return userDao.getAccount(username);
}
3.在Spring配置文件中定义UserBizImpl,并给其属性UserDao注入实例
<!--定义UserBizImpl,并给其属性注入实例 -->
<bean id="userBiz" class="com.netbank.biz.impl.UserBizImpl">
<property name="userDao" ref="userDao"></property>
</bean>
三、实现Action
在com.netbank.action包中创建UserAction,继承ActionSupport类,实现RquestAware和SessionAware接口。
public class UserAction extends ActionSupport implements RequestAware, SessionAware {
//定义通过@Resource注解注入的属性userBiz,可省略set方法
@Resource private UserBiz userBiz;
Map<String,Object> request;
Map<String,Object> session;
//定义Account类型对象,用于封装登陆表单参数
private Account account;
private Personinfo personinfo;
private Password pwd;
//省略account,personinfo和pwd三个属性的get和set方法
//省略其他请求的处理方法
@Override
public void setSession(Map<String, Object> session) {
// TODO Auto-generated method stub
this.session=session;
}
@Override
public void setRequest(Map<String, Object> request) {
// TODO Auto-generated method stub
this.request=request;
}
/*
* 登陆表单校验
*/
public void validateLogin(){
Account a=userBiz.getAccount(account.getUsername());
if(a==null){
this.addFieldError("username", "用户名不存在");
}else{
if(!account.getPassword().equals(a.getPassword())){
this.addFieldError("password", "密码不正确");
}
}
account=a;
}
/*
* 执行页面客户登陆请求
*/
public String login(){
//根据关联关系,从账户对象中获取个人信息对象
personinfo=(Personinfo) account.getPersoninfos().iterator().next();
//将账户对象存入Session
session.put("user",account);
//将该账户个人信息对象存入session
session.put("personinfo",personinfo);
//页面转发
return "success";
}
}
在UserAction类中,UserBiz接口声明的属性userBiz值得注入是通过基于Annotation注解方式完成的,如下所示
@Resource private UserBiz userBiz;
四、Spring配置
在Spring配置文件中配置UserAction类,类中的userBiz属性注入通过Annotation注解方式完成,不再需要使用property标记,从而使得配置文件得以瘦身
<!-- 使用原型模式定义UserAction类,UserAction类的属性通过Annotation注解方式注入 -->
<bean name="user" class="com.netbank.action.UserAction" scope="prototype" ></bean>
在Struts 2的Action委托给Spring容器管理时,考虑到Action是有状态的,因此需要通过设置scope=”prototype”,实现针对每个用户的请求生成一个全新的实例。
在Spring中配置了UserAction类后,Struts 2的配置文件中就可以直接引用UserAction类的Bean实例名”user”,无须指定UserAction类的全名了。
五、Struts 2配置
在Struts 2的配置文件struts.xml中配置UserAction类
<!--定义一个名称为user的包,继承Struts2的默认包,指定命名空间为"/user" -->
<package name="user" namespace="/user" extends="struts-default">
<!--使用通配符实现动态方法调用 -->
<action name="user_*" class="user" method="{1}">
<result name="success">/index.jsp</result>
<result name="login">/login.jsp</result>
<result name="input">/login.jsp</result>
</action>
...
</package>
用户的请求,Action中的处理方法以及结果的展示视图之间的对应关系必须在Struts 2的配置文件中进行正确配置
上述配置中,对于具有一定命名规则的用户请求可以使用通配符实现动态方法的调用,如“user_*”可表示以”user_”打头的Action请求。
六、登陆页面设计
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri='/struts-tags' prefix='s' %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>login</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<link rel="stylesheet" type="text/css" href="style/style.css" >
<link rel="stylesheet" type="text/css" href="style/default.css" >
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<script language="javascript" >
function login(){
var hidden=document.getElementById("hidden").value;
if(document.getElementById("username"+hidden).value ==""){
alert("用户名不能为空");
return false;
}else if(document.getElementById("password"+hidden).value ==""){
alert("密码不能为空");
return false;
} else {
return true;
}
}
function adminlogin(){
document.getElementById("username1").style.display="none";
document.getElementById("password1").style.display="none";
document.getElementById("username2").style.display="block";
document.getElementById("password2").style.display="block";
document.myform.action="admin/login"
}
function init(){
document.getElementById("username1").style.display="block";
document.getElementById("password1").style.display="block";
document.getElementById("username2").style.display="none";
document.getElementById("password2").style.display="none";
document.myform.action="user/user_login";
}
function change(){
var select=document.myform.type.value;
if(select=="0")
{
var username2=document.getElementById("username2").value;
var password2=document.getElementById("password2").value;
init();
document.getElementById("username1").value=username2;
document.getElementById("password1").value=password2;
}
if(select=="1")
{
var username1=document.getElementById("username1").value;
var password1=document.getElementById("password1").value;
adminlogin();
document.getElementById("username2").value=username1;
document.getElementById("password2").value=password1;
}
}
</script>
</head>
<body onload="init()">
<div align="center">
<form method="post" name="myform" action="user/user_login" onsubmit="return login()">
<table width="450" border="0" class="table">
<tbody>
<tr>
<td colspan="2" align="center">
</td>
</tr>
<tr>
<td> 用户名:</td>
<td>
<input id="username1" type="text" name="account.username" >
<input id="username2" type="text" name="admin.username" >
</td>
</tr>
<tr>
<td> 密码:</td>
<td>
<input id="password1" type="password" name="account.password">
<input id="password2" type="password" name="admin.password">
</td></tr>
<tr>
<td>
用户类型:
</td>
<td>
<select name="type" onchange="change()">
<option value="0" selected>客户</option>
<option value="1">管理员</option>
</select>
</td>
</tr>
<tr>
<td>
</td>
<td>
<input type="submit" value="登录" id="login">
<input type="hidden" id="hidden">
</td></tr>
</tbody>
</table>
<s:fielderror fieldName="username" cssStyle="color:red;"/>
<s:fielderror fieldName="password" cssStyle="color:red;"/>
</form>
</div>
</body>
</html>
剩下的功能如修改个人信息,修改密码和管理员功能模块等功能的实现与登陆功能实现的流程相似,不再赘述。