第四十三天(JavaEE应用&ORM框架&SQL预编译&JDBC&MyBatis&Hibernate&Maven)

#Maven配置

参考:IDEA配置maven_idea 配置maven-CSDN博客

Maven 是 Java 生态系统中广泛使用的项目管理和构建自动化工具,主要功能包括:

  1. 依赖管理:自动下载、管理项目所需的第三方库(JAR 包),并处理依赖之间的版本冲突,无需手动下载和复制 JAR 文件。
  2. 标准化项目结构 :规定了统一的项目目录结构(如 src/main/java 存放源代码、src/test/java 存放测试代码等),使不同 Java 项目的结构保持一致,降低协作成本。
  3. 构建自动化 :通过配置文件(pom.xml)定义项目的构建流程,支持编译、测试、打包(生成 JAR/WAR 等)、部署等一系列操作,可一键执行完整构建过程。
  4. 项目信息管理 :在 pom.xml 中可维护项目的基本信息(如名称、版本、开发者等),并能与代码仓库、持续集成工具等集成。

根据参考文档配置好,测试是否正确配置环境

配置时要注意,mirror是否包含在mirrors里面,是否少了 ,如果少了,就会报错了,导致第三方库无法下载下来

#JDBC

参考:JavaEE-JDBC基础 - 简书

新建项目

选好版本和依赖

1、引用依赖(pom.xml)

https://mvnrepository.com/

选择第二个

选择一个版本,别选最新,不然可能不兼容,会报错

选择maven,然后将那段代码复制

将代码复制到里面,然后点击右侧的maven

打开之后点击和刷新很像的符号,然后要注意左侧是否将库下载进去了,如果没有就换一个MySQL存储库

新建一个软件包放服务器的东西,写一个接收id的值,然后写一个查询语句

2、注册数据库驱动

Class.forName("com.mysql.jdbc.Driver");

  • MySQL 5.x 版本的驱动类名是 com.mysql.jdbc.Driver
  • MySQL 8.x 版本才引入 com.mysql.cj.jdbc.Driver 这个新的驱动类名

写上注册语句,这里会报异常,直接用try ,catch 包裹就行,这里用的5.7版本的MySQL和5版本的驱动

3、建立数据库连接

String url ="jdbc:mysql://localhost:3306/phpstudy";

Connection connection=DriverManager.getConnection(url,"root","123456");

测试一下是否连接正常, 连接正常,输出乱码是因为没定义输出的格式

4、创建Statement执行SQL

Statement statement= connection.createStatement();

ResultSet resultSet = statement.executeQuery(sql);

输入id值进行测试

5、结果ResultSet进行提取

*while (rs .next()) {
resp *.getWriter().println(rs *.getString(
"id"**));
//输出名称为id的列的值
resp .getWriter().println(rs *.getString("username"*)); //输出名称为username的列的值
resp .getWriter().println(rs *.getString("password"*)); //输出名称为password的列的值
resp *.getWriter().println(*rs .getString(3)); *//输出第三列的值
}

这里查询id为2 的数据,可以正常显示

安全注入例子:

预编译:PreparedStatement

安全写法(预编译): "select * from admin where id=?"

输入的sql注入语句没有生效 ,预编译中将查询语句写死了,在后面写的sql注入语句不会执行

完整代码:

@WebServlet("/jdbc")
public class JdbcServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String id = req.getParameter("id");
// 安全的拼接 SQL 语句
// String sql = "select * from admin where id = ?";
String url ="jdbc:mysql://localhost:3306/phpstudy";
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url,"root","654321");
PreparedStatement ps = conn.prepareStatement(sql); // 创建 PreparedStatement 对象
ps.setString(1,id); // 设置第一个参数的值
ResultSet rs = ps.executeQuery(); // 执行查询
while (rs.next()) {
resp.getWriter().println(rs.getString("id")); // 输出名称为 id 的列的值
resp.getWriter().println(rs.getString("username")); // 输出名称为 username 的列的值
resp.getWriter().println(rs.getString("password")); // 输出名称为 password 的列的值
resp.getWriter().println(rs.getString(3)); // 输出第三列的值
}
} catch (ClassNotFoundException | SQLException e) {
throw new RuntimeException(e);
}
}
}

不安全写法(拼接): "select * from admin where id="+id

可以执行后面的sql注入语句,就可以开始注入了

完整代码

@WebServlet("/jdbc")*
public classJdbcServlet extendsHttpServlet {
@Override
protected void doGet*(HttpServletRequest req ,*HttpServletResponse resp ) throwsServletException , IOException {
String id =req *.getParameter("id"*);
//不安全的拼接SQL语句,容易导致SQL**注入攻击
String sql = "select * from admin where id = "+id ;
String url *=
"jdbc:mysql://localhost:3306/phpstudy"
*;

try {
Class .forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager .getConnection(url *,"root","654321"*);
Statement statement =conn .createStatement(); //创建Statement对象
ResultSet rs *=statement .executeQuery(sql ); *//执行查询
while *(rs .next()) {
resp *.getWriter().println(rs *.getString(
"id"
));
//输出名称为id的列的值
resp *.getWriter().println(rs *.getString(
"username"
*));
//输出名称为username的列的值
resp .getWriter().println(rs *.getString("password"*)); //输出名称为password的列的值
resp *.getWriter().println(*rs .getString(3)); *//*输出第三列的值
}
} catch *(*ClassNotFoundException | SQLException e ) {
throw new RuntimeException *(e );
}
}
}

#Hibernate

项目创建和jdbc 一样,就是项目名称改一下

这里勾选一下 hibernate ,等会就不用引用了 (但是测试时用这个依赖库时会报错,可能是后面的id什么对不上或者版本不兼容等)

1、引用依赖(pom.xml)

https://mvnrepository.com/

hibernate-core,mysql-connector-java

创建项目时勾选的引用库

自己写引用

2、Hibernate配置文件

src/main/resources/hibernate.cfg.xml

<?xmlversion='1.0'encoding='utf-8'?>*
<!DOCTYPE hibernate-configuration**PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" >
< hibernate-configuration*>*
< session-factory*>*
<!--*数据库连接配置 -->
< property
name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</* property*>*
< propertyname="hibernate.connection.url">jdbc:mysql://localhost:3306/phpstudy?useUnicode=true &amp;*characterEncoding=UTF-8 &amp;serverTimezone=Asia/Shanghai</ property>
< property
name="hibernate.connection.username">root</* property*>*
< propertyname="hibernate.connection.password">654321</ property*>*
<!--*数据库方言 -->
< property
name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</* property*>*
<!--显示 SQL语句 -->
< propertyname="hibernate.show_sql">true</ property*>*
<!--*自动更新数据库表结构 -->
< property
name="hibernate.hbm2ddl.auto">update</* property*>*
<!--*映射实体类 -->
< mapping
class="com.example.hibermateddemo.entity.User"/>*
</ session-factory*>*
</ hibernate-configuration*>**

3、映射实体类开发

用来存储获取数据:

src/main/java/com/example/entity/User.java

packagecom* .example .*hibermateddemo .entity ;
import javax *.persistence .*;
@Entity
@Table
(name = *"admin"
)

public class
User
{
@Id
@GeneratedValue
(strategy *=GenerationType .IDENTITY)
private *int
id* ;
private String username ;
public User*()* {}
public int getId*()* {
returnid ;
}
public void setId*(intid* ) {
this*.id =id ;
}
public String getUsername
()
{
returnusername ;
}
public void setUsername
(String username ) {
this
.username =username ;
}
@Override
public String toString
()
{
return "User{id=" +id + ", username=" *+username + *"}";
}
}

4、Hibernate工具类

用来Hibernate使用:

src/main/java/com/example/util/HibernateUtil.java

packagecom* *.*example *.*hibermateddemo .util ;
import org .*hibernate .SessionFactory ;
import org *.hibernate *.cfg .*Configuration ;
public class
HibernateUtil
{
private static *final
SessionFactory sessionFactory
;
static {
try {
Configuration configuration = new Configuration ().configure();
sessionFactory =configuration .buildSessionFactory();
} catch (Throwable ex ) {
throw new ExceptionInInitializerError *(ex );
}
}
public *static
SessionFactory
getSessionFactory
()
{
return
sessionFactory
;
}
}

5、Servlet开发接受:

src/main/java/com/example/servlet/UserServlet.java

packagecom* *.*example *.*hibermateddemo *.*servlet ;
import com *.*example *.*hibermateddemo *.*entity *.*User ;
import com *.*example *.*hibermateddemo *.*util *.*HibernateUtil ;
import jakarta *.*servlet *.*ServletException ;
import jakarta *.*servlet *.*annotation *.*WebServlet ;
import jakarta .servlet *.http *.HttpServlet ;
import jakarta .servlet *.http *.HttpServletRequest ;
import jakarta .servlet .http *.HttpServletResponse ;
import org *.hibernate *.Session ;
import org .hibernate .Query ;
import java .*io .IOException ;
import java *.io *.PrintWriter ;
import java *.util *.List ;
@WebServlet
(
"/user"
)

public class
UserServlet
extends
HttpServlet
{
@Override
protected void doGet
(HttpServletRequest request ,*HttpServletResponse response ) throwsServletException , IOException {
response *.setContentType(
"text/html;charset=UTF-8"
);

PrintWriter out *=response .getWriter();
*//获取参数(这里假设根据用户名查询)
String username *=request *.getParameter(
"username"
);

//打开 Hibernate Session
Session session *=HibernateUtil .getSessionFactory().openSession();
try {
//修改后的 HQL语句,直接拼接字符串
// String hql = "FROM User WHERE username = '" + username + "'";
String hql = *"FROM User WHERE username=:username"
;

*//创建查询对象
Query <User >query *=session *.createQuery(hql *,User .class);
query *.setParameter(
"username"
,username ); *//设置参数值
*//执行查询
List <User *>users *=query .getResultList();
*//输出查询结果
out *.println(
"<html><body>"
);

if *(users .isEmpty()) {
out *.println(
"<p>未找到匹配的用户。</p>"
);

} else {
for (User user *:users ) {
out *.println(
"<p>"
*+user + *"</p>"
);

}
}
out *.println(
"</body></html>"
);

} catch *(Exception e ) {
e .printStackTrace();
out *.println(
"<html><body><p>查询出错,请稍后重试。</p></body></html>"
);

} finally {
*//关闭 Session
session .close();
}
}
}

完整流程:

***1.*启动阶段:Hibernate 初始化
  1. 加载配置文件
    应用启动时,HibernateUtil 类被加载,其静态代码块执行:
    • 通过new Configuration().configure() 读取类路径下的hibernate.cfg.xml配置文件。
    • 配置文件中包含:数据库连接信息(URL、用户名、密码、驱动)、Hibernate 方言、实体映射等。
  2. 创建 SessionFactory
    • configuration.buildSessionFactory() 根据配置信息创建SessionFactory(Hibernate 的核心工厂类,负责管理数据库连接池和会话)。
    • SessionFactory 是重量级对象,全局唯一,后续所有数据库操作都通过它创建Session
***2.*运行阶段:处理用户请求(以 /user 请求为例)
步骤 1**:接收 HTTP** 请求
  • 前端通过*/user?username=xxx* 发送 GET 请求,被*@WebServlet("/user")* 注解的UserServlet拦截。
  • doGet 方法被调用,获取请求参数username(用户输入的查询条件)。
步骤 2**:获取 Hibernate Session**
  • 通过HibernateUtil.getSessionFactory().openSession()SessionFactory 获取Session对象。
  • Session 是 Hibernate 与数据库交互的会话对象,类似 JDBC 的Connection,用于执行 CRUD 操作。
步骤 3**:执行 HQL** 查询
  1. 构建查询语句
    • 拼接 HQL 语句:"FROM User WHERE username = '" + username + "'" (根据用户名查询User实体)。
  2. 创建查询对象
    • 通过session.createQuery(hql, User.class) 创建Query 对象,指定返回结果为User类型。
  3. 执行查询
    • 调用query.getResultList() 执行查询,Hibernate 将 HQL 转换为对应数据库的 SQL(如SELECT * FROM user WHERE username = 'xxx'),并发送到数据库。
    • 数据库返回结果后,Hibernate 将结果集映射为User对象列表。
步骤 4**:响应查询结果**
  • 通过
  • HTML 响应:
    • 若查询结果为空,显示 "未找到匹配的用户"。
    • 若有结果,遍历User列表并输出用户信息。
步骤 5**:释放资源**
  • finally 块中调用session.close() 关闭Session,释放数据库连接资源。

安全注入例子: (修改UserServlet.java 中的语句实现效果)

安全写法:String hql = "FROM User WHERE username=:username";

输入正确的值是可以正常查询

用sqlmap 跑一下看是否存在 SQL 注入漏洞 用这个写法是不存在sql注入漏洞的

命令 : python sqlmap.py -u "http://localhost:8080/Hibermated_demo_war_exploded/user?username=xiaodi"

不安全写法:String hql = "FROM User WHERE username='"+username+"'";

这里用正确的username查询一下数据库的数据看一下

用sqlmap 跑一下看是否存在 SQL 注入漏洞 用这个写法是存在sql注入漏洞的

#MyBatis

1、引用依赖(pom.xml)

mybatis,mysql-connector-java

在pom.xml 中的 里面加入下面代码

< dependency>*
< groupId*>org.mybatis</* groupId*>*
< artifactId*>mybatis</* artifactId*>*
< version*>3.5.13</* version*>*
</ dependency*>*
< dependency*>*
< groupId*>mysql</* groupId*>*
< artifactId*>mysql-connector-java</* artifactId*>*
< version*>5.1.17</* version*>*
</ dependency*>**

要确保引入的库加载到了外部库中,否则是没有成功的

2、MyBatis配置文件

src/main/resources/mybatis-config.xml 文件路径

<?xmlversion="1.0"encoding="UTF-8"* ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd" >
< configuration*>*
< 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/phpstudy?serverTimezone=UTC"/>*
< property*name=
"username"value="root"/>*
< property*name=
"password"value="123456"/>*
</ dataSource*>*
</ environment*>*
</ environments*>*
< mappers*>*
< mapper*resource=
"AdminMapper.xml"/>*
</ mappers*>*
</ configuration*>

3、AdminMapper.xml创建

src/main/resources/AdminMapper.xml 文件路径

<?xmlversion="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=
"com.example.jdbcdemo43.mapper.AdminMapper">*
< select*id=
"selectAdminById"resultType="com.example.jdbcdemo43.model.Admin">*
SELECT * FROM admin WHERE id = #{id}
</ select*>*
</ mapper*>

4、创建数据实体类

com/example/mybatisdemo43/model/Admin.java

packagecom* .example *.mybatisdemo .*model ;
public class
Admin
{
private *int
*id
;
private String username ;
private String password ;
// Getters and Setters
public int getId*()* {
returnid ;
}
public void setId*(intid* ) {
this*.id =id ;
}
public String getUsername
()
{
returnusername ;
}
public void setUsername
(String username ) {
this
.username =username ;
}
public String getPassword
()
{
returnpassword ;
}
public void setPassword
(String password ) {
this
.*password =password ;
}
@Override
public String toString
()
{
return "Admin{" +
"id=" *+id +
", username='" +username + '\'' +
", password='" *+password + '\'' +
*'}'
;

}
}

5、创建mapper实体类

com/example/mybatisdemo43/mapper/AdminMapper.java

packagecom* *.*example *.mybatisdemo .mapper ;
import com *.example *.mybatisdemo *.model *.Admin ;
import org .apache *.ibatis .annotations .*Param ;
public interface
AdminMapper
{
Admin selectAdminById
(
@Param
(
"name"
)
String name );
}

6、创建servlet接受类

com/example/mybatisdemo43/servlet/SelectServlet.java

packagecom* *.*example *.*mybatisdemo *.*servlet ;
import com *.*example *.*mybatisdemo *.*mapper *.*AdminMapper ;
import com *.*example *.*mybatisdemo *.*model *.*Admin ;
import jakarta *.*servlet *.*ServletException ;
import jakarta *.*servlet *.*annotation *.*WebServlet ;
import jakarta *.*servlet *.*http *.*HttpServlet ;
import jakarta *.*servlet *.*http *.*HttpServletRequest ;
import jakarta *.*servlet *.*http *.*HttpServletResponse ;
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 java .*io .IOException ;
import java *.io *.InputStream ;
@WebServlet
(name = *"sql"
,value = *"/sql"
)

public class
SelectServlet
extends
HttpServlet
{
@Override
protected void doGet
(HttpServletRequest req ,*HttpServletResponse resp ) throwsServletException , IOException {
String name *=req *.getParameter(
"name"
);

if *(name == null *||name .isEmpty()) {
resp *.getWriter().write(
"none"
);

return
;

}
//加载 MyBatis配置文件
String resource = *"mybatis-config.xml"
;

InputStream inputStream = Resources .getResourceAsStream(resource );
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder
().build(inputStream );
*//获取 SqlSession
try *(SqlSession session =sqlSessionFactory .openSession()) {
//获取 Mapper接口
AdminMapper mapper *=session *.getMapper(AdminMapper .class);
//执行查询
Admin admin =mapper .selectAdminById(name );
*//输出结果
if (admin != null) {
resp *.getWriter().println(
"ID: "
*+admin .getId());
resp *.getWriter().println(
"用户名: "
*+admin .getUsername());
resp *.getWriter().println(
"密码: "
*+admin .getPassword());
} else {
resp *.getWriter().write(
"111111no"
);

}
} catch *(Exception e ) {
e .printStackTrace();
resp *.getWriter().write(
"shibai"
);

}
}
}

目录结构:

流程:

  1. mybatis-config.xml
    (最先被加载)程序启动时,MyBatis 首先读取该核心配置文件,解析数据源、事务管理和 Mapper 路径等信息,为后续创建SqlSessionFactory做准备。
  2. SelectServlet.java (核心执行代码)
    (接收请求后执行)当 Servlet 收到请求(doGet 方法被调用)时:
    • 先加载mybatis-config.xml 创建SqlSessionFactory
    • 再通过SqlSessionFactory 获取SqlSession
      这是运行时触发查询的起点。
  3. AdminMapper.java
    (获取代理对象时使用)通过*SqlSession.getMapper(AdminMapper.class)*获取接口的动态代理对象,此时 MyBatis 会关联接口与对应的映射文件。
  4. AdminMapper.xml
    (执行 SQL 时使用)调用AdminMapper.selectAdminById() 方法时,MyBatis 通过namespace +id找到该文件中定义的 SQL 语句,替换参数后执行查询。
  5. Admin.java
    (结果返回时使用)SQL 执行完成后,MyBatis 根据resultType 配置,将数据库返回的结果集自动映射为Admin对象,最终在 Servlet 中被处理并响应。
数据流向链路

请求触发 → SelectServlet加载mybatis-config.xml → 创建SqlSessionFactory → 获取SqlSession → 获取AdminMapper代理对象 → 调用方法匹配AdminMapper.xml中的SQL → 执行SQL查询 → 结果映射为Admin对象 → 响应结果

安全注入例子:

1、安全写法: select * from admin where id = #{id}

拿sqlmap跑一下看看是否有能注入 ,这里是没有的

2、不安全写法:select * from admin where id = ${id}

在AdminMapper.xml 写的查询语句是$

拿sqlmap跑一下看看是否有能注入 ,这里是有的

命令: (要进到sqlmap目录里面打开cmd输入下面命令)

python sqlmap.py -u "http://localhost:8080/mybatis_demo_war_exploded/sql?id=1"

#Spring JPA

由于涉及到开发框架,后续讲到,安全基本和Hibernate相似

相关推荐
仙俊红4 小时前
Spring Boot `@Configuration` 与 `@Component` 笔记
java·spring boot·笔记
Ysn07196 小时前
pytorch_grad_cam 库学习笔记—— Ablation-CAM 算法的基类 AblationCAM 和 AblationLayer
pytorch·笔记·学习
霜绛7 小时前
Unity笔记(七)——四元数、延迟函数、协同程序
笔记·学习·unity·游戏引擎
风和日丽 随波逐流7 小时前
java18学习笔记
笔记·学习·java18
HAORChain10 小时前
Hyperledger Fabric官方中文教程-改进笔记(十七)-编写第一个链码
笔记·区块链·fabric
喜欢你,还有大家11 小时前
Linux笔记10——shell编程基础-4
linux·运维·服务器·笔记
神齐的小马11 小时前
计算机网络学习笔记
笔记·学习·计算机网络
胡萝卜3.012 小时前
数据结构初阶:详解单链表(一)
数据结构·笔记·学习·单链表
YJlio13 小时前
第17章|PowerShell 安全警报——高分学习笔记(运维实战向)
笔记·学习·安全