【JavaWeb学习 | 第18篇】Servlet与MVC开发模式
在上一篇文章中,我们详细学习了 JSP九大内置对象,掌握了JSP如何动态生成页面。
但如果把所有业务逻辑、数据处理、页面展示全部写在JSP里(早期Model1模式),代码会非常混乱、难以维护。
MVC模式的出现,就是为了解决这个问题。它将“数据、业务逻辑、界面展示”彻底分离,让开发更清晰、更易扩展。
一、什么是MVC模式?
MVC 是 Model-View-Controller 的缩写,是一种经典的软件设计模式,特别适合Web开发。
| 组件 | 英文全称 | 对应JavaWeb技术 | 主要职责 |
|---|---|---|---|
| Model(模型) | Model | JavaBean(实体类 + 业务类) | 封装数据 + 处理业务逻辑(增删改查、计算等) |
| View(视图) | View | JSP(或HTML + EL + JSTL) | 负责数据展示,只做“看”的工作,不处理复杂逻辑 |
| Controller(控制器) | Controller | Servlet | 接收用户请求、调用Model处理业务、选择合适的View返回给用户 |
工作流程(核心理解点):
- 用户在浏览器发出请求(例如点击登录按钮) → 请求到达 Controller(Servlet)
- Servlet(Controller)接收请求参数,调用 Model(JavaBean/Service/DAO)进行业务处理
- Model处理完后返回数据给 Controller
- Controller把数据存入作用域(request/session),然后转发或重定向到对应的 View(JSP页面)
- JSP(View)使用EL表达式或JSTL从作用域中取出数据并展示给用户
优点:
- 分层清晰,职责单一
- 便于团队协作(前端写JSP,后端写Servlet+JavaBean)
- 代码可维护性、可扩展性大大提高
- 后期容易过渡到Spring MVC等框架
二、JavaWeb经典开发模式演进
- Model1(早期):JSP + JavaBean
JSP既当Controller又当View,适合小型项目,逻辑复杂后难以维护。 - Model2(推荐):Servlet + JSP + JavaBean(即MVC模式)
Servlet做控制器,JSP做视图,JavaBean做模型。这是我们本篇重点学习的模式。 - 三层架构(实际开发常用)
在MVC基础上进一步细化Model层:
- 表示层(Web层):Servlet + JSP(Controller + View)
- 业务逻辑层(Service层):处理复杂业务(如登录时检查权限、发邮件等)
- 数据访问层(DAO层):专门与数据库交互(CRUD操作) 实体类(POJO/JavaBean)通常放在Model中,被Service和DAO共用。
三、MVC模式核心代码示例(用户登录)
1. Model层 —— User实体类
// com.example.model.User.java
public class User {
private String username;
private String password;
// getter & setter + 无参构造
public User() {}
// ... 省略getter/setter
}
2. Controller层 —— LoginServlet
// com.example.web.LoginServlet.java
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1. 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// 2. 调用Model处理业务
UserService service = new UserService(); // 实际项目中常用Service层
User user = service.login(username, password);
// 3. 根据结果选择View
if (user != null) {
// 登录成功,数据放入session
req.getSession().setAttribute("user", user);
// 转发到成功页面(地址栏不变)
req.getRequestDispatcher("/success.jsp").forward(req, resp);
} else {
// 登录失败,放入错误信息到request
req.setAttribute("errorMsg", "用户名或密码错误!");
// 转发回登录页面
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
}
3. View层 —— login.jsp(登录页面)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>用户登录</title></head>
<body>
<h2>用户登录</h2>
<%-- 显示错误信息 --%>
<span style="color:red;">${errorMsg}</span>
<form action="${pageContext.request.contextPath}/login" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
4. View层 —— success.jsp(成功页面)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登录成功</title></head>
<body>
<h2>欢迎您,${user.username}!</h2>
<a href="${pageContext.request.contextPath}/logout">退出登录</a>
</body>
</html>
四、MVC开发中的关键技术点
- 请求转发(forward):
request.getRequestDispatcher().forward()
服务器内部跳转,地址栏不变,request作用域数据共享。 - 重定向(redirect):
response.sendRedirect()
客户端跳转,地址栏改变,request作用域数据丢失。 - ${pageContext.request.contextPath}:动态获取项目路径,避免硬编码。
- EL表达式 + JSTL:在JSP中尽量少写Java脚本,让页面更干净。
- 过滤器(Filter) 和 监听器(Listener):常配合MVC使用(如统一编码、登录权限检查)。
五、实际开发建议与注意事项
- 包结构推荐(三层架构):
com.example.model→ 实体类(User、Product等)com.example.dao→ 数据访问层(UserDao)com.example.service→ 业务逻辑层(UserService)com.example.web→ Servlet控制器com.example.utils→ 工具类webapp/→ JSP页面、静态资源(css、js、images)
- 不要在JSP中写复杂Java代码,尽量只做展示。
- Servlet中不要写数据库连接代码,应该交给DAO层。
- 使用JavaBean封装数据,便于在不同层之间传递。
- 早期学习时可以先用纯Servlet+JSP+JavaBean,掌握后再学习Spring MVC框架(它对MVC做了更优雅的实现)。
六、练习建议(强烈推荐动手做)
- 基于本篇示例,完整实现用户登录 + 注册功能。
- 增加记住我(Cookie)功能。
- 实现一个简单的商品列表展示(Servlet查询数据 → 存入request → JSP用JSTL循环展示)。
- 尝试把登录逻辑拆分成
UserDao + UserService + LoginServlet三层。
做完这些,你会深刻体会到“分层”带来的清晰感和成就感!
系列文章导航(持续更新中):
- 第16篇:JSP基础语法
- 第17篇:JSP内置对象
- 第18篇:Servlet与MVC(本文)
- 第19篇:预计将介绍 Filter过滤器 + Listener监听器(权限控制、编码过滤等)
有任何问题(如想看注册功能的完整代码、或三层架构的更多细节),欢迎在评论区留言!
继续加油!从Model1到MVC,是JavaWeb开发思维的一次重要升级,你已经走在正确的道路上!💪
下一篇文章见~ 🚀