项目分享:通过使用SSH框架的公司-学员关系管理系统(CRM)
----------------------------------------------------------------------------------------------
[版權申明:本文系作者原創,轉載請注明出處]?
文章出處:http://blog.csdn.net/sdksdk0/article/details/52506671
作者:朱培 ? ? ?ID:sdksdk0 ? ? ?郵箱: zhupei@tianfang1314.cn ??
--------------------------------------------------------------------------------------------
最近在做的是一個通過Struts2、Hibernate、spring框架整合做的一個CRM系統,整體開發比較簡單,就是細節的地方處理還是要花費一定的功夫,我主要負責的是人事管理(包括部門管理、職務管理、員工基本信息管理)、教學管理(班級管理、課程類別管理)、系統設置(修改密碼、登錄、退出)。整體功能比較簡單,適合一般性開發。涉及的技術要點就是通過HQL來進行數據的增刪改查、部門-職務級聯、分頁、通過struts進行文件上傳下載等。只不過有個別的地方還是花費了幾個小時。
?
首先是對整體的開發環境的搭建:
通過分模塊開發來處理,框架的使用時分為了struts和spring,不同的模塊的struts的命名也不同,spring也一樣,同時hibernate放到相應的實體bean的文件夾下面。
?
?
?
在開發中我們都有很多地方用到了Dao和DaoImpl,所以我們可以將其抽取出來,作為一個基本的Dao,然后讓其他用到的類去集成這個基礎的dao即可,這樣大大減少了開發的代碼。
在BaseDao中我們可以寫好常用的幾種方法:
?
?
//通用dao接口 public interface BaseDao<T> {//保存public void save(T t);//更新public void update(T t);//刪除public void delete(T t);//保存或更新public void SaveOrUpdate(T t);//查詢所有public List<T> findAll();//條件查詢public List<T> findAll(String condition,Object... params);//離線查詢public List<T> findAll(DetachedCriteria detachedCriteria);//分頁public List<T> findAllByPage(int startIndex,int pageSize);//分頁的總記錄數public int getTotalRecode();//查找T findById(Serializable serializable);}
然后我們需要一個DaoImpl去實現這個公共dao的方法:
?
?
?
public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T>{private Class daoImplClass;public BaseDaoImpl() {//運行時,通過反射獲得 泛型信息的實際內容/// * 運行時,this表示當前運行類(及子類的實例對象)//1 獲得被參數化類型 ,例如:BaseDaoImpl<CrmPost>ParameterizedType paramType = (ParameterizedType) this.getClass().getGenericSuperclass();//2 獲得實例參數daoImplClass = (Class) paramType.getActualTypeArguments()[0];}@Overridepublic void save(T t) {this.getHibernateTemplate().save(t);}@Overridepublic void update(T t) {this.getHibernateTemplate().update(t);}@Overridepublic void delete(T t) {this.getHibernateTemplate().delete(t);}@Overridepublic void SaveOrUpdate(T t) {this.getHibernateTemplate().saveOrUpdate(t);}@Overridepublic List<T> findAll() {return this.getHibernateTemplate().find("from " + daoImplClass.getName());}@Overridepublic List<T> findAll(String condition, Object... params) {String hql = "from " + daoImplClass.getName() + " where 1=1 " + condition;return this.getHibernateTemplate().find(hql,params);}public List<T> findAll(DetachedCriteria detachedCriteria) {return this.getHibernateTemplate().findByCriteria(detachedCriteria);}@Overridepublic List<T> findAllByPage(int startIndex, int pageSize) {String hql = "from " + daoImplClass.getName();return this.getHibernateTemplate().execute(new PageHibernateCallBack(hql, startIndex, pageSize));}@Overridepublic int getTotalRecode() {List<Long> list = this.getHibernateTemplate().find("select count(*) from " + daoImplClass.getName());return list.get(0).intValue();}@Overridepublic T findById(Serializable oid) {List<T> allT=this.getHibernateTemplate().find(" from "+daoImplClass.getName()+" where id=? ",oid);if(allT !=null && allT.size()==1){return allT.get(0);}return null;}/*** 通過編寫回調實現分頁*/class PageHibernateCallBack implements HibernateCallback<List<T>> {private String hql; //查詢hql語句private Object[] params; //對應實際參數private int firstResult; //分頁開始索引private int maxResults; //分頁每頁顯示個數public PageHibernateCallBack(String hql, int firstResult, int maxResults ,Object... params) {super();this.hql = hql;this.params = params;this.firstResult = firstResult;this.maxResults = maxResults;}@Overridepublic List<T> doInHibernate(Session session) throws HibernateException,SQLException {// 1 創建queryQuery queryObject = session.createQuery(hql);// 2 封裝參數if (params != null) {for (int i = 0; i < params.length; i++) {queryObject.setParameter(i, params[i]);}}// 3 分頁if (firstResult >= 0) {queryObject.setFirstResult(firstResult);}if (maxResults > 0) {queryObject.setMaxResults(maxResults);}//4 查詢所有return queryObject.list();}}}?
接下來我們就可以愉快的使用這些封裝好的方法了
?
例如我們的員工信息管理模塊中:
頁面效果如下:
?
?
public interface LessontypeDao extends BaseDao<CrmLessontype>{}
實現方法:
?
?
public class LessontypeDaoImpl extends BaseDaoImpl<CrmLessontype> implements LessontypeDao{}?
然后就是service進行處理:
?
public interface LessontypeService {PageBean<CrmLessontype> findAllPage(int pageNum,int pageSize);List<CrmLessontype> findAll();CrmLessontype findById(String lessonTypeId);void addOrEditLessontype(CrmLessontype model);}?
實現方法:
這里使用了一個分頁查詢的功能。
?
public class LessontypeServiceImpl implements LessontypeService {private LessontypeDao lessontypeDao;public void setLessontypeDao(LessontypeDao lessontypeDao) {this.lessontypeDao = lessontypeDao;}@Overridepublic PageBean<CrmLessontype> findAllPage(int pageNum, int pageSize) {//1 查詢數據庫,獲得總記錄數int totalRecord = lessontypeDao.getTotalRecode();//2 分頁數據PageBean<CrmLessontype> pageBean = new PageBean<CrmLessontype>(pageNum, pageSize, totalRecord);//3 查詢分頁結果pageBean.setData(lessontypeDao.findAllByPage(pageBean.getStartIndex(), pageSize));return pageBean;}@Overridepublic List<CrmLessontype> findAll() {return lessontypeDao.findAll();}@Overridepublic CrmLessontype findById(String lessonTypeId) {return lessontypeDao.findById(lessonTypeId);}@Overridepublic void addOrEditLessontype(CrmLessontype model) {lessontypeDao.SaveOrUpdate(model);}}?
接下來就需要把我們的service交由spring來管理了,在applicationContext-lessontype.xml中
?
?
<bean id="lessontypeService" class="cn.tf.lessontype.service.impl.LessontypeServiceImpl"><property name="lessontypeDao" ref="lessontypeDao"></property></bean><bean id="lessontypeDao" class="cn.tf.lessontype.dao.impl.LessontypeDaoImpl"><property name="sessionFactory" ref="sessionFactory"></property></bean>?
然后我們可以看到前臺頁面是:
?
<table width="97%" border="1" ><tr class="henglan" style="font-weight:bold;"><td width="14%" align="center">名稱</td><td width="33%" align="center">簡介</td><td width="13%" align="center">總學時</td><td width="18%" align="center">收費標準</td><td width="11%" align="center">編輯</td></tr><s:iterator value="pageBean.data"><tr class="tabtd1"><td align="center"><s:property value="lessonName"/> </td><td align="center"><s:property value="remark"/></td><td align="center"><s:property value="total"/></td><td align="center"><s:property value="lessonCost"/></td><td width="11%" align="center"><s:a namespace="/" action="lessontypeAction_addOrEditUI"><s:param name="lessonTypeId" value="lessonTypeId"></s:param><img src="${pageContext.request.contextPath}/images/button/modify.gif" class="img"/></s:a></td></tr></s:iterator> </table> <table border="0" cellspacing="0" cellpadding="0" align="center"><tr><td align="right"><p:page url="${pageContext.request.contextPath}/lessontypeAction_findAll" data="${pageBean}" /></td></tr> </table>?
所以這里我們可以使用的action。所以我們需要在struts中進行配置:
?
?
<package name="lessontype" namespace="/" extends="common"><action name="lessontypeAction_*" class="cn.tf.lessontype.action.LessontypeAction" method="{1}"><result name="findAll" >/WEB-INF/pages/lessontype/listLessontype.jsp</result><result name="addOrEditUI">/WEB-INF/pages/lessontype/addOrEditCourseType.jsp</result><result name="addOrEdit" type="redirectAction">lessontypeAction_findAll</result></action></package>
action要跳轉的類,說到這里,我們還可以對action進行一些封裝,畢竟使用action也是非常多的:
?
?
public class BaseAction<T> extends ActionSupport implements ModelDriven<T>{public BaseAction(){try {ParameterizedType parameterizedType=(ParameterizedType) this.getClass().getGenericSuperclass();Class<T> crmClass=(Class<T>) parameterizedType.getActualTypeArguments()[0];t=crmClass.newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}private T t;@Overridepublic T getModel() {return t;}//注入使用到service//分頁數據private int pageNum;private int pageSize=2;public void setPageNum(int pageNum) {this.pageNum = pageNum;}//簡化值棧操作public void set(String key,Object o){ActionContext.getContext().getValueStack().set(key,o);}public void push(Object o){ActionContext.getContext().getValueStack().push(o);}public void put(String key,Object value){ActionContext.getContext().put(key,value);}public void putSession(String key,Object value){ActionContext.getContext().getSession().put(key, value);}}?
然后我們就來愉快的引用一下吧:
?
public class LessontypeAction extends BaseAction<CrmLessontype> {private CrmLessontype crmLessontype = new CrmLessontype();@Overridepublic CrmLessontype getModel() {return this.crmLessontype;}//2 serviceprivate LessontypeService lessontypeService;public void setLessontypeService(LessontypeService lessontypeService) {this.lessontypeService = lessontypeService;}//3 分頁數據private int pageNum;public void setPageNum(int pageNum) {this.pageNum = pageNum;}private int pageSize = 5 ;/*** 查詢所有--分頁* @return*/public String findAll(){PageBean<CrmLessontype> pageBean = this.lessontypeService.findAllPage(pageNum, pageSize);this.set("pageBean", pageBean);return "findAll"; }//打開添加或修改頁面public String addOrEditUI(){CrmLessontype findLessontype=this.lessontypeService.findById(this.getModel().getLessonTypeId());this.push(findLessontype);return "addOrEditUI";}public String addOrEdit(){this.lessontypeService.addOrEditLessontype(this.getModel());return "addOrEdit";}}?
這樣的話整個開發流程就完成了。接下來的就是很多類似的操作了。整體來說是很簡單的,當然,雖然簡單還是需要花費時間的哈!
例如我在修改員工信息整理的時候,就遇到了這個密碼更新的問題。
?
我最開始是在這里把密碼顯示出來的,然后一更新,壞了,把加密后的數據又加密一次存進去了,因為我這里這個密碼是通過md5加密處理了,所以回顯出來也沒有多大的意義,畢竟md5密碼不能解密!既然不顯示那么我密碼肯定是沒有修改吧,但是在hibernate中,使用SaveOrUpdate來更新,然后突然,啪的一下密碼變成空了,我想壞了,不能這么干,因為如果這里不顯示的話,這個員工的實體還是每個選項都要賦值的,所以我在最后面用了另外一個方法:使用bulkUpdate來操作就可以了。
這個地方的話我和修改用戶密碼一起組合起來寫了,所以用了一個if ?..else..
?
@Overridepublic void update(CrmStaff crmStaff) {String staffCode=crmStaff.getStaffCode();if(staffCode!=null){//修改密碼String loginPwd=crmStaff.getLoginPwd();String staffId=crmStaff.getStaffId();String hql1="update CrmStaff c set c.loginPwd=? where c.staffId=?";this.getHibernateTemplate().bulkUpdate(hql1,loginPwd,staffId);}else{String loginName=crmStaff.getLoginName();String staffName=crmStaff.getStaffName();String gender=crmStaff.getGender();String postId=crmStaff.getCrmPost().getPostId();Date onDutyDate=crmStaff.getOnDutyDate();String staffId=crmStaff.getStaffId();String hql="update CrmStaff c set c.loginName=? ,c.staffName=?,c.gender=?,c.crmPost.postId=?, c.onDutyDate=? where c.staffId=? ";this.getHibernateTemplate().bulkUpdate(hql, loginName,staffName,gender,postId,onDutyDate,staffId);}}
哎,雖然麻煩了一些,好歹功能最后被我實現了,要是哪位小伙伴有更好的想法,歡迎留言交流哦!希望更懂的小伙伴們可以不吝賜教哦!項目源碼我已經放到我的github中啦!
?
?
項目總結:這是一個非常好的SSH框架的項目,非常簡單,整個過程更多的是需要細心和耐心,對于一些相似的功能如果想要復制黏貼的話千萬要記得修改相應的地方,不然的話...就會”蹦,傻卡拉卡“ 系統就炸掉了,哈哈!還有就是通過js來打開'window.showModalDialog彈出模態窗口的時候貌似只兼容火狐瀏覽器。至于解決窗口的嵌套我們可以使用
?
if(top.location!= self.location){
????????? top.location= self.location;? //賦值成功之后,將馬上跳轉
????? }
來解決。好了,今天的項目分享就到這里啦!明天又是新的一天啦!
?
?
項目源碼:https://github.com/sdksdk0/CRM
?
轉載于:https://www.cnblogs.com/sdksdk0/p/6060026.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的项目分享:通过使用SSH框架的公司-学员关系管理系统(CRM)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ibus无法出现选择框如何解决
- 下一篇: 20145240 《信息安全系统设计基础