第四十三天(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相似

相关推荐
QT 小鲜肉1 小时前
【孙子兵法之上篇】001. 孙子兵法·计篇
笔记·读书·孙子兵法
星轨初途2 小时前
数据结构排序算法详解(5)——非比较函数:计数排序(鸽巢原理)及排序算法复杂度和稳定性分析
c语言·开发语言·数据结构·经验分享·笔记·算法·排序算法
QT 小鲜肉2 小时前
【孙子兵法之上篇】001. 孙子兵法·计篇深度解析与现代应用
笔记·读书·孙子兵法
love530love5 小时前
【笔记】ComfUI RIFEInterpolation 节点缺失问题(cupy CUDA 安装)解决方案
人工智能·windows·笔记·python·插件·comfyui
愚戏师5 小时前
MySQL 数据导出
数据库·笔记·mysql
摇滚侠5 小时前
2025最新 SpringCloud 教程,教程简介,笔记01
笔记·spring cloud
RickyWasYoung7 小时前
【笔记】智能汽车、电动汽车政策文件
笔记·汽车
love530love10 小时前
【保姆级教程】Windows + Podman 从零部署 Duix-Avatar 数字人项目
人工智能·windows·笔记·python·数字人·podman·duix-avatar
草莓熊Lotso11 小时前
《算法闯关指南:动态规划算法--斐波拉契数列模型》--01.第N个泰波拉契数,02.三步问题
开发语言·c++·经验分享·笔记·其他·算法·动态规划
FFF团团员90918 小时前
树莓派学习笔记3:LED和Button
笔记·学习