OA项目开发遇到的问题总结

1:在显示部门的下拉框中

   |-财务部

       |-审计处

       |-报账处

这个功能的实现思路是:首先department类是有parent和childs【set集合】属性的,所以可以根据某个department得到它的父和子!那么就根据树的形式来递归得到所有的节点(department)吧!

设计两个方法,一个要得到所有的最高顶点(通过service实现),另一个方法打印顶点(传参数顶点)并且得到子节点然后再调用自己!

这个时候出现了两个问题,一个是在显示框中的|-符号防止保存到数据库中去,这个符号是在我们得到department对象的通过utils方法加上去的,好了逻辑是这样的,前面的service得到对象--utils加上符号然后显示,当我们不小心在utils后面又调用了一次service的方法后,这个符号就会保存到数据库中去,应为service的开启就对应着事务transactions的开始,service的关闭对于的事务的commit!

要解决这个符号不保存到数据库中去,需要知道,我们在herbinate懒加载那一篇博客中说过,延长了session的生命周期,我们的框架决定只有session管理的对象才能保存到数据库中,那么我们两种方法:

1 不使用session管理的对象

2 不再utils后面再打开事务也就是不再调用service方法

第二点是无法做到的,因为我们不能保证service方法日后不使用 

用第一点解决:new copyDepartment  将它作为session中得到的对象的副本!这样完美解决!!

 

第二点是在显示审计处和报账处两个同级的部门时候,会出现顺序不固定,不信刷新试试!

由于我们在departments.hbm.xml中使用了

解决办法:

1 不用sets

2

使用2的时候,可以看到herbinate输出的sql语句是这样的:

OA项目开发遇到的问题总结

2 session是一级缓存,sessionFactory是二级缓存???啥意思

翻阅自己的博客哦

 

3:很常见的反射技术得到泛型类

在DAO中药使用一次,DAO来得到这个这个T的具体类型,然后才能select * from T 或者将查找到的表列转换成真实的对象

继承者使用UserDAO extends DAO 来传入这个User,在DAO处得到使用的是:

注意这下面这段代码都写在父类的无参构造函数中的,且必须写在父类中,如果根本没有继承关系的话,比如说一个students类中的构造函数写下面的这段代码会出现:Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType错误,原因是无法得到自己的泛型

public BaseDaoImpl(){
 //使用反射技术得到T的真实类型
//1:获取当前类的直接父类的类型type,强转成ParameterizedType
 ParameterizedType pt=(ParameterizedType)this.getClass.getGenericSuperClass();
 //返回表示此类型的实际类型参数的Type对象的数组
//Arguments?如果类型是map就是两个(0-K,1--v)咯,这里只是一个基本类型只有第0位
 this.clazz=(Class)pt.getActualTypeArguments()[0];
}

点需要注意的是,在写子类继承父类的时候必须要将真实类型传送过去,比如“:

UserDAOImpl extends BaseDaoImpl<User>   //不能写T了

 

#############################

3:整个项目开发中的模块化的思路:

模块化的地方有以下几处:当然还有jsp页面中的一些公共模块未显示在这里

OA项目开发遇到的问题总结

这里可以看到实际上我们只分了两层,将DAO层去除掉了,因为在service层中就只是简单的调用dao中的方法(即数据库的增删改查),并未有很强的逻辑代码在环绕,所以还不如写成两层(实际上就是讲dao的代码写到了service中),所以现在的service层代码是这样的:

package cn.itcast.oa.base;

import java.util.List;

public interface DaoSupport {

 
 void save(T entity);

 
 void delete(Long id);

 
 void update(T entity);

 
 T getById(Long id);

 
 List getByIds(Long[] ids);

 
 List findAll();

}

*******************

package cn.itcast.oa.base;

import java.lang.reflect.ParameterizedType;
import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;

// @Transactional注解可以被继承
// @Transactional注解对父类中声明的方法无效
@Transactional
@SuppressWarnings("unchecked")
public abstract class DaoSupportImpl implements DaoSupport {

 @Resource
 private SessionFactory sessionFactory;
 private Class clazz;

 public DaoSupportImpl() {
  // 使用反射技术得到T的真实类型
  ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取当前new的对象的 泛型的父类 类型
  this.clazz = (Class) pt.getActualTypeArguments()[0]; // 获取第一个类型参数的真实类型
  System.out.println("clazz ---> " + clazz);
 }

 
 protected Session getSession() {
  return sessionFactory.getCurrentSession();
 }

 public void save(T entity) {
  getSession().save(entity);
 }

 public void update(T entity) {
  getSession().update(entity);
 }

 public void delete(Long id) {
  Object obj = getById(id);
  if (obj != null) {
   getSession().delete(obj);
  }
 }

 public T getById(Long id) {
  if (id == null) {
   return null;
  } else {
   return (T) getSession().get(clazz, id);
  }
 }

 public List getByIds(Long[] ids) {
  if (ids == null || ids.length == 0) {
   return Collections.EMPTY_LIST;
  } else {
   return getSession().createQuery(//
     "FROM " + clazz.getSimpleName() + " WHERE id IN (:ids)")//
     .setParameterList("ids", ids)//
     .list();
  }
 }

 public List findAll() {
  return getSession().createQuery(//
    "FROM " + clazz.getSimpleName())//
    .list();
 }

}

看了上面的代码是不是以前都是写在dao中的,所以没有什么神秘的,也要注意到为什么要这样做!!!灵活运用,mvc不是必须的!!

************

接下来是BaseDao代码,原来我们常写的代码都是继承actionSupport,现在我们将BaseDao继承了actionSupport,然后让所有的action继承BaseDao,不仅不减少actionsupport的功能更扩展了功能:

package cn.itcast.oa.base;

import java.lang.reflect.ParameterizedType;

import javax.annotation.Resource;

import cn.itcast.oa.service.DepartmentService;
import cn.itcast.oa.service.PrivilegeService;
import cn.itcast.oa.service.RoleService;
import cn.itcast.oa.service.UserService;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public abstract class BaseAction extends ActionSupport implements ModelDriven {

 // =============== ModelDriven的支持 ==================

 protected T model;

 public BaseAction() {
  try {
   // 通过反射获取model的真实类型
   ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
   Class clazz = (Class) pt.getActualTypeArguments()[0];
   // 通过反射创建model的实例
   model = clazz.newInstance();
  } catch (Exception e) {
   throw new RuntimeException(e);
  }
 }

 public T getModel() {
  return model;
 }

 // =============== Service实例的声明 ==================
 @Resource
 protected RoleService roleService;
 @Resource
 protected DepartmentService departmentService;
 @Resource
 protected UserService userService;
 @Resource
 protected PrivilegeService privilegeService;

}

可以看到BaseDao也只是加了ModelDriven这个东西,主要目的是让我们传入一个实体对象进来,这样在页面中可以直接对此对象的属性进行添加了(不用写get/set,只写一个getModel就行了);

还有一个非常重要的地方Service实例的声明 原来这个东西我是写在action中的,现在写到这个地方有什么好处???如果我们有两个action都需要用RoleService ,那么就不必写两次了嘛,在action中已经不需要写这个依赖注入了,直接拿来用就是了(protected是不同包中子类也可以访问),只要在action头上标志@Controller
@Scope("prototype")即可直接roleService.XX

那么上面的这个模板就写好了:

 

 

*****************

页面模块化:

添加、修改、删除成功后 要重定向到列表功能,这样在刷新页面时才不会出现 又做一次增、删、改 的操作。
列表与删除功能都是只有一个请求
添加与修改功能都是有两个请求
 
作用
方法名
返回值
对应的 JSP 页面
列表
list()
list
list.jsp
删除
delete()
toList

 

添加页面
addUI()
addUI
addUI.jsp
添加
add()
toList

 

修改页面
editUI()
editUI
editUI.jsp
修改
edit()
toList

 

 
增删改查共4个功能,6个请求,需要在Action中有6个对应的处理方法。
toList的配置为:type="redirectAction" actionName=“xxAction_list
 
public String list() throws Exception { return "list"; }
public String delete() throws Exception { return "toList"; }
public String addUI() throws Exception { return "saveUI"; }
public String add() throws Exception { return "toList"; }
public String editUI() throws Exception { return "saveUI"; }
public String edit() throws Exception { return "toList"; }
 
上面的准备工作做足了,接下来一些页面只需要进行重复的操作
 一、做Action相关的准备
1,创建 MyAction extends BaseAction.
2,定义出Action中的方法,要写出方法名、作用、返回值。
3,创建出所用到的JSP页面(目前还没有具体内容)。
4,配置Action
1,在MyAction上写注解 @Controller@Scope("prototype").
2,在strtus.xml中配置这个Action与所用到的result.
 
二、做Service相关的准备
1,创建接口MyService extends BaseDao.
2,创建实现类MyServiceImpl extends BaseDaoImpl.
3,配置:在MyServiceImpl上写注解:
@Service @Transactional
4,声明:在BaseAction 中声明:
@Resource protected MyService myService;
 
三、填空:
1Action方法。
2,新增的Service方法。
3JSP页面的内容:
a,拷贝静态页面中的源代码到JSP中。
b,包含进来公共的资源:
 ****************
控制层非常有意思的地方:在访问时使用过滤器:struts.xml
上面的CheckPrivilegeInterceptor非常的有意思:
public class CheckPrivilegeInterceptor extends AbstractInterceptor {
 public String intercept(ActionInvocation invocation) throws Exception {
  // System.out.println("---------> 之前");
  // String result = invocation.invoke(); // 放行
  // System.out.println("---------> 之后");
  // return result;
  // 获取信息
  User user = (User) ActionContext.getContext().getSession().get("user"); // 当前登录用户
  String namespace = invocation.getProxy().getNamespace();
  String actionName = invocation.getProxy().getActionName();
  String privUrl = namespace + actionName; // 对应的权限URL
  // 如果未登录
  if (user == null) {
   if (privUrl.startsWith("/user_login")) { // "/user_loginUI", "/user_login"
    // 如果是去登录,就放行
    return invocation.invoke();
   } else {
    // 如果不是去登录,就转到登录页面
    return "loginUI";
   }
  }
  // 如果已登 录,就判断权限
  else {
   if (user.hasPrivilegeByUrl(privUrl)) {
    // 如果有权限,就放行
    return invocation.invoke();
   } else {
    // 如果没有权限,就转到提示页面
    return "noPrivilegeError";
   }
  }
 }
}

1.actionInvocation是什么

ActionInvocation就是Action的调用者。ActionInvocation在Action的执行过程中,负责Interceptor、Action和Result等一系列元素的调度。

理解ActionInvocation你需要对Action的调用过程有一个全面的了解:

http://tech.ddvip.com/2009-01/1232090919106049.html

 

讲的还是很清楚地!

2.ActionInvocation干什么

Interceptor通过ActionInvocation可以完全的改变Action行为:不让它执行、改变返回值、甚至可以细颗粒的操作Action的方法

查看ActionINvocation 的API,他有getActionProxy(),getResultCode();getActionContext();

ActionProxy在action中用来构建执行环境,ActionProxy提供Action执行的时候一切所需要的配置、参数等等,当然,也要有进行Action调用的入口。

你可能感兴趣的:(WEB开发)