1.什么是SpringMVC
SpringMVC是一个web框架,它是Spring家族的一员,见名知意,它实现了MVC架构模式,所以我们必须知道什么是MVC模式
2.什么是MVC模式
要知道MVC架构模式干了什么事,我们就必须知道不用MVC架构模式的话会带来什么问题:
先来看看一段基于servlet的web代码:
package com.jtl.web.servlet;
import com.jtl.web.exception.AppException;
import com.jtl.web.exception.NoMoneyException;
import com.jtl.web.utils.DBUtils;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @description:
*/
@WebServlet("/transfer")
public class AccountTransferServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
String fromActno = request.getParameter("fromActno");
String toActno = request.getParameter("toActno");
double money = Double.parseDouble(request.getParameter("money"));
Connection c = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//1.根据fromActno连接数据库,查询所在人有没有钱转出去先
c = DBUtils.getConnection();
ps = c.prepareStatement("select balance from t_account where actno = ?");
ps.setString(1,fromActno);
rs = ps.executeQuery();
//如果查到,只有一条记录
if(rs.next()){
double balance = rs.getDouble("balance");
if(balance < money){
//如果余额比要转出去的还少
throw new NoMoneyException("余额不足,无法完成转账!!!");
}
//开启事物:
c.setAutoCommit(false);
//走到这里可以开始转账:
//先让转账的人扣钱
ps = c.prepareStatement("update t_account set balance = balance - ? where actno = ?");
ps.setDouble(1,money);
ps.setString(2,fromActno);
int count = ps.executeUpdate();
//入账的人加钱
ps = c.prepareStatement("update t_account set balance = balance + ? where actno = ?");
ps.setDouble(1,money);
ps.setString(2,toActno);
count += ps.executeUpdate();
if(count != 2){
throw new AppException("app出错!!!");
}
c.commit();
out.print(fromActno + "向" + toActno + "转账成功");
}
} catch (SQLException e) {
try {
c.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
throw new RuntimeException(e);
} catch (NoMoneyException e) {
try {
c.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
out.print(e.getMessage());
} catch (AppException e) {
try {
c.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
out.print(e.getMessage());
}finally {
DBUtils.close(rs,c,ps);
}
}
}
这段代码干的事情很简单,接收前端传递的用户账号和转账金额,并完成转账功能。
但是这个代码有几个非常大的问题:
- 代码的复用性太差了。比如这个转账方法要操作底层数据库,但是我们可能还有其他的业务方法也需要进行类似甚至相同的操作,难道我们把相同的jdbc代码写十遍甚至一百遍吗?这样的无用功是没有意义的
- 耦合度高,代码很难进行扩展。比如里面的sql语句,全都是固定写好的,那么假设在这个项目发布一年后,业务需求突然改变,那么此时就必须把整个项目代码都进行修改,然后再编译发布,这样违背了软件开发的基本原则:OCP开闭原则,我们不应当修改已经运行的代码。
- 操作数据库的代码和业务代码糅杂在一起,很容易出错,无法专注业务逻辑的编写
所以我们要对项目进行分层管理,分层开发,这样才能做到专人干专事,各司其职,可以让代码的耦合度降低,扩展力增强,组件的可复用性增强
这里就要用到一个非常著名的架构模式:MVC架构模式
M:(Model 数据/业务,是秘书,负责处理业务和数据)
V: (View 视图/页面展示,是秘书,负责页面展示)
C: (Controller 控制器,这个是核心,是司令官)

用户发送一个请求,首先经过控制器,控制器可以调用Model层处理业务和数据,处理完毕后再返回给控制器;控制器也可以调用View层进行页面展示
在控制器调用Model这边,还可以细分层次,我们知道,我们一般是通过sql语句查询mysql数据库表中的数据的,那么Model可以分为处理业务和处理数据的;
我们把从数据库表中处理数据的这个层叫做DAO(data access object 数据访问对象),它只负责数据库表的CRUD,没有任何逻辑业务在里面,我们业务层service通过调用这个DAO层来查询数据,所以业务层只需要专注于业务代码即可,这就降低了耦合度。
而DAO层持久层的框架我们已经学习了Mybatis框架,利用Mybatis我们就可以很方便的完成对数据库的CRUD。