狂神 原生JavaWeb 三层架构 JDBC (超市订单管理系统smbms)---【优化版】

  • 本项目中供应商、订单模块没有实现,实现步骤与用户管理类似!
  • 在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;
        }

        // 把默认值赋于返回值
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

土味儿~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值