src/
├── com.javaweb.bean.User # 實體類
├── com.javaweb.dao
│ ├── DBDao.java # 通用數據訪問基類(反射+元數據映射)
│ └── UserDao.java # 業務 DAO
├── com.javaweb.action
│ ├── Servlet.java # 頁面跳轉 Servlet
│ └── ServletSql.java # CRUD 業務 Servlet
└── com.javaweb.utils
├── DBUtlis.java # 連接獲取/關閉
├── PropertiesUtil.java # 配置文件讀取
├── DateUtlis.java # 日期格式化
└── StringUtlis.java # UUID/駝峰轉換
WebContent/
├── index.jsp # 首頁/添加表單
├── delete.jsp # 刪除表單
├── update.jsp # 修改表單
└── queryAll.jsp # 列表展示
WEB-INF/
├── web.xml
└── config/db.properties
public class DBDao<T> {
// 查詢:返回 List<T>
public <T> List<T> findAll(String sql, Class<T> clazz, List<Object> params) {
// 1. 獲取連接、PreparedStatement、ResultSet
// 2. ResultSetMetaData 獲取列名/列數
// 3. 遍歷 ResultSet,clazz.newInstance() 創建實例
// 4. 列名轉駝峰 (camelName) 匹配字段,反射 setAccessible(true) 注入值
// 5. 日期類型轉換 (DateUtlis)
// 6. 關閉資源,返回列表
}
// 增刪改:返回影響行數
public int execute(String sql, List<Object> params) {
// PreparedStatement 設置參數 -> executeUpdate()
}
}
public class UserDao {
private DBDao dao = new DBDao();
public List<User> findAll() {
String sql = "SELECT id, username, password FROM user";
return dao.findAll(sql, User.class, null);
}
public int add(User u) {
String sql = "INSERT INTO user(id, username, password) VALUES(?,?,?)";
return dao.execute(sql, Arrays.asList(u.getId(), u.getUsername(), u.getPassword()));
}
public int delete(User u) {
return dao.execute("DELETE FROM user WHERE id=?", Collections.singletonList(u.getId()));
}
public int update(User u) {
StringBuilder sql = new StringBuilder("UPDATE user SET ");
List<Object> params = new ArrayList<>();
if (StringUtils.isNoneBlank(u.getUsername())) { sql.append("username=?, "); params.add(u.getUsername()); }
if (StringUtils.isNoneBlank(u.getPassword())) { sql.append("password=?, "); params.add(u.getPassword()); }
sql.deleteCharAt(sql.length()-1).append(" WHERE id=?"); // 去掉尾隨逗號
params.add(u.getId());
return dao.execute(sql.toString(), params);
}
}
public class ServletSql extends HttpServlet {
private UserDao dao = new UserDao();
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String op = req.getParameter("op");
if ("queryAll".equalsIgnoreCase(op)) queryAll(req, resp);
else if ("add".equalsIgnoreCase(op)) add(req, resp);
else if ("delete".equalsIgnoreCase(op)) delete(req, resp);
else if ("update".equalsIgnoreCase(op)) update(req, resp);
}
private void queryAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("list", dao.findAll());
req.getRequestDispatcher("/queryAll.jsp").forward(req, resp); // 轉發保持請求屬性
}
private void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (dao.add(init(req, resp)) > 0) queryAll(req, resp); else resp.sendRedirect("index.jsp");
}
// delete/update 同理:操作成功後重新 queryAll 刷新列表
private User init(HttpServletRequest req, HttpServletResponse resp) { ... 從參數構建 User 對象 ... }
}
DBUtlis:靜態塊讀取 db.properties,提供 getConnection()、多重 close() 重載、事務控制 rollback()/setAutoCommit()PropertiesUtil:Class.getResourceAsStream("/config/db.properties") 載入類路徑配置StringUtlis.camelName():USER_NAME → userName,解決數據庫下劃線與 Java 駝峰映射DateUtlis:java.sql.Date ↔ String 互轉<!-- index.jsp 添加表單 -->
<form action="<%=basePath%>/servletSql?op=add" method="post">
<input name="id"> <input name="name"> <input name="password">
<input type="submit" value="保存">
</form>
<!-- queryAll.jsp 列表 -->
<table>
<c:forEach items="${list}" var="u">
<tr><td>${u.id}</td><td>${u.username}</td><td>${u.password}</td>
<td><a href="update.jsp?id=${u.id}">修改</a> <a href="delete.jsp?id=${u.id}">刪除</a></td></tr>
</c:forEach>
</table>
# db.properties
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/javaweb?useSSL=false
db.userName=root
db.password=123456789
https://localhost:8080/項目名/

JdbcTemplate 簡化連接/語句/結果集管理,RowMapper 替代反射映射@Transactional 聲明式替代手動 try-catchDriverManager本例展示「手工構建 ORM 雛形」全過程,理解其原理後,框架學習將事半功倍。