hxtao001
hxtao001
2013-04-17 19:53

关于代码如何组织的疑惑

已采纳

刚入行,接触的项目不多,第一次接触的一个SSH项目是这样分层的
抽象一个Dao接口,这个接口包含对象基本增删改查,然后提供一个Dao实现(比如叫Support),至此Dao层结束,然后业务层接口继承Dao接口,业务层继承Support。然后每一个模块一个Action.这样做一个好处就是直接通用一个Dao,不用每个业务类都写一个Dao。但坏处就是因为涉及到泛型,每个个数据表都要对应一个业务对象。如果数据库中有很多的表,就会有很多业务接口业务实现。
具体结构看贴图:

另一个SSH项目是这样分的:
每个模块各一个增删改查Dao加Dao实现,Dao之前互相交错。

问题:个人觉得这两种设计都不好,那么该如何设计,还有,这两个项目中的业务层代码跟Dao层代码感觉都差不多,比如有一个业务层的代码是这样的:
public void deleteIp(Filterip ip){

    deleteDao.deleteIp(ip);
}

public void deleteDev(Devinfo devinfo){

    deleteDao.deleteDev(devinfo);
}

public void deleteBackup(Backup bp){

    deleteDao.deleteBackup(bp);
}

public void deleteDevdetail(Devdetail devdetail){

    deleteDao.deleteDevdetail(devdetail);
}

那这样分逻辑层有什么意义呢,然后最繁重的是action,判断都写在Action方法里面,导致一个方法少则一百多行,多则几百行,一个类上千行。

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

4条回答

  • Dead_Knight Dead_Knight 8年前

    [code="java"]
    public String importFile() {
    // TODO Auto-generated method stub

    this.flag="import";
    //从此处开始属于预先校验部分。
    //这部分校验的全部放到一个StrutsUtils这样的工具类的validateFile方法中。统一返回String,如果为null,则验证成功,不为null,则验证失败,msg为失败信息
    if (myFile == null) {
    this.msg="导入文件名获取失败!";
    return SUCCESS;
    }

    if (fileName == null || "".equals(fileName)) {
    this.msg="导入文件名获取失败!";
    return SUCCESS;
    }
    String[] tempfn=fileName.split("_");
    SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss");
    boolean isImport=true;
    try {
    sdf.parse(tempfn[0]);
    } catch (ParseException e) {
    // TODO Auto-generated catch block
    isImport=false;
    }
    if(!isImport){
    this.msg="文件名不符合命名规则,请选择正确的备份文件导入!";
    return SUCCESS;
    }
    //从此处结束属于预先校验部分

    //下面文件处理部分,放到文件处理帮助类中,也可放到StrutsUtils工具类中。
    String localfilePath = ServletActionContext.getServletContext()
    .getRealPath("/backup/files");

    File imageFile = new File(localfilePath);

    if (!imageFile.exists()) {
    imageFile.mkdirs();
    }

    localfilePath += "/" + fileName;

    imageFile = new File(localfilePath);

    HttpServletRequest request = ServletActionContext.getRequest();
    HttpSession session = request.getSession();

    Object keyname = session.getAttribute("keyname");
    Object keyright = session.getAttribute("keyright");

    int right = 0;
    String pcname="";

    if (keyright != null) {
    right=Integer.valueOf(keyright.toString());
    }
    if(keyname!=null){
    pcname=keyname.toString();
    }
    //这里需要业务层处理,直接在action调用
    Backup bk=auditlogService.findBackupByName(fileName);
    if (!imageFile.exists()) {// 如果文件存在不覆盖,直接返回导入成功

    boolean isCopy=auditlogService.importFile(pcname, request.getRemoteAddr(), right, pcname, myFile, imageFile, request.getLocalAddr());

    if(!isCopy){
    this.msg="导入失败!";
    }else{
    this.msg="导入完成!";
    }

    }else{
    if(bk==null){//如果文件存在,数据库没有备份记录
    //下面若干语句应该放在业务层处理
    Backup bkis = new Backup();
    bkis.setName(fileName);
    bkis.setStatus("0");
    bkis.setAuthority(right);
    String createtime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    .format(new Date());
    bkis.setCreatedate(createtime);

    auditlogService.backup(bkis);
    }
    Auditlog a = new Auditlog();
    a.setSn(sn);
    a.setInternettype(0);
    a.setTypeid(right);
    Auditlogtype auditlogtype = auditlogService.findTypeById(right);
    if (auditlogtype != null) {
    a.setTypename(auditlogtype.getName());
    }
    a.setCreatedate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    a.setAddress(request.getRemoteAddr());
    a.setSubname(pcname);
    a.setObjname(request.getLocalAddr());
    a.setActionid(9);
    a.setActionname("导入");
    a.setLevelid(1);
    a.setLevelname("一般");
    a.setExpandrecord("导入文件:" + fileName+" 文件已存在,不能重复导入!");
    a.setResult(1);
    auditlogService.save(a);
    this.msg="文件存在,不能重复导入!";

    }

    return SUCCESS;
    }
    [/code]

    点赞 评论 复制链接分享
  • jinnianshilongnian jinnianshilongnian 8年前

    早上没事,帮你重构下,

    你的逻辑是这样的
    1、校验是否可导入
    1.1、如果失败 直接返回

    2、得到图片文件

    3、如果文件存在 直接导入成功
    3.1、如果文件无备份 备份

    4、导入
    4.1、导入成功/失败

    5、记录审核日志

    因此我给你重构第一段 你可以按照相应的路子继续重构
    [code="java"]

    public String importFile() {

    //不使用异常
    String errorMsg = canImportFile(); //此处把校验放到里边
    if(!StringUtils.isEmpty(errorMsg)) {
    this.msg = errorMsg;
    return SUCCESS;
    }

    //或者使用异常
    try {
    assertCanImportFile();
    } catch(ImportException e) {
    this.msg = e.getMessage();
    return SUCCESS;
    }

    }[/code]

    还有比如
    fileName == null || "".equals(fileName)

    完全可以使用如apache commons lang包 缩短 如StringUtils.isEmpty(errorMsg)
    建议学学apache commons 包

    还有如下代码
    [code]Auditlog a = new Auditlog();
    a.setSn(sn);
    a.setInternettype(0);
    a.setTypeid(right);
    Auditlogtype auditlogtype = auditlogService.findTypeById(right);
    if (auditlogtype != null) {
    a.setTypename(auditlogtype.getName());
    }
    a.setCreatedate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    a.setAddress(request.getRemoteAddr());
    a.setSubname(pcname);
    a.setObjname(request.getLocalAddr());
    a.setActionid(9);
    a.setActionname("导入");
    a.setLevelid(1);
    a.setLevelname("一般");
    a.setExpandrecord("导入文件:" + fileName+" 文件已存在,不能重复导入!");
    a.setResult(1);
    auditlogService.save(a); [/code]

    可以分为两步
    log = populateAuditlog();
    auditlogService.save(a);

    比如备份也是这样

    Backup bkis = new Backup();

    bkis.setName(fileName);

    bkis.setStatus("0");

    bkis.setAuthority(right);

    String createtime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

    .format(new Date());

    bkis.setCreatedate(createtime);

    auditlogService.backup(bkis);

    把这些代码抽象到一个方法中

    这样你的主逻辑非常清晰

    还有你这里边的功能应该放到服务层(如果事务加在服务层) 否则假设备份成功了 但往下执行出问题了 则回滚不了

    在action 我们只需要组装我们的数据 然后把数据交给业务层/服务层处理 然后根据返回值/异常决定返回的页面 即action应该代码越少越好。。

    点赞 9 评论 复制链接分享
  • Dead_Knight Dead_Knight 8年前

    我之前做过类似的这种分层封装,我是这么做的,仅供你参考:
    dao接口,如:
    BaseDao接口(该接口提供常用的orm操作:save、update、delete、find、findByPage、searchBySQL……)
    dao的实现类,如:
    BaseDaoHibernate
    BaseDaoIbatis
    BaseDaoJdbc
    这几种实现类各自完成orm框架需要做的常用操作。

    service接口,实际上与BaseDao接口差不多,也是常用的增删改查,如:
    BaseManager
    service实现类,该实现类中注入BaseDao实例变量,完成常用的操作。如:
    BaseManagerImpl

    每个业务模块均定义自己的业务层、orm层接口,实现类。如:
    UserManager extends BaseManager
    UserManagerImpl extends BaseManagerImpl implements UserManager

    UserDao extends BaseDao
    这里以hibernate为例,
    UserDaoHibernate extends BaseDaoHibernate implements UserDao

    并把UserDao注入到UserManager中。

    如果业务逻辑复杂,在业务层接口增加业务层方法,由实现类具体实现。

    Action只要注入业务层bean,在具体方法中,做一些简单的预处理,再交给业务层处理业务逻辑

    建议你看看springside的源码以及一些其它优秀的基础框架。对你肯定有帮助。只要基础框架封装好了,业务模块做的事情非常少,增删改查这样的简单模块,基本上UserDao、UserManager接口不需要任何其它代码。

    当你对基础框架有深入的了解了,再建议你学习领域驱动等系统设计知识……

    点赞 2 评论 复制链接分享
  • yunzhu666 yunzhu666 8年前

    1、分层,action、service、dao,然后每层中各模块代码放在一起
    2、分模块,user、order,然后每模块中各曾代码放一起
    3、分层,各层有再分模块
    4、分模块,各模块中再分层

    权衡利弊,根据需要选择

    点赞 评论 复制链接分享

相关推荐