博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【项目总结】电厂安全培训管理系统总结
阅读量:6646 次
发布时间:2019-06-25

本文共 20266 字,大约阅读时间需要 67 分钟。

  第一个项目开发也有将近半年了,这也是自己的第一个比较成熟的系统,项目从刚开始的8个人到最后的三个人,开发团队的人也越来越少,系统也越来越成熟。中间开发也遇到了大量的问题,尤其在开发考试与试卷管理,由于界面交互太复杂一个JS可以上千行。17年11月中旬系统的第一次上线,我带着服务器到机房给客户安装部署好之后,客户的需求发生了很大的变化,直到18年元旦之后,系统才算正式开发完成,中间在客户的地方开发了将近20天,每天与客户沟通完需求之后进行开发,同时也要不停的修改别的代码,也真正理解到清晰的思路与清晰的代码的重要性,指不定哪天别人会修改你的代码,所以最好是将代码写的清除点,乱七八糟的代码容易暴露自己的实力。项目也逐渐成熟,直到项目后期才真正使用上git,刚开始人多只是不停的写代码,写完之后手动合并代码浪费了大量的时间。到客户的地方开发才使用上git,也理解了git的强大。

  项目也学会了、、、以及利用。、访问。也学会了自己封装一些常用的工具类。

 

 

一、项目描述

  开发环境:Eclipse+Jdk1.7+Git+Spring3.2+struts2.3+mybatis3.2+shiro1.3+mysql 5.7

  前台技术:bootstrap+Easuui的分页插件+zTree树插件+jedate日期插件+kindeditor文本编辑器插件+其他

   硬件:研腾身份证识别仪、南昊判卷机、指纹识别仪、人脸识别仪

  项目描述:电厂安全培训管理系统是一个用于电厂进行培训的系统,主要是考试与成绩管理。考试可以分为在线考试与线下考试,在线考试就是登录系统之后在线考试,考完之后系统自动给出成绩,线下考试是将试卷导出成pdf进行线下考试,并用判卷机进行判卷之后将成绩导入系统。辅助的功能有部门管理与人员管理、违章管理。权限管理是系统的一大难点,采用了shiro框架,对不同的用户显示不同的菜单与显示界面上不同的按钮,也就是不同的用户可以看见不同的菜单,也可以看见不同的按钮。

菜单后台主界面:(主要模块)

二、前台总结:

  前台技术:bootstrap+Easuui的分页插件+zTree树插件+jedate日期插件+kindeditor文本编辑器插件+其他

  前台主要是bootstrap,分页统一用的是EasyUi的分页插件(使用参考:,树用的zTree插件(使用参考:),编辑器用的是kindeditor(使用参考:)。日期插件用的jeDate的日期插件。

  前台学到最多的是jQuery的使用以及ajax的使用,项目中大量的使用异步请求数据,使用了jQuery封装的三种ajax:

  前台学到的主要开发思想:打开模态框之前清除之前的废旧数据,分页点击的时候带着条件去查询(将当前页与页大小存到页面的隐藏域),有时候reset按钮不能清空隐藏域,最可靠的办法就是将需要被清空的东西加个特殊的class,点击清除的时候清空所有的带class的。

 

--------------------jQuery封装的三种ajax:---------------------------------

第一种:    $.ajax

$.ajax({        url : contextPath + '/exam_getEmployeeIns4Exam.action',        data : $("#queryInnerForm").serialize(),        type : 'POST',        dataType : 'json',        success : showEmployeeInModal,        error : function() {            alert("查询内部员工出错!!!")        }    });

 

第二种:$.post

$.post(baseurl + '/distribute_getUnitInfoByBigIdAndUnitId.action', {            "unitId" : unitId,            "bigId" : bigId        }, function(response) {            var unit = response.unitInfo;            $("#unitTbody").html("");            $("#unitTbody").append(                    '' + treeNode.name + '' + unit.manager                            + '' + unit.managerPhone + ''                            + unit.secure + '' + unit.securePhone                            + '' + unit.projectNames + ''                            + unit.perNum + '' + unit.unitMinisMum                            + '');            $("#unitInfoDiv").css("display", "block");        }, 'json')

 

 第三种:  $.get

$.get(            "/Ajax/ajaxServlet2",    //请求地址            //"name=qlq&password=qlq",   //请求参数            {"name":"qlq","password":"nicai"},  //请求传递的参数,也可以是JSON            function(data){     //data表示传递回来的数据,只有在成功的时候才有                alert(data);                },                "json"         //表示返回内容的格式,json会将传回来的自动解析成json对象    );

 

 参考:

 

------------常用的jQuery的选择器=---------------------------------

参考:

 

三、后台总结:

   后台技术:Eclipse+Jdk1.7+Git+Spring3.2+struts2.3+mybatis3.2+shiro1.3+mysql 5.7

  后台用的技术主要就是SSM框架+Shiro,项目刚开始的时候是分模块开发,也没有使用上git,都是手工的合称代码。直到项目的后期才使用上git,也真正了解到git的作用(git 的使用参考:)

。spring主要用到了spring的IOC和AOP,IOC主要用来管理项目的对象,AOP用在事务管理。IOC主要使用基于注解方式的配置,AOP采用XML配置。(spring事务配置参考:)。struts采用页面跳转与json结合的方式,struts与json结合主要是struts的package继承json-default。剩下的json转换交给struts。mybatis开发采用动态代理的方式,简单的写一下接口然后在xml中实现即可。spring与struts整合主要是将struts创建对象的一个常量配置为spring:<constant name="struts.objectFactory" value="spring"></constant>,剩下的配置spring扫描struts的包就行了,struts的配置只用写类名(第一个字母小写)。后台在Action层对异常的捕捉以及对日志的记录非常重要,在部署之后可以通过日志查看错误信息

  0.dp.properties

;;;;;;;;;;;;;;;;;;;;;DataBaseConnection;;;;;;;;;;;;;;;;;;;;;jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/exam9jdbc.username=rootjdbc.password=123456jdbc.initialPoolSize=10 jdbc.minPoolSize=5  jdbc.maxPoolSize=30  jdbc.maxIdleTime=200  jdbc.maxStatementsPerConnection=50

 

 1.Spring框架的配置:

大致的配置过程:

  配置数据库配置文件存放位置、将连接池放入spring容器(数据源)、配置mybatis会话工厂、配置mybatis扫描的基本包、配置事务管理器、配置事务模板对象、配置事务通知、将通知织入切面、配置扫描service与Action的包

 

 

2.mybatis配置:

SqlMapConfig.xml(主配置)    开启二级缓存与配置别名

 

 与接口对应的mapper(开启二级缓存)

and title like '%${title}%'
AND departmentId=#{departmentId}
and level=#{level}
LIMIT #{index},#{currentCount}
UPDATE `exampaper` SET useTimes = useTimes+1 WHERE paperId=#{value}
UPDATE `exampaper` SET useTimes = useTimes-1 WHERE paperId=#{value}

 

 

 mybatis开启二级缓存的配置:(与encache整合      默认就是开启)

(1) 在核心配置文件SqlMapConfig.xml中settings标签中加入下面开启总缓存

<setting name="cacheEnabled" value="true"/>

(2)在UserMapper.xml中开启二缓存  (实体需要实现序列化接口  serializable)

<cache type="org.mybatis.caches.ehcache.EhcacheCache" />

 

 

encache缓存的配置:

ehcache.xml

 

 

3.struts配置:

struts.xml

 

 

struts一个模块的配置:

Exam.xml     (继承struts-default与json-default)

response
/view/examParper/exam/modifyExam.jsp
application/octet-stream
inputStream
attachment;filename="${downloadFileName}"
8192
application/octet-stream
inputStream
attachment;filename="${downloadFileName}"
8192
application/octet-stream
inputStream
attachment;filename="${downloadFileName}"
8192
/files/downloadFiles
application/octet-stream
inputStream
attachment;filename=${name}
1024

 

 4.shiro配置:

applicationContext-shiro.xml

/ = anon
/index.jsp = anon /newsIP_**.action = anon /train_**.action = anon /unauthorized.jsp = anon /user_login.action = anon /view/public/** = anon /view/index/** = anon /bs/** = anon /controls/** = anon /css/** = anon /image/** = anon /js/** = anon /META-INF/** = anon
/logout.action = logout
/** = authc

 

shiro缓存配置

shiro-ehcache.xml

 

5.web.xml配置:

xm
index.jsp
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
classpath:spring/applicationContext-*.xml
shiroFilter
org.springframework.web.filter.DelegatingFilterProxy
targetFilterLifecycle
true
shiroFilter
/*
struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts2
/*
404
/404.jsp
500
/500.jsp

 

 

四、mysql数据库总结:

  项目在使用mysql的过程中也遇到了好多问题,并通过各种手段解决了这些问题。

1. 索引:

    在查询的时候有时候特别慢,通过项目也了解到索引的重要性,索引是真实存在于表中的,

mysql有哪些索引类型:

  1. 数据结构角度上可以分:B+tree索引,hash索引,fulltext索引(innodb,myisam都支持)

  2. 存储角度上可以分:聚集索引,非聚集索引

  3. 逻辑角度上可以分:primary key,normal key,单列,复合,覆盖索引

  索引也会占用内存。就对某秀特殊的列建立了索引,有时候通过代码建立索引,有时候通过sqlyog建立索引。参考:

 

2. 触发器:

  项目中在扣个人积分的同时使用触发器自动修改器对应部门的积分,触发器是建立在某个表上针对表的某种操作建立的触发事件,参考

  下面是项目中的一个触发器:

DELIMITER $$USE `exam9`$$DROP TRIGGER /*!50032 IF EXISTS */ `add_unit_after_add_break`$$CREATE    /*!50017 DEFINER = 'root'@'localhost' */    TRIGGER `add_unit_after_add_break` AFTER INSERT ON `breakrules`     FOR EACH ROW BEGINDECLARE big_id VARCHAR(40);DECLARE unit_id VARCHAR(40);SET big_id=(SELECT bigId FROM haulemployeeout WHERE BigEmployeeoutId=new.BigEmployeeoutId);SET unit_id=(SELECT unitId FROM haulemployeeout WHERE BigEmployeeoutId=new.BigEmployeeoutId);UPDATE haulunit SET unitMinisMum=unitMinisMum+new.minusNum WHERE unitId=unit_id AND bigId=big_id;END;$$DELIMITER ;

 

 

3.存储过程

 

  相当于sql脚本,可以执行多条sql语句,项目在根据时间动态修改状态的时候使用的是存储过程,比如根据当前时间与考试的开始时间动态修改考试的状态,参考:

  下面是项目中的一个不带输入输出参数的存储过程:

DELIMITER $$USE `exam9`$$DROP PROCEDURE IF EXISTS `updateStatus`$$CREATE DEFINER=`root`@`localhost` PROCEDURE `updateStatus`()BEGIN    UPDATE exam SET `status`="已结束" WHERE  `status` != "已结束" AND  (NOW() - endTime)>0  ;    UPDATE exam  SET `status`="正在答题"  WHERE   `status` != "已结束" AND ( NOW() - startTime)>=0     AND  (NOW() - endTime)<=0;        UPDATE haulinfo SET bigStatus="已结束" WHERE  bigStatus != "已结束" AND  (CURDATE() - bigEndDate)>0;     UPDATE haulinfo SET bigStatus="进行中" WHERE  (CURDATE() - bigEndDate)<=0     AND  (CURDATE() - bigBeginDate)>=0;        UPDATE exam SET bigStatus=(SELECT bigStatus FROM haulinfo WHERE bigId=exam.bigId);END$$DELIMITER ;

 

存储过程与自定义函数的区别:存储过程实现的过程要复杂一些,而函数的针对性较强;存储过程可以有多个返回值,而自定义函数只有一个返回值;存储过程一般独立的来执行,而函数往往是作为其他SQL语句的一部分来使用;

4.事件与任务调度

  项目中遇到大量的根据时间修改状态,另外有一个功能就是每年的1月1日清空积分,第一个修改状态是创建一个每秒钟执行一次的事件,第二个需求是每年执行一次并且开始执行是在1月1日。任务调度需要结合存储过程来完成其功能,每秒钟或者每年执行存储过程(:参考:)。下面附两个项目的事件

  事件使用的前提是开启任务调度:

#查看是否开启任务调度:(on代表开)    show variables like '%event_scheduler%'; # 开启事件调度器    SET GLOBAL event_scheduler = ON;     SET @@global.event_scheduler = ON;     SET GLOBAL event_scheduler = 1;     SET @@global.event_scheduler = 1; 或者是通过配置文件my.cnf    event_scheduler = 1 #或者ON

 

 

 

  第一个:每秒钟都执行修改状态的存储过程:

更新状态的存储过程:

DELIMITER $$USE `exam9`$$DROP PROCEDURE IF EXISTS `updateStatus`$$CREATE DEFINER=`root`@`localhost` PROCEDURE `updateStatus`()BEGIN    UPDATE exam SET `status`="已结束" WHERE  `status` != "已结束" AND  (NOW() - endTime)>0  ;    UPDATE exam  SET `status`="正在答题"  WHERE   `status` != "已结束" AND ( NOW() - startTime)>=0     AND  (NOW() - endTime)<=0;        UPDATE haulinfo SET bigStatus="已结束" WHERE  bigStatus != "已结束" AND  (CURDATE() - bigEndDate)>0;     UPDATE haulinfo SET bigStatus="进行中" WHERE  (CURDATE() - bigEndDate)<=0     AND  (CURDATE() - bigBeginDate)>=0;        UPDATE exam SET bigStatus=(SELECT bigStatus FROM haulinfo WHERE bigId=exam.bigId);END$$DELIMITER ;

 

一个每秒钟执行一次的事件调用上面的存储过程:

DELIMITER $$ALTER DEFINER=`root`@`localhost` EVENT `eventUpdateStatus` ON SCHEDULE EVERY 1 SECOND STARTS '2017-11-21 00:12:44' ON COMPLETION PRESERVE ENABLE DO CALL updateStatus()$$DELIMITER ;

 

 

 第二个:每年的1月1日清空积分

存储过程:

DELIMITER $$USE `exam9`$$DROP PROCEDURE IF EXISTS `clearEmInBreakInfo`$$CREATE DEFINER=`root`@`localhost` PROCEDURE `clearEmInBreakInfo`()BEGIN    DELETE FROM emplyin_breakrules WHERE empInMinusnum < '12';    DELETE FROM blacklist WHERE temporaryInStatus = '0' AND employeeStatus = '0';END$$DELIMITER ;

 

每年的1月1日执行的事件调用上面的存储过程:

DELIMITER $$ALTER DEFINER=`root`@`localhost` EVENT `eventEmpInBreaksInfo` ON SCHEDULE EVERY 1 YEAR STARTS '2018-01-01 01:00:00' ON COMPLETION PRESERVE ENABLE DO CALL clearEmInBreakInfo()$$DELIMITER ;

 

 

5.其他:

  项目中也遇到了自定义变量,通过对查出的两列进行除法运算用到了自定义变量。参考:

          列转行,对一个人分配部门与班组时需要将多行转为一列,遇到了列转行。参考:

        中文排序:

SELECT * FROM employee_in ORDER BY CONVERT(NAME USING gbk)

 

        

  还遇到一些根据年份统计或者根据不同的情况进行查询,参考case when then用法(用于分类统计):

      SQL随机抽取几条数据:

    计算时间差函数

    MySql授权和撤销权限操作

 

五、部署与优化

  服务器配置:windows server 2012   64G运行内存

  部署主要就是将tomcat设置为服务器启动,每次更新程序将服务停掉,更换war包。mysql设置任务调度开机开启 (参考:),设置mysql最长连接时间:(参考:)。tomcat优化设计并发优化、JVM参数优化以及JVM参数查看(参考:),tomcat配置虚拟路径参考:

1.tomcat优化

(1)并发优化

  在部署的时候因为tomcat的server.xml配置中出现中文注释导致启动一直失败,因此最好在server.xml中不要用中文注释,有可能导致启动失败。

服务器server.xml配置:

 

  (2)JVM优化

主要通过以下的几个jvm参数来设置堆内存的:-Xmx512m     最大总堆内存,一般设置为物理内存的1/4-Xms512m     初始总堆内存,一般将它设置的和最大堆内存一样大,这样就不需要根据当前堆使用情况而调整堆的大小了-Xmn192m     年轻带堆内存,sun官方推荐为整个堆的3/8堆内存的组成     总堆内存 = 年轻带堆内存 + 年老带堆内存 + 持久带堆内存年轻带堆内存     对象刚创建出来时放在这里年老带堆内存     对象在被真正会回收之前会先放在这里持久带堆内存     class文件,元数据等放在这里-XX:PermSize=128m     持久带堆的初始大小-XX:MaxPermSize=128m     持久带堆的最大大小,eclipse默认为256m。如果要编译jdk这种,一定要把这个设的很大,因为它的类太多了。

 

在开发当中,当一个项目比较大时,依赖的jar包通常比较多,我们都知道,在应用服务器启动时,会将应用引用到的所有类通过ClassLoader 依次全部加载到内存当中。Java的逻辑内存模型大致分为堆内存、栈内存、静态内存区,也称持久区,该区的内存不会被GC回收。堆内存用于存储类的实例、 数组等引用类型数据,也就是用new生成的对象,都存放在这里,栈内存存储局部变量(如:方法参数),静态内存区存储常量、静态变量、类元数据信息(方 法、属性等)。开发当中常遇到的三类内存溢出异常:

  • java.lang.OutOfMemoryError: Java heap space异常 
    表示堆内存空间满了,如果不是程序逻辑的bug,可能是因为项目中引用的jar比较多,导到内存溢出。JVM默认堆的最小使用内存为物理内存的1/64, 最大使用内存为物理内存的1/4,如8G的物理内存,JVM默认堆的最小和最大内存分别为128m和2048m。通过调整JVM的-Xms(初始内存)和 -Xmx(最大内存)两个参数加大内存使用限制。
  • java.lang.OutOfMemoryError: PermGen space异常 
    表示静态内存区满了,通常是由于加载的类过多导致。jdk8以下版本通过修改JVM的-XX:PermSize和-XX:MaxPermSize两个参 数,限制静态区最小和最大内存范围。jdk8改变了内存模型,将类定义存放到了元数据(MetaspaceSize)空间,而元数据空间是与堆空间共享同 一块内存区域的,所以在JDK8以后版本不会存在PermGen space异常了,故不用设置此参数。
  • java.lang.StackOverflowError异常 
    表示栈内存溢出。通常是由于死循环、无限递归导致。

 

优化方法:

修改Tomcat的内存配置,打开$TOMCAT_HOME/bin/catalina.sh文件(Windows系统是catalina.bat文件),大楖在250行左右,在JAVA_OPTS参数上添加内存参数设置即可。完整的JVM参数设置如下所示:

linux修改TOMCAT_HOME/bin/catalina.sh,在前面加入

JAVA_OPTS="$JAVA_OPTS -server -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=256 -Djava.awt.headless=true"

windows修改TOMCAT_HOME/bin/catalina.bat,在前面加入 

set JAVA_OPTS=-server -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=256 -Djava.awt.headless=true

 如果是Windows配置服务式的参考我的另一篇博客:

 

 

-server参数:表示以服务模式启动,启动速度会稍微慢一点,但性能会高很多。不加这个参数,默认是以客户端模式启动。 

java.awt.headless=true参数:与图形操作有关,适用于linux系统。如生成验证码,含义是当前使用的是没有安装图安装图形界面的服务器,应用中如果获取系统显示有关参数会抛异常。

  

(3)数据库连接池c3p0配置

dp.properties

;;;;;;;;;;;;;;;;;;;;;DataBaseConnection;;;;;;;;;;;;;;;;;;;;;jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/exam9jdbc.username=rootjdbc.password=123456jdbc.initialPoolSize=10 jdbc.minPoolSize=5  jdbc.maxPoolSize=30  jdbc.maxIdleTime=200  jdbc.maxStatementsPerConnection=50

 

 spring配置:

 

参考:

 

 

   整个开发也经历了将近半年,学到的更多的是开发思想与一些常用的开发技术,在平时开发中也都记录下来啊了。

  一个牛逼的程序员不仅是每天是敲多少行代码,更重要的是每天能学到多少,要时刻保持清晰的思路,养成良好的编程思路。

 

转载地址:http://imuto.baihongyu.com/

你可能感兴趣的文章
C# 程序性能提升篇-1、装箱和拆箱,枚举的ToString浅析
查看>>
电梯模拟系统——BUAA OO第二单元作业总结
查看>>
V3 微信支付-预支付C#
查看>>
legend2---开发日志6(后端和前端如何相互配合(比如php,js,元素状态和数据改变))...
查看>>
关于宏的一点注意
查看>>
CentOS7.0使用Yum安装Nginx
查看>>
laravel获取checkbox值的小技巧
查看>>
安装DotNetCore.1.0.1-VS2015Tools.Preview2.0.2出现0x80072f8a未指定的错误
查看>>
Java关于String类的赋值符号一些验证
查看>>
android OTA更新
查看>>
copyright symbol issue
查看>>
【树状数组】Codeforces Round #755 D. PolandBall and Polygon
查看>>
二维数组遍历的方式(for普通循环遍历、foreach循环遍历、toString方式遍历)
查看>>
递归神经网络RNN桨距控制控制风力发电机组
查看>>
R语言混合时间预测更好的时间序列点估计
查看>>
wireshark过滤规则(两年前记录在qq空间的日志)
查看>>
django基础-ORM操作
查看>>
javascript 关于倒计时与输入框选中状态的判断
查看>>
【转】php pdo连接数据库 解决中文乱码问题(wordpress mysql 问号?? ??)
查看>>
jquery中html(), text(),val()区别
查看>>