从零开始学习JavaWeb-6 - 详解
以下是 JavaWeb 学习之旅 Day 6 的深度笔记,聚焦 MVC 分层架构设计与实战落地,结合企业级开发规范与性能优化策略,助你构建高内聚、低耦合的 Web 应用。
一、MVC 分层架构核心思想
1. 核心目标与价值
- 解决痛点:传统 Servlet 混杂业务逻辑、数据操作和页面渲染,导致代码臃肿难维护。
- 分层职责:
层级 职责 技术实现 Model(模型层) 数据处理与业务逻辑 JavaBean + Service + DAO View(视图层) 数据展示与用户交互 JSP/Thymeleaf + EL + JSTL Controller(控制层) 协调模型与视图,处理请求路由 Servlet/Spring MVC
✅ 核心优势:
- 高内聚:每层专注单一职责(如 DAO 只操作数据库)。
- 低耦合:层间通过接口交互,修改业务逻辑不影响视图。
二、分层架构详细实现
1. 项目结构规范
src/
├── main/
│ ├── java/
│ │ ├── com.example.dao # 数据访问层(接口 + 实现)
│ │ ├── com.example.service # 业务逻辑层(事务控制)
│ │ ├── com.example.web # Servlet 控制器
│ │ └── com.example.model # 实体类(POJO)
│ ├── webapp/
│ │ ├── WEB-INF/views/ # JSP 文件
│ │ └── resources/ # CSS/JS 静态资源
└── test/ # 单元测试
2. 各层协作流程
graph TB
A[浏览器请求] --> B[Controller]
B --> C[调用 Service]
C --> D[调用 DAO]
D --> E[操作数据库]
E --> D
D --> C
C --> B
B --> F[返回 Model 数据]
F --> G[View 渲染 HTML]
G --> A
关键交互代码:
- Controller 层(路由 + 数据传递)
@WebServlet("/user/list")
public class UserServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
// 调用 Service 获取数据
UserService service = new UserService();
List users = service.getAllUsers();
// 数据传递到 View
req.setAttribute("userList", users);
req.getRequestDispatcher("/WEB-INF/views/userList.jsp").forward(req, resp);
}
}
- Service 层(事务控制)
public class UserService {
private UserDao userDao = new UserDaoImpl();
// 添加事务控制
public void addUser(User user) {
try {
Connection conn = DataSourceUtil.getConnection();
conn.setAutoCommit(false); // 关闭自动提交
userDao.insert(user);
// 其他业务操作...
conn.commit();
} catch (SQLException e) {
conn.rollback();
}
}
}
- DAO 层(数据库操作)
public class UserDaoImpl implements UserDao {
@Override
public List findAll() {
String sql = "SELECT * FROM users";
try (PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
List users = new ArrayList<>();
while (rs.next()) {
users.add(new User(rs.getInt("id"), rs.getString("name")));
}
return users;
}
}
}
三、企业级优化实践
1. 架构升级策略
痛点 | 解决方案 | 技术实现 |
---|---|---|
硬编码 SQL 难维护 | ORM 框架 | MyBatis/Hibernate(注解或 XML) |
层间耦合度高 | 依赖注入(DI) | Spring IoC 容器 |
视图技术侵入性强 | 前后端分离 | RESTful API + Vue.js/React |
事务手动控制风险大 | 声明式事务 | Spring @Transactional |
2. Spring MVC 进阶示例
@Controller
@RequestMapping("/product")
public class ProductController {
@Autowired // 依赖注入
private ProductService productService;
@GetMapping("/{id}")
public String getProduct(@PathVariable int id, Model model) {
Product product = productService.getById(id);
model.addAttribute("product", product);
return "product/detail"; // 视图解析为 /WEB-INF/views/product/detail.jsp
}
@PostMapping("/create")
@Transactional // 声明式事务
public String createProduct(@Valid Product product, BindingResult result) {
if (result.hasErrors()) return "product/form";
productService.save(product);
return "redirect:/product/list";
}
}
四、避坑指南与性能优化
1. 常见分层误区
- 误区 1:在 Controller 中写 SQL 操作
修正:SQL 只允许出现在 DAO 层。 - 误区 2:实体类(Model)直接暴露给前端
修正:使用 DTO 屏蔽敏感字段(如UserDTO
隐藏password
)。 - 误区 3:事务控制在 Controller 层
修正:事务边界应限定在 Service 层。
2. 性能优化表
场景 | 优化方案 | 性能提升 |
---|---|---|
高频查询 | 添加 Redis 缓存 | 响应时间 ↓ 80% |
批量插入 | JDBC 批处理 + 连接池 | 吞吐量 ↑ 5x |
复杂页面渲染 | 静态化 + CDN 加速 | QPS ↑ 300% |
数据库连接瓶颈 | HikariCP 调优(maxPoolSize=20 ) | 并发能力 ↑ 2x |
连接池配置参考:
HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/db"); config.setMaximumPoolSize(20); // 连接数 = CPU核心数 * 2 + 1 config.setConnectionTimeout(3000);
五、综合实战:商品管理系统
1. 功能模块设计
- 商品列表展示(分页)
- 商品添加(表单校验)
- 商品删除(事务控制)
- 商品搜索(AJAX 异步加载)
2. 核心代码结构
// Model: Product.java
public class Product {
private Integer id;
private String name;
private BigDecimal price;
// Getters & Setters
}
// DAO: ProductDao.java
public interface ProductDao {
List getByPage(int start, int size);
}
// Service: ProductService.java
public class ProductService {
@Autowired
private ProductDao productDao;
public PageInfo getProducts(int pageNum) {
PageHelper.startPage(pageNum, 10); // MyBatis 分页插件
return new PageInfo<>(productDao.getAll());
}
}
// Controller: ProductController.java
@Controller
public class ProductController {
@GetMapping("/products")
public String list(@RequestParam(defaultValue="1") int page, Model model) {
model.addAttribute("pageInfo", productService.getProducts(page));
return "product/list";
}
}
3. 视图层关键技术(JSP + JSTL)
${prod.name}
上一页
当前第 ${pageInfo.pageNum} 页
六、总结与核心对比
架构方式 | 开发效率 | 维护成本 | 适用场景 |
---|---|---|---|
原生 Servlet 混合式 | 快(初期) | 高(后期) | 小型工具类应用 |
MVC 分层 | 中(设计期) | 低 | 中大型业务系统 |
Spring MVC | 高(框架支持) | 极低 | 企业级分布式系统 |
学习进度:
✅ Day 1~3: Servlet/JSP/EL/JSTL 基础
✅ Day 4~5: JDBC/连接池/事务
✅ **Day 6: MVC 分层架构**
➡️ Day 7: Spring 整合与框架进阶
“MVC 是架构设计的起跑线,分层是解耦的艺术。” 掌握今日内容,后续学习框架如水到渠成。