最近写了一个javaweb项目,以此记录项目中MVC的思想并探究原因。
MVC
-
model层 ------------------ 包含service层和dao层
-
view层 ------------------ 可以理解为jsp
-
controller层 ------------------ servlet负责处理请求和页面转发
那么这里的model层我们今天就来聊聊,为什么要有这两个东西
-
dao层:数据持久层
-
service层:业务逻辑层
这里需要画一个http请求web项目的流程图

通常我们的项目目录如下
├─bean │ User.java │
├─dao │ └─user │ UserDao.java │ UserDaoImpl.java
├─service │ └─user │ UserService.java │ UserServiceImpl.java
那么这里我以注册功能为例
Register.java核心代码
UserService userService = new UserServiceImpl();
try{
//判断用户名是否已经被注册过
User u = userService.findUserByName(user);
if(u==null){
//查询没找到用户,user表
添加一条记录
userService.addUser(user);
System.out.println("注册成功");
}
UserService.java
//业务逻辑层
public interface UserService {
public void addUser(User user) throws Exception;
public User findUserByName(User user) throws Exception;
}
UserServiceImpl.java
public class UserServiceImpl implements UserService{
UserDao userDao = new UserDaoImpl();
@Override
public void addUser(User user) throws Exception {
userDao.addUser(user);
}
@Override
public User findUserByName(User user) throws Exception {
return userDao.findUserByName(user);
}
}
UserDao.java
public interface UserDao {
public void addUser(User user)throws Exception;
public User findUserByName(User user) throws Exception;
}
UserDaoImpl.java
public class UserDaoImpl implements UserDao{
//插入一个用户
@Override
public void addUser(User user) throws Exception {
Connection conn = null;
PreparedStatement preparedStatement = null;
try{
conn = DBUtil.getConnection();
//构造一个sql语句
preparedStatement = conn.prepareStatement("insert into user(username, password, role) values (?,?,?)");
preparedStatement.setString(1,user.getUsername());
preparedStatement.setString(2,user.getPassword());
preparedStatement.setString(3,user.getRole());
//执行sql语句
preparedStatement.executeUpdate();
System.out.println("添加用户完成!");
preparedStatement.close();
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException("添加用户失败");
}
}
}
首先说说mvc思想的好处
在以前,我们的所有代码都是在一个servlet中完成的,它既要接收处理请求,又要写业务逻辑(简单举例这里是查表),还要转发页面,工作十分冗余而且不易后期维护,你想想如何哪天需求变了,数据库也变了我们要在servlet中进行大量的代码更改,如果是个大工程,几万行的代码会让你崩溃掉。
现在我们把业务逻辑单独分离出来了,servlet不用再关心业务逻辑怎么写,只需要调用接口的方法,若哪天需求变更,servlet不需要改变,我们只需要在具体的实现方法上更改就好了。
Question 1:我们还需要Service层吗?
虽然我按照这样分层了,其实你会发现service层几乎没有任何代码,也只是调用了dao层接口的方法,未免有些多余,起初让我觉得十分困惑。那么是不是只需要dao层而不需要service层了呢?
按道理来说我这个小工程,service还真没什么必要,因为这里涉及到的业务只是简单的增删改查。servlet明明可以直接调用dao层接口的方法,而不需要经过service的手再去调用dao层,但是这么设计必然是有他的原因,那么service层到底做了什么事?
其实dao层的任务具体和数据库的每一张表一一对应,不应该在里面写任何的业务逻辑,他的任务需要专一化,只是和数据库的表打交道,也就是增删改查的工作;service层是不能简单看做一次对dao层的调用,他可以有更多的操作,比如要实现一个分页功能,前端传递过来当前页码pagecurrent,service层需要将pagesize和pagecurrent都传递给dao层,dao层只做模糊查询,而service层的工作此时就多了,需要封装pagebean的数据,将分页的数据封装返回给servlet,而这些事情dao层做不了。分层的目的就是为了让工作解耦,各自负责对应的部分,便于多人合作也易于维护,修改成本小。
比说你现在用的是SSH框架,做一个用户模块:
- 1、假设现在你做这个功能会用到user表和权限表,那么你前台的页面访问action,action再去调用用户模块service,用户模块service判断你是操作user表还是权限表,如果你操作的是user表则service的实现类就去调用userDAO。如果是操作的是权限表则调用权限的DAO。
- 2、也就是说DAO一定是和数据库的每张表一一对应,而service则不是。明白的没?其实你一个项目一个service和一个DAO其实也一样可以操作数据库,只不过那要是表非常多,出问题了,那找起来多麻烦,而且太乱了。
- 3、好处就是你的整个项目非常系统化,和数据库的表能一致,而且功能模块化,这样以后维护或者改错比较容易,性能也高一些。
Question 2:为什么Dao和Service层需要使用接口?
- 为什么要用Service接口?
是让表示层不依赖于业务层的具体实现。
- 为什么要用DAO接口?
是让业务层不依赖于持久层的具体实现。
举个例子,用DAO接口,那么持久层用Hibernate,还是用iBatis,还是 JDBC,随时可以替换,不用修改业务层Service类的代码。不用接口的话,假如修改了dao中的代码,因为service引用了dao中的类,那么也要改变service里面的代码,改完之后要重新编译运行,当项目比较大的时候,编译和运行很浪费时间的,而且会产生一些意外,本来只要编译dao中的代码,现在不光要编译dao中的代码,还要编译service。因为你不用接口,间接着action里的代码也要改,因为action中引用了service中的类,到最后,就变成了,牵一发而动全身。
- 为什么要写Imp实现类?
是因为后期维护的时候如果要修改功能只需要修改实现类里面的那个代码,而不需要修改其他包的代码。
网友评论