本人表达能力较差,举个例子来说明:
假设有个有个用户登录的功能,Servlet url是:login.do,BO是UserBo,简略代码如下://实体类
public class User {
String name;
String password;

public User(){
}

public User(String name, String password) {
super();
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}

}//Dao 类
public class UserDao {
public User findUserByName(String username){
return new User(username, "password");
}        public boolean addUser(User user){
// do something...
return true;
}
}
//Bo 类public class UserBo {
private UserDao dao = new UserDao();

public boolean login(String username,String password){
User u = dao.findUserByName(username);
if( u != null && u.getPassword().equals(password)){
return true;
}
return false;
} public boolean addUser(User user){
return dao.addUser(user);
}
}//Servlet
import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class Login extends HttpServlet {

private UserBo bo = new UserBo();

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
boolean b = bo.login(username, password);
if( b ){
request.setAttribute("user", username);
response.sendRedirect("loginSuccess.jsp");
}else{
response.sendRedirect("loginError.jsp");
}
}}以上是简单的代码,现在很明显的一个问题摆在面前了,那就是Bo类的login方法只是简单的返回一个boolean值
是无法满足我们需求的,因为只返回boolean值的话只能知道登录是成功和失败,但是不能知道失败的原因是什么
所以无法给客户端一个丰富的结果。这只是一个小小的例子,大家来分析一下BO层如何设计才能解决这类问题。
还有,BO类的addUser方法,我以前做的项目里类似的add、update、delete、方法都只是简单的包装下dao的方法
BO在这里又能做些什么呢?都知道分层有好处,但是,如果只是简单的包装,BO就差不多算是没用的了,直接在
Servlet里面引用Dao的接口一样不会影响程序的偶和性。
我的问题的很明确,就是:业务层(BO)该做什么事?该怎样做事?
因为马上就要做项目了,我想在新项目里把功能做的更完善些。
呵呵,本人还是有点可用分的,如果在这里能得到有建设性的回答的话,我是不会吝啬那点点分滴。~

解决方案 »

  1.   


    public User login(String username,String password) throws LoginException{
            User u = dao.findUserByName(username);
            if(u == null) {
             throw new LoginException("不存在的用户");
            }
            if(!u.getPassword().equals(password)){
                throw new LoginException("密码错误");
            }
            return u;
    }我个人都是这么做的。
      

  2.   

    业务层(BO)该做什么事?该怎样做事?
    业务复杂些的话你就需要在public class Login extends HttpServlet {
    调用多个DAO------什么能称为业务就是这种方式LZ您知道了么,如果调用了多个DAO就知道他的好处了。
      

  3.   

    BO业务层,处理业务的流程的
                BO又调用DAO层,DAO直接与数据库进行访问
      

  4.   

    嗯,如果用到了多个DAO,确实是封装到BO层好点。
    以前做的项目中没有遇到过这样的情况,所以没有考虑到。
      

  5.   

    D=Data
    B=Businessdata是天然的,孤立的
    Business是逻辑的,是处理关系的所以,如果没有逻辑可处理,也确实无需BO,
    技术只是手段,需要我们合理利用。
    ----------具体问题,你说的Bo的login返回boolean信息少,
    可以为UserBo增加方法返回详细信息:
    //Dao 类
    public class UserDao {
        public User findUserByName(String username){
            return new User(username, "password");
        }        public boolean addUser(User user){
            // do something...
            return true;
        }

    //Bo 类public class UserBo {
        private UserDao dao = new UserDao();
        
        public boolean login(UserDao user){
            User u = dao.findUserByName(username);
            if( u != null && u.getPassword().equals(password)){
                return true;
            }
            errMsg="登录失败原因在这里。";
            return false;
        }    public String getErrorMsg(){
            return errMsg;
        }
        public boolean addUser(User user){
            return dao.addUser(user);
        }
    }
      

  6.   

    dao是操作数据的最小原子,bo是多个原子的统一调用。没有bo的话如何实现事务,如何进行事务嵌套,如何进行代码复用至于登陆参数返回值可使用exception方式或传统的错误定义 用int做为返回值 方式 0 为成功 定义大于0 的或者小于0的为失败方式,
    同时对应错误代码表
    0 成功
    1 用户不存在
    2 密码错误
    .....后一种方式可降低错误提示信息与代码的耦合度,方便修改
      

  7.   

    照这种方法BO对象只能一个线程就new一个了,多个用户同时调用的话肯定会出问题的。
      

  8.   

    9 楼 jinxfei 的方法给我了一些提示,我想到了一种可以在多线程中使用这种方法的
    解决办法,ThreadLocal类。感谢!
      

  9.   


    额,为什么一定要用到ThreadLocal?你觉得多线程有什么问题啊。
      

  10.   

    jinxfei的回帖总是那么的精辟,呵呵。
      

  11.   


    LZ 想多了吧。 Servlet 本身就是线程安全的,你的请求会在一个单独的线程中执行。何况login验证后 User 的生命周期也就是在 Session 内吧。何来多线程问题。
      

  12.   

    一般情况下BO是不会在使用的时候再去new一个吧?
    BO一般也是单态的,当多个用户同时请求login的时候
    必定会有多个线程同时访问UserBo的login方法,你说这个时候
    public String getErrorMsg(){
            return errMsg;
    }
    这个方法还安全吗?
    当然,如果每个请求就new一次UserBO就不存在这个问题
     
      

  13.   

    两种实现方法,
    第一种:private static ThreadLocal<String> local = new ThreadLocal<String>();
    public boolean login(String username,String password){
    User u = dao.findUserByName(username);
    if( u != null && u.getPassword().equals(password)){
    return true;
    }
    local.set("some error message");
    return false;
    }

    public String getMessage(){
    return local.get();
    }
    第二种,要借助另外一个类://  引入一个BR类
    public class BR<T> {

    private boolean success;
    private T result;
    private Object error;

    public BR(){}

    public BR(boolean success, T result, Object error) {
    super();
    this.success = success;
    this.result = result;
    this.error = error;
    }
    //省略getter and setter

    }//  具体使用 public BR<?> addUser(User user){
    if( dao.addUser(user)){
    return new BR<Object>(true,null,null);
    }
    return new BR<Object>(false,null,"some error message");
    }

    public static void main(String[] args){
    UserBo bo = new UserBo();
    BR<?> br = bo.addUser(new User());
    if( br.isSuccess() ){

    //do something success
    }else{
    //failure 
    System.out.println("add user failed, because: " + br.getError());
    }
    }
    大家来这两种方法可行吗?
      

  14.   

    再不济,将login方法的返回值改成一个对象也可以啊。
      

  15.   

    如果一个dao内部不存储conn的话,也就是说仅仅是方法,没有方法可能调用的公共成员的话,可以直接单例,就像用spring管理一样,默认都是单例的dao。相反每次就要new一个了,对于事物来说可以用threadlocal存储每个线程所持有的conn,从而保证一个线程内只开一个conn。
      

  16.   


    标准的话,推荐第2种,第一种有点为了解决问题而解决问题的意思。
    另外exception是最好的对你来说,exception并不是错误,而是正常情况下出现的意外。用exception是很通常的做法的
      

  17.   

    返回值用这个 public  enum  LoginError{     
         NameError,     
         PasswordError,     
         Success; 
      }
      

  18.   

    不予采用,该做法类似返回int型,我有N多BO,每个BO又有N多方法
    难道要定义N多枚举?而且也不灵活。
      

  19.   

    不是没考虑过异常,但是异常太过繁杂,在调用的地方要写很烦人的try-catch语句,用的少还好,
    用的多了,当一个方法里用到多个BO功能时,到处充斥着try-catch,容易造成逻辑混乱。
    所以最后还是舍弃了异常机制。
      

  20.   

    data是天然的,孤立的 
    Business是逻辑的,是处理关系的
      

  21.   

    我也只知道dao多了用bo封装是件很舒服的事~~
      

  22.   

    我想的是,dao 层也就是持久层,他真正的用途就是只对数据进行操作,这样的话就有一点不好,当我们这传进来的参数进行判断的时候,如果在这里进行判断的话,会增加操作数据的负担,所以才会有业务逻辑层,直接调用dao里面的方法,到时候在servlet或是action中直接调用业务逻辑时里的方法就ok了
      

  23.   

    我们公司一般喜欢用Service或是Manager,Bundle之间用Servie,Bundle之内用Manager。