0. 认识JavaWeb

Note

先导内容: Java

在系统性地掌握了 ​JavaSE​(标准版)的核心语法、面向对象思想及基础API,并理解了 ​JavaEE​(企业版)的多层架构、组件模型与分布式概念后,我们站在了一个新的起点。此时,我们脑海中应自然而然地浮现出一个根本性问题:​如何利用我们已经掌握的Java技术,去构建一个能够通过浏览器访问、与用户交互、并处理复杂业务逻辑的动态应用程序?​​ 换言之,如何让我们的Java代码不再仅仅运行于本地命令行或桌面程序,而是能够在互联网的浪潮中提供服务?这个问题的答案,正是我们接下来要深入探索的领域——JavaWeb。

JavaWeb技术提供了一整套完整的解决方案来回答上述问题。它的核心思想是基于HTTP协议,接收来自客户端(通常是浏览器)的请求,由服务器端的Java程序处理业务逻辑,生成动态内容,并最终返回给客户端渲染展示。这个过程涉及几个关键层面的思考与解决:​如何接收和解析HTTP请求?如何保持用户的状态(如登录信息)?如何与数据库进行高效、安全的交互?如何将处理结果组织成HTML页面?​​ 这些在JavaSE和JavaEE中未曾深入触及的、属于Web领域的特定问题,都将在JavaWeb技术栈中找到答案。例如,Servlet作为请求的“调度中心”,JSP/Servlet用于动态页面渲染,Cookie/Session用于状态管理,JDBC用于数据库连接,它们共同构成了JavaWeb应用的骨架。

1. 前端基础

相关内容

2. Ajax

概述

Ajax(Asynchronous JavaScript And XML)​是一种在不刷新整个页面的情况下,与服务器交换数据并局部更新页面的技术。它的出现让Web应用从”点击-等待-刷新”的模式,升级到了更流畅的”实时交互”体验。虽然名字里带XML,但现代开发中绝大多数情况使用JSON作为数据交换格式。

2.1. 核心原理: XMLHttpRequest

Ajax的核心是浏览器内置的XMLHttpRequest对象,它充当了JavaScript与服务器之间的”信使”。

工作流程

  1. 浏览器创建 XMLHttpRequest 对象
  2. 通过 open() 指定请求方式(GET/POST)和URL
  3. 通过 send() 发送请求
  4. 监听 onreadystatechange 事件,在 readyState==4 且 status==200 时接收响应数据
  5. 用JavaScript操作DOM,将数据渲染到页面

示例: 原生Ajax发送GET请求

// 1. 创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 2. 配置请求
xhr.open("GET", "/servlet/queryUser?name=zhangsan", true);
// 3. 发送请求
xhr.send();
// 4. 监听响应
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        // 5. 处理响应数据
        var data = JSON.parse(xhr.responseText);
        document.getElementById("result").innerHTML = data.name;
    }
};

2.2. Axios

原生Ajax写法较为繁琐,现代开发中常用Axios库来简化请求。

示例: Axios发送POST请求

axios.post("/servlet/login", {
    username: "admin",
    password: "123456"
}).then(function(response) {
    if (response.data.success) {
        window.location.href = "/index.html";
    } else {
        alert("登录失败");
    }
}).catch(function(error) {
    console.log("请求出错:", error);
});

2.3. Ajax与JavaWeb Servlet配合

在JavaWeb中,Ajax请求也由Servlet接收和处理,唯一区别是Servlet返回的不是HTML页面,而是JSON字符串。

示例: Servlet处理Ajax请求并返回JSON

@WebServlet("/servlet/queryUser")
public class QueryUserServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        resp.setContentType("application/json;charset=UTF-8");
        String name = req.getParameter("name");
        PrintWriter out = resp.getWriter();
        out.write("{\"name\":\"" + name + "\", \"age\":20}");
    }
}

总结

Ajax的核心价值在于异步交互与局部刷新,它让前后端通过JSON数据”对话”,前端负责渲染,后端专注业务逻辑。在JavaWeb中,Servlet接收Ajax请求后返回JSON即可完成交互。


3. Maven

概述

Maven是Java生态中最主流的项目构建与依赖管理工具。它解决了传统Java项目中的两大痛点:jar包手动管理混乱(依赖地狱)和项目结构不统一。通过一个核心配置文件pom.xml,Maven可以自动下载依赖、编译代码、运行测试、打包部署。

3.1. Maven核心概念

坐标(Coordinate)

Maven用三个字段唯一定位一个jar包,称为坐标:groupId(组织名)、artifactId(项目名)、version(版本号)。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

仓库(Repository)

Maven有三类仓库:本地仓库(本机缓存)、私服(公司内部)、中央仓库(Maven官方)。依赖查找顺序为:本地仓库 → 私服 → 中央仓库。

生命周期(Lifecycle)

Maven定义了三套生命周期,最常用的是default生命周期,包含以下核心阶段:

阶段作用
compile编译源代码
test运行单元测试
package打包(jar/war)
install安装到本地仓库
clean清理target目录

3.2. pom.xml 核心结构

示例: 一个标准JavaWeb项目的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <!-- 项目坐标 -->
    <groupId>com.example</groupId>
    <artifactId>my-webapp</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
 
    <dependencies>
        <!-- Servlet依赖 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <!-- Tomcat插件,用于运行和调试 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>8080</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3.3. Maven标准目录结构

项目根目录/
├── src/
│   ├── main/
│   │   ├── java/          ← Java源代码
│   │   ├── resources/     ← 配置文件
│   │   └── webapp/        ← Web资源(HTML/CSS/JS/WEB-INF)
│   └── test/
│       ├── java/          ← 测试代码
│       └── resources/     ← 测试配置
├── target/                ← 编译输出(自动生成)
└── pom.xml                ← Maven核心配置

3.4. 常用命令

命令作用
mvn clean清理target目录
mvn compile编译源代码
mvn test运行测试
mvn package打包为war/jar
mvn install安装到本地仓库
mvn tomcat7:run使用Tomcat插件运行项目

总结

Maven的核心价值在于约定优于配置——只要你按标准目录结构组织代码,Maven就能自动完成编译、测试、打包。掌握坐标、依赖、生命周期这三个概念,配合几个常用命令,就能高效管理JavaWeb项目。


4. Web核心原理

概述

Web核心原理是JavaWeb中最关键的部分。它解释了从浏览器输入URL到看到页面,背后发生了什么。核心角色是Servlet——运行在服务器端的Java程序,负责接收请求、调用业务逻辑、返回响应。围绕Servlet,还有HTTP协议、Cookie/Session状态管理、Filter过滤器、Listener监听器等机制,共同构成完整的Web应用骨架。

4.1. HTTP协议

HTTP(HyperText Transfer Protocol)是浏览器与服务器之间的通信规则,基于”请求-响应”模型,每次交互都由客户端发起。

4.1.1. 请求格式

HTTP请求结构

一个HTTP请求由四部分组成:请求行、请求头、空行、请求体(GET请求没有请求体)。

POST /servlet/login HTTP/1.1              ← 请求行: 方法 URL 协议版本
Host: www.example.com                      ← 请求头: 键值对
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
                                           ← 空行(分隔符)
username=admin&password=123456             ← 请求体(POST参数)

4.1.2. 响应格式

HTTP响应结构

HTTP响应也由四部分组成:状态行、响应头、空行、响应体。

HTTP/1.1 200 OK                            ← 状态行: 协议版本 状态码 描述
Content-Type: text/html;charset=UTF-8       ← 响应头
Set-Cookie: JSESSIONID=ABC123
                                           ← 空行
<html><body>登录成功</body></html>           ← 响应体(页面内容)

常见状态码

状态码含义典型场景
200成功请求正常处理
302重定向登录后跳转到首页
404未找到URL不存在
405方法不允许GET访问了只支持POST的接口
500服务器内部错误后端代码抛异常

4.1.3. GET 与 POST 的区别

说明

对比维度GETPOST
参数位置URL后面(查询字符串)请求体中
安全性参数暴露在URL中相对安全(不显示在URL)
数据量有限(URL长度限制约2KB)理论上无限制
缓存可被浏览器缓存不会被缓存
用途查询数据提交数据(表单、登录等)

4.2. Servlet 核心

Servlet是JavaWeb的核心调度器,运行在Servlet容器(如Tomcat)中。每个Servlet负责处理特定的URL请求。

4.2.1. Servlet生命周期

说明

Servlet的生命周期由容器管理,分为三个阶段:初始化 → 服务 → 销毁。

  1. init():Servlet被首次访问时调用一次,用于初始化资源
  2. service():每次请求到来时调用,根据请求方法分发到doGet()或doPost()
  3. destroy():容器关闭或Servlet被卸载时调用一次,用于释放资源

关键点:Servlet是单例多线程的——容器中每种Servlet只有一个实例,但多个请求由不同线程调用同一个实例的service()方法。

示例: 一个完整的Servlet

@WebServlet("/servlet/hello")
public class HelloServlet extends HttpServlet {
 
    // 初始化: Servlet首次被访问时执行
    public void init() throws ServletException {
        System.out.println("HelloServlet 初始化完成");
    }
 
    // 处理GET请求
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        // 设置响应内容类型和编码
        resp.setContentType("text/html;charset=UTF-8");
        // 获取请求参数
        String name = req.getParameter("name");
        // 向浏览器输出响应
        PrintWriter out = resp.getWriter();
        out.write("<h1>你好, " + (name != null ? name : "世界") + "!</h1>");
    }
 
    // 处理POST请求
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        // POST请求通常转交给doGet统一处理(或反之)
        doGet(req, resp);
    }
 
    // 销毁: 容器关闭时执行
    public void destroy() {
        System.out.println("HelloServlet 被销毁");
    }
}

4.2.2. HttpServletRequest 与 HttpServletResponse

说明

这两个对象是Servlet与HTTP交互的”双手”:

  • HttpServletRequest:代表请求,用于获取客户端传来的所有信息
  • HttpServletResponse:代表响应,用于向客户端发送数据

HttpServletRequest 常用方法

// 获取请求参数
String name = request.getParameter("name");        // 单个值
String[] hobbies = request.getParameterValues("hobby"); // 多值(复选框)
 
// 获取请求头信息
String userAgent = request.getHeader("User-Agent");
String cookie = request.getHeader("Cookie");
 
// 获取请求方式
String method = request.getMethod();  // "GET" 或 "POST"
 
// 设置请求编码(解决POST乱码)
request.setCharacterEncoding("UTF-8");
 
// 域对象: 在一次请求范围内共享数据
request.setAttribute("user", userObj);   // 存
Object user = request.getAttribute("user"); // 取
 
// 获取Session对象
HttpSession session = request.getSession();

HttpServletResponse 常用方法

// 设置响应头
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
 
// 获取输出流
PrintWriter out = response.getWriter();  // 字符流(用于文本)
// ServletOutputStream out = response.getOutputStream(); // 字节流(用于文件下载)
 
// 重定向
response.sendRedirect("/index.html");

4.2.3. Servlet的两种配置方式

说明

方式一: 注解配置(Servlet 3.0+,推荐)。直接在类上使用@WebServlet注解。

@WebServlet("/servlet/demo")                // 精确匹配
@WebServlet("*.do")                         // 后缀匹配
@WebServlet(urlPatterns = {"/a", "/b"})    // 多个URL映射

说明

方式二: web.xml配置(传统方式)。在WEB-INF/web.xml中声明。

<servlet>
    <servlet-name>DemoServlet</servlet-name>
    <servlet-class>com.example.DemoServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>DemoServlet</servlet-name>
    <url-pattern>/servlet/demo</url-pattern>
</servlet-mapping>

4.3. 请求转发与重定向

在Servlet处理请求后,经常需要跳转到另一个资源(另一个Servlet或JSP页面),有转发和重定向两种方式。

转发(Forward)

服务器内部行为,客户端无感知。URL不变,请求对象在跳转前后是同一个。

request.getRequestDispatcher("/success.jsp").forward(request, response);
  • URL不变(仍然显示原始请求地址)
  • 只能跳转到当前项目内部资源
  • 前后共享同一个request对象(可以传递数据)
  • 浏览器发出一次请求

重定向(Redirect)

浏览器行为,服务器告诉浏览器”你去访问另一个地址”。URL会变成新地址。

response.sendRedirect("/success.jsp");
  • URL变为新地址
  • 可以跳转到任意URL(项目内或外部)
  • 前后是两个不同的request对象(不能共享request数据)
  • 浏览器发出两次请求(302 + 新请求)

选择建议

场景推荐方式
需要携带数据到下一个页面转发(Forward)
避免表单重复提交(PRG模式)重定向(Redirect)
跳转到外部网站重定向(Redirect)
访问WEB-INF下的受保护资源转发(Forward)

HTTP协议本身是无状态的,服务器无法区分两个请求是否来自同一用户。Cookie和Session就是为了保持状态而生的两种机制。

说明

Cookie:存储在浏览器端的小数据片段(大小限制约4KB)。每次请求会自动携带到服务器。常用于记住登录状态、用户偏好等。

Session:存储在服务器端的用户会话数据。每个用户有一个唯一的SessionID,通过Cookie传递给浏览器。服务器根据SessionID找到对应用户的数据。

4.4.1. Cookie的使用

示例: 服务端创建Cookie

// 创建Cookie
Cookie cookie = new Cookie("username", "zhangsan");
cookie.setMaxAge(60 * 60 * 24);  // 有效期: 24小时(秒)
cookie.setPath("/");              // Cookie作用的路径
response.addCookie(cookie);       // 写入浏览器

示例: 服务端读取Cookie

Cookie[] cookies = request.getCookies();
if (cookies != null) {
    for (Cookie cookie : cookies) {
        if ("username".equals(cookie.getName())) {
            String value = cookie.getValue();
            System.out.println("用户名: " + value);
        }
    }
}

4.4.2. Session的使用

说明

Session的实现原理:浏览器首次访问时,服务器创建Session并生成唯一的JSESSIONID,通过Cookie写入浏览器。后续请求携带该Cookie,服务器即可找到对应Session。

示例: Session存取数据

// 获取Session(没有则创建)
HttpSession session = request.getSession();
 
// 存入数据
session.setAttribute("user", userObj);
 
// 取出数据
User user = (User) session.getAttribute("user");
 
// 设置过期时间(秒)
session.setMaxInactiveInterval(30 * 60);  // 30分钟
 
// 手动销毁Session(用于退出登录)
session.invalidate();

Cookie vs Session 对比

对比维度CookieSession
存储位置浏览器端服务器端
安全性较低(可被篡改/窃取)较高(数据在服务器)
容量限制约4KB无限制(受内存影响)
性能影响不占服务器资源大量用户时消耗服务器内存
典型用途记住用户名、购物车登录用户信息、权限数据

4.5. JSP(Java Server Pages)

概述

JSP是一种在HTML中嵌入Java代码的技术,本质上是Servlet的一种”简写形式”。JSP文件在首次访问时会被Tomcat编译成Servlet然后执行。它解决了在Servlet中用out.write()拼接大段HTML的痛点。

4.5.1. JSP三大指令

page指令 — 页面配置

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List, com.example.User" %>
<%@ page isELIgnored="false" %>

include指令 — 静态包含(合并后再编译)

<%@ include file="/common/header.jsp" %>

taglib指令 — 引入标签库

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

4.5.2. JSP九大内置对象

说明

JSP中可以直接使用以下9个对象,无需声明:

对象名类型说明
requestHttpServletRequest请求对象
responseHttpServletResponse响应对象
sessionHttpSession会话对象
applicationServletContext全局上下文(整个应用共享)
outJspWriter输出流
pageObject当前页面的this引用
pageContextPageContext页面上下文(可获取其他8个对象)
configServletConfigServlet配置对象
exceptionThrowable异常对象(仅错误页面可用)

4.5.3. EL表达式 与 JSTL

重要

JSP中应避免直接写Java代码(Scriptlet),改用EL表达式和JSTL标签库来保持页面整洁,实现视图与逻辑分离。

EL表达式(Expression Language)

用于替代<%= %>,简化取值操作:

<!-- 传统写法 -->
<%=((User)request.getAttribute("user")).getName()%>
 
<!-- EL表达式写法 -->
${user.name}

JSTL常用标签

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
<!-- 条件判断 -->
<c:if test="${user.vip}">
    <span>VIP会员</span>
</c:if>
 
<!-- 多条件 -->
<c:choose>
    <c:when test="${score >= 90}">优秀</c:when>
    <c:when test="${score >= 60}">及格</c:when>
    <c:otherwise>不及格</c:otherwise>
</c:choose>
 
<!-- 循环遍历 -->
<c:forEach items="${userList}" var="user">
    <tr><td>${user.name}</td><td>${user.age}</td></tr>
</c:forEach>

4.6. Filter(过滤器)

概述

Filter是拦截请求和响应的组件。它在请求到达Servlet之前和响应返回客户端之前执行,形成一条”过滤链”。典型用途:字符编码设置、登录验证、权限检查、敏感词过滤。

示例: 编码过滤器

@WebFilter("/*")  // 拦截所有请求
public class EncodingFilter implements Filter {
 
    public void init(FilterConfig config) throws ServletException {
        System.out.println("EncodingFilter 初始化");
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp, 
            FilterChain chain) throws IOException, ServletException {
        // 预处理: 设置请求和响应的编码
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        // 放行: 让请求继续走下一个Filter或Servlet
        chain.doFilter(req, resp);
    }
 
    public void destroy() {
        System.out.println("EncodingFilter 销毁");
    }
}

示例: 登录验证过滤器

@WebFilter("/admin/*")  // 只拦截管理后台
public class LoginFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, 
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        // 获取Session中的登录信息
        Object user = request.getSession().getAttribute("user");
        if (user != null) {
            chain.doFilter(req, resp);  // 已登录, 放行
        } else {
            response.sendRedirect("/login.html");  // 未登录, 跳转登录页
        }
    }
}

Filter执行顺序

多个Filter按照类名字母序依次执行。请求方向是 Filter1 → Filter2 → Servlet,响应方向是 Servlet → Filter2 → Filter1。

4.7. Listener(监听器)

概述

Listener用于监听Web应用中的事件,当特定事件发生时自动触发回调。常用监听器有三类:ServletContext监听、Session监听、Request监听。

示例: 统计在线人数

@WebListener
public class OnlineCountListener implements HttpSessionListener {
 
    private int onlineCount = 0;
 
    // Session创建时触发(用户上线)
    public void sessionCreated(HttpSessionEvent se) {
        onlineCount++;
        se.getSession().getServletContext()
            .setAttribute("onlineCount", onlineCount);
    }
 
    // Session销毁时触发(用户下线/超时/主动退出)
    public void sessionDestroyed(HttpSessionEvent se) {
        onlineCount--;
        se.getSession().getServletContext()
            .setAttribute("onlineCount", onlineCount);
    }
}

总结

Web核心原理是JavaWeb的”灵魂”所在。掌握HTTP协议、Servlet的生命周期、Cookie/Session的状态管理、Filter的拦截机制,就掌握了构建Web应用的核心能力。JSP在实际开发中逐渐被前后端分离架构取代,但理解其原理有助于阅读和维护老项目。


5. 数据库集成

相关内容

MySQL

JavaWeb通过JDBC(Java Database Connectivity)与数据库交互。JDBC是Java提供的标准API,定义了连接数据库、执行SQL、处理结果的统一接口,各数据库厂商提供对应的驱动实现。

5.1. JDBC核心步骤

说明

使用JDBC操作数据库的标准流程:加载驱动 → 获取连接 → 执行SQL → 处理结果 → 释放资源。

示例: JDBC查询数据库

import java.sql.*;
 
public class JdbcDemo {
    public static void main(String[] args) {
        // JDBC四大配置参数
        String url = "jdbc:mysql://localhost:3306/db_name?useSSL=false&serverTimezone=Asia/Shanghai";
        String username = "root";
        String password = "123456";
        
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
 
        try {
            // 1. 加载驱动(MySQL 8.0+会自动注册, 此行可省略)
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 获取数据库连接
            conn = DriverManager.getConnection(url, username, password);
            // 3. 准备SQL(使用PreparedStatement防止SQL注入)
            String sql = "SELECT id, name, age FROM users WHERE age > ?";
            ps = conn.prepareStatement(sql);
            ps.setInt(1, 18);  // 设置?占位符的值
            // 4. 执行查询
            rs = ps.executeQuery();
            // 5. 处理结果集
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                System.out.println(id + " - " + name + " - " + age);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 6. 释放资源(按创建顺序的逆序)
            try { if (rs != null) rs.close(); } catch (SQLException e) { }
            try { if (ps != null) ps.close(); } catch (SQLException e) { }
            try { if (conn != null) conn.close(); } catch (SQLException e) { }
        }
    }
}

5.2. PreparedStatement vs Statement

重要

永远使用PreparedStatement,避免使用Statement,原因有二:

  1. 防SQL注入:PreparedStatement对参数进行预编译和转义,黑客无法通过恶意输入修改SQL逻辑
  2. 性能更优:SQL模板预编译后可重复使用,批量操作时效率更高

SQL注入演示

// 危险写法(Statement): 用户输入 " ' OR '1'='1 " 会绕过密码验证
String sql = "SELECT * FROM users WHERE name='" + name + "' AND pwd='" + pwd + "'";
 
// 安全写法(PreparedStatement): 参数自动转义,杜绝注入
String sql = "SELECT * FROM users WHERE name=? AND pwd=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, name);
ps.setString(2, pwd);

5.3. 数据库连接池

概述

每次请求都创建和销毁数据库连接开销巨大。连接池预先创建一批连接放入”池”中,需要时取出,用完归还,大幅提升性能。常用实现:Druid(阿里)、HikariCP(Spring Boot默认)。

总结

JDBC是JavaWeb与数据库交互的基础。掌握PreparedStatement杜绝SQL注入、使用连接池优化性能,是实际开发中的基本要求。后续学习MyBatis、JPA等ORM框架时,它们底层仍基于JDBC。