资源描述
办公自动化系统OA系统分析与设计
33
2020年4月19日
资料内容仅供参考,如有不当或者侵权,请联系本人改正或者删除。
概述
OA是Office Automation的缩写, 本意为利用技术的手段提高办公的效率, 进而实现办公的自动化处理。实现信息化、 无纸化办公, 可方便的生成统计报表等。
OA是OFFICE AUTOMATION的缩写, 本意为利用技术的手段提高办公的效率, 进而实现办公的自动化处理。采用Internet/Intranet技术, 基于工作流的概念, 使企业内部人员方便快捷地共享信息, 高效地协同工作; 改变过去复杂、 低效的手工办公方式, 实现迅速、 全方位的信息采集、 信息处理, 为企业的管理和决策提供科学的依据。
OA软件解决企业的日常管理规范化、 增加企业的可控性、 提高企业运转的效率的基本问题。范围涉及日常行政管理、 各种事项的审批、 办公资源的管理、 多人多部门的协同办公、 以及各种信息的沟通与传递。能够概括的说, OA软件跨越了生产、 销售、 财务等具体的业务范畴, 更集中关注于企业日常办公的效率和可控性, 是企业提高整体运转能力不可缺少的软件工具。
系统作用
组织的核心竞争力源自单位对内外部资源的有效利用。对它们之间的关系进行协调, 最大限度的发挥所有资源的作用, 并用系统的观点, 在整个系统价值最大化的基础上来发挥各个资源的作用, 使资源的运作产生协同效用。因此可经过协同办公系统打造单位的核心竞争力。本协同办公系统的主要作用为:
1、 建立内部的通信平台。
2、 建立信息发布的平台。
3、 文档管理的自动化。
4、 工作流程的自动化。
5、 行政日常事务处理。
6、 安全机制的可靠性。
本系统旨在加速单位信息化进程, 充分利用计算机和现代通讯手段面向单位服务。建立单位内部信息交流的快速通道, 以共享信息资源。强化部门业务管理, 加强各业务部门之间的交流。实现单位信息的快速上传下达, 促进协同办公。提高办公效率, 为各级领导及业务人员提供辅助办公和决策服务。
1、 本系统将最大限度地提高办公效率和办公质量, 降低管理和办公成本, 改进办公环境和条件, 提高办公管理和决策的自动化和科学化水平。
2、 以人为中心, 致力于帮助用户实现共享资源、 规范流程、 推动执行的目的。帮助用户节省办公费用, 减少中间环节, 优化业务流程, 提高整体效率, 促进管理进步。
设计原则
以应用为核心, 要突出”实用、 易用、 简洁、 稳定”。既注重实效, 满足用户的现实需要, 又为系统的后续升级和扩展留有余地。在技术实现上, 要突出”结构清晰、 实现合理、 通俗易懂( 简单) ”。
1. 实用: 满足用户现实需要, 解决实际问题, 做细核心功能。
2. 易用: 使用方便, 各项功能一目了然。满足用户的使用习惯, 易使用、 易维护、 易升级。实现”傻瓜”式的操作, 将实施、 培训成本和周期降到最低。
3. 简洁: 页面简洁, 功能简洁, 每一个元素都有存在的意义。
4. 稳定: 从底层数据库到功能层经过严格测试, 能在不同的硬件环境中长期平稳运行。
功能说明
OA是辅助办公的软件, 使用OA与不使用OA相对比的好处是: 能够用计算机管理所有的数据, 并能够方便的实现统计与报表的功能。提高办公效率。( 实现信息化) 。
以下是一个OA系统的全部功能列表:
说明: 不是所有的OA都有全部的功能, 而是根据需要确定的。
软件开发的步骤说明
需求确认—概要设计—详细设计—编码—单元测试—集成测试—系统测试—维护。
单元测试是由程序员自己来完成, 最终受益的也是程序员自己。能够这么说, 程序员有责任编写功能代码, 同时也就有责任为自己的代码编写单元测试。执行单元测试, 就是为了证明这段代码的行为和我们期望的一致。
集成测试, 也叫组装测试或联合测试。在单元测试的基础上, 将所有模块按照设计要求( 如根据结构图〕组装成为子系统或系统, 进行集成测试。实践表明, 一些模块虽然能够单独地工作, 但并不能保证连接起来也能正常的工作。程序在某些局部反映不出来的问题, 在全局上很可能暴露出来, 影响功能的实现。
系统测试是将已经确认的软件、 计算机硬件、 外设、 网络等其它元素结合在一起, 进行信息系统的各种组装测试和确认测试, 其目的是经过与系统的需求相比较, 发现所开发的系统与用户需求不符或矛盾的地方, 从而提出更加完善的方案。
整体说明
要完成的功能
模块
功能
说明
组织与用户管理
岗位管理
部门管理
用户管理
权限
初始化权限
分配权限
验证权限
网上交流--论坛
版块管理
看帖、 发帖、 回帖
文章管理
审批流转( 工作流)
表单模板管理
审批流程管理
审批流转
表单查询
说明: 按列出的顺序实现功能。效果以静态页面为准。
分层
一、 JavaEE的三层架构
二、 关于分层的说明
1, 上面调用下面, 即View调用Service, Service调用Dao。
2, 层与层之间用接口。除定义的接口外, 不能使用其它层的特有类或接口。
3, 使用实体作为DTO( Data Transfer Object, 数据传输对象)
要做到任一层换掉后, 其它层不受影响。我们在此项目中使用两层: View+Service即在Service中直接操作Hibernate.Session。因为如果使用三层, 在Service中就会有一部分方法只是直接调用DAO中的方法。一般情况下只有在多个数据源的场合下适合引入DAO层。
三、 有关分层的几个问题
1, 一定要分层吗?
不一定。假如公司要求你写一个能够给指定员工发送短信的小程序, 用于开会通知与自动发送生成祝福短信。这个程序很小, 没有多少行代码, 而且不变, 这时不分层能够吗? 完全能够呀。但我们在写程序时, 还是要分层的, 分层的程序结构清晰, 可维护性高。
2, 一定要3层吗?
不一定。分3层是推荐的, 而不是必须的, 应根据自己的具体情况进行安排。我们如果使用3层的结构, 用起来就麻烦, 因为在Service中会有一部分方法只是直接调用Dao中的方法, 而Dao中的方法只是调用Session完成某操作。此时分2层更好, 即在Service中可直接操作Session, 以简化结构。其实Hibernate已经能够支持多种数据库。
3, 一定要使用接口吗?
不一定。以前就有同学问我: ”在设计程序时确定的技术在开发后一般不会更换的, 实现类一般也不会更换, 这种情况还用接口吗, 一般的小项目是不是能够不使用接口? ”。是的, 如果不会变( 一般也不会变) , 这是完全能够的。
我们所学习的框架、 技术都是解决问题的推荐方案, 而不是必须要用的。遇到问题后优化使用成熟的技术与方案, 以避免很多潜在的或后发的问题, 避免走不必要的弯路。
所用框架、 技术
编号
工具
版本
说明
1.
Struts
1.3.8
2.
JSTL
1.1
3.
Hibernate
3
实现持久化操作
4.
jBPM
工作流支持
5.
Junit
4
单元测试
6.
jQuery
说明: 还有jQuery.validate与jQuery.treeview等小插件
开发环境
操作系统
Windows XP
开发工具
MyEclipse6.0
数据库
MySql5.0.22
Web容器
Tomcat6.0
浏览器
IE6
说明: 推荐使用MyEclipse, 这样出现工具问题能够一起解决。当然也能够使用自已熟悉的工具, 如Eclipse、 NetBeans、 IntelliJ。重点是代码, 不是工具。应使用有效的工具。
约定
7、 工程中所有的文件都采用utf-8编码。所有的页面都是使用utf-8编码, 这样方便解决表单内容的乱码问题。乱码一般情况下是乱用编码产生的。
8、 实体的主键属性的类型使用Long型。
代码规范
1, 命名: 使用驼峰命名法。
2, 注释: 在代码中加入适当的注释: 说明步骤, 与说明非简单逻辑。
3, 空行: 在代码中加入适当的空行, 就像写文章时要分段一样( 增强可读性) 。
总之, 要保证代码的清晰、 简洁、 可读。
详细设计
TODO 详见每一个模块对应的文档
环境与工程配置
主要配置开发工具、 MyEclipse工程、 数据库。
1, 新建Web工程, 名称为: ItcastOA。
2, 使用数据库名为: itcastoa_${当前日期}。
3, 工程编码使用UTF-8。不要改workspace编码, 因为她会影响里面的所有工程。
配置工具
配置快捷键
1, 把Content Assist设为Alt+/
2, 把Word Completion 设为Alt+.
3, 其它常见快捷键说明:
Alt+/
Content Assist 代码提示
Ctrl+T
显示类的继承结构
Ctrl+O
列出类中的成员( 成员变量、 方法等)
Ctrl+/
注释/取消注释
Ctrl+Shift+O
导入要使用的包、 并去除不使用的包
Ctrl+Shift+F
格式化当前文件中的代码/格式化选中的代码
Ctrl+Alt+Up
复制当前行到下面
Ctrl+Alt+Down
复制当前行到上面
Ctrl+D
删除当前行/删除选中文本占的所有行
Shift+Enter
相当于按End后再按Enter
Alt+Left
Alt+Right
Ctrl+Shift+X
变为大写
Ctrl+Shift+Y
变为小写
配置文件的默认编码
1, 配置JSP的默认编码为utf-8
2, 配置JavaScript的默认编码为utf-8
说明: 在MyEclipse7.x不用修改,
配置格式化的代码样式
1, 使用Ctrl+Shift+F能够格式化代码。
2, 在WindowàPreferencesàJavaàCode StyleàFormatter中能够设置代码样式。 要把Java代码与注释的行宽设为130。( 其它使用默认样式)
3, 搜索XML Sources, 修改xml的行宽为130。( 不考虑打印的情况)
MyEclipse工具使用说明
1, 导入工程时能够直接选择一个zip文档: FileàImportàExisting Projects into Workspace-->Select archive file。
2, 工程改名后, 发果发布到Tomcat下, 对应的应用的名称不一定改变。这个名称是在MyEclipseà Web中的Web Context-root中配置的。
创立数据库
使用MySql数据库。创立数据库时, 要注意编码要支持中文。建表语句如下:
create database itcastoa default character set utf8;
show create database itcastoa;
新建Web工程并准备环境
新建一个Web Project, 并设置工程的编码为UTF-8。
添加框架环境
1, 添加Junit4的Jar包。
2, 添加Struts1.3.8环境:
a) jar包
b) 配置文件( struts-config.xml、 修改web.xml) 、 国际化资源文件、 自定义标签库的TLD文件。配为*.do拦截的请求。
3, 添加Hibernate环境:
a) jar包( 含JDBC驱动的jar包)
b) 配置文件( hibernate.cfg.xml) 。
4, 添加jBPM环境( Jbpm的jar包中已包含Hibernate的jar包) 。
说明:
1, JSTL 已包含在JavaEE5.0中, 因此不用配置。
2, 不要引用外面的Jar包, 应全部拷贝到工程中。
配置数据库
修改Hibernate.cfg.xml中的数据库连接信息。并在hibernate.cfg.xml中做如下配置:
<!-- 显示sql语句 -->
<property name="show_sql">true</property>
<!-- 自动更新表结构 -->
<property name="hbm2ddl.auto">update</property>
目录结构
源码文件夹
src 项目源代码
config 配置文件
test 单元测试
WebRoot文件夹下
script JavaScript脚本文件
style CSS样式文件
WEB-INF/jsp jsp页面文件( 再创立子文件夹分类存放)
包结构
使用三层: 显示层( View) , 业务层( Service) , 数据访问层( Dao)
包名
说明
cn.itcast.oa.domain
实体( Domain)
cn.itcast.oa.dao
Dao接口
cn.itcast.oa.dao.impl
Dao的实现类
cn.itcast.oa.service
Service接口
cn.itcast.oa.service.impl
Service的实现类
cn.itcast.oa.web.struts
Struts有关的类
cn.itcast.oa.web.struts.action
Struts的Action
cn.itcast.oa.web.struts.formbean
Struts的FormBean( ActionForm)
cn.itcast.oa.util
一些工具类
cn.itcast.oa.cfg
cn.itcast.oa.web.filter
基础功能
BaseDao与BaseDaoImpl的设计
每个实体都应有一个对应的Dao, 她封装了对这个实体的数据库操作。例
实体 Dao接口 实现类
========================================================
User --> UserDao --> UserDaoImpl
Role --> RoleDao --> RoleDaoImpl
Department --> DepartmentDao --> DepartmentDaoImpl
Article --> ArticleDao --> ArticleDaoImpl
...
说明:
1, 实体的Dao接口要继承BaseDao接口。
2, Dao的实现类要继承DaoImplBase类。
3, 也能够不继承指定的接口或类, 这样就要自己写相应的方法。
4, T getById(Long id)与List<T> getByIdList(Long[] idList)不要合并为List getById(Long... ids), 因为获取一个对象时也是返回List, 不方便。
问题:
3, 有了DaoBase与DaoImplBase, 还要用UserDao、 RoleDao吗?
答: 要用。因为UserDao或RoleDao中的方法能够分为有公有的方法与特有的方法两部分。公有的方法是经过继承BaseDao得到的, 特有的方法要写在自己里面( BaseDao中是没有的) 。
4, UserDaoImpl已经继承了BaseDaoImpl, 就不实现UserDao能够吗?
答: 不能够。否则UserDao userDao = new UserDaoImpl(); 就不成立。
使用反射获取类型参数的真实类型的代码如下:
public DaoBaseImpl () {
Type type = this.getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) type;
this.clazz = (Class<T>) pt.getActualTypeArguments()[0];
}
说明:
7. 使用Session时, 不要自己创立, 也不要管理事务, 直接调用getSession()即可。
8. 暂时不实现getSession()方法, 在后面的事务管理中实现:
protected Session getSession(){
throw new UnsupportedOperationException();
}
事务管理( Session管理)
事务边界。
1, 一个事务的范围是一个业务操作。
转帐(){
A - 100; // update
// throw exception
B + 100; // update
}
2, 在Dao中只是使用Session, 而不论理Session与事务
3, 一次请求的执行过程
1, 在Action中要做什么?
1, 获取用户输入
2, 进行业务处理( 调用业务方法)
3, 给用户反馈( 转到一个显示页面)
1, 事务说明: 事务的范围是一个业务方法, 而不是一个数据库操作。能够用银行转账的例子来说明。
2, 事务管理就是要解决两个问题:
a) 在同一个请求中怎么使用同一个Session?
b) 怎么才能不重复写业务方法中的开关Session与管理事务的模板代码?
3, 解决思路:
a) 第一个问题: 使用SessionFactory.getCurrentSession()
b) 第二个问题: 使用过滤器, 拦截的地址为”*.do”。
4, 说明:
a) 每个请求使用一个线程来执行。
b) 同时执行的多个请求是多个不同的线程。
c) 先后的两次请求, 有可能使用的是同一个线程( Web容器有线程池) 。
要使用SessionFactory.getCurrentSession()方法, 需要先在hibernate配置文件中做如下配置, 否则不能使用( 会报错) : ”<property name="hibernate.current_session_context_class">thread</property>”配置后影响的行为如下:
SessionFactory.getCurrentSession()
获取当前线程对应的Session, 如果没有( 一个线程中的第一次调用) , 就会创立一个Session并关联到当前线程后返回。
Tmit()
提交事务, 在提交后会自动关闭Session
Transaction.rollback()
回滚事务, 在回滚后会自动关闭Session
说明: 如果配置了currentSessionContext, 在提交或回滚事务后会自动关闭Session。使用时就不要再调用关闭的代码了。在关闭的时候就会出现异常了。
注意: SessionFactory.openSession()后, 本次打开的Session不会与当前线程绑定, 也就是说用SessionFactory.getCurrentSession()是拿不到的!
对象管理( BeanFactory)
使用工厂模式完解决对实现类依赖的问题, 并使用配置文件配置要使用的实现类。需要一个工具类, 名为BeanFactory, 其中有一个获取实现类的方法, 能够定义为:
Object BeanFactory.getBean( clazz ); 或
<T> T BeanFactory.getBean(Class<T> clazz)
在实现时, 所使用的实现类应是在配置文件( BeanFactory.properties) 中配置的。
解决提交的表单内容的中文乱码
因为所有的页面都将使用utf-8编码, 因此提交的表单也是utf-8编码。在过滤器中设置request的编码为utf-8就能够解决POST方式提交表单的中文乱码问题:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
request.setCharacterEncoding("utf-8");
chain.doFilter(request, response);
}
对于GET方式乱码不做处理。如做处理, 可使用包装或代理的方式。
出现问题了, 怎么办?
解决异常的方法
3、 先看一下是什么异常。比如NullPointerException, 是说明某行代码中的”.”前面的对象为null; 或是异常java.langClassNotFoundException, 是找不到类异常。这时还要看异常的类型与后面的简单信息, 如java.lang.ClassNotFoundException: java.lang.String。说明是java.lang.String这个类找不到。在这一步要搞清楚是什么错误。
4、 找到出错的代码位置。
1, 在异常信息中会显示出错时执行的代码是在哪一行, 而且有超链接, 点击就能够了。
2, 错误不在Java代码中, 如异常javax.servlet.ServletException: mands.InvalidPathException: No action config found for the specified url.就是说访问的.do地址没有进行Action配置, 这时就知道应该打struts-config.xml。
5、 根据异常类型进行推测, 一般的异常就能够解决了。如NullPointerException, 就找这一行中的”.”然后看是不是为null, 如果是, 找出某对象为null的原因, 问题就解决了。
说明:
3, 调试代码时, 最好关闭所有其它的工程, 在有多个工程代码相近的情况下特别要这样做, 比如有两个工程分别为ItcastOA_1、 ItcastOA_2。否则可能会出现代码写错地方的情况, 或是点击异常信息中的超链接, 转到的是另外一个工程中的相同名称的类中。
4, 异常要看最下面的, 即最后一个”Caused by:”, 因为她是最里层的。上面的异常都是捕获某异常后包装后再次抛出的。
一些的异常的解决办法
java.lang.IllegalArgumentException: node to traverse cannot be null!
java.lang.IllegalArgumentException: node to traverse cannot be null!
org.hibernate.hql.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:31)
org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:254)
org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:157)
org.hibernate.hql.ast.QueryTranslatorIpile(QueryTranslatorImpl.java:111)
org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
原因1: HQL语顺的词法有错误, 这时应找到出错的代码在哪一行, 找出HQL中的语法错误。
java.lang.NoSuchMethodError: org.hibernate.hql.antlr.HqlBaseParser.recover(Lantlr/RecognitionException;Lantlr/collections/impl/BitSet;)V
java.lang.NoSuchMethodError: org.hibernate.hql.antlr.HqlBaseParser.recover(Lantlr/RecognitionException;Lantlr/collections/impl/BitSet;)V
at org.hibernate.hql.antlr.HqlBaseParser.statement(HqlBaseParser.java:179)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:248)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:157)
at org.hibernate.hql.ast.QueryTranslatorIpile(QueryTranslatorImpl.java:111)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)
... 40 more
原因1: 只要是java.lang.NoSuchMethodError: org.hibernate.hql.antlr..., 一般是由于HQL语顺的词法有错误, 如写查询所有User时”FROM User”, From后没有加空格等。这时应找到出错的代码在哪一行, 找出HQL中的语法错误。
原因2: 有一同学也报类似的错误, 不过她的原因是jar包冲突。在她的lib/中有: antlr2.7.6与antlr2.7.2, 删除antlr2.7.2后就正常了。她的异常信息如下:
Caused by: java.lang.NoSuchMethodError: org.hibernate.hql.antlr.HqlBaseParser.recover(Lantlr/RecognitionException;Lantlr/collections/impl/BitSet;)V
at org.hibernate.hql.antlr.HqlBaseParser.statement(HqlBaseParser.java:179)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:248)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:157)
at org.hibernate.hql.ast.QueryTranslatorIpile(QueryTranslatorImpl.java:111)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)
... 42 more
java.lang.IllegalArgumentException: Resources cannot be null.
异常信息如下:
java.lang.IllegalArgumentException: Resources cannot be null.
at mons.validator.Validator.<init>(Validator.java:158)
at org.apache.struts.validator.Resources.initValidator(Resources.java:507)
at org.apache.struts.validator.ValidatorForm.validate(ValidatorForm.java:111)
at mands.servlet.ValidateActionForm.validate(ValidateActionForm.java:58)
at mands.AbstractValidateActionForm.execute(AbstractValidateActionForm.java:120)
at mands.ActionCommandBase.execute(ActionCommandBase.java:51)
at mons.chain.impl.ChainBase.execute(ChainBase.java:190)
at mons.chain.generic.LookupCommand.execute(LookupCommand.java:304)
at mons.chain.impl.ChainBase.execute(ChainBase.java:190)
at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
... 19 more
原因: 写的FormBean类没有继承ActionForm。
解决问题的方式说明与一些建议
1, 出问题了, 要先从简单的原因入手, 是快速解决问题的一个好办法。例如显示器不显示了, 不要直接把她拆掉, 而应先检查有没有插电源。在我们现阶段( 水平还不是很高) , 有很多错误就是这样简单的原因, 因此更要这样做。
2, 没有很快的解决问题, 也不见得是水平不高, 也有可能是自己的状态太不好了。有时在熬夜写程序时遇到一个小问题, 却怎么都解决不了, 有可能两个小时都搞不定, 这时就该休息了, 可能第二天早上再看时, 一眼就能看到问题所在。还有一个办法, 就是让别人帮你找错, 不一定要找一个水平比你高的人, 她可能很快就能找到错误原因。当然我们还是要保重身体, 保持最好的状态, 这才是更重要的。
3, 总是能解决问题的是高手, 总是能避免问题的则是更高的高手。我们就要注意避免问题, 要防治结合。怎么才能避免问题呢? 有一个好方法是就养成良好的书写习惯, 比如总是使用驼峰命名法、 慎用缩写等等。如AF是代表ActionForm呢还是ActionForward呢, 除非都很请楚, 否则不能用, 如用Del表示Delete就很清楚。咱们同学就有好几个在大小写上出了问题了, 这应该是能够避免的。
展开阅读全文