`
wlh269
  • 浏览: 463293 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

OA开发手记

阅读更多
oa_01:

1、建立机构管理的实体类,并映射【重点理解一对多双向关联映射的原理】(Organization.hbm.xml)
<!--一对多双向关联 -->
<many-to-one name="parent" column="pid"/>
<set name="children">
<key column="pid"/>
<one-to-many class="com.wlh.oa.model.Organization"/>
</set>


2、根据顺序图的分析,得到业务逻辑接口设计方案(OrgManager.java)
3、实现业务逻辑类(OrgManagerImpl.java)
4、编写测试单元对关键的接口(或没有把握的接口)进行测试,在测试中发现问题并修正(OrgManagerTest.java)
- 重点理解在SSH架构中,spring如何对事务和hibernate session进行管理
* spring通过AOP机制,在业务逻辑对象的方法上添加事务处理
* 需正确的配置事务的传播特性


每个模块的基本开发过程:
1、理解需求(用例分析),创建领域模型
2、细化领域模型,创建实体类,并映射实体类,测试映射的正确性(自动生成数据库表)
3、根据对用例的分析结果,创建业务逻辑接口以及方法,并实现以及测试
4、分析页面操作流程,根据MVC的想法,搞清楚都需要哪些JSP以及Action(可用状态图来分析)
5、逐步实现呈现层的各种内容



oa_02:

整合Spring和Hibernate之后,对于业务逻辑类的测试方法,可让测试类继承AbstractTransactionalSpringContextTests(所在jar包:spring-mock.jar),
而不是直接继承TestCase,避免在测试单元中出现懒加载问题。如果数据应该保留在数据库中,
需要在测试方法中调用setComplete方法
- 重点理解为何会出现懒加载问题


AbstractTransactionalSpringContextTests
是一个针对需要在事务环境下执行测试的便利超类,通常会在每个测试完成时执行事务回滚。许多情况下,这是非常有用的,比如:
可以在不影响别的测试的情况下在数据库中插入或删除任何数据。
为任何要求事务的代码提供事务上下文。
如果数据应该保留在数据库中,需要在测试方法中调用setComplete方法。
可以调用startNewTransaction方法创建一个新的事务,前提是必须先调用endTransaction方法终止旧的事务。
事务行为要求在上下文中有一个实现PlatformTransactionManager接口的Bean实例,这将通过其超类的依赖注入机制自动注入,
如果需要使用超类的字段注入机制,那么Bean实例必须命名为transactionManager,这种机制允许上下文配置中存在一个或多个事务管理器实例的情况。
如果没有配置事务管理器,将不会使用事务管理,需要当心的是这可能会造成数据更改,一旦关闭超类的信赖检测将会启动此模式。
此类主要是通过重写AbstractSingleSpringContextTests超类提供的onSetUp和onTearDown方法,在相应的方法中创建和关闭事务来实现的。
AbstractTransactionalDataSourceSpringContextTests
此类给其超类添加了一些针对JDBC操作的便利方法,要求有一个javax.sql.DataSource实例定义在上下文中,
此类会暴露一个org.springframework.jdbc.core.JdbcTemplate实例,并提供了一些便利方法,如删除某个表中的数据,计算某个表的行数,执行数据库脚本等。
范例Springside框架就充分利用spring提供的工具类,简化测试工作量。比如springside提供一个DaoTestCase子类用于Hibernate的测试
,该类继承自AbstractTransactionalDataSourceSpringContextTests,只需要重写如下方法:


oa03:
增加/删除机构,以及返回操作:

=====================增加组织机构===========================

1.如果想将Action交给spring创建,则将Action的type类型为org.springframework.web.struts.DelegatingActionProxy,
  然后将Action作为bean配到spring配置文件中, 而且该bean 没有id属性,而是有name属性,而且name属性的值前面加一个“/”;

2.节省Action的方法,是让一个类的的Action继承DispatchAction,然后将对该类的对象进行相关操作的方法都方法哦该Action中,
从而节省Action。注意 :该Action的action标签必须含有parameter属性例如:parameter="method",用于接收参数,
  如果接收的到的请求为:'org.do?method=addInput',则调用该Action的addInput方法
 
  3.当前项目着重看OrgAciton.java的方法:
  protected ActionForward unspecified(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
  因为该方法在进入主界面(默认会来到这里),此外不带参数?method="XXx",的org.do请求也都会进入这个方法

4.添加对象,将接收的表单信息拷贝到另外一个新的对象可以用:BeanUtils.copyProperties(object,object);
     类OrgAciton.java:
     public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
   OrgActionForm oaf=(OrgActionForm)form;
   Organization org=new Organization();
   BeanUtils.copyProperties(org,oaf);//拷贝属性
   orgManager.addOrg(org, oaf.getParentId());
return mapping.findForward("add_success");
  }
 
  =====================删除组织机构========================
  删除一个机构及其子机构:
public ActionForward del(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
OrgActionForm oaf=(OrgActionForm)form;
int orgId=oaf.getId();
int parentId=oaf.getParentId();
orgManager.delOrg(orgId);
//return mapping.findForward("del_success");
//=========自定义ActionForward,必须是重定向=======//
ActionForward forward=new ActionForward("/org.do?parentId="+parentId);
forward.setRedirect(true);
return forward;

}

//===============为了实现返回功能=======================//
int ppid=0;
if(parentId!=0){
Organization parent=orgManager.findOrg(parentId);
if( parent.getParent()!=null){
ppid=parent.getParent().getId();
}
}
request.setAttribute("ppid",ppid);
 

====================异常处理===========================
==修改==
a.加入SystemException.java继承自RunTimeException
b.加入SystemExceptionHandler.java继承子ExceptionHandler.java
c.在国际化资源文件中加入:
errors.org.hassuborg=Org[{0}] has {1} sub orgs
d.修改OrgManagerImpl.java的方法delOrg,抛出自定义异常SystemException
e.修改OrgAciton的方法del,不再捕捉业务层抛过来的异常,而是继续往上抛给Struts框架;
f.在Struts配置文件中添加异常配置:type属性表示指出异常类,handler表示指出处理异常的类
  <global-exceptions>
  <exception key="error.exception" type="com.wlh.oa.manager.SystemException" handler="com.wlh.oa.web.SystemExceptionHandler"/>
  </global-exceptions>
==总结==:
参考代码:struts_autoexceptionhandle_login
a.自定义一个异常类:ErrorCodeException继承RunTimeException,该类含有属性错误码和占位符,构造方法可以接收错误码,和占位符
b.自定义一个异常处理类:ErrorCodeExceptionHandler继承自ExceptionHandler,
c.负责登录的Action不进行捕捉异常,而是继续晚上抛,由框架中的ExceptionHandler及其子类来处理异常,具体要要看Struts-config.xml文件中配置而定,在以下的配置中,则由ErrorCodeExceptionHandler复写了ExceptionHandler中的方法execute(),则由ErrorCodeExceptionHandler来处理异常:
  例如:<!-- 全局exception -->
   <global-exceptions>
    <exception key="error.exception"    type="com.wlh.exception.ErrorCodeException" handler="com.wlh.exception.handler.ErrorCodeExceptionHandler"/>
  </global-exceptions>

d、ErrorCodeExceptionHandler的execute方法中从ErrorCodeException对象中得到错误码和占位符的填充值,然后就可以将异常信息添加到Globals.EXCEPTION_KEY
e.最后和手动异常处理一样,可以通过html:messages和html:errors得到错误和成功信息

oa04忽略。。

oa05分页处理

====================分页处理================================
==修改==
a.增加类:AbstractManager.java
b.修改类OrgManagerImpl中的方法 searchOrgs
    /**
* 根据父机构Id查找子机构
*/
public PagerModel searchOrgs(int parentId,int offSet,int pageSize)
c.加入jar包pager-taglib.jar;
d.在common/common.jsp页面引入pager-taglib标签库 :
   <%@ taglib prefix="pg"  uri="http://jsptags.com/tags/navigation/pager" %>
e.修改org/index.jsp的机构的列表数据栏,改为pg标签分页;

==总结==
从现有的分页处理方案中,将ManagerImpl类中的抽象出AbstractManager,以便将分页逻辑进行封装处理,
使得分页处理更加简单(不需要拷贝分页逻辑);此外将一个页面的的数据封装到一个对象PageModel中;
- 重点理解抽象的概念(如何抽象?抽象哪些内容?)

仔细体会:
  1.oa04中OrgManagerImpl.java是继承了HibernateDaoSupport.java的;
  2.在oa05中,我们抽象出一个分页逻辑AbstractManager,让其继承了HibernateDaoSupport,
     而让我们的类OrgManagerImpl,继承自AbstractManager,此时OrgManagerImpl也间接继承了AbstractManager,
     OrgManagerImpl得到父类的父类HibernateDaoSupport的功能;
  3. 一个类既实现了接口,又继承了一个类!则接口的的引用调用父类的方法时候,必须在接口中也声明父类的方法。
      例如:OrgAction.java中的代码:
          PagerModel pm=orgManager.searchOrgs(parentId,offset,pageSize);调用的searchOrgs并不是接口中的searchOrgs,
           而是其父类AbstractManager中的,但是必须在接口中声明一个和父类中一样的接口,负责会出错!


利用ThreadLocal实现分页参数的透明传输(通过使用ThreadLocal能够避免在Manager的接口设计中添加分页参数)
- 重点理解ThreadLocal的基本原理以及实现方法

oa06:分页2
使用ThreadLocal分页参数透明传输
==修改==
1.添加封装pageSize和offSet的ThreadLocal的类SystemContext.java
2.添加一个过滤器类:PagerFilter,配置WEB.XML使得每个请求都可以访问该过滤器
  而该过滤器就是向ThreadLocal中设置分页参数
3.修改OrgAciton中的方法unspecified中的代码,
PagerModel pm=orgManager.searchOrgs(parentId,offset,pageSize);
改为代码:-->PagerModel pm=orgManager.searchOrgs(parentId);
4.修改接口OrgManager和其实现类OrgManagerImpl的方法:
public PagerModel searchOrgs(int parentId,int offSet,int pageSize)改为
public PagerModel searchOrgs(int parentId)
5.在AbstractManager中添加一个方法:
public PagerModel searchPaginated(String hql){
return searchPaginated(hql,SystemContext.getOffset(),SystemContext.getPagesize());
}

oa07:Ant脚本:

使用ant脚本文件build.xml,生成Hibernate配置文件hibernate.cfg.xml和映射文件;

<?xml version="1.0" encoding="GBK"?>
<project name="OA系统构建脚本" default="生成Hibernate配置文件" basedir=".">

   <property name="src.dir" value="${basedir}/"/>
   <property name="build.dir" value="${basedir}/bin"/>
<property name="xdoclet.home" value="D:/代码库/BJSXT/xdoclet-plugins-1.0.3"/>

   <!-- Build classpath -->
   <path id="xdoclet.task.classpath">
      <fileset dir="${xdoclet.home}/lib">
         <include name="**/*.jar"/>
      </fileset>
      <fileset dir="${xdoclet.home}/plugins">
         <include name="**/*.jar"/>
      </fileset>
   </path>
<taskdef
name="xdoclet"
classname="org.xdoclet.ant.XDocletTask"
classpathref="xdoclet.task.classpath"
/>

<target name="生成Hibernate配置文件">
<xdoclet>
<fileset dir="${src.dir}/com/wlh/oa/model">
<include name="**/*.java"/>
</fileset>
<component
classname="org.xdoclet.plugin.hibernate.HibernateConfigPlugin"
destdir="${src.dir}"
version="3.0"
hbm2ddlauto="update"
jdbcurl="jdbc:mysql://127.0.0.1/oa01"
jdbcdriver="com.mysql.jdbc.Driver"
jdbcusername="root"
jdbcpassword="bjsxt"
dialect="org.hibernate.dialect.MySQLDialect"
showsql="true"
/>
</xdoclet>
</target>
<target name="生成hibernate映射文件">
<xdoclet>
<fileset dir="${src.dir}/com/wlh/oa/model">
<include name="**/*.java"/>
</fileset>
<component
classname="org.xdoclet.plugin.hibernate.HibernateMappingPlugin"
version="3.0"
destdir="${src.dir}"
/>
</xdoclet>
</target>
</project>



oa09:添加:用户,角色,用户角色、模块、ACL类,及其映射文件:


1.用户类User对应组织机构中的类Person:使用了一对一唯一外键双向关联映射
2.访问控制列表ACL与User,Role,Module所关联:而Module使用了一对多双向关联映射
3.用户User和角色Role相互关联:user和Role使用了多对多双向映射
4.此处User和Role的多对多使用了第3个类UsersRoles,其实没必要UsersRoles也可以完成多对多映射双向映射
5.添加接口UserManager,RoleManager,personManager,ModuleManager,AClManager等以及实现类;
   添加ActionForm和对应的Action
6.OrgAcitonForm中添加了一个属性select,如果是select,则弹出可选择机构的窗口


oa10:
DOM4J实现数据的导入  参考:InitSystemDatasImpl.java

oa11,oa12 :授权
主要是通过“用户管理”和“角色管理”中的“用户授权”和“角色授权”链接触发一个权限列表的窗口,在其中可以勾选或者取消复选框,从而修改ACl对象的持久化数据,从而进行权限管理.

a、版本oa11:只有对角色和用户做了普通授权,没有考虑继承的问题
b、版本oa12考虑了授权的继承的问题;
  
***ACL的状态为继承(即无效,判断的时候应该判断其所属角色的授权)***
***ACL的状态为不继承(即有效,判断的时候,直接根据aclState判断授权)***  
继承与不继承的具体体现在什么地方?

   答:体现在查找一个用户是否有操作某个模块的权限的时候,查找到相应的授权记录(也就是acl对象),然后查找acl的属性aclTriState(判断是否继承),
      如果该用户的这个权限继承了角色,则授权中立,此时还得判断该用户的所有角色对该模块的权限,因为acl的状态为继承(即无效,判断的时候应该判断其所属角色的授权)
      **请参考:AClManagerImpl.java中的方法:**
   public boolean hasPermission(int userId, int moduleId, int permission)
   public int getPermission(int permission)
  
如何更改主体对模块的访问权限的?
  答: 主体(用户User或者角色Role)对模块Module的访问能力;
访问控制对象ACL是一个主体和模块的关联对象,其中包括User的Id或者Role的Id还有Module的Id,还有一个int类型的访问控制状态aclState(取值范围0~15),分别代表能否对模块进行C/R/U/D操作;
我们修改访问权限就是修改ACL对象中的属性aclState,将其的的二进制形式的某一位或者某几位修改为0或1。

1.只要点击user/index.jsp中的用户授权,则将所有的模块及其拥有的操作全部都列出来;
2.为什么AclAction中的方法很少呢?
    答:因为使用的DWR,业务逻辑方法的调用转移到了页面的JS代码里;
3.HTML标签的自定义属性:
   例如:acl/index.jsp中moduleId 和 permission都是自定义的属性;
   <input type="checkbox" id="${module.id}_C" moduleId="${module.id}" permission="0" onclick="addOrUpdatePermission(this)">C
4.页面的js中也支持EL表达式:${}吗?
   答:支持
5. dwr负责处理返回值的函数中,如何获得对某个页面元素对象的引用 ?
    答:$(“元素的ID或名称”)
        例如:acl/index.jsp
     function initTable(){
      ..............
      $(moduleId+"_C").checked=cState==0?false:true;
      $(moduleId+"_R").checked=rState==0?false:true;
      $(moduleId+"_U").checked=uState==0?false:true;
      $(moduleId+"_D").checked=dState==0?false:true;
      .................
     }
      中$(moduleId+"_C"),就是拿到一个复选框元素;
6.dwr是否支持spring?
    答:支持
    例如:dwr.xml文件中,是将Spring配置文件中的bean:aclManager动态生成一个js库,然后调用其中的方法;
  <dwr>
  <allow>
    <create creator="spring" javascript="aclManager">
      <param name="beanName" value="aclManager"/><!--Spring配置文件中的bean:aclManager -->
    </create>
  </allow>
  </dwr>
7.dwr使用的时候要加入dwr.jar
8.
1).给用户和角色授权,共用了一个呈现页面/acl/index.jsp,呈现用户和角色对所有模块的访问权限
2).学习:jstl的<c:forEach>两层嵌套标签显示父模块和子模块的信息,
3).該版本讓我最遇到挫折的地方就是授权列表在点击角色授权的时候加载不上来:  
解决的思路:
    a.dwr客户端调用代码出错?经对比正确代码,发现没错误....
    b.通过url:http://localhost:8080/oa_11/dwr 观察到:
       Classes known to DWR:
       aclManager ($Proxy19)点击进去,发现动态生成的js库中并没有查找授权列表的方法searchAclRecord....
       问题在什么地方呢?清除work目录,重启服务,还是不管用,
    c.最后才意识到,只是在实现类aclManagerImpl中添加了方法searchAclRecord及其实现,
        但是没有在接口aclManager中添加方法的声明:
       public List searchAclRecord(String principalType,int principalId);
    
      然而,声明dwr.xml中声明的是接口spring的bean名称aclManager,接口中必须要有实现类总所有方法的声明。。。。
      <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd">
<dwr>
  <allow>
    <create creator="spring" javascript="aclManager">
      <param name="beanName" value="aclManager"/>
    </create>
  </allow>
</dwr>
oa12继承性授权
  oa_12:
思路总结:
======从页面效果上看=========:
1.点击CRUD四个按钮的的任意一个,会将不继承按钮和启用按钮选中,
2.反选启用按钮,这一模块(一行)中所有的按钮将被取消选中,
======从业务逻辑的执行上看=====:
1.选中或者取消CRUD4个中的任意一个按钮:
  a.则改变Acl对象的int型变量aclStrate,最低4位中的1位,表示是否允许CRUD操作
  b.将不继承和启用按钮都选中
2.选中或者取消"不继承"按钮,则实质上就是将Acl对象的aclTriState属性设置为ACL_TRI_STATE_EXTENDS或者ACL_TRI_STATE_UNEXTENDS
3.选中或者取消"启用"按钮;
  a.如果选中,则触发CRUD4个按钮的事件(包括选中和取消),然后还会触发继承事件(包括选中和取消),
  b.如果取消选中,则:
    (1).删除某条Acl记录
    (2).将前面的CRUD按钮和不继承按钮全部反选,同时也触发各个按钮的事件(),
oa13:登录(重点)
实现登录功能
index.jsp-->login.do-->LoginAciton(如果不存在用户则转向index.jsp)-->
-->(登录成功)back_index.jsp-->(frameSet)index.do-->indexAction(继承BaseAction)-->outlook.jsp和main.jsp
-->在outlook.jsp中使用JSTL动态加载显示当前用户可以操作的各个模块;
===修改===
1. LoginAction
   a.查找是否存在找个用户;
   b.密码是否正确;
   c.判断用户账号是否过期;
   d.将当前用户纳入session管理:request.getSession().setAttribute("login", user);
2. 创建一个BaseAction [让其它所有需要登录之后才能执行的操作继承此Action]
3. 创建一个继承自BaseAction的IndexAction
     a.IndexAction负责检查session中是否有用户;
        代码:request.getSession().getAttribute("login");
     b.如果有用户,则将当前用户的所有模块全部查询上来,然后放到request中;
       List modules = aclManager.searchModules(user.getId());
   request.setAttribute("modules", modules);
  
4.修改之前的outlook.html中模块显示部分代码为动态代码:
   a.在头部加入<%@include file="/common/common.jsp" %>
   b.修改中间部分,使用JSTL的<c:forEach>标签,动态加载并显示当前用户可以操作的各个模块;
     
5.添加一个日期类型转换器类:UtilDateConverter.java
6.添加一个InitServlet,主要是用来注册日期类型转换器(UtilDateConverter)
<servlet>
    <servlet-name>initServlet</servlet-name>
    <servlet-class>com.bjsxt.oa.web.InitServlet</servlet-class>
    <load-on-startup>3</load-on-startup>
  </servlet>

重点理解:
- Action的抽象(统一进行登录认证的控制),
   本代码:IndexAciton继承自BaseAction,在调用IndexAction的时候先执行BaseAction中的execte方法,检查当前用户是否存在,即,session中是是否有用户
   a.如果存在则调用 return super.execute(mapping, form, request, response), 让子类IndexAciton接着执行;
   b.如果session中没有用户,则转向转向登陆页面
- 页面框架的运用:frameset
- javascript中的try{}catch(e){}的使用


oa14:利用JSTL自定义函数实现即时认证:

注意:授权和认证是一个组合,两者结合才是一个完整的权限管理,前面的版本做了授权,这里做认证
oa14:
利用JSTL自定义函数实现即时认证:
  1.怎理解认证?
   答:认证中判断用户的权限然后显示出对应的模块:
      重点理解AClManagerImpl.java中的方法hasPermission和getPermission
  ***ACL的状态为继承(即无效,判断的时候应该判断其所属角色的授权)***
  ***ACL的状态为不继承(即有效,判断的时候,直接根据aclState判断授权)***
  2.继承与不继承的具体体现在什么地方?
    答:体现在查找一个用户是否有操作某个模块的权限的时候,查找到相应的授权记录(也就是acl对象),然后查找acl的属性aclTriState(判断是否继承),
      如果该用户的这个权限继承了角色,则授权中立,此时还得判断该用户的所有角色对该模块的权限
      **请参考:AClManagerImpl.java中的方法:**
   public boolean hasPermission(int userId, int moduleId, int permission)
   public int getPermission(int permission)
  

==修改==
a. 创建类:SecurityFunctions.java
/**
* JSTL函数,主要功能是可以完成权限的即时认证
* @author Administrator
*
*/
    public class SecurityFunctions {
private static AclManager aclManager;
public static boolean hasPermission(int userId,String resourceSn,int permission){
return aclManager.hasPermissionByResourceSn(userId, resourceSn, permission);
}
//这个方法不能定义为static,因为这将导致spring无法注入
public void setAclManager(AclManager aclManager) {
SecurityFunctions.aclManager = aclManager;
}
     }

b.在AclManager中添加
  public boolean hasPermissionByResourceSn(int userId,String reourceSn,int permission);
  接口,以便于在JSP中使用JSTL函数来进行即时认证
       
          c.在AclManagerImpl中添加hasPermissionByResourceSn的实现:
            public boolean hasPermissionByResourceSn(int userId, String resourceSn, int permission) {
String hql = "select m.id from Module m where m.sn = ? ";
return hasPermission(
userId,
(Integer)getSession().createQuery(hql).setParameter(0,     resourceSn).uniqueResult(),
permission);
  }
d.在spring配置文件中添加bean想认证函数中注入aclManager:
    <!-- JSTL函数 -->
    <bean id="sucurityFunctions" class="com.bjsxt.oa.web.SecurityFunctions">
  <property name="aclManager" ref="aclManager"/>
    </bean>
e.在WEB-INF/下添加文件my.tld
  <?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
  version="2.0">
  <tlib-version>1.0</tlib-version><!--taglib的版本-->
  <short-name>my</short-name><!--短名-->
  <uri>http://www.bjsxt.com/oa/functions</uri>uri
  <function>
      <name>hasPermission</name><!--函数的调用名称-->
      <function-class>com.bjsxt.oa.web.SecurityFunctions</function-class><!--类的全路径-->
      <function-signature>boolean hasPermission(int, java.lang.String,int)</function-signature><!--函数名称和参数-->
  </function>
</taglib>
f.在common/common.jsp中添加引入标签:
    <%@ taglib prefix="my"  uri="http://www.bjsxt.com/oa/functions" %>
   
g.在InitServlet中,将一些变量CREATE/READ/UPDATE/DELETE放入(getServletContext)application scope
    以便于在JSP中使用它来表示操作类型,也就是person的index.jsp页面中的CREATE
 
  h. 在人员管理页面添加人员,跟新,删除等地方加入认证标签:关键是test后面跟的JSTL自定义函数;
        <c:if test="${my:hasPermission(login.id,'person',CREATE) }">
            <a href="#" onclick="openWin('person.do?method=addInput','addperson',600,200);">添加人员信息</a>
         </c:if>
         备注:*******只要是放到request,session,application中的变量,在EL表达式中都可以拿到*****
            test="${my:hasPermission(login.id,'person',CREATE) }
                1.login.id是LoginAction放到session中的User对象的id;
                2.person是模块的唯一表示;
                3.CREATE是在InitServlet中,将一些变量CREATE/READ/UPDATE/DELETE放入(getServletContext)application scope;


oa15:根据公文流转领域模型创建相关的实体类,并使用xdoclet映射


1.用hibernate来映射byte[]类型的属性时,把它当成普通属性来映射,并指定type="binary" length="99999999"
  例如:
  公文类Document的属性,private byte[] content;
  流程类workflow的属性,private byte[] processDef;
  流程类workflow的属性,private byte[] processImage;
===============修改===============
1.根据领域模型,创建实体类Document,ApproveInfo,Workflow,修改User;
2.添加接口JbpmDelegate和 流程管理接口WorkflowManager;

oa_16:
根据顺序图的分析,创建流程管理接口以及JbpmDelegate接口

oa_17:集成JBPM到OA系统,并实现JbpmDelegate接口


- 第一步:创建数据库表
* 拷贝依赖包:bsh.jar/jcr-1.0.jar/jbpm-identity.jar/jbpm-jpdl.jar
* 修改hibernate.cfg.xml,添加JBPM的映射配置,以及缓存属性的配置
* 因为JBPM中的User类与OA系统中的User类在名称上有冲突,所以需要修改OA
  系统中的User类的auto-import="false",并更改查询User对象的HQL语句,加上
  全路径的类名进行查找,可以参考UserManagerImpl类。
- 第二步:与spring集成
* 集成spring与JBPM,需要用到第三方的类库:spring-modules-0.8.zip
* 将其中的spring-modules-jbpm31.jar拷贝到web-inf/lib下面即可
* 集成JBPM与spring的方法是:将JbpmConfiguration对象交给spring来创建
* 所以,需要在spring配置文件里面配置JbpmConfiguration对象的创建
<bean id="jbpmConfiguration" class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
<property name="configuration" value="classpath:jbpm.cfg.xml"></property>
</bean>
* 这个时候,需要拷贝jbpm.cfg.xml到类路径中
(可以从jbpm-jpdl-3.2.GA\src\jpdl\org\jbpm目录中拷贝(default.jbpm.cfg.xml)文件,
并重命名即可)
- 第三步:如何实现业务逻辑接口JbpmDelegate,实现类为JbpmDelegateImpl
* 用到jbpmConfiguration的时候,需要注入
  所以在spring配置文件中加入:
  <bean id="jbpmDelegate" class="com.wlh.oa.manager.impl.JbpmDelegateImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
<property name="jbpmConfiguration" ref="jbpmConfiguration"></property>
</bean>
* 当我们使用jbpmContext对象来操纵JBPM的时候,需要将JbpmContext内部的Hibernate session对象设置为当前的
  hibernate session对象。
  private JbpmContext getJbpmContext(){
JbpmContext context = jbpmConfiguration.createJbpmContext();
context.setSession(getSession());
return context;
}
* 当我们使用jbpmContext操纵JBPM数据结束的时候,注意不要关闭jbpmContext!!


oa_18:实现WorkflowManager接口,以及流程管理的界面

  1.添加类workflowManagerImpl.java
  2.添加workFlowAction和WorkflowActionForm
  2.在spring配置文件applicationContext-beans.xml中加入:
 
  <!-- 流程管理 -->
<bean id="workflowManager" class="com.wlh.oa.manager.impl.WorkflowManagerImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
<property name="jbpmDelegate" ref="jbpmDelegate"></property>
</bean>

  3.在spring配置文件applicationContext-beans.xml中加入:
   <bean name="/workflow" class="com.bjsxt.oa.web.actions.WorkflowAction" scope="prototype">
    <property name="workflowManager" ref="workflowManager"></property>
    </bean>
   
oa_19: 实现公文管理的业务逻辑类以及界面 


实现公文管理的业务逻辑类以及界面
1.添加DocumentManagerImpl和DocumentManager;
  还要JbpmDelegateImpl添加公文,删除公文,查找待审批的公文等方法;
2.spring配置文件中添加:
  <!-- 公文管理 -->
<bean id="documentManager" class="com.bjsxt.oa.manager.impl.DocumentManagerImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
<property name="jbpmDelegate" ref="jbpmDelegate"></property>
</bean>
3.添加DocumentActionForm和DocumentAction
4.spring配置文件中添加action的配置:
  <!-- 公文管理 -->
     <bean name="/document" class="com.wlh.oa.web.actions.DocumentAction" scope="prototype">
    <property name="documentManager" ref="documentManager"></property>
    <property name="jbpmDelegate" ref="jbpmDelegate"></property>
    <property name="workflowManager" ref="workflowManager"></property>
    </bean>
5.
struts配置文件中添加:
(a).action配置
   <!--公文管理 -->
<action
path="/document"
type="org.springframework.web.struts.DelegatingActionProxy"
name="documentForm"
scope="request"
parameter="method"
   >
<forward name="index" path="/document/index.jsp"></forward>
<forward name="add_input" path="/document/add_input.jsp"></forward>
<forward name="approve_input" path="/document/approve_input.jsp"></forward>
<forward name="select_flow" path="/document/select_flow.jsp"></forward>
<forward name="submit_input" path="/document/submit_input.jsp"></forward>
<forward name="approved_list" path="/document/approved_list.jsp"/>
<forward name="approving_list" path="/document/approving_list.jsp"/>
<forward name="approve_history" path="/document/approve_history.jsp"/>
  </action>
  (b).actionForm配置
<form-bean name="documentForm" type="com.wlh.oa.web.forms.DocumentActionForm"></form-bean>

6.  4.webRoot下添加/document/..和相关页面

7.由于在User.hbm.xml中添加了:<hibernate-mapping auto-import="false">
所以需要在Document.hbm.xml中手动添加: <many-to-one     name="creator"/>
8.修改生事务的传播特性:
要不然提交公文的时候就会出错(参考文章:http://blog.csdn.net/shendl/archive/2006/12/01/1423460.aspx)
  
   <!-- 配置事务的传播特性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager" >
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>





          
          
          
          
          
分享到:
评论

相关推荐

    PLC与WinCC实现三部十层电梯协同控制及优化技巧

    内容概要:本文详细介绍了参与西门子杯比赛中关于三部十层电梯系统的博图V15.1程序设计及其WinCC画面展示的内容。文中不仅展示了电梯系统的基本架构,如抢单逻辑、方向决策、状态机管理等核心算法(采用SCL语言编写),还分享了许多实际调试过程中遇到的问题及解决方案,例如未初始化变量导致的异常行为、状态机遗漏空闲状态、WinCC画面动态显示的挑战以及通信配置中的ASCII码解析错误等问题。此外,作者还特别提到一些创意性的设计,如电梯同时到达同一层时楼层显示器变为闪烁爱心的效果,以及节能模式下电梯自动停靠中间楼层的功能。 适合人群:对PLC编程、工业自动化控制、电梯调度算法感兴趣的工程技术人员,尤其是准备参加类似竞赛的学生和技术爱好者。 使用场景及目标:适用于希望深入了解PLC编程实践、掌握电梯群控系统的设计思路和技术要点的人士。通过学习本文可以更好地理解如何利用PLC进行复杂的机电一体化项目的开发,提高解决实际问题的能力。 其他说明:文章风格幽默诙谐,将严肃的技术话题融入轻松的生活化比喻之中,使得原本枯燥的专业知识变得生动有趣。同时,文中提供的经验教训对于从事相关领域的工作者来说非常宝贵,能够帮助他们少走弯路并激发更多创新思维。

    数据库第一章选择题练习(1).docx

    数据库第一章选择题练习(1).docx

    spring-ai-pdf-document-reader-1.0.0-M7.jar中文文档.zip

    # 【spring-ai-pdf-document-reader-1.0.0-M7.jar中文文档.zip】 中包含: 中文文档:【spring-ai-pdf-document-reader-1.0.0-M7-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【spring-ai-pdf-document-reader-1.0.0-M7.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【spring-ai-pdf-document-reader-1.0.0-M7.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【spring-ai-pdf-document-reader-1.0.0-M7.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【spring-ai-pdf-document-reader-1.0.0-M7-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: spring-ai-pdf-document-reader-1.0.0-M7.jar中文文档.zip,java,spring-ai-pdf-document-reader-1.0.0-M7.jar,org.springframework.ai,spring-ai-pdf-document-reader,1.0.0-M7,org.springframework.ai.reader.pdf,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,springframework,spring,ai,pdf,document,reader,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【spri

    深度学习答辩PPT案例展示

    适用于理工专业的毕业生,毕业答辩时可供参考,叙述详细准确,可以作为自己答辩PPT的参考

    weixin248食堂订餐小程序ssm(文档+源码)_kaic

    weixin248食堂订餐小程序ssm(文档+源码)_kaic

    spring-ai-weaviate-store-1.0.0-M6.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    【RF-SSA-LSTM】随机森林-麻雀优化算法优化时间序列预测研究附Python代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    【图像分割和识别】活动形状模型 (ASM) 和活动外观模型 (AAM)附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    基于主从博弈的电热综合能源系统动态定价与能量管理MATLAB仿真

    内容概要:本文详细介绍了如何利用主从博弈(Stackelberg Game)模型进行电热综合能源系统的动态定价与能量管理。首先解释了主从博弈的基本概念及其在电热综合能源系统中的应用背景,即供电公司作为领导者通过制定电价策略影响用户行为,用户作为追随者根据电价调整用电模式。接着,通过MATLAB编写仿真程序,具体展示了供电公司定价策略、用户响应模型以及主从博弈迭代过程。仿真结果显示,电价与用电需求之间存在动态平衡关系,供电公司可通过调整电价引导用户合理用电,实现系统整体最优运行。此外,文中还讨论了热力系统建模、成本计算方法、博弈迭代收敛条件等关键技术细节,并对未来的研究方向进行了展望。 适合人群:从事能源管理系统设计、优化及相关领域的研究人员和技术人员,特别是对博弈论在能源系统中的应用感兴趣的学者。 使用场景及目标:适用于希望深入了解电热综合能源系统中动态定价与能量管理机制的人群。主要目标是通过理论分析和MATLAB仿真,帮助读者掌握主从博弈模型的应用方法,为实际工程设计提供参考。 其他说明:文中提供了详细的MATLAB代码示例,便于读者理解和复现实验结果。同时强调了在实际应用中需要考虑更多不确定性和个性化需求等问题。

    Android SO逆向-基本数据类型及函数的工作原理.pdf

    Android逆向过程学习

    2级C全国计算机考试上机题库汇总.doc

    2级C全国计算机考试上机题库汇总.doc

    房地产 -龙湖物业品质提升小方法.doc

    房地产 -龙湖物业品质提升小方法.doc

    基于S7-200 PLC与MCGS组态的煤矿排水系统自动化控制方案解析

    内容概要:本文详细介绍了基于S7-200 PLC和MCGS组态软件构建的煤矿排水系统控制方案。主要内容涵盖IO分配、梯形图程序设计、接线图原理、MCGS组态画面配置等方面。通过对水位传感器、故障传感器等输入设备和排水泵、报警装置等输出设备的精确控制,确保了排水系统的高效、可靠运行。文中还分享了一些实际项目中的调试经验和故障排除技巧,如硬件配置优化、信号干扰处理、水位监测精度提升等。 适合人群:从事工业自动化领域的工程师和技术人员,特别是对PLC编程和组态软件有一定了解的人群。 使用场景及目标:适用于煤矿及其他矿业企业的排水系统自动化改造项目,旨在提高排水系统的安全性、稳定性和智能化水平,减少人工干预,预防潜在风险。 其他说明:文章不仅提供了理论指导,还包括大量实战经验分享,有助于读者更好地理解和掌握相关技术和应用场景。

    【蓝桥杯EDA】客观题解析:第十三届省赛模拟题一.pdf

    【蓝桥杯EDA】客观题解析

    从移动激光雷达点云中提取电源线附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    【数学建模竞赛】华中杯数学建模竞赛介绍:参赛指南与备赛建议

    内容概要:“华中杯”是由华中地区高校或相关机构举办的数学建模竞赛,旨在培养学生的创新能力和团队合作精神。比赛主要面向全国高校在校生(以本科生为主,部分赛事允许研究生参加),采用团队赛形式(3人一组),参赛队伍需在72小时内完成建模、编程及论文写作。竞赛一般在每年4月或5月举行,设有多个奖项,具体比例根据参赛队伍数量确定。; 适合人群:对数学建模感兴趣并希望提升自身能力的全国高校在校生(本科生为主,部分赛事允许研究生参加)。; 使用场景及目标:①帮助学生了解数学建模竞赛的形式与流程;②为参赛者提供备赛建议,如学习往届真题、掌握Matlab、Python、LaTeX等工具以及明确团队分工;③鼓励学生关注官方通知,确保获取最新赛程和规则信息。; 其他说明:2025年的具体赛程、规则可能会有所调整,请以“华中杯数学建模竞赛官网”或主办方通知为准。可通过学校数学系或相关社团获取报名信息。

    光强温湿度计stm32.7z

    光强温湿度计stm32.7z

    基于TMS320F2812的永磁同步电机(PMSM)矢量控制与双闭环系统的实现

    内容概要:本文详细介绍了基于TMS320F2812 DSP控制器的永磁同步电机(PMSM)矢量控制系统的设计与实现。主要内容涵盖电流环和转速环的双闭环控制,包括ADC采样配置、坐标变换(Clarke和Park变换)、PI调节器的实现以及SVPWM生成等关键技术环节。文中特别强调了各个部分的具体代码实现及其调试技巧,如电流采样的三相两线法、PI调节器的积分限幅处理、SVPWM的扇区判断与作用时间计算等。此外,还讨论了一些常见的调试陷阱和解决方案,如QEP解码配置错误、死区时间设置不当等问题。 适合人群:具有一定嵌入式系统和电机控制基础知识的研发人员和技术爱好者。 使用场景及目标:适用于需要深入了解和掌握基于DSP2812的PMSM矢量控制系统的开发者。主要目标是帮助读者理解并实现高效的电流环和转速环双闭环控制系统,确保电机稳定运行并达到预期性能指标。 其他说明:文章不仅提供了详细的代码片段,还分享了许多实用的经验和教训,有助于读者在实际项目中少走弯路。同时,对于一些复杂的技术细节进行了深入浅出的解释,使得初学者也能逐步理解和应用这些高级控制算法。

Global site tag (gtag.js) - Google Analytics