一、servlet
Servlet 是 Java 处理 HTTP 请求的规范。浏览器发请求 → Servlet 接收处理 → 返回响应。
1. 生命周期
scss
加载类
实例化(new Servlet)
init() //初始化,只执行一次
service() //每次请求都执行
└── doGet()+ doPost()
destroy() //销毁,只执行一次
2.案例
Java
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.println("<h1>Hello Servlet</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String username = req.getParameter("username");
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println("你好," + username);
}
}
二、jdbc
JDBC (Java Database Connectivity)是 Java 访问数据库的标准 API。
1.执行步骤
Java
// 1. 加载驱动(JDBC 4.0+ 可省略,驱动 jar 在 classpath 即可)
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获取连接
String url = "jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=Asia/Shanghai";
Connection conn = DriverManager.getConnection(url, "root", "密码");
// 3. 编写 SQL
String sql = "SELECT id, username, email FROM user WHERE id = ?";
// 4. 创建 PreparedStatement
PreparedStatement ps = conn.prepareStatement(sql);
ps.setLong(1, 1L); // 第 1 个 ? 设为 1
// 5. 执行查询
ResultSet rs = ps.executeQuery();
// 6. 处理结果
while (rs.next()) {
long id = rs.getLong("id");
String username = rs.getString("username");
String email = rs.getString("email");
System.out.println(id + ", " + username + ", " + email);
}
// 7. 关闭资源(顺序:后开先关)
rs.close();
ps.close();
conn.close();
2.案例
如下可以看到JDBC操作数据库需要编写sql代码,结果需手动映射到Java对象。
Java
import java.sql.*;
public class JdbcDemo {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=Asia/Shanghai";
String sql = "SELECT id, username, email, age FROM user WHERE id = ?";
try (Connection conn = DriverManager.getConnection(url, "root", "");
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setLong(1, 1L);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
System.out.println("id=" + rs.getLong("id"));
System.out.println("username=" + rs.getString("username"));
System.out.println("email=" + rs.getString("email"));
System.out.println("age=" + rs.getInt("age"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
三、maven
maven是Java的构建与依赖管理工具,类似前端的webpack工具
1.pom.xml
pom.xml是maven最重要的配置文件,其内部定义了项目配置与依赖管理配置。
xml
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<!-- 本项目坐标 -->
<groupId>org.example</groupId>
<artifactId>mybatis-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 全局属性 -->
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 依赖列表 -->
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
</dependencies>
</project>
2.目录结构
css
mybatis-demo/
├── pom.xml Maven 配置文件
├── src/
│ ├── main/
│ │ ├── java/Java 源码
│ │ └── resources/ 配置文件(xml、yml)
│ └── test/
│ ├── java/测试代码
│ └── resources/
└── target/ 编译输出(自动生成,勿提交 Git)
四、mybatis
mybatis解决了jdbc操作数据库时编写大量样板间代码的缺陷。把数据库连接,增删改查等操作全部配置在xml文件。
1.结构组成
css
src/main/java/org/example/
├── entity/ ← 实体类(和数据库表对应)
│ ├── User.java
│ ├── Department.java
│ └── Order.java
├── mapper/ ← Mapper 接口(定义数据库操作方法)
│ └── UserMapper.java
└── Main.java ← 程序入口(测试用)
src/main/resources/
├── mybatis-config.xml ← 全局配置
├── mapper/
│ └── UserMapper.xml ← SQL 映射文件

- 1.mybatis-config.xml:保存mybatis基础配置与mapper映射
Java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 开启驼峰命名自动映射:create_time → createTime -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<package name="org.example.entity"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- XML 放在 resources/mapper/ 下,需显式注册 -->
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
- 2.实体类(entity目录)
实体类定义了其数据库对象的映射表,例如user表格包含id,name,age字段,那我们的实体对象必须定义这几个属性,并添加get、set、重写equals方法。
Java
package org.example.entity;
import java.time.LocalDateTime;
import java.util.List;
public class User {
private Long id;
private String username;
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "xxx"
}
}
- 3.xml文件(SQL映射)
UserMapper.xml保存了User表的所有数据库操作,其中namespace属性定义其xml文件的路径,id标记了唯一的数据库操作语句。
Java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mapper.UserMapper">
<select id="findAll" resultType="User">
SELECT * FROM user WHERE 1=1
</select>
</mapper>
- 4.mapper目录
mapper目录下定义操作数据库的接口方法,其方法名和xml数据库操作的id一一映射。
java
package org.example.mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.example.entity.User;
import java.util.List;
public interface UserMapper {
List<User> findAll();
}
- 5.入口配置
Java
package org.example;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.example.mapper.UserMapper;
import org.example.entity.User;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
// 1. 加载配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 2. 构建 SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
// 3. 获取 SqlSession
try (SqlSession session = factory.openSession();
Scanner scanner = new Scanner(System.in)) {
// 4. 获取 Mapper 代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
// 5. 执行查询
List<User> users = mapper.findAll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2. XML文件
2.1 增删改查
mybatis为数据库操作添加了4种标签,增删改查。
sql
<select id="findById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (username, password, email, age)
VALUES (#{username}, #{password}, #{email}, #{age})
</insert>
2.2 参数传递
标签的值传递通过#{xx}进行传递。
- 简单的id查询
sql
User findById(Long id);
<select id="findById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
- 多个参数操作
大于等于2个参数传递时,必须使用@Param("xxx")进行标记,param里面的名称与xml参数名一致
less
List<User> findByUsernameAndAge(@Param("username1") String username, @Param("age1") Integer age);
<select id="findByUsernameAndAge" resultType="User">
SELECT * FROM user WHERE username = #{username1} AND age = #{age1}
</select>
- 参数解构
如果接口中的参数是实例对象,那xml的标签可以自动读取到对象的属性
sql
List<User> findByUsernameAndAge(User user);
<select id="findByUsernameAndAge" resultType="User">
SELECT * FROM user WHERE username = #{username} AND age = #{age}
</select>
2.3 注解
mybatis的数据库查询有两种,1种是上面的接口与xml分离,第二种就接口中直接定义注解实现。实际项目中简单sql查询用注解,复杂sql用分离
Java
package org.example.mapper;
import org.apache.ibatis.annotations.*;
import org.example.entity.User;
import java.util.List;
public interface UserAnnotationMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(Long id);
@Select("SELECT * FROM user")
List<User> findAll();
@Insert("INSERT INTO user (username, password, email, age) " +
"VALUES (#{username}, #{password}, #{email}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
@Update("UPDATE user SET email = #{email}, age = #{age} WHERE id = #{id}")
int update(User user);
@Delete("DELETE FROM user WHERE id = #{id}")
int deleteById(Long id);
}
2.4 动态SQL
在操作sql时,如果需要针对不同的条件进行增删改查,当条件数量很多时,需要定义大量重复的条件xml和方法,为此引入了动态sql。
2.4.1 if标签
如下表示查询username,age、email等多种情况。
Java
// xml
<select id="findByCondition" resultType="User">
SELECT * FROM user
WHERE 1=1
<if test="username != null and username != ''">
AND username = #{username}
</if>
<if test="age != null">
AND age = #{age}
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
</select>
//接口
List<User> findByCombine(User user);
//main
List<User> users = mapper.findByCombine(user);
2.4.2 Where
where标签省略了上面的where 1=1的操作
bash
<select id="findByCondition" resultType="User">
SELECT * FROM user
<where>
<if test="username != null and username != ''">
AND username = #{username}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
2.4.3 choose
choose标签类似java的switch表达式
sql
<select id="findByAgeRange" resultType="User">
SELECT * FROM user
<where>
<choose>
<when test="ageRange == 'young'">
AND age < 30
</when>
<when test="ageRange == 'middle'">
AND age BETWEEN 30 AND 50
</when>
<otherwise>
AND age > 50
</otherwise>
</choose>
</where>
</select>
2.4.4 foreach
foreach标签用于批量操作。
sql
<select id="findByIds" resultType="User">
SELECT * FROM user WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
//接口中定义
List<User> findByIds(@Param("ids") List<Long> ids);
2.4.5 trim
trim标签用于在动态 SQL 片段外面加前缀/后缀,并去掉多余的符号(通常是逗号)。
| 属性 | 含义 | 例子 |
|---|---|---|
| prefix | 在最前面加什么 | ( → 变成 (name, description |
| suffix | 在最后面加什么 | ) → 变成 (name, description) |
| prefixOverrides | 去掉开头多余内容 | 如 AND、OR |
| suffixOverrides | 去掉结尾多余内容 | 如 , |
如下是一段插入的sql表达式 insert into category (name,description) values (xx,xx)
Java
INSERT INTO category
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name != null">name,</if>
<if test="description != null">description,</if>
</trim>
<trim prefix="VALUES (" suffix=")" suffixOverrides=",">
<if test="name != null">#{name},</if>
<if test="description != null">#{description},</if>
</trim>
2.5 结果映射
resultType还能用于sql简单查询,数据库的表格字段与对象的属性完全一致。但复杂场景或者多表关联时就必须引入结果映射resultMap了。
2.5.1 基础结构
其中property表示User类的属性,column表示映射sql查询时用到的变量。
ini
<resultMap id="UserResultMap" type="User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="email" column="email"/>
<result property="age" column="age"/>
<result property="createTime" column="create_time"/>
</resultMap>
<select id="findById" resultMap="UserResultMap">
SELECT id, username, email, age, create_time FROM user WHERE id = #{id}
</select>
2.6 关联查询
关联查询即数据库中的多表操作。需要使用association或者collection标签关联。如果是1对1关系使用association,1对多关系用collection。
案例是在user属性有个order\[\]数组,也就是1对多存储
ini
<resultMap id="UserWithOrdersMap" type="User">
<id property="id" column="user_id"/>
<result property="username" column="username"/>
<collection property="orders" ofType="Order">
<id property="id" column="order_id"/>
<result property="amount" column="amount"/>
<result property="status" column="status"/>
</collection>
</resultMap>
<select id="findUserWithOrders" resultMap="UserWithOrdersMap">
SELECT u.id AS user_id, u.username,
o.id AS order_id, o.amount, o.status
FROM user u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.id = #{id}
</select>
案例是user属性有个部门对象,也就是1对1关系
ini
<resultMap id="UserWithDeptMap" type="User">
<id property="id" column="user_id"/>
<result property="username" column="username"/>
<association property="department" javaType="Department">
<id property="id" column="dept_id"/>
<result property="name" column="dept_name"/>
</association>
</resultMap>
<select id="findUserWithDept" resultMap="UserWithDeptMap">
SELECT u.id AS user_id, u.username,
d.id AS dept_id, d.name AS dept_name
FROM user u
LEFT JOIN department d ON u.dept_id = d.id
WHERE u.id = #{id}
</select>