一 用户模块 用户实体->DAO
注册,登录,注销
1. 用户实体
User : id, loginName, nickName[使用2个名字的好处],password(MD5), email, avatar:byte[]
gender, birthday
autoLoginKey
2. 写User和映射
(1) Class - User
属性, hashCode(), equals(),gender使用常量---
(2) User.hbm.xml, 加到hibernate.cfg.xml
*** birthday- date
*** avatar - length=512000
3. 写UserDAO
(1) UserDAO extendsGenericDAO<User>
(2) UserDAOImpl extendsGenericDAOImpl<User> implementsUserDAO
(3) BaseService中增加
protectedUserDAO userDAO; 及初始化
(4) beans-dao.properties增加UserDAO
4. 分析用户有关的功能
注册,登录(可以自动登录),注销,显示用户的头像
4.1 注册的流程
4.2 注册的验证:
(1) 表单的客户端验证;js
(2) 表单的服务器端验证:
格式是否正确;
用户名是否已被使用;
(3) 客户端格式验证规则:
(3.1)用户名不能为空;
(3.2)密码不能为空;
(3.3)如果密码不为空,确认密码与密码一致;
(3.4)Email的格式要正确;
(4) 服务端格式验证规则同(3)
(4.5)用户名是否已被使用,使用AJAX;
能在不提交的情况下检查用户名是否已经被使用(用户名后放一个框)
(5) 客户端和服务器端2遍验证的原因;
4.3 分析Action的方法
registerUI(), register(),login(), logout(), showAvatar();
isLoginNameRegistered(); ---Ajax
4.4 分析Service的方法
addUser(),isLoginNameRegistered(), getByLoginNameAndPassword(),getUser();
4.5 写UserAction extendsBaseAction,并写出上述分析的每个方法的结构;
检查哪个方法需要单独jsp页面
4.6 注册功能:
(1) jsp页面: register.jsp;
检测用户名是否存在;
日期控件;jQuery--WebRoot/script/jquery.js&datepicker/ui.datepicker.js
WebRoot/script/jquery.js
WebRoot/script/datepicker/ui.datepicker.js
WebRoot/script/datepicker/zh-cn.js
WebRoot/script/datepicker/ui.datepicker.css
<html:rewritepage="/script/jquery.js" /> ====也可以使用相对路径
<input type="text" name="birthday"id="txtBirthday">
<script>
$("#txtBirthday").datepicker
(2) 准备FormBean
avatar ---FormFile
FormBean中的属性与User相同的较多,可以直接使用User;
(3)准备Service:接口->实现类;
(3.1)beans-service.properties;
(3.2)BaseAction中增加一个Service;
==== 练习:
(ex1)Action
register();
(1)验证表单
(2)验证用户名是否已经被占用;
(3)验证通过,添加用户
isLoginNameRegistered:Ajax
===== 遇到的问题:
birthday字段使用了js,如果用标准的html,有个id属性,struts用什么属性?====styleId
===== 课堂编写
(1)jsp表单:使用Struts标签
---回显:value="" or redisplay=false
---性别:可以使用html:radio
--- password2: Form中增加属性;
(2)UserAction中:
---验证表单;->可以使用ForumAction中的代码;重写UserForm.validate
---验证用户名重复:返回至registerUI;
---属性的复制,图像的单独处理;size>0表示上传了文件;
---添加用户成功后,转到index
全局,重定向;
(3)测试问题;
不要把Action的方法写成protected,必须是public
(3.1)组装Form表单FormFile avatar
==原因:上传文件的enctype="multipart/form-data"
(3.2)组装Form表单birthday
==暂时不处理,处理的话需要转换器;
(3.3)实现用户名已经注册的方法isLoginNameRegistered;
==list().size()>0
==测试服务端;
(3.4)birthday字段的处理
== BeanUtils 的DateConverter implement Converter
convert()
== 注册转换器
使用前被使用;通常放在启动的时候;
在过滤器的init方法中注册;
ConvertUtils.register();
BeanUtils.copyProperties()的内部实现;
先将src属性作转换,再设置dst的属性
转换器要考虑:传过来的是null和 传过来的就是目标类型的情况;
==回显时出现了英语的日期表示法,解决:
--使用Jstl, fmt:formatDate
--将birthday改为String
--写一个Date的子类,重写toString,再写子类的转换器
(3.5)完成UserForm.validate
==为空部分作成工具类StringUtil
==用户名,密码,email
==email 正则表达式
aa@xx.yy[.zz.xx]
atom:表示一个字母或数字或下划线;
aa:
由至少一个atom组成的字符串
A-Z,a-z, 0-9, _, .; 至少1个字符
xx:
由至少一个atom组成的字符串
A-Z,a-z, 0-9, _; 至少1个字符
yy:
由一个或多个.xx组成的字符串
[a-zA-Z0-9_.]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-])+
==UserForm中写个main测试
使用不同的邮箱地址来测试;
==将正则表达式作为常量放在UserForm中;
==Pattern.matches(pattern, string);
注意空值异常;
Pattern.matches两种不同的用法;
(3.6)完成客户端js校验;
functionvalidate(form)
js的正则表达式与java的有所不同
"^...$"
js中只匹配部分;
jQuery的使用;
(3.7)对密码进行MD5加密
写一个工具类:MD5Util
staticString digest(String str);
位运算,转换为字符;
判断b>0xf决定是否+0;
b& 0xff, 不判断高位,类型自动转换带来的问题
对null的处理,抛出异常;空字符串没有问题
(3.8) addUser
对密码作一次MD5运算;
登录时需要用加密后的密码与数据库中的密码比较;
如何实现自动登录;
如何保证用户密码安全
如何保证有效期起作用;
cookie.setMaxAge不太好,不太安全,使用?
expriyTime= currentTime + 7tian;
数据库中再存一份未加密的信息;
自动登录:使用Cookie;
在登录时勾选自动登录;
在用户成功登录后,给客户端发cookie,内容是用户名和密码;
在每次访问网站时,在有效期,都有一个过滤器,检测自动登录的cookie,
取出其中的内容进行验证;如果通过就登录这个用户;
如果存的是用户名密码会不安全:
内容是MD5(userId_currentTime_expriyTime);
发给客户端,同时存进数据库;
验证时取cookie.value== user.autoLoginKey
cookie.value== MD5(user.autoLoginKey);
expiryTime= autoLoginKey.split("_")[2]
与当前时间比较,如果未过期;
登录用户;