- 本项目中供应商、订单模块没有实现,实现步骤与用户管理类似!
- 在JDBC、结果集、分页工具及部分功能的实现逻辑等方面做了优化
- 实测可以正常运行!
- 后面有源码、文档、资源下载链接!
- 如遇问题请联系!
1、项目分析
1.1、功能分析
1.2、数据库
2、环境搭建
1)搭建 maven web 项目
更新web.xml为新版
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
</web-app>
2)配置Tomcat
3)导jar包
<dependencies>
<!-- junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!-- jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<!-- JSTL表达式的依赖 -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- standard标签库 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
</dependencies>
4)构建包结构
5)测试环境
3、实体、基础类
1)编写实体类
public class User {
private Integer id; //id
private String userCode; //用户编码
private String userName; //用户名称
private String userPassword; //用户密码
private Integer gender; //性别
private Date birthday; //出生日期
private String phone; //电话
private String address; //地址
private Integer userRole; //用户角色
private Integer createdBy; //创建者
private LocalDateTime creationDate; //创建时间
private Integer modifyBy; //更新者
private LocalDateTime modifyDate; //更新时间
@SuppressWarnings("unused")
private Integer age;//年龄
private String userRoleName; //用户角色名称
}
出生日期为:Date型
时间为:LocalDateTime型
2)编写基础公共类
(1)db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
ps=123456
(2)数据库操作基础类
BaseDao.java
- 定义变量及读取资源文件
package com.tuwer.dao;
import com.sun.rowset.CachedRowSetImpl;
import javax.sql.RowSet;
import java.io.*;
import java.sql.*;
import java.util.Properties;
/**
* @author 土味儿
* Date 2021/12/15
* @version 1.0
* 数据库公共类
* 静态方法
*/
public class BaseDao {
private static String driver;
private static String url;
private static String username;
private static String ps;
// 静态代码块:读取资源文件(类加载时执行一次)
static {
loadResources3();
}
/**
* 方式一
* FileInputStream 读取资源文件
*/
private static void loadResources1() {
// ---得到资源文件流---
Properties properties = new Properties();
FileInputStream fis = null;
try {
String configFile = ".\\target\\classes\\db.properties";
fis = new FileInputStream(configFile);
properties.load(fis);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
ps = properties.getProperty("ps");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 方式二
* FileReader 读取资源文件
*/
private static void loadResources2() {
// ---得到资源文件流---
Properties properties = new Properties();
FileReader reader = null;
try {
String configFile = ".\\target\\classes\\db.properties";
reader = new FileReader(configFile);
properties.load(reader);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
ps = properties.getProperty("ps");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 方式三
* 类加载器读取资源文件
* BaseDao.class.getClassLoader().getResourceAsStream(configFile);
*/
private static void loadResources3() {
// ---得到资源文件流---
Properties properties = new Properties();
InputStream is = null;
try {
// 方式三
String configFile = "db.properties";
is = BaseDao.class.getClassLoader().getResourceAsStream(configFile);
properties.load(is);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
ps = properties.getProperty("ps");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 获取数据库连接
/**
* 获取数据库连接
*
* @return
*/
public static Connection getConnection() {
Connection connection = null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, username, ps);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
- 查询方法
1、查询结束后关闭 PreparedStatement 和 ResultSet
2、Connection 放在业务层关闭,方便事务操作
3、返回 RowSet 行集,不是 ResultSet 结查集。ResultSet 和 PreparedStatement 有关联关系,关闭 PreparedStatement 后,在下次执行 ResultSet 时,也会关闭;RowSet 没有关联关系;结果转为 RowSet 后就可以及时关闭 ResultSet 和 PreparedStatement;通过 CachedRowSetImpl 类可以把 ResultSet 转为 RowSet
/**
* 查询
* 查询结束后关闭PreparedStatement和ResultSet
* Connection放在业务层关闭,方便事务操作
*
* @param connection 连接
* @param sql 查询语句(可以有占位符)
* @param params 参数数组|List
* @return
* @throws SQLException
*/
public static RowSet executeQuery(
Connection connection,
String sql,
List params) throws SQLException {
PreparedStatement ps = connection.prepareStatement(sql);
if (params != null) {
// 为占位符赋值
for (int i = 0; i < params.size(); i++) {
ps.setObject(i + 1, params.get(i));
}
}
// 查询
ResultSet rs = ps.executeQuery();
// 把ResultSet结果集转为RowSet行集
// 联表查询时,行集不支持别名,行集中的列名仍然为表中的列名,不是别名
// 用 rs.getMetaData().getColumnName(列位置) 查列名,列位置从1开始
CachedRowSetImpl crs = new CachedRowSetImpl();
crs.populate(rs);
if(params!=null){
params.clear();
}
// 关闭PreparedStatement和ResultSet
// Connection放在业务层关闭,方便事务操作
close(null, ps, rs);
return crs;
}
- 更新方法
/**
* 更新
*
* @param connection 连接
* @param sql 查询语句(可以有占位符)
* @param params 参数数组|List
* @return
* @throws SQLException
*/
public static int executeUpdate(
Connection connection,
String sql,
List params) throws SQLException {
PreparedStatement ps = connection.prepareStatement(sql);
if (params != null) {
// 为占位符赋值
for (int i = 0; i < params.size(); i++) {
ps.setObject(i + 1, params.get(i));
}
}
// 更新
int i = ps.executeUpdate();
if(params!=null){
params.clear();
}
// 关闭PreparedStatement
close(null, ps, null);
return i;
}
- 关闭
/**
* 关闭/释放资源
* @param connection
* @param ps
* @param rs
* @return
*/
public static boolean close(
Connection connection,
PreparedStatement ps,
ResultSet rs) {
boolean flag = true;
if (rs != null) {
try {
rs.close();
// 方便GC回收
rs = null;
System.out.println("ResultSet关闭");
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if (ps != null) {
try {
ps.close();
ps = null;
System.out.println("PreparedStatement关闭");
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if (connection != null) {
try {
connection.close();
connection = null;
System.out.println("Connection关闭");
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
return flag;
}
(3)字符乱码过滤器
public class CharacterFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf8");
response.setCharacterEncoding("utf8");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
- web.xml配置
<filter>
<filter-name>characterFilter</filter-name>
<filter-class>com.tuwer.filter.CharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(4)导入静态资源
(5)分页工具类
- PageUtil.java
package com.tuwer.util;
import java.util.regex.Pattern;
import static java.util.regex.Pattern.*;
/**
* @author 土味儿
* Date 2021/12/19
* @version 1.0
* 分页工具
*/
public class PageUtil {
/**
* 得到总页数
*
* @param rows 总数据量
* @param pageSize 每页显示数量
* @return 总页数
*/
public static int getPages(int rows, int pageSize) {
if (rows < 1) {
return 0;
}
if (pageSize < 1) {
pageSize = 1;
}
if (pageSize > rows) {
pageSize = rows;
}
return (int) Math.ceil(((double) rows) / pageSize);
}
/**
* 得到页面数据量
*
* @param pageSizeStr 页面数据量字符串
* @param max 最大页面数据量
* @return 返回Int值,介于 1 和 最大值 之间
*/
public static int getPageSize(String pageSizeStr, int max) {
return strToInt_123(pageSizeStr, max, 1);
}
/**
* 得到当前页码
*
* @param currentPageStr 当前页码字符串
* @param max 最大页码
* @return 返回Int值,介于 1 和 最大值 之间
*/
public static int getCurrentPage(String currentPageStr, int max) {
return strToInt_123(currentPageStr, max, 1);
}
/**
* 得到当前页的数据起始索引
*
* @param currentPage 当前页码
* @param pageSize 当前数据量
* @return
*/
public static int getStartIndex(int currentPage, int pageSize) {
if (currentPage < 1) {
currentPage = 1;
}
if (pageSize < 1) {
pageSize = 1;
}
return (currentPage - 1) * pageSize + 1;
}
/**
* 字符串转正整数
*
* @param str 目标字符串
* @param max 最大值
* @param def 默认值
* @return 返回Int值,介于 默认值 和 最大值 之间
*/
private static int strToInt_123(String str, int max, int def) {
// 判断max和def大小
if (max < 1) {
max = 1;
}
if (def < 1) {
def = 1;
}
if (def > max) {
def = max;
}
// 把默认值赋于返回值