最近利用业余时间看了两个ssh架构的项目教程,有所获,记录一下
----------------------------------------环境搭建----------------------------------------
【1】导入jar包
如果是web工程,导入ssh以及相关数据库的所需jar包,具体可以去官网下载;
如果是maven工程,则需要相关的maven配置;
pom.xml
4.0.0
com.winssage.fengshu
winssage
0.0.1-SNAPSHOT
war
winssage
http://maven.apache.org
UTF-8
junit
junit
4.10
test
org.apache.struts
struts2-core
2.3.1
org.apache.struts
struts2-spring-plugin
2.3.1
org.hibernate
hibernate-core
3.6.5.Final
commons-dbcp
commons-dbcp
1.4
log4j
log4j
1.2.16
org.slf4j
slf4j-api
1.6.1
org.slf4j
slf4j-nop
1.6.4
javassist
javassist
3.11.0.GA
org.springframework
spring-core
3.1.1.RELEASE
org.springframework
spring-beans
3.1.1.RELEASE
org.springframework
spring-context
3.1.1.RELEASE
org.springframework
spring-jdbc
3.1.1.RELEASE
org.springframework
spring-orm
3.1.1.RELEASE
org.springframework
spring-web
3.1.1.RELEASE
org.apache.struts
struts2-spring-plugin
${struts2.version}
c3p0
c3p0
0.9.1.2
mysql
mysql-connector-Java
5.1.6
【2】数据库表
这里以用户、角色、部门为例(每个用户有不同的角色,每个角色都归属相关的部门)
【3】目录规范
方式一:com.公司名称.项目名称.子模块.分层
方式二:com.公司名称.项目名称.分层.子模块
com.itheima.crm.staff.dao.impl 员工dao层和实现类
com.itheima.crm.staff.service.impl 员工service层和实现类
com.itheima.crm.staff.web.action 员工web
com.itheima.crm.staff.domain 员工javabean
【4】编写po类和hbm文件(可以用hibernate插件生成,生成方法请查看http://www.jianshu.com/p/6c0afa1ed210)
CrmStaff.java
/**
* @author:lvfang
* @date:2017-7-8
* @desc:员工bean
*/
public class CrmStaff {
/*
* CREATE TABLE `crm_staff` (
`staffId` varchar(255) NOT NULL PRIMARY KEY,
`loginName` varchar(100) DEFAULT NULL,
`loginPwd` varchar(100) DEFAULT NULL,
`staffName` varchar(100) DEFAULT NULL,
`gender` varchar(20) DEFAULT NULL,
`onDutyDate` datetime DEFAULT NULL,
`postId` varchar(255) DEFAULT NULL,
CONSTRAINT FOREIGN KEY (`postId`) REFERENCES `crm_post` (`postId`)
); */
private String staffId;
private String loginName; //登录名
private String loginPwd; //登录密码
private String staffName; //员工姓名
private String gender; //性别
private Date onDutyDate; //入职时间
//多对一:多个员工 属于 【一个职务】
private CrmPost post; (注意,这里员工表中对应postId,但对应到java中代表post对象)
//getter setter方法
}
CrmStaff.hbm.xml
CrmPost.java
/**
* @author:lvfang
* @date:2017-7-8
* @desc:职务bean
*/
public class CrmPost {
/*
* CREATE TABLE `crm_post` (
`postId` varchar(255) NOT NULL PRIMARY KEY,
`postName` varchar(100) DEFAULT NULL,
`depId` varchar(255) DEFAULT NULL,
CONSTRAINT FOREIGN KEY (`depId`) REFERENCES `crm_department` (`depId`)
); */
private String postId;
private String postName; //职务名称
//多对一:多个职务 属性 【一个部门】
private CrmDepartment department;
//一对多: 一个职务 可以有 【多个员工】
private Set staffSet = new HashSet();
//getter setter方法
}
CrmPost.hbm.xml
CrmDepartment.java
/**
* @author:lvfang
* @date:2017-7-8
* @desc:部门bean
*/
public class CrmDepartment {
/*
* CREATE TABLE `crm_department` ( `depId` varchar(255) NOT NULL PRIMARY
* KEY, `depName` varchar(50) DEFAULT NULL );
*/
private String depId;
private String depName; //部门名称
//一对多: 一个部门 对应 【多个职务】 ,选择集合 Set --> 不重复、没有顺序
private Set postSet = new HashSet();
//getter setter方法
}
CrmDepartment.hbm.xml
这里po和hbm文件要注意的是
(1)po类的类型要与数据库字段对应,主外键列为某表主键时,对应到javabean是该对象,而非对象ID
(2)hbm文件配置是注意包配置和关系映射
(3)hibernate版本不同,所对应的hbm头也不一样,一定要在对应的版本jar下寻找案例
(4)hbm文件一般与javabean放在一个包下
(5)如果还要加一点,那就是要细心
【5】spring配置
一般ssh项目配置文件比较多,所以大都单建一个包resource,在resource目录下在分包,加载路径对应好即可
resource/jdbcInfo.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3307/crmdb
jdbc.user=root
jdbc.password=root
resource/applicationContext.xml
org.hibernate.dialect.MySQL5Dialect
false
false
【6】struts配置
/WEB-INF/pages/{1}/{2}.jsp
【7】web.xml
openSession
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
openSession
/*
contextConfigLocation
classpath:spring/applicationContext.xml
org.springframework.web.context.ContextLoaderListener
struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts2
/*
【8】开发思路
【9】daoImpl,继承HibernateDaoSupport 实现Dao
public class StaffDaoImpl extends HibernateDaoSupport implements StaffDao {
@Override
public CrmStaff find(String loginName, String loginPwd) {
List allStaff = this.getHibernateTemplate().find("from CrmStaff where loginName=? and loginPwd = ?", loginName,loginPwd);
if(allStaff.size() == 1){
return allStaff.get(0);
}
return null;
}
}
【10】serviceImpl 实现对应的service接口,setter注入Dao接口
public class StaffServiceImpl implements StaffService {
private StaffDao staffDao;
public void setStaffDao(StaffDao staffDao) {
this.staffDao = staffDao;
}
@Override
public CrmStaff login(CrmStaff staff) {
return staffDao.find(staff.getLoginName(), staff.getLoginPwd());
}
}
【11】添加对应的子spring配置文件,给service注入dao,给dao注入sessionFactory,注意这里的sessionFactory要与全局spring中的sessionFactory名一致
applicationContext-staff.xml
【12】Action要继承ActionSupport 实现ModelDriven
public class StaffAction extends ActionSupport implements ModelDriven {
//封装数据
private CrmStaff staff = new CrmStaff();
@Override
public CrmStaff getModel() {
return staff ;
}
//默认按照名称注入
private StaffService staffService;
public void setStaffService(StaffService staffService) {
this.staffService = staffService;
}
public String login(){
//1 查询员工
CrmStaff findStaff = staffService.login(staff);
//业务处理
return "login";
}
}
【13】struts子配置文件,注意要把子配置文件引入全局struts
struts-staff.xml
staffAction_home
/WEB-INF/pages/frame.jsp
【12】jsp文件
所有的jsp页面存在WEB-INF目录下。 (不能通过浏览器直接访问)
WEB-INF/page/模块/*.jsp
【13】base开发
由于每个模块之间都包括基础的怎删改查方法,以及action都要去注入对应的javaBean等等操作,这样过于繁琐
【14】baseDao
public interface BaseDao {
public void save(T t);
public void update(T t);
public void delete(T t);
public void saveOrUpdate(T t);
/**
* 通过id查询
* @param id
* @return
*/
public T findById(Serializable id);
/**
* 查询所有
* @return
*/
public List findAll();
/**
* 条件查询
* @param condition ,格式:" and ..? and ..."
* @param params
* @return
*/
public List findAll(String condition, Object[] params);
/**
* 分页,查询总记录数
* @param condition
* @param params
* @return
*/
public int getTotalRecord(String condition, Object[] params);
/**
* 分页,查询结果
* @param condition 条件
* @param params 条件实际参数
* @param startIndex 开始索引
* @param pageSize 每页显示个数
* @return
*/
public List findAll(String condition, Object[] params, int startIndex, int pageSize);
/**
* 离线条件查询,使用QBC
* @param criteria
* @return
*/
public List findAll(DetachedCriteria criteria);
/**
* 分页
* @param criteria
* @param startIndex
* @param pageSize
* @return
*/
public List findAll(DetachedCriteria criteria , int startIndex ,int pageSize);
}
【15】BaseDaoImpl
public class BaseDaoImpl extends HibernateDaoSupport implements BaseDao{
//T 编译时,注释变量,运行时,才可以获取到具体的类型
private Class> beanClass;
public BaseDaoImpl(){
//获得运行时的类型 , BaseDaoImpl被参数化的类型
ParameterizedType paramType = (ParameterizedType) this.getClass().getGenericSuperclass();
// 泛型里可以规定多个,所以getActualTypeArguments获取的是数组,我们这里泛型只有一个T所以取[0]
beanClass = (Class>) paramType.getActualTypeArguments()[0];
}
public void save(T t) {
this.getHibernateTemplate().save(t);
}
public void update(T t) {
this.getHibernateTemplate().update(t);
}
public void delete(T t) {
this.getHibernateTemplate().delete(t);
}
public void saveOrUpdate(T t) {
this.getHibernateTemplate().saveOrUpdate(t);
}
public T findById(Serializable id) {
return (T) this.getHibernateTemplate().get(beanClass, id);
}
public List findAll() {
return this.getHibernateTemplate().find("from " + beanClass.getName());
// hql
// session.createQuery("from CrmStaff"); //简写,存在自动导包 ,
// session.createQuery("from com.itheima.crm.staff.domain.CrmStaff"); //完整写法
}
public List findAll(String condition, Object[] params) {
String hql = "from "+beanClass.getName()+" where 1=1 " + condition;
return this.getHibernateTemplate().find(hql , params);
}
public int getTotalRecord(String condition, Object[] params) {
String hql = "select count(c) from "+beanClass.getName()+" c where 1=1 " + condition;
List list = this.getHibernateTemplate().find(hql,params);
return list.get(0).intValue();
}
public List findAll(String condition, Object[] params, int startIndex, int pageSize) {
String hql = "from "+beanClass.getName()+" where 1=1 " + condition;
return this.getHibernateTemplate().execute(new PageHibernateCallback(hql, params, startIndex, pageSize));
}
public List findAll(DetachedCriteria criteria) {
return this.getHibernateTemplate().findByCriteria(criteria);
}
public List findAll(DetachedCriteria criteria, int startIndex, int pageSize) {
return this.getHibernateTemplate().findByCriteria(criteria, startIndex, pageSize);
}
}
【16】baseAction
public class BaseAction extends ActionSupport implements ModelDriven {
private static final long serialVersionUID = 5028961270688544619L;
// 封装数据Bean
private T t;
public T getModel() {
return t;
}
// 1.1 实例化t
public BaseAction() {
try {
// 1 获得T运行时Class
ParameterizedType paramType = (ParameterizedType) this.getClass().getGenericSuperclass();
Class clazz = (Class) paramType.getActualTypeArguments()[0];
// 2 反射创建实例
t = clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 2 spring注入service,多个service直接注入baseAction中,具体的action就不用去注入,并直接调用
// 员工
private StaffService staffService;
public void setStaffService(StaffService staffService) {
this.staffService = staffService;
}
public StaffService getStaffService() {
return staffService;
}
// 分页数据
private int pageNum = 1;// 默认是从前台传入
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageNum() {
return pageNum;
}
private int pageSize = 10; // 默认是从前台传入
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPageSize() {
return pageSize;
}
//4 简化值栈操作
/*
* 方式一:context(map)存放 put(key,val) ,jsp页面获取“#key”
* ActionContext.getContext().put(key, value);
* 方式二:root(值栈),push(obj),一般数据为javaBean 或 map , jsp页面获取“属性名”或"key"
* ActionContext.getContext().getValueStack().push(obj);
* 方式三:root(值栈),set(key,value),一般数据为list,jsp页面获取“key”
* ActionContext.getContext().getValueStack().set(key, value)
* set() 底层是new Map(key,value),将其在push(map);
* */
//方式一 put(list)
public void put(String key, Object value){
ActionContext.getContext().put(key, value);
}
//方式二 push(object)
public void push(Object o){
ActionContext.getContext().getValueStack().push(o);
}
//方式三
public void set(String key ,Object o){
ActionContext.getContext().getValueStack().set(key, o);
}
public void putSession(String key, Object value){
ActionContext.getContext().getSession().put(key, value);
}
public void putApplication(String key, Object value){
ActionContext.getContext().getApplication().put(key, value);
}
}
【17】分页容器类
/**
*
*/
package com.itheima.crm.utils;
import java.util.List;
/**
* @author:lvfang
* @date:2017-7-13
* @desc:
* @version:V1.0
*/
public class PageBean {
// 必选项
private int pageNum; // 第几页(当前页)
private int pageSize; // 每页显示个数(固定值)
private int totalRecord; // 总记录数(查询数据库)--注意条件
// 计算项
private int startIndex; // 开始索引(计算)
private int totalPage; // 总分页数(计算)
// 数据
private List data; // 分页数据
// 动态显示条
private int start;
private int end;
public PageBean(int pageNum, int pageSize, int totalRecord) {
super();
this.pageNum = pageNum;
this.pageSize = pageSize;
this.totalRecord = totalRecord;
// 计算
// 1 开始索引
this.startIndex = (this.pageNum - 1) * this.pageSize;
// 2 总分页数
this.totalPage = (this.totalRecord + this.pageSize - 1) / this.pageSize;
// 3 动态显示条
// 3.1 初始化数据 -- 显示10个分页
this.start = 1;
this.end = 10;
// 3.2 初始数据 , totalPage = 4
if (this.totalPage <= 10) {
this.end = this.totalPage;
} else {
// totalPage = 22
// 3.3 当前页 前4后5
this.start = this.pageNum - 4;
this.end = this.pageNum + 5;
// * pageNum = 1
if (this.start < 1) {
this.start = 1;
this.end = 10;
}
// * pageNum = 22
if (this.end > this.totalPage) {
this.end = this.totalPage;
this.start = this.totalPage - 9;
}
}
}
//getter setter方法
}