Java入门级教程11——导出数据库表到CSV文件,数据库查询的进一步学习,Java Web查询
目录
4.3 在HBuilder X中实现前端查询(数据是发送给浏览器)
1.实现导出t_emp表数据到CSV文件
步骤一:数据库准备
-- 创建t_emps表 --
CREATE TABLE t_emps(
eid INT PRIMARY KEY auto_increment, -- 员工的编号
ename VARCHAR(20) NOT NULL, -- 员工的姓名
epwd CHAR(8) NOT NULL, -- 员工的密码
ebirthday datetime, -- 员工的出生年月,不设计年龄字段,会造成字段冗余
esalary DOUBLE NOT NULL, -- 员工的工资
eaddress VARCHAR(100), -- 员工的地址
estate INT NOT NULL -- 员工的状态
)
-- 删除t_emps表 --
DROP TABLE t_emps
-- 插入数据 --
INSERT INTO t_emps(ename,epwd,ebirthday,esalary,eaddress,estate)
VALUES('张三','11111','2000-05-28',90000.56,'南京',1);
INSERT INTO t_emps(ename,epwd,ebirthday,esalary,eaddress,estate)
VALUES('李四','22222','2004-06-15',88000.69,'盐城',1);
INSERT INTO t_emps(ename,epwd,ebirthday,esalary,eaddress,estate)
VALUES('李老八','22222','1996-12-30',5600,'无锡',1);
INSERT INTO t_emps(ename,epwd,ebirthday,esalary,eaddress,estate)
VALUES('赵二','22222','1996-12-30',5800,'无锡',0);
-- 查询表 --
SELECT * FROM t_emps
实现效果:

步骤二:若是在eclipse新建Maven项目,需要在pom.xml文件中添加依赖,按Ctrl+S保存并加载
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.24</version>
</dependency>
步骤三:创建测试类用于实现导出t_emp表数据到CSV文件
注意:数据库名称,用户名和密码需要修改为自己的
package com.hy.chapter1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.core.util.CharsetUtil;
public class Test {
// 声明一个连接对象
Connection conn;
public void connDB() {
try {
// 1. 加载MySQL JDBC驱动(MySQL 8.0+ 使用 com.mysql.cj.jdbc.Driver)
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 建立数据库连接(URL、用户名、密码)
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql2025", // 数据库地址:本地3306端口的mysql2025库
"root", // 数据库用户名
"yourpaaword" // 数据库密码
);
} catch (ClassNotFoundException e) {
e.printStackTrace(); // 驱动类未找到异常(通常是驱动包缺失)
} catch (SQLException e) {
e.printStackTrace(); // 数据库连接异常(如URL、用户名、密码错误)
}
}
public void exportCsv(String tableName) {
// 定义SQL:sql1查总记录数,sql2查所有记录
String sql1 = "select count(*) from " + tableName; // 查总记录数(用于初始化数组行数)
String sql2 = "select * from " + tableName; // 查所有记录(含字段值)
String[][] datas = null;
try {
// 步骤1:执行sql1,获取总记录数row
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
ResultSet rs1 = pstmt1.executeQuery(); // 执行查询,返回结果集
int row = 0;
while (rs1.next()) {
row = rs1.getInt(1); // 获取count(*)的结果(第一列),即总记录数
}
// 步骤2:执行sql2,获取所有记录和字段信息
PreparedStatement pstmt2 = conn.prepareStatement(sql2);
ResultSet rs2 = pstmt2.executeQuery(); // 执行查询,返回所有记录
// Java8 Stream 对数据的一个流式处理
// 从功耗的角度,我们对数据库动作了2次。
// 步骤3:获取字段名(表头)
ResultSetMetaData rsmd = rs2.getMetaData(); // 获取结果集元数据(含字段信息)
int column = rsmd.getColumnCount(); // 总列数(字段数量)
String[] heads = new String[column]; // 存储表头(字段名)
for (int i = 0; i < column; i++) {
// 获取第i+1列的字段名(元数据列索引从1开始)
heads[i] = rsmd.getColumnName(i + 1);
System.out.println(heads[i]); // 打印字段名(调试用)
}
// 步骤4:存储所有记录到二维数组datas
datas = new String[row][column]; // 初始化数组(行数=总记录数,列数=总字段数)
int count = 0; // 记录当前行数(数组索引)
while (rs2.next()) { // 遍历每条记录
for (int i = 0; i < column; i++) {
// 获取第i+1列的字段值(转为字符串),存入数组
datas[count][i] = rs2.getString(i + 1);
}
count++; // 行数+1,准备存储下一条记录
}
// 步骤5:创建CSV写入器(指定文件路径和编码)
CsvWriter cwriter = CsvUtil.getWriter("d:/emps.csv", CharsetUtil.CHARSET_GBK);
// 二维数组,数组中的数组,{{},{},{}};
// 步骤6:写入表头(字段名数组)
cwriter.writeHeaderLine(heads);
// 步骤7:写入所有记录(遍历二维数组,逐行写入)
for (int k = 0; k < datas.length; k++) {
cwriter.write(datas[k]); // 写入一行数据
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) { // 关闭数据库连接(避免资源泄漏)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Test t = new Test();
t.connDB(); // 建立数据库连接
t.exportCsv("t_emps"); // 导出t_emps表数据到CSV
}
}
运行结果:
eid
ename
epwd
ebirthday
esalary
eaddress
estate
步骤四:在设置的文件路径中查看emp.csv文件
注:若ebirthday显示为“###”,适当调整列宽即可显示成功

2.实现数据库模糊查询
2.1 概括
基于 JDBC 实现 MySQL 数据库的查询操作,核心功能是通过模糊查询(like)获取指定表的符合条件数据,并以二维 Object 数组返回结果。
2.2 核心类功能
- Connection:数据库连接对象,是所有数据库操作的基础。
- PreparedStatement:预编译 SQL 执行对象(虽被使用,但未发挥参数化优势,下文会分析)。
- ResultSet:存储 SQL 查询结果的结果集。
- ResultSetMetaData:获取结果集的 “元数据”(如列数、列名),用于动态处理结果结构。
2.3 具体实现过程
package com.hy.chapter1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
public class Dao {
Connection conn;
public Dao() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql2025",
"root",
"yourpassword"
);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void closeDB() {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public Object[][] queryDatas() {
return null;
}
public Object[][] queryDatas(String columnsName, Object params, String tabelName) {
String sql1 = "select count(*) from " + tabelName + " where " + columnsName + " like '" + params + "%" + "'";
String sql2 = "select * from " + tabelName + " where " + columnsName + " like '" + params + "%" + "'";
System.out.println("数据库查询语句sql1:" + sql1);
System.out.println("数据库查询语句sql2:" + sql2);
Object[][] datas = null;
try {
PreparedStatement pstmt = this.conn.prepareStatement(sql1);
ResultSet rs1 = pstmt.executeQuery();
int row = 0;
while (rs1.next()) {
row = rs1.getInt(1);
System.out.println("sql1查询结果count的值:" + row);
}
// 把这个查询的句柄对象的游标(结果集),设置为可滚动
// PreparedStatement pstmt2 = this.conn.prepareStatement(sql2,
// ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
PreparedStatement pstmt2 = this.conn.prepareStatement(sql2);
ResultSet rs2 = pstmt2.executeQuery();
int column = 0;
ResultSetMetaData rsmd = rs2.getMetaData();
column = rsmd.getColumnCount();
System.out.println("sql2查询结果数据的列数:" + column);
datas = new Object[row][column];
int count = 0;
// 当遍历完成(rs2.next()返回 false)后,游标停在 “末尾”,此时若想再次读取数据(需重新遍历),
// 直接调用 rs2.next() 会一直返回 false,必须通过 beforeFirst() 重置游标。
// 前提:游标已经设置为可滚动
// rs2.beforeFirst(); // 回到第一行
while (rs2.next()) {
for (int i = 0; i < column; i++) {
datas[count][i] = rs2.getObject(i + 1);
}
count++; // 移动到下一行
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
this.closeDB();
}
return datas;
}
public static void main(String[] args) {
Dao dao = new Dao();
Object[][] datas = dao.queryDatas("ename", "李", "t_emps");
System.out.println("输出sql2数据库查询结果:");
for (int i = 0; i < datas.length; i++) {
for (int j = 0; j < datas[i].length; j++) {
System.out.print(datas[i][j] + ",");
}
System.out.println();
}
}
}
输出结果:
数据库查询语句sql1:select count(*) from t_emps where ename like '李%'
数据库查询语句sql2:select * from t_emps where ename like '李%'
sql1查询结果count数量:2
sql2查询结果数据的列数:7
输出sql2数据库查询结果:
2,李四,22222,2004-06-15T00:00,88000.69,盐城,1,
3,李老八,22222,1996-12-30T00:00,5600.0,无锡,1,
2.4 拓展知识点
2.4.1 设置游标可滚动并回到初始位置
① 当遍历完成(rs2.next()返回 false)后,游标停在 “末尾”,此时若想再次读取数据(重新遍历),直接调用 rs2.next() 会一直返回 false,必须通过 beforeFirst() 重置游标。
rs2.beforeFirst(); // 回到第一行
② 但前提是:所查询句柄对象的游标已经设置为可滚动
PreparedStatement pstmt2 = this.conn.prepareStatement(sql2,
ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
③ 应用:修正因遍历获取“sql2查询结果数据的列数”,导致游标停在“末尾”位置
// 将所查询句柄对象的游标(结果集),设置为可滚动
PreparedStatement pstmt2 = this.conn.prepareStatement(sql2, ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet rs2 = pstmt2.executeQuery();
int column = 0;
// 当遍历完成(rs2.next()返回 false)后,游标停在 “末尾”,此时若想再次读取数据(需重新遍历),
// 直接调用 rs2.next() 会一直返回 false,必须通过 beforeFirst() 重置游标。
// 前提:游标已经设置为可滚动
// 用可滚动游标修正原因:这里不需要遍历结果集,可以直接获取ResultSetMetaData
while (rs2.next()) {
ResultSetMetaData rsmd = rs2.getMetaData();
column = rsmd.getColumnCount();
}
System.out.println("sql2查询结果数据的列数:" + column);
2.4.2 构造函数中传递其他参数,并输出sql语句
package com.hy.chapter1;
public class Dao1 {
// 构造函数传入不同参数,打印查询语句
public Object[][] queryDatas(String tableName, String column) {
String sql = "select count(*), " + column + " from " + tableName + " group by " + column;
System.out.println("数据库查询语句sql:" + sql);
return null;
}
public Object[][] queryDatas(String columnsName, Object[] params, String tabelName) {
String sql = "select * from " + tabelName + " where " + columnsName + " BETWEEN ";
for (int i = 0; i < params.length; i++) {
if (i == params.length - 1) {
sql += params[i];
} else {
sql += params[i] + " and ";
}
}
System.out.println("数据库查询语句sql:" + sql);
return null;
}
public static void main(String[] args) {
Dao1 dao1 = new Dao1();
Object[][] data1 = dao1.queryDatas("esalary", new Object[] { 6000, 9000 }, "t_emps");
Object[][] data2 = dao1.queryDatas("t_emps", "eaddress");
}
}
输出结果:
数据库查询语句sql:select * from t_emps where esalary BETWEEN 6000 and 9000
数据库查询语句sql:select count(*), eaddress from t_emps group by eaddress
3.实现分组查询以及最高值查询
3.1 查询数据库表中信息
package com.hy.chapter6;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
public class Dao {
Connection conn;
public Dao() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql2025",
"root",
"yourpassword"
);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void closeDB() {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public Object[][] queryDatas(String tableName) {
Object[][] datas = null;
try {
// 第一个SQL:查询表的记录总数(用于初始化二维数组的行数)
String sql = "select count(*) from " + tableName;
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
int count = 0;
while (rs.next()) {
count = rs.getInt(1);
}
System.out.println("sql1查询结果count的值:" + count);
// 第二个SQL:查询表中所有记录
String sql1 = "select * from " + tableName;
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
ResultSet rs1 = pstmt1.executeQuery();
// 获取结果集元数据(用于获取列数)
ResultSetMetaData rsmd = rs1.getMetaData();
int columns = rsmd.getColumnCount();
System.out.println("sql2查询结果数据的列数:" + columns);
// 初始化二维数组
datas = new Object[count][columns];
// 把数据赋值给二维数组
int row = 0;
while (rs1.next()) {
for (int i = 0; i < columns; i++) {
datas[row][i] = rs1.getObject(i + 1);
}
row++;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return datas;
}
public static void main(String[] args) {
Dao dao1 = new Dao();
Object[][] data1 = dao1.queryDatas("t_emps");
for (int i = 0; i < data1.length; i++) {
for (int j = 0; j < data1[i].length; j++) {
System.out.print(data1[i][j] + ",");
}
System.out.println();
}
}
}
输出结果:
sql1查询结果count的值:4
sql2查询结果数据的列数:7
1,张三,11111,2000-05-28T00:00,90000.56,南京,1,
2,李四,22222,2004-06-15T00:00,88000.69,盐城,1,
3,李老八,22222,1996-12-30T00:00,5600.0,无锡,1,
4,赵二,22222,1996-12-30T00:00,5800.0,无锡,0,
3.2 分组查询
对地址(eaddress)进行分组,并统计每组的数量,打印每组数量和对应地址名
package com.hy.chapter6;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
public class Dao {
Connection conn;
public Dao() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql2025",
"root",
"yourpassword"
);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void closeDB() {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public Object[][] queryDatas(String tableName, String column) {
// 获取名为"column"的列,得到去重后的这一列
String sql1 = "select DISTINCT " + column + " from t_emps";
// 对列名为"column"中的值进行分组,并统计每组的数量,命名为cn
// 查询得到两列,第一列名为cn,第二列名为"column"
String sql2 = "select count(*) cn, " + column + " from " + tableName + " group by " + column;
Object[][] datas = null;
try {
// 执行sql1得到结果
PreparedStatement pstmt = this.conn.prepareStatement(sql1);
ResultSet rs1 = pstmt.executeQuery();
// 遍历rs1,统计去重后的行数
int row = 0;
while (rs1.next()) {
row++;
}
// 执行sql2得到结果
PreparedStatement pstmt2 = this.conn.prepareStatement(sql2);
ResultSet rs2 = pstmt2.executeQuery();
// 获取结果列数
int columnCount = 0;
ResultSetMetaData rsmd = rs2.getMetaData();
columnCount = rsmd.getColumnCount();
// 初始化二维数组
datas = new Object[row][columnCount];
int count = 0;
// 遍历rs2,将每组统计数据存入数组
while (rs2.next()) {
for (int i = 0; i < columnCount; i++) {
datas[count][i] = rs2.getObject(i + 1);
}
count++;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
this.closeDB();
}
return datas;
}
public static void main(String[] args) {
// 对地址(eaddress)进行分组,并统计每组的数量,打印每组数量和对应地址名
Dao dao1 = new Dao();
// 调用查询方法:按 t_emps 表的 eaddress 列分组统计
Object[][] data1 = dao1.queryDatas("t_emps", "eaddress");
// 遍历二维数组,打印统计结果
for (int i = 0; i < data1.length; i++) {
for (int j = 0; j < data1[i].length; j++) {
System.out.print(data1[i][j] + ",");
}
System.out.println();
}
}
}
输出结果:
1,南京,
1,盐城,
2,无锡,
3.2 最高值查询
获取薪资(esalary)最高的员工,打印其薪资经过处理后的值和员工姓名
package com.hy.chapter6;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
public class Dao {
Connection conn;
public Dao() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql2025",
"root",
"yourpassword"
);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void closeDB() {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public Object[] queryDatas() {
// 获取薪资(esalary)最高的员工,返回其薪资除以 100 四舍五入后的值和姓名
String sql = "select round(esalary/100) salary, ename from t_emps "
+ " where esalary = (select max(esalary) from t_emps)";
Object[] datas = new Object[2];
try {
PreparedStatement pstmt = this.conn.prepareStatement(sql);
ResultSet rs1 = pstmt.executeQuery();
// 遍历结果集,将数据存入数组
while (rs1.next()) {
// 获取结果集第 1 列的值(对应 round(esalary/100))
datas[0] = rs1.getObject(1);
// 获取结果集第 2 列的值(对应 ename)
datas[1] = rs1.getObject(2);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
this.closeDB();
}
return datas;
}
public static void main(String[] args) {
// 获取薪资(esalary)最高的员工,打印其薪资经过处理后的值和员工姓名
Dao dao2 = new Dao();
// 调用查询方法,获取最高薪资员工数据
Object[] data2 = dao2.queryDatas();
// 打印结果(格式:处理后薪资,员工姓名)
System.out.println(data2[0] + "," + data2[1]);
}
}
输出结果:
900.0,张三
4.实现浏览器查询数据库(做跨域处理)
4.1 在eclipse中实现后端连接数据库并做跨域处理
package com.hy.chapter6;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
public class Dao {
Connection conn;
public Dao() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql2025",
"root",
"yourpassword"
);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void closeDB() {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public Object[][] queryDatas(String tableName) {
Object[][] datas = null;
try {
// 第一个SQL:查询表的记录总数(用于初始化二维数组的行数)
String sql = "select count(*) from " + tableName;
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
int count = 0;
while (rs.next()) {
count = rs.getInt(1);
}
System.out.println("sql1查询结果count的值:" + count);
// 第二个SQL:查询表中所有记录
String sql1 = "select * from " + tableName;
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
ResultSet rs1 = pstmt1.executeQuery();
// 获取结果集元数据(用于获取列数)
ResultSetMetaData rsmd = rs1.getMetaData();
int columns = rsmd.getColumnCount();
System.out.println("sql2查询结果数据的列数:" + columns);
// 初始化二维数组
datas = new Object[count][columns];
// 把数据赋值给二维数组
int row = 0;
while (rs1.next()) {
for (int i = 0; i < columns; i++) {
datas[row][i] = rs1.getObject(i + 1);
}
row++;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return datas;
}
public Object[][] queryDatas(String tableName, String column) {
// 获取名为"column"的列,得到去重后的这一列
String sql1 = "select DISTINCT " + column + " from t_emps";
// 对列名为"column"中的值进行分组,并统计每组的数量,命名为cn
// 查询得到两列,第一列名为cn,第二列名为"column"
String sql2 = "select count(*) cn, " + column + " from " + tableName + " group by " + column;
Object[][] datas = null;
try {
// 执行sql1得到结果
PreparedStatement pstmt = this.conn.prepareStatement(sql1);
ResultSet rs1 = pstmt.executeQuery();
// 遍历rs1,统计去重后的行数
int row = 0;
while (rs1.next()) {
row++;
}
// 执行sql2得到结果
PreparedStatement pstmt2 = this.conn.prepareStatement(sql2);
ResultSet rs2 = pstmt2.executeQuery();
// 获取结果列数
int columnCount = 0;
ResultSetMetaData rsmd = rs2.getMetaData();
columnCount = rsmd.getColumnCount();
// 初始化二维数组
datas = new Object[row][columnCount];
int count = 0;
// 遍历rs2,将每组统计数据存入数组
while (rs2.next()) {
for (int i = 0; i < columnCount; i++) {
datas[count][i] = rs2.getObject(i + 1);
}
count++;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
this.closeDB();
}
return datas;
}
public Object[] queryDatas() {
// 获取薪资(esalary)最高的员工,返回其薪资除以 100 四舍五入后的值和姓名
String sql = "select round(esalary/100) salary, ename from t_emps "
+ " where esalary = (select max(esalary) from t_emps)";
Object[] datas = new Object[2];
try {
PreparedStatement pstmt = this.conn.prepareStatement(sql);
ResultSet rs1 = pstmt.executeQuery();
// 遍历结果集,将数据存入数组
while (rs1.next()) {
// 获取结果集第 1 列的值(对应 round(esalary/100))
datas[0] = rs1.getObject(1);
// 获取结果集第 2 列的值(对应 ename)
datas[1] = rs1.getObject(2);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
this.closeDB();
}
return datas;
}
}
package com.hy.chapter6;
import java.nio.charset.Charset;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.server.SimpleServer;
public class Server {
public void SendTabDatas(SimpleServer server) {
server.addAction("/querytabdatas", (request, response) -> {
System.out.println("querytabdatas is start...........");
// 设置字符集不乱码
response.setCharset(Charset.forName("UTF-8"));
// 设置可以跨域,让不同IP和端口的请求可以访问
response.setHeader("Access-Control-Allow-Origin", "*");
Dao dao1 = new Dao();
Object[][] datas = dao1.queryDatas("t_emps");
JSONArray arrays = new JSONArray();
for (int i = 0; i < datas.length; i++) {
JSONObject obj = new JSONObject();
obj.put("eid", datas[i][0]);
obj.put("ename", datas[i][1]);
obj.put("epwd", datas[i][2]);
obj.put("ebirthday", datas[i][3].toString().substring(0, 10));
obj.put("esalary", datas[i][4]);
obj.put("eaddress", datas[i][5]);
if (datas[i][6].toString().equals("1")) {
obj.put("estate", "在职");
} else {
obj.put("estate", "离职");
}
arrays.add(obj);
}
response.write(arrays.toString(), ContentType.JSON.toString());
});
}
public void SendGroupAddressDatas(SimpleServer server) {
server.addAction("/querygroupaddressdatas", (request, response) -> {
System.out.println("querygroupaddressdatas is start...........");
// 设置字符集不乱码
response.setCharset(Charset.forName("UTF-8"));
// 设置可以跨域,让不同IP和端口的请求可以访问
response.setHeader("Access-Control-Allow-Origin", "*");
Dao dao1 = new Dao();
Object[][] datas = dao1.queryDatas("t_emps", "eaddress");
JSONArray arrays = new JSONArray();
for (int i = 0; i < datas.length; i++) {
JSONObject obj = new JSONObject();
obj.put("value", Integer.parseInt(datas[i][0].toString()));
obj.put("name", datas[i][1].toString());
arrays.add(obj);
}
response.write(arrays.toString(), ContentType.JSON.toString());
});
}
public void sendSalaryDatas(SimpleServer server) {
server.addAction("/querysalarydatas", (request, response) -> {
System.out.println("querysalarydatas is start...........");
// 设置字符集不乱码
response.setCharset(Charset.forName("UTF-8"));
// 设置可以跨域,让不同IP和端口的请求可以访问
response.setHeader("Access-Control-Allow-Origin", "*");
Dao dao1 = new Dao();
Object[] datas = dao1.queryDatas();
String result = JSONArray.toJSONString(datas);
response.write(result, ContentType.JSON.toString());
});
}
public Server() {
SimpleServer server = HttpUtil.createServer(8891);
this.SendTabDatas(server);
this.SendGroupAddressDatas(server);
this.sendSalaryDatas(server);
server.start();
}
public static void main(String[] args) {
Server s = new Server();
}
}
输出结果:
Hutool Simple Http Server listen on 【0:0:0:0:0:0:0:0:8891】
querytabdatas is start...........
sql1查询结果count的值:4
sql2查询结果数据的列数:7
querygroupaddressdatas is start...........
querysalarydatas is start...........
4.2 网址查询成功



4.3 在HBuilder X中实现前端查询(数据是发送给浏览器)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
function queryTabData() {
//1.创建原生ajax请求对象
let ajaxObj = new XMLHttpRequest();
//2.设置请求方法和链接
ajaxObj.open("get", "http://127.0.0.1:8891/querytabdatas");
//3.发送请求
ajaxObj.send();
//4.回调,得到服务器传送的数据
ajaxObj.onreadystatechange = () => {
if (ajaxObj.readyState == 4 && ajaxObj.status == 200) {
let result = ajaxObj.responseText;
console.log('服务器端传回的数据为:' + result);
}
}
}
queryTabData();
</script>
</html>
输出结果:

网址查询:

拓展:
readyState总共有5个状态值,分别为0~4,每个值代表了不同的含义
- 0:初始化,XMLHttpRequest对象还没有完成初始化
- 1:载入,XMLHttpRequest对象开始发送请求
- 2:载入完成,XMLHttpRequest对象的请求发送完成
- 3:解析,XMLHttpRequest对象开始读取服务器的响应
- 4:完成,XMLHttpRequest对象读取服务器响应结束
所以说readyState == 4表示已经完成了ajax请求
4.4 html用表格显示数据库表格
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
table {
width: 100%;
height: 20vh;
}
td {
text-align: center;
font-weight: bold;
}
tr:hover {
background-color: azure;
}
</style>
</head>
<body>
</body>
<script type="text/javascript">
function queryTabData() {
//1.创建原生ajax请求对象
let ajaxObj = new XMLHttpRequest();
//2.设置请求方法和链接
ajaxObj.open("get", "http://127.0.0.1:8891/querytabdatas");
//3.发送请求
ajaxObj.send();
//4.回调,得到服务器传送的数据
ajaxObj.onreadystatechange = () => {
if (ajaxObj.readyState == 4 && ajaxObj.status == 200) {
let result = ajaxObj.responseText;
console.log('服务器端传回的数据为:' + result);
console.log(typeof result);
//eval函数把这个文本转换成js对象:json的字符串对象
let re1 = eval(result)
if (re1 != undefined) {
let objdatas = JSON.parse(JSON.stringify(re1));
console.log(objdatas);
console.log(typeof objdatas);
createTabel(objdatas);
}
}
}
}
function createTabel(objdatas) {
//获取body对象
let bodyObj = document.body
//创建表格对象标签
let tabObj = document.createElement("table");
//设置表格边框
tabObj.border = 1;
let trObj1 = document.createElement("tr");
//加载key es6语法
Object.keys(objdatas[0]).forEach(function(key) {
console.log("->" + key);
if (key == 'eid') {
key = "员工编号"
}
if (key == 'ename') {
key = "员工姓名"
}
if (key == 'eaddress') {
key = "员工地址"
}
if (key == 'esalary') {
key = "员工工资"
}
if (key == 'epwd') {
key = "员工密码"
}
if (key == 'estate') {
key = "员工状态"
}
if (key == 'ebirthday') {
key = "员工出生年月"
}
let thObj0 = document.createElement("th");
thObj0.innerText = key;
trObj1.appendChild(thObj0);
});
//添加到表格中
tabObj.appendChild(trObj1);
//加载数据
for (let i = 0; i < objdatas.length; i++) {
//创建行
let trObj = document.createElement("tr");
//创建td
let tdObj0 = document.createElement("td");
let tdObj1 = document.createElement("td");
let tdObj2 = document.createElement("td");
let tdObj3 = document.createElement("td");
let tdObj4 = document.createElement("td");
let tdObj5 = document.createElement("td");
let tdObj6 = document.createElement("td");
tdObj0.innerText = objdatas[i].eid;
tdObj1.innerText = objdatas[i].eaddress;
tdObj2.innerText = objdatas[i].ename;
tdObj3.innerText = objdatas[i].esalary;
tdObj4.innerText = objdatas[i].epwd;
tdObj5.innerText = objdatas[i].estate;
tdObj6.innerText = objdatas[i].ebirthday;
trObj.appendChild(tdObj0);
trObj.appendChild(tdObj1);
trObj.appendChild(tdObj2);
trObj.appendChild(tdObj3);
trObj.appendChild(tdObj4);
trObj.appendChild(tdObj5);
trObj.appendChild(tdObj6);
//添加到表格中
tabObj.appendChild(trObj);
}
//表格添加到body标签中
bodyObj.appendChild(tabObj);
}
queryTabData();
</script>
</html>
运行结果:

显示效果:

网址查询:

4.5 html用饼图显示数据库表格
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#main {
width: 90vh;
height: 60vh;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/echarts@6.0.0/dist/echarts.min.js"></script>
</head>
<body>
<div id="main"></div>
</body>
<script type="text/javascript">
function loadView() {
// 1. 创建AJAX核心对象:XMLHttpRequest是浏览器原生API,负责发起HTTP请求、接收服务器响应
let ajaxObj = new XMLHttpRequest();
// 2. 配置AJAX请求参数:open(请求方法, 请求地址)
// - 请求方法:"get"(适合查询类操作,参数会拼在URL后,此处无额外参数)
// - 请求地址:http://127.0.0.1:8891/querygroupaddressdatas(本地服务器接口,需确保服务器已启动且接口存在)
ajaxObj.open("get", "http://127.0.0.1:8891/querygroupaddressdatas");
// 3. 发送AJAX请求:向配置的服务器地址发起请求,触发数据获取流程
ajaxObj.send();
// 4. 监听AJAX请求状态变化:当请求状态(readyState)或响应状态(status)变化时触发回调
ajaxObj.onreadystatechange = () => {
// - readyState=4:服务器已返回所有数据,请求流程完全结束
// - status=200:HTTP响应状态码为200,表示请求成功
if (ajaxObj.readyState == 4 && ajaxObj.status == 200) {
// 获取服务器返回的原始数据:responseText是字符串格式(服务器通常返回JSON格式的字符串)
let result = ajaxObj.responseText;
// 控制台打印原始数据和数据类型,用于开发调试(查看数据是否符合预期)
console.log('服务器端传回的数据为:' + result);
console.log(typeof result); // 此时输出"string",因为原始响应是文本
// 将字符串格式的数据转为JavaScript对象:使用eval函数
let re1 = eval(result)
// 数据校验:若解析后的数据不为空,进行深拷贝并调用饼图渲染函数
if (re1 != undefined) {
// 深拷贝数据:通过JSON.stringify转为字符串再JSON.parse转回对象,避免原数据被后续操作污染
let objdatas = JSON.parse(JSON.stringify(re1));
// 打印深拷贝后的数据,确认数据格式
console.log(objdatas);
console.log(typeof objdatas); // 此时输出"object"(数组属于object类型)
// 调用饼图渲染函数,传入处理后的有效数据
loadPieView(objdatas)
}
}
}
}
function loadPieView(objdatas) {
// 1. 初始化ECharts实例:绑定到id为"main"的DOM容器(即图表挂载载体)
let echartObj = echarts.init(document.getElementById("main"));
// 2. 配置ECharts图表选项:option是ECharts的核心配置,定义图表类型、数据、样式等
let option = {
series: [{
type: 'pie',
data: objdatas // 饼图数据:传入服务器返回的统计数据,决定扇区的名称和大小
}]
};
// 3. 应用图表配置:将option中的配置渲染到ECharts实例,生成最终的可视化饼图
echartObj.setOption(option);
}
loadView();
</script>
</html>
运行结果:

显示效果:

更多推荐
所有评论(0)