Servlet 3.0 + JSP 用户管理 CRUD 实战:5个核心类与3个JSP页面构建完整流程
·
Servlet 3.0 + JSP 用户管理 CRUD 实战:从零构建企业级开发思维
在Java Web开发领域,掌握Servlet和JSP技术栈是每位开发者的必修课。本文将带您从实战角度出发,通过一个完整的用户管理模块开发过程,深入理解MVC架构的精髓。不同于简单的代码堆砌,我们将重点关注模块化设计、数据流向控制和可维护性实践。
1. 项目架构设计与环境准备
1.1 技术选型与项目结构
现代Java Web开发虽然涌现了Spring Boot等框架,但理解原生Servlet/JSP的工作机制仍是核心基础。我们的技术栈选择:
- Servlet 3.0 :支持注解配置,简化web.xml管理
- JSP 2.2 :结合EL表达式和JSTL标签库
- MySQL 5.7+ :关系型数据库标准选择
- Maven :项目依赖管理工具
标准项目目录结构应遵循Maven约定:
src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ ├── model/ # 数据模型
│ │ ├── dao/ # 数据访问层
│ │ ├── service/ # 业务逻辑层
│ │ └── web/ # 控制器层
│ ├── resources/ # 配置文件
│ └── webapp/
│ ├── WEB-INF/
│ │ └── views/ # JSP视图文件
│ └── static/ # 静态资源
1.2 数据库设计与初始化
用户表设计应考虑基础字段和扩展性:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`email` varchar(100) DEFAULT NULL,
`phone` varchar(20) DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`status` tinyint(1) DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
提示:密码字段应存储加密后的值,推荐使用BCrypt等强哈希算法
2. 核心组件实现
2.1 领域模型构建
采用Java Bean规范定义用户实体:
package com.example.model;
import java.time.LocalDateTime;
public class User {
private Integer id;
private String username;
private String password;
private String email;
private String phone;
private LocalDateTime createTime;
private LocalDateTime updateTime;
private Boolean status;
// 省略getter/setter和构造方法
}
2.2 数据访问层实现
DAO层采用JDBC模板模式,避免重复代码:
public class UserDao {
private final DataSource dataSource;
public UserDao(DataSource dataSource) {
this.dataSource = dataSource;
}
public User findById(int id) throws SQLException {
String sql = "SELECT * FROM users WHERE id = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, id);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
return mapUser(rs);
}
return null;
}
}
private User mapUser(ResultSet rs) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
// 其他字段映射...
return user;
}
}
2.3 服务层设计
服务层处理业务逻辑和事务管理:
public class UserService {
private final UserDao userDao;
public UserService(UserDao userDao) {
this.userDao = userDao;
}
public User getUserById(int id) throws BusinessException {
try {
User user = userDao.findById(id);
if (user == null) {
throw new BusinessException("用户不存在");
}
return user;
} catch (SQLException e) {
throw new BusinessException("数据库查询失败", e);
}
}
}
3. 控制器与视图开发
3.1 Servlet控制器实现
使用Servlet 3.0注解简化配置:
@WebServlet("/users/*")
public class UserServlet extends HttpServlet {
private UserService userService;
@Override
public void init() throws ServletException {
DataSource dataSource = (DataSource) getServletContext()
.getAttribute("dataSource");
userService = new UserService(new UserDao(dataSource));
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String pathInfo = req.getPathInfo();
if (pathInfo == null || pathInfo.equals("/")) {
listUsers(req, resp);
} else if (pathInfo.equals("/new")) {
showCreateForm(req, resp);
} else {
String[] parts = pathInfo.split("/");
if (parts.length == 2) {
showUser(Integer.parseInt(parts[1]), req, resp);
}
}
}
private void listUsers(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 获取用户列表逻辑
req.getRequestDispatcher("/WEB-INF/views/users/list.jsp")
.forward(req, resp);
}
}
3.2 JSP视图开发
采用JSTL和EL表达式简化页面逻辑:
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>用户列表</title>
</head>
<body>
<h2>用户管理</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>邮箱</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${users}" var="user">
<tr>
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.email}</td>
<td>
<a href="<c:url value='/users/${user.id}'/>">查看</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
4. 完整CRUD流程实现
4.1 创建用户流程
表单提交到Servlet的POST处理:
@WebServlet("/users")
public class UserServlet extends HttpServlet {
// ...其他方法
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
User user = new User();
user.setUsername(req.getParameter("username"));
user.setPassword(encrypt(req.getParameter("password")));
// 其他字段处理...
try {
userService.createUser(user);
resp.sendRedirect(req.getContextPath() + "/users");
} catch (BusinessException e) {
req.setAttribute("error", e.getMessage());
req.getRequestDispatcher("/WEB-INF/views/users/new.jsp")
.forward(req, resp);
}
}
}
4.2 更新与删除实现
采用RESTful风格设计URL:
@WebServlet("/users/*")
public class UserServlet extends HttpServlet {
// ...其他方法
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 解析ID
String[] parts = req.getPathInfo().split("/");
int userId = Integer.parseInt(parts[1]);
// 更新逻辑...
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 解析ID并删除
String[] parts = req.getPathInfo().split("/");
int userId = Integer.parseInt(parts[1]);
userService.deleteUser(userId);
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
}
5. 高级特性与优化
5.1 分页查询实现
服务层添加分页支持:
public class UserService {
public Page<User> listUsers(int page, int size) {
// 计算偏移量
int offset = (page - 1) * size;
List<User> users = userDao.findByPage(offset, size);
int total = userDao.count();
return new Page<>(users, page, size, total);
}
}
5.2 表单验证与错误处理
前端结合后端验证:
<c:if test="${not empty errors}">
<div class="alert alert-danger">
<ul>
<c:forEach items="${errors}" var="error">
<li>${error}</li>
</c:forEach>
</ul>
</div>
</c:if>
5.3 日志与异常处理
配置全局异常处理器:
@WebServlet("/errorHandler")
public class ErrorHandlerServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
Throwable throwable = (Throwable) req.getAttribute("javax.servlet.error.exception");
logger.error("请求处理异常", throwable);
// 根据异常类型返回不同错误页面
if (throwable instanceof BusinessException) {
req.getRequestDispatcher("/WEB-INF/views/error/business.jsp")
.forward(req, resp);
} else {
req.getRequestDispatcher("/WEB-INF/views/error/system.jsp")
.forward(req, resp);
}
}
}
6. 项目部署与测试
6.1 Tomcat配置优化
server.xml连接池配置:
<Context>
<Resource name="jdbc/UserDB"
auth="Container"
type="javax.sql.DataSource"
maxTotal="100"
maxIdle="30"
maxWaitMillis="10000"
username="dbuser"
password="dbpass"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/userdb"/>
</Context>
6.2 集成测试策略
使用HttpClient进行端到端测试:
public class UserSystemTest {
@Test
public void testCreateUser() throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost("http://localhost:8080/users");
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("username", "testuser"));
// 其他参数...
post.setEntity(new UrlEncodedFormEntity(params));
try (CloseableHttpResponse response = client.execute(post)) {
assertEquals(302, response.getStatusLine().getStatusCode());
// 验证重定向位置
}
}
}
通过这个完整的开发流程,您不仅掌握了Servlet/JSP的技术实现,更重要的是理解了企业级Web应用的分层架构和最佳实践。这种模块化、分层的设计思想,正是现代Java Web框架(如Spring MVC)的基础。
更多推荐



所有评论(0)