1. 第二天 重点内容
搭建SSH 完成框架
以用户管理为例
• 用户登录
• 用户退出
• 修改密码
2. 开发流程
2.1. 业务分析
2.2. 数据库设计
MySQL : 新建 DataBase 、 新建用户 User 、进行授权
Oracle : 新建用户 User 、 创建表空间 、 在表空间进行操作
MySQL 操作步骤 :
步骤: 新建数据库
查看字符集 show variables like ‘%char%’;
client、connection、results 这三个字符集 和 安装mysql命令窗口相关
database 、 server 、system 这三个字符集服务器 (设置 utf8 )
修改 my.ini 文件 [mysqld] 下面
character-set-server=utf8
创建数据库使用默认字符集
新建用户
create user 用户名@localhost (本机)/ 用户名@%(远程) identified by ‘密码’ ;
为账户授权
2.3. 完成项目SSH 配置集成
在Spring 的applicationContext.xml 连接数据库 (整合Hibernate )
步骤:
整合Hibernate ,配置SessionFactory
事务管理
引入外部属性文件,为了项目维护更加方便
config.properties
配置事务
建立项目包结构
cn.itcast.bos.domain 数据实体类
cn.itcast.bos.dao 数据层
cn.itcast.bos.service 业务逻辑层
cn.itcast.bos.web 表现层
2.4. 数据库建模工具 PD的使用
安装12.5版本,进行破解
PD 是最专业数据建模工具, 是 Sybase 公司一个 产品
PD 提供四种模型文件
PDM 物理数据模型,面向数据库表结构设计,直接生成SQL语句或者通过ODBC工具直接导入数据
(JDBC 类型 jdbc-odbc桥、 NativeAPI、 Middleware 、 纯java驱动)
CDM 概念数据模型,类似E-R图 主要数据模型分析
OOM 面向对象模型,将表关系,表示类之间关系
BPM 业务流程模型,业务流程图
CDM 、PDM、OOM 三者相互转换
PDM 直接生成数据库文件,完成数据库建表
课程: PDM设计使用
2.5. 建立 user数据表
/* 创建user数据表 */
create table user (
id varchar(32) primary key,
username varchar(20),
password varchar(32), /* md5加密密码 */
salary double ,
birthday date ,
gender varchar(10),
station varchar(40),
telephone varchar(11),
remark varchar(255)
);
/* 初始化一条记录 */
insert into user(id,username,password) values('abcdefghijklmn','admin',md5('admin'));
作业: 使用PowerDesigner 绘制 user 数据模型
使用 Hibernate 开发
第一条: 创建数据表,根据数据表 编写PO类和 hbm映射
第二条: 面向对象设计 表关系,使用类动态 生成数据表
使用 MyEclipse 反转引擎,生成
步骤:
1、 新建 Database 连接
2、 新建web项目 temp
添加myeclipse hibernate 能力
3、 Hibernate 反转构建
将 User.java 类 复制 src/main/java , User.hbm.xml 复制 src/main/resources
3. 编程实现 用户登录操作
3.1. 设计 数据访问层 DAO
企业实际项目中,各层之间面向接口整合 ,好处将业务和实现解耦合,方便程序维护和扩展 ,程序中面向接口编程,在程序中看不到实现类,实现类都是通过Spring 配置
在企业开发各层内部,一定会存在重复可复用的代码 ,设计BaseXXX 类,是抽象类 ,将重复代码放入抽象类中, 自定义DAO 或者 Service 基础BaseDAO 或者 BaseService
设计通用 DAO 组件,只编写 一个DAO 工具类完成 所有表 CURD
需要依赖 反射和泛型 技术
在 cn.itcast.bos.dao.impl 提供 GenericDAO 实现
使用Session操作 Hibernate
使用HibernateTemplate 操作 Hibernate
public class GenericDAOImpl<T> extends HibernateDaoSupport implements GenericDAO<T> {
…
}
因为基础 HibernateDaoSupport 向DAO 注入SessionFactory 使用HibernateTemplate
配置具体DAO
applicationContext.xml 分离
<import resource="classpath:applicationContext-common.xml"/>
<import resource="classpath:applicationContext-dao.xml"/>
<import resource="classpath:applicationContext-service.xml"/>
<import resource="classpath:applicationContext-action.xml"/>
在 applicationContext-dao.xml 为每张表,配置一个DAO Bean
<!-- 配置DAO -->
<!-- 为每个表 配置一个DAO -->
<bean id="userDAO" class="cn.itcast.bos.dao.impl.GenericDAOImpl">
<!-- 构造器注入 ,传入 实体类 完整类名 -->
<constructor-arg index="0" type="java.lang.String" value="cn.itcast.bos.domain.user.User"></constructor-arg>
<!-- 注入SessionFactory -->
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
3.2. 完成用户登录功能
3.2.1. 修改登陆页面
将 login.jsp 中form 修改为 <s :form>
好处: 使用 <s :form>
进行数据回显
通常会将登陆功能,编写单独Action (与用户管理其他功能分离开 )
好处: 便于进行权限控制
账户: username
密码: password
验证码 : checkcode
点击 提交 链接,提交form表单
3.2.2. 编写服务器程序
Web层
public abstract class BaseAction extends ActionSupport {
}
public class LoginAction extends BaseAction implements ModelDriven<User> {}
将可以复用代码 抽取 BaseAction 中
Service层
public abstract class BaseService {
}
public interface UserService {
}
public class UserServiceImpl extends BaseService implements UserService {}
BaseService 实现代码复用, UserService 接口和Web层整合,UserServiceImpl 业务实现类
整合
将 DAO 注入 BaseService
将 Service 注入 BaseAction
业务层实现登陆, 需要根据用户名和密码查询 (条件查询 )
<!-- 命名查询 -->
<query name="User.login">
<![CDATA[from User where username = ? and password = ?]]>
</query>
在业务层调用 名称查询时,别忘记对密码 md5 加密
统一配置
struts.xml
<!-- 登陆功能 -->
<action name="login" class="loginAction">
<result name="input">/login.jsp</result>
<result type="redirect">/index.jsp</result>
</action>
applicationContext-action.xml
<!-- 配置Action -->
<bean id="loginAction"
class="cn.itcast.bos.web.action.user.LoginAction" scope="prototype"/>
applicationContext-service.xml
<!-- 配置Service -->
<bean id="userService"
class="cn.itcast.bos.service.impl.user.UserServiceImpl" />
使用注解注入,在applicationContext-common.xml
这里写代码片
4. 登陆功能主页完善和系统退出
4.1. 主页信息显示完善
4.1.1. 主页面 右上方,登陆用户显示
/page_common_index.action 对应 /WEB-INF/pages/common/index.jsp
[<strong>${user.username }</strong>],欢迎你!您使用[<strong>${pageContext.request.remoteAddr }</strong>]IP登录!
4.1.2. 主页面右下方,弹出窗口提示
使用 EasyUI 提供 messager控件,制作提示框架效果
$.messager.show 右下角提示框
$.messager.alert 弹出警告框
$.messager.confirm 确认框
// 1 alert
$.messager.alert("标题","内容","info");
// 2 confirm
$.messager.confirm('标题','确认删除吗?',function(isConfirm){
if(isConfirm){
alert("执行删除");
}else{
alert("取消...");
}
});
制作右下角提示窗口
// 3、show
$.messager.show({
title : '标题',
msg : '<a href="#">传智播客</a>',
timeout : 5000 , // 5秒后自动消失
});
4.2. 系统退出
// 退出登录
function logoutFun() {
// 询问 用户是否确认退出
$.messager.confirm("确认窗口","你确定退出系统吗?", function(isConfirm){
if(isConfirm){
// 确认退出
location.href = "${pageContext.request.contextPath}/invalidate.jsp";
}
});
}
用户确认退出,直接跳转 invalidate.jsp
invalidate.jsp 退出操作,销毁当前用户对应的Session
<%
// 清除用户Session
session.invalidate();
// 重定向 login.jsp
response.sendRedirect(request.getContextPath()+"/login.jsp");
%>
5. 编写自定义拦截器,控制页面访问
自定义拦截器 LoginInterceptor 实现,如果用户未登陆,阻止访问 WEB-INF 下所有页面和 除登陆之外其它 Action
步骤 :
1、 编写 拦截器类,实现 Interceptor 接口
public class LoginInterceptor extends AbstractInterceptor {
2、 实现intercept 方法,判断当前用户是否登陆
User user = (User) ServletActionContext.getRequest().getSession().getAttribute("user");
if (user == null) {
// 没有登陆
return "login"; // 登陆页面
} else {
// 已经登陆
return invocation.invoke();
}
3、 注册拦截器,配置结果页面
<!-- 注册拦截器 -->
<interceptors>
<interceptor name="login" class="cn.itcast.bos.web.interceptor.LoginInterceptor"></interceptor>
<!-- 定义新的拦截器栈 -->
<interceptor-stack name="loginStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="login"></interceptor-ref>
</interceptor-stack>
</interceptors>
将拦截器 设置package默认拦截器
<!-- 设置默认拦截器栈 -->
<default-interceptor-ref name="loginStack"></default-interceptor-ref>
配置全局结果集
<!-- 配置全局结果集 -->
<global-results>
<result name="login">/login.jsp</result>
</global-results>
4、 使用拦截器传递错误信息
ActionSupport action = (ActionSupport) invocation.getAction();
action.addActionError("你还未登陆或者长时间未使用,请重新登陆!");
问题: 使用iframe嵌套,主页嵌套主页 情况
可以,在未登陆,跳转提示信息页面,用户点击链接,跳到登陆 (整个浏览器跳转) 或者
在登陆form 添加 target=”_top
”
6. 密码修改
6.1. 弹出遮罩窗口
使用 EasyUI 的 window 控件制作 (dialog 是对window扩展,提供 工具栏)
使用 class=”easyui-window” 将任意div 变为窗口 ,设置属性
collapsible boolean 定义是否显示折叠按钮。 true
minimizable boolean 定义是否显示最小化按钮。 true
maximizable boolean 定义是否显示最大化按钮。 true
closable boolean 定义是否显示关闭按钮。 true
控制window的 按钮,默认四个按钮都是显示
通过 modal 属性 设置窗口遮罩效果
打开和关闭窗口。
$('#win').window('open'); // open a window
$('#win').window('close'); // close a window
示例代码:
<!-- 通过 easyui的 class 将任意 div 变为 窗口 -->
<!-- 为窗口 设置标题属性 和 宽高 -->
<div id="mywindow" class="easyui-window" data-options="title:'自定义窗
口',maximizable:false,minimizable:false,modal:true,closed:true"
style="width:200px;height: 150px">传智播客</div>
<input type="button" value="打开窗口"
onclick="$('#mywindow').window('open');"/>
6.2. 修改密码窗口,进行form校验
点击修改密码 : $('#editPwdWindow').window('open');
弹出窗口
输入密码,点击确定 : 执行js函数 ,对密码进行校验
// 获得新密码和确认密码的输入内容
var newPass = $("#txtNewPass").val(); // document.getElementById("txtNewPass").value;
var rePass = $("#txtRePass").val();
// 进行校验
// 新密码是否为空
if($.trim(newPass)==""){ // 也可以写为 jQuery.trim
// 新密码输入为空
$.messager.alert('警告','新密码不能为空或者空白字符!','warning');
return ;
}
// 两次密码是否一致
if($.trim(newPass) != $.trim(rePass)){
$.messager.alert('警告','两次密码输入不一致!','warning');
return ;
}
6.3. Ajax实现密码修改功能
1、 发起Ajax请求
// 通过 Ajax 将新密码发送到服务器
$.post("${pageContext.request.contextPath}/user_editpassword.action", {password: newPass}, function(data){
});
2、 编写服务器,完成密码修改功能
UserAction
注入 UserService
public class UserAction extends BaseAction implements ModelDriven<User> {}
// 如果修改用户某个属性,先查询,再修改
User exist = userDAO.findById(user.getId()); // 持久态
exist.setPassword(MD5Utils.md5(user.getPassword()));
3、 返回json 格式
对象 {key:value, key:value}
数组 [{},{}]
结果数据转换为json 推荐
flexjson 框架
struts2 自带 json plugin
使用 struts2 自带json插件
提供一个新的package : json-default , 提供新 result-type : json
插件基于值栈返回的
// 调用业务层
try {
userService.editPassword(user);
// 修改成功
Map<String, Object> map = new HashMap<String, Object>();
map.put("result", "success");
map.put("msg", "修改密码成功");
ActionContext.getContext().put("map", map);
} catch (Exception e) {
// 修改失败
Map<String, Obj`这里写代码片`ect> map = new HashMap<String, Object>();
map.put("result", "failure");
map.put("msg", "修改密码失败," + e.getMessage());
ActionContext.getContext().put("map", map);
}
配置 struts.xml
配置包 <package name="needlogin" extends="json-default">
配置result
<!-- 用户管理 -->
<action name="user_*" class="userAction" method="{1}">
<!-- 修改密码 -->
<result name="editpasswordSUCCESS" type="json">
<!-- 配置root参数,指定将值栈哪个数据返回 -->
<param name="root">map</param>
</result>
</action>
配置applicationContext-action.xml
<bean id="userAction"
class="cn.itcast.bos.web.action.user.UserAction" scope="prototype" />
4、使用 firebug调试
控制台、 网络、脚本 三个面板 启用
在 applicationContext-common.xml 配置事务管理
对editPassword 方法添加事务
<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT"/>
5、 编写回调函数
if(data.result == "success"){
$.messager.alert("信息", data.msg, "info");
}else{
$.messager.alert("信息", data.msg, "info");
}
// 窗口关闭
$("#editPwdWindow").window('close');
其它
课前资料
powerdesigner
里面有PD教程