MVC架构模式

什么是MVC架构模式?

  1. MVC(Model View Controller)架构模式不属于23种设计模式,应该称其为软件开发架构模式,它的出现可以帮助后端程序员从繁杂的后端开发中抽离出来,在不同的层面只需要关注特定的需求即可。
  2. 如果用jsp+servlet进行开发,那么业务逻辑的编写,数据库的连接以及CRUD操作,都需要在一个Servlet中完成,这样代码复用性太低,而且看起来十分繁杂。
    MVC架构模式的出现就解决了这种情况,就如其字面意思,MVC将后端业务的开发大体上分为了三个部分:
    • Controller层,主要进行业务的调度和页面的展示。(可以看为司令员,servlet)
    • View层,展示页面。(可以看为展示秘书:jsp,thymeleaf等)
    • Model层,负责处理业务。(可以看为业务秘书:dao,bean,service等)
  3. MVC和三层架构的关系。在三层架构模式中,分为web层(表示层servlet和jsp或theymeleaf等),业务逻辑层(service)以及持久化层(DAO)。而在MVC中Controller是servlet;Model包括pojo(bean),dao,service;View层包括jsp,thymeleaf等。

MVC架构模式的工作过程(例如银行转账)

  1. 首先提供一个Account类,用来封装账户信息。这种简单的Java类被称为bean(也有叫做pojo,domain的)。
**
 * 账户实体类:封装账户信息的
 */
public class Account { // 这种简单的对象被称为pojo对象。
    // 一般属性不建议设计为基本数据类型,使用包装类,防止空带来的问题
    /**
     * 主键
     */
    private Long id;

    /**
     * 账号
     */
    private String actno;

    /**
     * 余额
     */
    private Double balance;

    public Account() {
    }

    public Account(Long id, String actno, Double balance) {
        this.id = id;
        this.actno = actno;
        this.balance = balance;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", actno='" + actno + '\'' +
                ", balance=" + balance +
                '}';
    }
}

  1. 其次准备一个DAO(Data Access Object)数据库访问对象,用来连接数据库,执行增删改查(CRUD)操作,DAO只负责数据库表的增删改查,没有任何业务逻辑在里面,这样的对象被称为DAO对象。
public class AccountDao {

    /**
     * 负责插入数据
     *
     * @param act 账户信息
     * @return 1 表示插入成功
     */
    public int insert(Account act) {
        Connection conn = null;
        PreparedStatement ps = null;
        int count = 0;
        try {
            conn = DBUtil.getConnection();
            String sql = "insert into t_act(actno,balance) values(?,?)";
            ps = conn.prepareStatement(sql);
            ps.setString(1, act.getActno());
            ps.setDouble(2, act.getBalance());
            count = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(null, ps, null);
        }
        return count;
    }


    /**
     * 根据主键删除账户
     *
     * @param id
     * @return
     */
    public int deleteByID(Long id) {
        Connection conn = null;
        PreparedStatement ps = null;
        int count = 0;
        try {
            conn = DBUtil.getConnection();
            String sql = "delete from t_act where id=?";
            ps = conn.prepareStatement(sql);
            ps.setLong(1, id);
            count = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(null, ps, null);
        }
        return count;
    }

    /**
     * 更改账户信息
     *
     * @param act 账户
     * @return
     */
    public int update(Account act) {
        Connection conn = null;
        PreparedStatement ps = null;
        int count = 0;
        try {
            conn = DBUtil.getConnection();
            String sql = "update t_act set actno=?,balance=? where id=?";
            ps = conn.prepareStatement(sql);
            ps.setString(1, act.getActno());
            ps.setDouble(2, act.getBalance());
            ps.setLong(3, act.getId());
            count = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(null, ps, null);
        }
        return count;
    }

    /**
     * 根据账号查询账户信息
     *
     * @param actno
     * @return
     */
    public Account selectByActno(String actno) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Account act = null;
        try {
            conn = DBUtil.getConnection();
            String sql = "select actno,balance from t_act where actno=?";
            ps = conn.prepareStatement(sql);
            ps.setString(1, actno);
            rs = ps.executeQuery();
            if (rs.next()) {
                Long id = rs.getLong("id");
                double balance = rs.getDouble("balance");
                act = new Account();
                act.setId(id);
                act.setActno(actno);
                act.setBalance(balance);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(null, ps, rs);
        }
        return act;
    }

    /**
     * 查询所有用户信息
     *
     * @return
     */
    public List<Account> selectAll() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<Account> accountList = null;
        try {
            conn = DBUtil.getConnection();
            String sql = "select id,actno,balance from t_act";
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            while (rs.next()) {
                Long id = rs.getLong("id");
                String actno = rs.getString("actno");
                Double balance = rs.getDouble("balance");
                Account act = new Account(id, actno, balance);
                accountList.add(act);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(null, ps, rs);
        }
        return accountList;
    }
}

  1. 在Model层编写相应的业务逻辑,Model层就是专门处理业务的,在该类中编写纯业务代码。
/**
 * 专门处理Account业务的一个类
 * 在该类中编写纯业务代码
 */
public class AccountService {
    // 这里的方法起名要表明处理什么业务
    private AccountDao accountDao = new AccountDao();

    /**
     * 完成转账的业务逻辑
     *
     * @param fromActno 转出账户
     * @param toAcrno   转入账户
     * @param money     转账金额
     */
    public void transfer(String fromActno, String toAcrno, double money) throws MoneyNotEnoughException, AppException {
        // 查询余额是否充足

        try (Connection connection = DBUtil.getConnection()){
            // 开启事务
            connection.setAutoCommit(false);

            Account fromAccount = accountDao.selectByActno(fromActno);
            Double fromAccountBalance = fromAccount.getBalance();
            if (fromAccountBalance < money) {
                throw new MoneyNotEnoughException("对不起,余额不足");
            }
            Account toAccount = accountDao.selectByActno(toAcrno);
            Double toAccountBalance = toAccount.getBalance();
            // 从转出账户中减去money
            fromAccount.setBalance(fromAccountBalance - money);
            int count = accountDao.update(fromAccount);
            // 向转入账户中添加money
            toAccount.setBalance(toAccountBalance + money);
            count += accountDao.update(toAccount);
            if (count!=2) {
                throw new AppException("账户转账异常!");
            }
            // 提交事务
            connection.commit();
        } catch (SQLException e) {
            throw new AppException("账户转账异常!");
        }
    }
}

工作过程:当用户发送过来一个请求,首先会在Controller层进行处理,当用户发送转账需求的时候,Controller层首先会进行处理,并调用Model层相应的业务方法(transfer),在Model层执行transfer的时候,会自动创建AccounDao对象执行相应的操作,最终将结果返给Controller,然后Controller层根据Model层里面传来的结果,调用View层进行展示。

/**
 * 账户小程序
 * AccountServlet是一个Controller
 *
 * @author 琨哥
 * @version 2.0
 * @since 2.0
 */
@WebServlet("/transfer")
public class AccountServlet extends HttpServlet {
    private AccountService actService = new AccountService();
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 接收数据,调用业务方法(Model)处理业务
        String fromActno = request.getParameter("fromActno");
        String toActno = request.getParameter("toActno");
        double money = Double.parseDouble(request.getParameter("money"));
        try {
            actService.transfer(fromActno, toActno, money);
            // 执行到这里说明转账成功,调用view层展示响应的代码
            response.sendRedirect(request.getContextPath()+"/success.jsp");
        } catch (MoneyNotEnoughException e) {
            // 调用view层进行展示
            response.sendRedirect(request.getContextPath() + "/MoneyNotEnough.jsp");
        } catch (Exception e) {
            response.sendRedirect(request.getContextPath() + "/error.jsp");
        }
    }
}

这样Controller负责业务的调度和页面的展示,Model层负责编写业务逻辑,view层负责编写前端页面,分工合作极大的提高了代码的复用性!

你可能感兴趣的:(java,servlet,tomcat,开发语言,http)