我的平台功能介绍

 

我的平台功能介绍

分类: 项目总结 Java   40人阅读  评论(0)  收藏  举报

 

主体架构

 

主体采用Struts2 Spring3 Hibernate3.3架构。

 

Spring和Hibernate都采用Annotation方式省去了大量Bean的配置和ORM映射文件。

界面展示用JSP结合 Struts2 tags的方式。

 

主要模块的页面采用form,和list两个页面,前者负责新增、编辑、查看,后者负责数据列表展现。

 

权限管理

平台采用基于角色的访问控制RBAC模型,通过给角色授予访问某资源(模块,URL),再将角色分配给用户,使用户获得访问某些资源的权限。

 

对应的领域模型有“用户”User,“角色”Role,“模块”Module,“部门”Department。

 

权限采用Spring Security。

邮件发送组件

系统已在com.epro.crm.util.message.EmailHelper工具类中集成了JavaMail, 并在EmailService内置在了CommonBaseService中。如果业务需要发送邮件,只需在将邮件内容写在EmailServiceImpl中,然后在Service中直接调用即可。系统将异步调用EmailHelper.sendEmail(…)方法,将邮件发出。

 

参考:com.epro.crm.service.system.impl.UserServiceImpl.add(User)

注册用户时,系统将注册成功信息,异步的发送至用户的注册邮箱中。

 

[java]  view plain copy
  1. protected void sendEmail(final List<String> recipientAccounts,final String message, final String subject){  
  2.         //判断 系统设置 (是否已开启 发送邮件模块)  
  3.         if(Constants.YES.equals(Configurations.SEND_EMAIL)){  
  4.             //异步发送  
  5.             taskExecutor.execute(new Runnable() {  
  6.                 public void run() {  
  7.                     EmailHelper.sendEmail(recipientAccounts,message, subject);  
  8.                 }  
  9.             });  
  10.         } else {  
  11.             log.info("系统邮件发送功能未开启,无法发送短信");  
  12.         }  
  13.     }  

 

 

界面表单验证

 

使用了jQuery validate 表单验证框架

 

参考 /page/user/user_form.jsp

 

[javascript]  view plain copy
  1. jQuery(function(){  
  2.     $("#submitForm").validate({  
  3.         rules: {  
  4.             name: "required",  
  5.             username: {  
  6.                 required: true,  
  7.                 minlength: 4  
  8.                 //remote:"UserAction!validateUsername"  
  9.             },  
  10.             phone:"digits",  
  11.             birthDay: "dateISO",  
  12.             email: {  
  13.                 required: true,  
  14.                 email: true  
  15.             }  
  16.         },  
  17.         success: function(label) {  
  18.             label.text('').addClass("success");  
  19.         },  
  20.         messages: {  
  21.             name: "请输入用户的姓名",  
  22.             phone:"电话号码必须是数字",  
  23.             username: {  
  24.                 required: "请输入该用户的登录名(登录账号)",  
  25.                 minlength: "登录名最短4位"  
  26.             },  
  27.             birthDay: "请输入合法日期格式 如:2011-3-11",  
  28.             email: "请输入合法email格式"  
  29.         }  
  30.     });  
  31.       
  32. });  

增删改查封装

 

普通的数据访问对象(Dao)接口应继承于com.epro.crm.dao.base.CommonDaoInterface<T>,其默认已有增删改查的接口。其实现类应继承于com.epro.crm.dao.base.CommonBaseDao<T>,默认已有增删改查等基本操作的实现,并可通过HibernateTemplate扩展其他的操作。如果需要按自定义的条件查询,可以重写CommonBaseDao类的String appendConditionHQL(T t)方法。

 

参考:com.epro.crm.dao.system.impl.UserDaoImpl

 

增加

[java]  view plain copy
  1. public void add(T t) {  
  2.         String stateStr = null;  
  3.         try {  
  4.             if (t instanceof DeletedByLogic ) {  
  5.                 stateStr = BeanUtils.getProperty(t, "state");  
  6.                 if(stateStr == null){  
  7.                     BeanUtils.setProperty(t, "state",Constants.STATE_VALID);  
  8.                 }  
  9.                 hibernateTemplate.save(t);  
  10.             } else if (t instanceof DeletedByPhysics) {  
  11.                 hibernateTemplate.save(t);  
  12.             } else {  
  13.                 hibernateTemplate.save(t);  
  14.             }  
  15.         } catch (Exception e) {  
  16.             log.error(e.getMessage(),e);  
  17.             throw new CrmSystemException("新增数据出错",e);  
  18.         }   
  19.     }  
删除
[java]  view plain copy
  1. public void delete(T t) {  
  2.         try {  
  3.             String idStr = BeanUtils.getProperty(t, "id");  
  4.             long id = Long.parseLong(idStr);  
  5.             Object delObject = hibernateTemplate.get(t.getClass(), id);  
  6.             if (t instanceof DeletedByLogic) {  
  7.                 BeanUtils.setProperty(delObject, "state",  
  8.                         Constants.STATE_DELETED);  
  9.             } else if (t instanceof DeletedByPhysics) {  
  10.                 hibernateTemplate.delete(delObject);  
  11.             } else {  
  12.                 throw new CrmSystemException("实体类 " + t.getClass().getName()  
  13.                         + " 既不是物理删除,也不是逻辑删除");  
  14.             }  
  15.         } catch (Exception e) {  
  16.             log.error(e.getMessage(),e);  
  17.             throw new CrmSystemException("删除对象" + t + "时,系统异常");  
  18.               
  19.         }  
  20.     }  

 

 查询

 

[java]  view plain copy
  1. public List<T> getList(T t, final int offset, final int length) {  
  2.     final String hql = getListHQL(t);  
  3.     List<T> list = getHibernateTemplate().executeFind(  
  4.             new HibernateCallback() {  
  5.                 public Object doInHibernate(Session session)  
  6.                 throws HibernateException, SQLException {  
  7.                     Query query = session.createQuery(hql);  
  8.                     query.setFirstResult(offset);  
  9.                     query.setMaxResults(length);  
  10.                     List<T> list = query.list();  
  11.                     return list;  
  12.                 }  
  13.   
  14.                   
  15.             });  
  16.     return list;  
  17. }  
  18.   
  19.   
  20.   
  21. /** 
  22.  * 子类需要重写HQL时,可继承重写该方法 
  23.  * @param t 
  24.  * @return 
  25.  */  
  26. protected String getListHQL(T t){  
  27.     String className = t.getClass().getSimpleName();  
  28.     StringBuffer hqlBuffer = new StringBuffer("from " + className + " as t " + (appendJoinHQL(t)==null?"":appendJoinHQL(t)) + " where 1 = 1 ");  
  29.     String appender = appendConditionHQL(t);  
  30.     if(appender != null){  
  31.         hqlBuffer.append(appender);  
  32.     }  
  33.     if(t instanceof DeletedByLogic){  
  34.         hqlBuffer.append(" and t.state != '" + Constants.STATE_DELETED + "'");  
  35.     }  
  36.     hqlBuffer.append(" order by " + getOrderByHQL()+ " " );  
  37.     String hql = hqlBuffer.toString();  
  38.     return hql;  
  39. }  

 

 

统计条数
[java]  view plain copy
  1. public int getCount(T t, int offset, int length) {  
  2.         String className = t.getClass().getSimpleName();  
  3.         StringBuffer hqlBuffer = new StringBuffer("select count(*) from " + className + " as t where 1=1 ");  
  4.         String appender = appendConditionHQL(t);  
  5.         if(appender != null){  
  6.             hqlBuffer.append(appender);  
  7.         }  
  8.         if(t instanceof DeletedByLogic){  
  9.             hqlBuffer.append(" and t.state != '" + Constants.STATE_DELETED + "'");  
  10.         }  
  11.         final String hql = hqlBuffer.toString();  
  12.         Object uniqueResult = createQuery(hql).uniqueResult();  
  13.         return Integer.parseInt(uniqueResult.toString());  
  14.       
  15.     }  


普通的业务处理对象(Service)接口应继承于com.epro.crm.service.base.CommonServiceInterface<T>,其默认已有增删改查的接口。其实现类应继承于com.epro.crm.service.base.CommonBaseService<T>,该类有增删改查,日志等功能。

 参考:com.epro.crm.service.system.impl.UserServiceImpl

 

[java]  view plain copy
  1. public PageModel<T> getPageModel(T sample, PageModel<T> pageModel){  
  2.         if(sample == null)  
  3.             sample = getNewEntity();  
  4.         List<T> dataList = getCommonDao().getList(sample, pageModel.getOffset(), pageModel.getPageSize());  
  5.         Integer total =  getCommonDao().getCount(sample, pageModel.getOffset(), pageModel.getPageSize());  
  6.         pageModel.setDataList(dataList);  
  7.         pageModel.setTotalItemNumber(total);  
  8.         return pageModel;  
  9.     }  

 

分页模型

页面上采用pager-taglib 标签进行分页页码显示及偏移量计算,由分页模型对象com.epro.crm.model.util.PageModel<T>接收偏移量offset,页大小,在DAO层由com.epro.crm.dao.base.CommonBaseDao.getList(T,int, int)方法将分页查询的结果放在PageModel对象中,在页面通过Struts-tag显示。

 

[java]  view plain copy
  1. public class PageModel<T> {  
  2.     /**  
  3.      * 总记录数  
  4.      */    
  5.     private Integer totalItemNumber;    
  6.     /**  
  7.      * 当前页结果集  
  8.      */    
  9.     private List<T> dataList;  
  10.       
  11.     /**  
  12.      * 偏移量:当前页第一条记录,在总记录数中的序号 
  13.      */  
  14.     private Integer offset = 0;   
  15.     /** 
  16.      * 每页显示记录数 
  17.      */  
  18.     private Integer pageSize = Configurations.DEFAULT_PAGE_SIZE;  
  19.     /** 
  20.      * 页码 
  21.      */  
  22.     private Integer pageNumber = null;  
  23.     /** 
  24.      * 总页码 
  25.      */  
  26.     private Integer totalPageNumber = null;  
  27.   
  28.     /** getters and setters **/  
  29. }   

 

数据字典

 

数据字典由“数据字典类型”com.epro.crm.model.system.DataDictType以及“数据字典项”com.epro.crm.model.system.DataDictItem组成。

 

在数据库中添加了数据字典类型,及对应的数据字典项后。在Action层中,通过DataDictTypeService准备数据字典内容。在界面中可通过

 

[html]  view plain copy
  1. <s:select list="allTaskTypes" name="taskType.id" headerKey="" headerValue="请选择.." listKey="id" listValue="name" value="taskType.id" cssClass="required"></s:select>  

的Struts标签,即可显示数据字典列表。

 

 

 

系统日志/操作日志    

 

平台提供两种日志方式。

 

系统日志:系统日志由log4j记录,输出至/crm_log.html文件中。程序中可通过以下方式获得日志记录对象。

 

[java]  view plain copy
  1. protected final Log log = LogFactory.getLog(getClass());  


 

 

操作日志:操作日志是由平台提供用来将用户的重要操作记录到数据库中,以及日志的显示模块。记录的内容包括操作时间,操作者用户名,IP,以及操作描述。见com.epro.crm.model.system.Log

 

已经在BaseAction中封装,所以可以在Action中直接使用logService.log(“”)记录。

 

参考:

 

[java]  view plain copy
  1. public void log(String summary, String description){  
  2.        Log log = new Log((User)sessionMap.get(Constants.SESSION_USER),getIpAddr(),  
  3.               summary, description);  
  4.        logService.add(log);  
  5.     }  

平台中的领域对象删除后的状态支持两种模式。

 

逻辑删除是采用一个标记字段表示该记录的状态,如已删除,则修改标记字段为删除状态,查询时将其忽略。物理删除即为普通delete删除。

 

采用物理删除的类中实现com.epro.crm.model.base.DeletedByPhysics接口即可。

采用逻辑删除的类中实现com.epro.crm.model.base.DeletedByLogic接口即可。

 

CommonBaseDao在删除和查询对象时,会根据类所表明的模式,进行判断。

 

参考:com.epro.crm.model.system.User

 

 

上传下载  

Struts 2 的常用方式,有待封装

见 ResumeAction:111

Json支持

由于使用Struts2 Json plugin 时,response默认content type为”text/json”,部分浏览器对该格式解析不正确,产生下载页面。

所以本平台采用另外一种手动设置的方式

 

[java]  view plain copy
  1. <span style="white-space:pre">    </span>   this.getResponse().setContentType("text/html");  
  2.            this.getResponse().setCharacterEncoding("GBK");  
  3.            PrintWriter out = this.getResponse().getWriter();  
  4.            ajaxResult = "{error: '简历上传成功!但无法提取信息,请手动填写表单!',msg:'',filename:'"+ resumeFileFileName + "',filepath : ' " + targetDirectory+ "/" + targetFileName + " '}";  
  5.            out.write(ajaxResult);  
  6.            out.flush();  

见 ResumeAction:111

 

你可能感兴趣的:(介绍)