Day06之smbms项目创建

1、JavaWeb学习(smbms准备工作)

1、Http响应

200:请求成功

3xx:请求重定向

4xx:资源不存在

5xx:服务器代码错误 500

502:网关错误

2、两个时代

  • http 1.0

    • HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接

  • http 2.0

    • HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源

  • https是安全的,端口号443;http端口号80

3、Maven

自动帮忙导入和配置jar包

4、Servlet(初学)

Ctrl + o 可以快速重写( override ) doGet和doPost方法

  1. 在类中重写完doGet等方法后,进入web.xml中写注释,映射才能反映到浏览器中显示

 public class ErrorServlet extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         resp.setContentType("text/html");//响应的类型为html
         resp.setCharacterEncoding("UTF-8");//字符集类型为UTF-8
 ​
         PrintWriter writer = resp.getWriter();
         writer.println("<h1>404</h1>");
         super.doGet(req, resp);
     }
 ​
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         super.doPost(req, resp);
     }
 }
//继承父亲类的接口
public class HelloServlet extends HttpServlet {
    //由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑一样
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入了doGet方法");
        PrintWriter writer = resp.getWriter();//响应流
        writer.println("<html>");
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

web.xml

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <!--    注册Servlet映射,为了能在浏览器中访问-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.mao.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--    Servlet的请求路径-->
<!--    url-pattern这里必须是/开头,不能只是hello
        servlet的映射地址必须以 “/” 开头
        *前面不能加项目映射的路径
-->
    <servlet-mapping>    <!--    mapping映射-->
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <!--    404报错-->
    <servlet>
        <servlet-name>error</servlet-name>
        <servlet-class>com.mao.servlet.ErrorServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>error</servlet-name>
        <!--        通配符,访问下面的任意网页-->
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

2、搭建一个Maven项目

  1. 创建一个Maven web app的项目

  2. 把pom.xml删干净

  3. 建立java包、resources包

  4. 把Tomcat最新的web.xml的内容移植到maven项目中的web.xml中,删除tomcat多余内容

  5. 配置tomcat

  6. 测试项目是否能够进入index.jsp

  7. 导入jar包,通过pom.xml进行导入

    1. 导入Mysql的jar包时出现问题,版本号不对应

      • 例如我自己是8.0的版本,需要补齐8.0.32才能自动加载成功

    2. 导入javax.servlet的jar包

    3. 导入javax.servlet.jsp的jar包

    4. 导入JSTL、Standard的jar包

  8. 编写实体类

1、编写实体类

  1. 根据数据库中的变量、变量类型在IDEA中定义字段

  2. 获取其get / set方法,用于返回具体值

    • 特殊的:年龄字段应为 当前年份 — 出生年份

  3. image-20250325155346337

  4. 用Integer去定义时,需要大写!!!!同时定义访问权限如:private

    1.1 实体类的编写其实就是在ORM映射的过程 从表 到 类的映射

    package com.mao.pojo;
    
    import java.math.BigDecimal;
    import java.util.Date;
    
    public class Bill {
        private Integer id;
        private String billCode;//账单编码
        private String productName;
        private String productDesc;
        private String productUnit;//账单单位
        private BigDecimal productCount;
        private BigDecimal totalPrice;
        private Integer isPayment;
        private Integer createdBy;
        private Date createDate;
        private Integer modifyBy;
        private Date modifyDate;
        private Integer providerId;//供应商ID
        private String providerName;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getBillCode() {
            return billCode;
        }
    
        public void setBillCode(String billCode) {
            this.billCode = billCode;
        }
    
        public String getProductName() {
            return productName;
        }
    
        public void setProductName(String productName) {
            this.productName = productName;
        }
    
        public String getProductDesc() {
            return productDesc;
        }
    
        public void setProductDesc(String productDesc) {
            this.productDesc = productDesc;
        }
    
        public String getProductUnit() {
            return productUnit;
        }
    
        public void setProductUnit(String productUnit) {
            this.productUnit = productUnit;
        }
    
        public BigDecimal getProductCount() {
            return productCount;
        }
    
        public void setProductCount(BigDecimal productCount) {
            this.productCount = productCount;
        }
    
        public BigDecimal getTotalPrice() {
            return totalPrice;
        }
    
        public void setTotalPrice(BigDecimal totalPrice) {
            this.totalPrice = totalPrice;
        }
    
        public Integer getIsPayment() {
            return isPayment;
        }
    
        public void setIsPayment(Integer isPayment) {
            this.isPayment = isPayment;
        }
    
        public Integer getCreatedBy() {
            return createdBy;
        }
    
        public void setCreatedBy(Integer createdBy) {
            this.createdBy = createdBy;
        }
    
        public Date getCreateDate() {
            return createDate;
        }
    
        public void setCreateDate(Date createDate) {
            this.createDate = createDate;
        }
    
        public Integer getModifyBy() {
            return modifyBy;
        }
    
        public void setModifyBy(Integer modifyBy) {
            this.modifyBy = modifyBy;
        }
    
        public Date getModifyDate() {
            return modifyDate;
        }
    
        public void setModifyDate(Date modifyDate) {
            this.modifyDate = modifyDate;
        }
    
        public Integer getProviderId() {
            return providerId;
        }
    
        public void setProviderId(Integer providerId) {
            this.providerId = providerId;
        }
    
        public String getProviderName() {
            return providerName;
        }
    
        public void setProviderName(String providerName) {
            this.providerName = providerName;
        }
    }
    package com.mao.pojo;
    
    import java.util.Date;
    
    public class Provider {
        private Integer id;
        private String proCode;//供应商编码
        private String proName;
        private String proDesc;
        private String proContact;
        private String proPhone;
        private String proAddress;
        private String proFax;//供应商传真
        private Integer createdBy;
        private Date creationDate;
        private Date modifyDate;
        private Integer modifyBy;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getProCode() {
            return proCode;
        }
    
        public void setProCode(String proCode) {
            this.proCode = proCode;
        }
    
        public String getProName() {
            return proName;
        }
    
        public void setProName(String proName) {
            this.proName = proName;
        }
    
        public String getProDesc() {
            return proDesc;
        }
    
        public void setProDesc(String proDesc) {
            this.proDesc = proDesc;
        }
    
        public String getProContact() {
            return proContact;
        }
    
        public void setProContact(String proContact) {
            this.proContact = proContact;
        }
    
        public String getProPhone() {
            return proPhone;
        }
    
        public void setProPhone(String proPhone) {
            this.proPhone = proPhone;
        }
    
        public String getProAddress() {
            return proAddress;
        }
    
        public void setProAddress(String proAddress) {
            this.proAddress = proAddress;
        }
    
        public String getProFax() {
            return proFax;
        }
    
        public void setProFax(String proFax) {
            this.proFax = proFax;
        }
    
        public Integer getCreatedBy() {
            return createdBy;
        }
    
        public void setCreatedBy(Integer createdBy) {
            this.createdBy = createdBy;
        }
    
        public Date getCreationDate() {
            return creationDate;
        }
    
        public void setCreationDate(Date creationDate) {
            this.creationDate = creationDate;
        }
    
        public Date getModifyDate() {
            return modifyDate;
        }
    
        public void setModifyDate(Date modifyDate) {
            this.modifyDate = modifyDate;
        }
    
        public Integer getModifyBy() {
            return modifyBy;
        }
    
        public void setModifyBy(Integer modifyBy) {
            this.modifyBy = modifyBy;
        }
    }
    package com.mao.pojo;
    
    import java.util.Date;
    
    public class Role {
        private Integer id;
        private String roleCode;//角色编码
        private String roleName;
        private Integer createBy;
        private Date creationDate;
        private Integer modifyBy;
        private Date modifyDate;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getRoleCode() {
            return roleCode;
        }
    
        public void setRoleCode(String roleCode) {
            this.roleCode = roleCode;
        }
    
        public String getRoleName() {
            return roleName;
        }
    
        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }
    
        public Integer getCreateBy() {
            return createBy;
        }
    
        public void setCreateBy(Integer createBy) {
            this.createBy = createBy;
        }
    
        public Date getCreationDate() {
            return creationDate;
        }
    
        public void setCreationDate(Date creationDate) {
            this.creationDate = creationDate;
        }
    
        public Integer getModifyBy() {
            return modifyBy;
        }
    
        public void setModifyBy(Integer modifyBy) {
            this.modifyBy = modifyBy;
        }
    
        public Date getModifyDate() {
            return modifyDate;
        }
    
        public void setModifyDate(Date modifyDate) {
            this.modifyDate = modifyDate;
        }
    }
    package com.mao.pojo;
    
    import java.util.Date;
    
    public class User {
        private Integer 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 createBy;//创建角色
        private Date creationDate;//创建日期
        private Integer modifyBy;//更新者
        private Date modifyDate;//更新日期
        private String idPicPath;
        private String workPicPath;
    
    
        private Integer age;//年龄
        private String userRoleName;//用户角色名称
    /*特殊的日期计算——必须掌握*/
        public Integer getAge() {
            //导入Date工具包,利用当前年份 —— 出生年份 得到年龄
            Date date = new Date();
            Integer age = date.getYear() - birthday.getYear();
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getUserRoleName() {
            return userRoleName;
        }
        
        public void setUserRoleName(String userRoleName) {
            this.userRoleName = userRoleName;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUserCode() {
            return userCode;
        }
    
        public void setUserCode(String userCode) {
            this.userCode = userCode;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public String getUserPassword() {
            return userPassword;
        }
    
        public void setUserPassword(String userPassword) {
            this.userPassword = userPassword;
        }
    
        public Integer getGender() {
            return gender;
        }
    
        public void setGender(Integer gender) {
            this.gender = gender;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public String getPhone() {
            return phone;
        }
    
        public void setPhone(String phone) {
            this.phone = phone;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public Integer getUserRole() {
            return userRole;
        }
    
        public void setUserRole(Integer userRole) {
            this.userRole = userRole;
        }
    
        public Integer getCreateBy() {
            return createBy;
        }
    
        public void setCreateBy(Integer createBy) {
            this.createBy = createBy;
        }
    
        public Date getCreationDate() {
            return creationDate;
        }
    
        public void setCreationDate(Date creationDate) {
            this.creationDate = creationDate;
        }
    
        public Integer getModifyBy() {
            return modifyBy;
        }
    
        public void setModifyBy(Integer modifyBy) {
            this.modifyBy = modifyBy;
        }
    
        public Date getModifyDate() {
            return modifyDate;
        }
    
        public void setModifyDate(Date modifyDate) {
            this.modifyDate = modifyDate;
        }
    
        public String getIdPicPath() {
            return idPicPath;
        }
    
        public void setIdPicPath(String idPicPath) {
            this.idPicPath = idPicPath;
        }
    
        public String getWorkPicPath() {
            return workPicPath;
        }
    
        public void setWorkPicPath(String workPicPath) {
            this.workPicPath = workPicPath;
        }
    }

    1.2 编写基础公共类(重点)

    1. 数据库配置文件

    //驱动器
    driver = com.mysql.jdbc.Driver
    //地址(后面加了两个保证安全的验证)
    url = jdbc:mysql://localhost:3306?useSSL=true&useUnicode=true&usecharacterEncoding=utf-8
    //用户名和密码
    username = root
    password = 123456
    1. 编写数据库的公共类(BaseDao、提供对数据库的基本操作)

    package com.mao.dao;
    
    import com.mysql.jdbc.Driver;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.sql.*;
    import java.util.Objects;
    import java.util.Properties;
    
    /*
    * BaseDao 是一种通用的数据访问对象(DAO),用于提供对数据库的基本操作,例如插入、更新、删除和查询数据等
    * */
    //操作数据库的公共类
    public class BaseDao {
        //定义字段(静态方便调用)
        private static String driver;
        private static String url;
        private static String username;
        private static String password;
        //静态代码块,类加载的时候就初始化了,将获取的数据转成流的形式
        static{
            //properties 是一个 Java 类,可以用来读取、写入 properties 文件。
            //这个对象可以用来储存一组 key-value 对,方便配置文件的读取、写入等操作。
            Properties properties = new Properties();
    /*
            通过类加载器读取对应的资源转成流的形式,InputStream 提供了从输入流中读取数据的方法,通过对象能够去调用方法
            Class是当前类的Class对象,Class.getClassLoader()是获取当前类的类加载器。类加载器的大概作用是当需要使用一个类时,加载该类		         的".class"文件并创建对应的class对象,将class文件加载到虚拟机的内存。
            getResourceAsStream()是获取资源的输入流,当使用Class.getClassLoader.getResourceAsStream()加载资源时
            是从classPath路径下进行加载,放在resources下的文件加载时不能加(“/”)
    */
            InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
            try {
                //加载properties 文件,读取数据库的连接
                properties.load(is);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //通过getProperty方法获取数据库参数,四个参数被获取并赋值
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
        }
        //获取数据库的连接
        //Connection 对象是JDBC(Java数据库连接)中的一个接口,它代表着与数据库的物理连接。
        //通过这个对象,您可以与数据库建立通信,发送SQL语句,并获取查询结果。
        public static Connection getConnection(){
            Connection connection = null;
            try {
                //此为一个静态方法,用于提前加载类
                Class.forName(driver);
                //返回一个connection对象
                //DriverManager 是 Java JDBC API 的一部分,用于管理数据库驱动程序和建立数据库连接。
                //它的主要功能包括注册数据库驱动程序、创建数据库连接以及管理数据库连接池
                //将数据库的三个大属性获取再传给connection,用于获取连接
                connection = DriverManager.getConnection(url,username,password);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return connection;
        }
        //编写查询公共类
        public static ResultSet execute(Connection connection, String sql, Object[] params,ResultSet resultSet,PreparedStatement preparedStatement) throws SQLException{
            //预编译传sql,在后面直接执行就可以了,PreparedStatement 是 Java 中用于执行预编译 SQL 语句的接口
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                //setObject,占位符从1开始,但是我们的数组是从0开始的
                preparedStatement.setObject(i + 1, params[i]);
            }
            //执行查询返回结果数据集
            resultSet = preparedStatement.executeQuery();
            return resultSet;
        }
        //编写增删改公共方法
        public static int execute(Connection connection, String sql, Object[] params,PreparedStatement preparedStatement) throws SQLException{
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                //setObject,占位符从1开始,但是我们的数组是从0开始的
                //使用PreparedStatement:是Statement的子接口,可以传入带占位符的SQL语句,提供了补充占位符变量的方法
                //作用如下:
                //		  String sql="insert into examstudent values(?,?,?,?,?,?,?)";
                preparedStatement.setObject(i + 1, params[i]);
            }
            //本质上是只修改了这里的处理方法,返回值变成		整数型的行数		也就是修改的行数
            int updateRows = preparedStatement.executeUpdate();
            return updateRows;
        }
        //释放资源
        public static boolean closeResource(Connection connection, ResultSet resultSet, PreparedStatement preparedStatement){
            boolean flag = true;
            //资源若存在,进入语句块进行关闭
            if(resultSet != null){
                try {
                    resultSet.close();
                    //若未关闭,则GC回收
                    resultSet = null;
                } catch (SQLException e) {
                    e.printStackTrace();
                    //关闭失败
                    flag = false;
                }
            }
    
            if(connection != null){
                try {
                    connection.close();
                    //若未关闭,则GC回收
                    connection = null;
                } catch (SQLException e) {
                    e.printStackTrace();
                    flag = false;
                }
            }
    
            if(preparedStatement != null){
                try {
                    preparedStatement.close();
                    //若未关闭,则GC回收
                    preparedStatement = null;
                } catch (SQLException e) {
                    e.printStackTrace();
                    flag = false;
                }
            }
            //最后返回一个释放资源的结果
            return flag;
        }
    }
    1. 编写字符编码过滤器

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                            https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
               version="6.0"
               metadata-complete="true">
              <!--        字符编码过滤器-->
              <filter>
                  <filter-name>CharacterEncodingFilter</filter-name>
                  <!--        所用到的类的地址-->
                  <filter-class>com.mao.filter.CharacterEncodingFilter</filter-class>
              </filter>
              <filter-mapping>
                  <filter-name>CharacterEncodingFilter</filter-name>
                  <!--        模式:  /* 表示所有请求都会被过滤-->
                  <url-pattern>/*</url-pattern>
              </filter-mapping>
      
              <!--    设置欢迎界面-->
              <welcome-file-list>
                  <welcome-file>login.jsp</welcome-file>
              </welcome-file-list>
      </web-app>
    2. Filter过滤器的类

      package com.mao.filter;
      
      import javax.servlet.*;
      import java.io.IOException;
      
      public class CharacterEncodingFilter implements Filter {
          public void init(FilterConfig filterConfig) throws ServletException {
      
          }
      
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
              request.setCharacterEncoding("UTF-8");
              response.setCharacterEncoding("UTF-8");
              chain.doFilter(request,response);
          }
          public void destroy() {
      
          }
      }

2、导入静态资源

导入login.jsp和静态资源,启动Tomcat进入网页的登录界面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>系统登录-超市订单管理系统</title>
    <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/statics/css/style.css">
    <script>

    </script>
</head>
<body class="login_bg">
<section class="loginBox">
    <header class="loginHeader">
        <h1>超市订单管理系统</h1>
    </header>
    <section class="loginCont">
<%--        action  的   login.do  判断是否登录成功--%>
        <form class="loginForm" action="${pageContext.request.contextPath}/login.do" name="actionForm" id="actionForm"
              method="post">
            <div class="info">${error}</div>
            <div class="inputbox">
                <label>用户名:</label>
                <input type="text" class="input-text" id="userCode" name="userCode" placeholder="请输入用户名"
                       required/>
            </div>
            <div class="inputbox">
                <label>密码:</label>
                <input type="password" id="userPassword" name="userPassword" placeholder="请输入密码" required/>
            </div>
            <div class="subBtn">
                <input type="submit" value="登录"/>
                <input type="reset" value="重置"/>
            </div>
        </form>
    </section>
</section>
</body>
</html>

3、登录功能的实现

1. Dao层(持久层)

(1) dao层登录用户登录的接口
package com.mao.dao.user;

import com.mao.pojo.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//接口只是抽象的一个约束,不去真正的实现方法,所以只需要定义它的方法即可
public interface UserDao {
    //得到要登录的用户(根据userCode去查询要查询的数据,如admin )
    //Connection用于与数据库的物理连接通信,发送sql语句,并获取查询结果
    //这里出现了一个问题,使用抽象类方法后,需要去重写这个方法,重写这个方法需要注意的是参数值、参数类型、参数个数必须一致,否则会报错
    public User getLoginUser(Connection connection, String userCode) throws SQLException;

}
(2) dao接口的实现类
  1. 真正实现dao接口的实现类,注意抽象方法的真正实现的参数情况

package com.mao.dao.user;

import com.mao.dao.BaseDao;
import com.mao.pojo.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//实现接口的方法,接口只是一个约束,实现才是具体的事情(接口的真正实现)
public class UserDaoImpl implements UserDao {

    public User getLoginUser(Connection connection, String userCode) throws SQLException {
        //就不在方法头上进行传参了,直接在下面进行定义
        PreparedStatement pstm =  null;
        ResultSet rs = null;
        User user = null;

        if (connection != null) {
            //where后的条件语句用于获取预编译的userCode数据,安全考虑
            String sql = "select * from smbms_user where userCode = ?";
            //封装参数(用于存储后访问获取)
            Object[] params = {userCode};
            //连接数据库后,sql语句传递给rs参数
            rs = BaseDao.execute(connection, pstm, rs, sql, params);

            //挨个对数据库中存在的数据进行遍历
            if (rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setUserCode(rs.getString("userCode"));
                user.setUserName(rs.getString("userName"));
                user.setUserPassword(rs.getString("userPassword"));
                user.setGender(rs.getInt("gender"));
                user.setBirthday(rs.getDate("birthday"));
                user.setPhone(rs.getString("phone"));
                user.setAddress(rs.getString("address"));
                user.setUserRole(rs.getInt("userRole"));
                user.setCreateBy(rs.getInt("createdBy"));
                user.setCreationDate(rs.getTimestamp("creationDate"));
                user.setModifyBy(rs.getInt("modifyBy"));
                user.setModifyDate(rs.getTimestamp("modifyDate"));

                user.setIdPicPath(rs.getString("idPicPath"));
                user.setWorkPicPath(rs.getString("workPicPath"));
            }
            //对资源的关闭(连接可以不用关闭,因为有别的层可能还需要)关闭时需要注意关闭顺序
            BaseDao.closeResource(null, pstm, rs);
        }
        return user;
    }
}

2. Service层(业务层)

(1) 业务层的接口(service层)
package com.mao.service.user;

import com.mao.pojo.User;

//用户登录的业务层
public interface UserService {
    //用户登录的抽象方法,包括用户名和密码,有具体实现类
    public User login(String userCode, String password);
}
(2) 业务层接口的实现类(service层)
package com.mao.service.user;

import com.mao.dao.BaseDao;
import com.mao.dao.user.UserDao;
import com.mao.dao.user.UserDaoImpl;
import com.mao.pojo.User;
import org.junit.jupiter.api.Test;

import java.sql.Connection;
import java.sql.SQLException;

public class UserServiceImpl implements UserService {

    //service层调用dao层,因为业务层都会调用dao层,所以引入dao层
    private UserDao userDao;
	//实现dao接口的被调用
    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }
	//抽象方法的重写,注意参数
    @Override
    public User login(String userCode, String password) {
        Connection connection = null;
        User user = null;
        try {
            //Dao层获得了数据库的连接传到Service层中继续使用
            connection = BaseDao.getConnection();
            //通过业务层调用对应的具体的数据库操作
            user = userDao.getLoginUser(connection, userCode);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            //关闭连接,以免资源浪费
            BaseDao.closeResource(connection,null,null);
        }
        //最后返回得到的user对象
        return user;
    }
    //单元测试用例,需要在pom.xml中导入junit依赖
    /*
    测试是否能够正确调用数据库中的数据,这里是传admin进去获取其密码,我们可以看到密码不受我们所提前定义的123abc所影响
    测试说明,只与我们传入的userCode有关,根据userCode去查询其密码
    */
	@Test
    public void test(){
        UserServiceImpl userService = new UserServiceImpl();
        User admin = userService.login("ass", "7867");
        System.out.println(admin.getUserPassword());
    }
}

image-20250327172338100

image-20250327172348812

3. Servlet层(控制服务层)

package com.mao.servlet.user;

import com.mao.pojo.User;
import com.mao.service.user.UserService;
import com.mao.service.user.UserServiceImpl;
import com.mao.util.Constants;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

//首先要继承内部的HttpServlet类
public class LoginServlet extends HttpServlet {
    // Servlet: 控制层,调用业务层代码

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //通过request请求获取用户名和密码
        String userCode = req.getParameter("userCode");
        String userPassword = req.getParameter("userPassword");

        //和数据库中的密码进行对比,调用业务层(通过接口进行调用)
        UserService userService = new UserServiceImpl();

        User user = userService.login(userCode, userPassword);//后半段是调用login的登录方法,获取用户名和密码,前半段是获取后传递给user对象
        //判断是否查有此人,可以登录,并请信息传递给Constants类里的常量,完成登录后进行跳转
        if (user != null) {
            //将用户的信息放到Session中
            req.getSession().setAttribute(Constants.User_Session, user);
            //跳转到主页(请求重定向——用于跳转网页)
            resp.sendRedirect("jsp/frame.jsp");
        } else {
            //页面相应请求,与jsp页面中的  ${error}  进行相应   并返回字符串提示
            req.setAttribute("error","用户名或密码错误");
            /*
            getRequestDispatcher()包含两个重要方法,分别是请求转发和请求包含。一个请求跨多个Servlet时,需要使用请求转发和请求包含。
            首先需要获得一个RequestDispatcher 对象:RequestDispatcher rd = request.getRequestDispatcher("/MyServlet");

            请求转发: rd.forward( request , response );
            请求包含: rd.include( request  , response);
             */
            //请求转发到新页面,并带入两个请求参数
            req.getRequestDispatcher("login.jsp").forward(req,resp);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}
(1) 工具类的常量设定(此处为了存储获取的用户信息)
package com.mao.util;

public class Constants {
    //编写常量,用于存储控制层获取到的业务层字符段属性
    public final static String User_Session = "userSession";//等待被调用
}
(2) Frame.jsp的编写
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/1/27
  Time: 19:57
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="/jsp/common/head.jsp"%>
<div class="right">
    <img class="wColck" src="${pageContext.request.contextPath}/statics/images/clock.jpg" alt=""/>
    <div class="wFont">
        <h2>${userSession.userName}</h2>
        <p> 欢迎来到超市订单管理系统!</p>
    </div>
</div>
</section>
<%@ include file="/jsp/common/foot.jsp"%>
(3) web.xml 中 servlet的注册
    <!--编写Servlet的xml文件     注册Servlet文件-->
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.mao.servlet.user.LoginServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
    <!--        登录请求页面-->
        <url-pattern>/login.do</url-pattern>
    </servlet-mapping>

这里出现一个问题,frame.jsp中某一行代码的初始化失败,经检查是 pom.xml的依赖没有导入

<!--     https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-spec-->
 <dependency>
   <groupId>org.apache.taglibs</groupId>
   <artifactId>taglibs-standard-spec</artifactId>
   <version>1.2.5</version>
 </dependency>
<!--     https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl-->
 <dependency>
   <groupId>org.glassfish.web</groupId>
   <artifactId>jakarta.servlet.jsp.jstl</artifactId>
   <version>3.0.1</version>
 </dependency>
(4) 测试登录成功后,注销登录

思路:将session的信息进行移除,然后返回到登录界面

package com.mao.servlet.user;

import com.mao.util.Constants;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

//先要继承HttpServlet服务类
public class LogoutServlet extends HttpServlet {
    //servlet层进行业务服务,编写业务逻辑!doPost、doGet,利用快捷键Ctrl + o

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //清除已经保存的session信息,再重定向回登录界面(但是此处还需要进行优化、因为没有做登录拦截优化,简单来说就是复制登录后的地址同样能进入,无须账号密码)
        req.getSession().removeAttribute(Constants.User_Session);//对工具常量类的对象进行移除,接着进行重定向
        resp.sendRedirect("/login.jsp");//重定向需要编写退出的xml文件
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }

}

编写注销登录的xml文件

<!--    注销登录的xml文件-->
    <servlet>
        <servlet-name>LogoutServlet</servlet-name>
        <servlet-class>com.mao.servlet.user.LogoutServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LogoutServlet</servlet-name>
        <url-pattern>/logout.do</url-pattern>
    </servlet-mapping>
(5) 登录拦截优化

编写系统过滤类(此处必须导入jakarta.servlet的包,而不是javax.servlet的包)

package com.mao.filter;


import com.mao.pojo.User;
import com.mao.util.Constants;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

//登录拦截过滤器
public class SysFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    //系统拦截登录过滤优化
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        /*1. 先定义请求变量
         * 2. 通过请求变量去session中拿到信息
         * 3. 判断是否获取到用户
         * 4. 需要在xml文件中编写登录拦截过滤器
         * */
        //1.定义请求变量
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //2.获取session信息(通过常量类中存储的session信息),并且用变量进行接收
        //这里出现了一个致命错误,我们是需要去拿到它的信息,而不是setAttribute设置它的信息
        User user = (User) request.getSession().getAttribute(Constants.User_Session);
        //3.判断是否获取到用户
        if (user == null) {//未登录、已退出登录、获取失败等情况,并重定向至错误界面
            response.sendRedirect(request.getContextPath() + "/error.jsp");
        } else {//获取到了用户就继续执行此过滤方法
            chain.doFilter(req, resp);
        }
        //4.接着去xml文件中编写登录拦截过滤器
    }
}

编写登录拦截优化的xml文件

<!--    登录拦截过滤器-->
    <filter>
        <filter-name>SysFilter</filter-name>
        <filter-class>com.mao.filter.SysFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>SysFilter</filter-name>
<!--        过滤jsp文件夹下面的所有文件-->
        <url-pattern>/jsp/*</url-pattern>
    </filter-mapping>

登录拦截后,检测到未登录或登录错误,则返回error.jsp界面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ERROR,Please return login.jsp</title>
</head>
<style type="text/css">
* {
    margin: 0;
    padding: 0;
}

body {
    background: url("${pageContext.request.contextPath}/statics/images/pic-error.png") 0 0 no-repeat;
     background-position:55% -70%;
}
/* body{
    background-color: #ccc;
} */
</style>
<body>
    <!-- 使用输出全局异常信息-->
    <%-- <h1>全局异常信息:${exception.message}</h1> --%>
    <%-- 用来使用局部输出 <h1>${e}</h1> --%>
    <a href="${pageContext.request.contextPath }/login.jsp">返回</a>
</body>
</html>

4、密码修改

  1. 导入前端素材:pwdmodify.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file="/jsp/common/head.jsp" %>
<div class="right">
    <div class="location">
        <strong>你现在所在的位置是:</strong>
        <span>密码修改页面</span>
    </div>
    <div class="providerAdd">
        <form id="userForm" name="userForm" method="post" action="${pageContext.request.contextPath }/jsp/user.do">
            <input type="hidden" name="method" value="savepwd"/>
            <!--div的class 为error是验证错误,ok是验证成功-->
            <div class="info">${message}</div>
            <div class="">
                <label for="oldPassword">旧密码:</label>
                <input type="password" name="oldpassword" id="oldpassword" value="">
                <font color="red"></font>
            </div>
            <div>
                <label for="newPassword">新密码:</label>
                <input type="password" name="newpassword" id="newpassword" value="">
                <font color="red"></font>
            </div>
            <div>
                <label for="newPassword">确认新密码:</label>
                <input type="password" name="rnewpassword" id="rnewpassword" value="">
                <font color="red"></font>
            </div>
            <div class="providerAddBtn">
                <!--<a href="#">保存</a>-->
                <input type="button" name="save" id="save" value="保存" class="input-button">
            </div>
        </form>
    </div>
</div>
</section>
<%@include file="/jsp/common/foot.jsp" %>
<script type="text/javascript" src="${pageContext.request.contextPath }/statics/js/pwdmodify.js"></script>
  1. 搞清楚逻辑,如图所示:(编写应该自底向上,先数据库,再Dao,再Service,再Servlet,因为他们存在调用关系,调用则是反过来)

    image-20250328200945913

    6.1 UserDao层接口(修改用户密码)

    //修改密码的抽象方法(返回值类型为int型、1则是修改成功,0则是修改失败)根据ID进行修改
    public int updatePassword(Connection connection,int id,String password) throws SQLException;

    6.2 修改密码的UserDao接口实现类

    //修改当前用户密码
    @Override
    public int updatePassword(Connection connection, int id, String password) throws SQLException {
        PreparedStatement pstm = null;
        int result = 0;
        //若连接不为空,也即没有进行此操作才进入执行语句
        if (connection != null) {
            //编写即将执行的修改密码sql语句
            String sql = "update smbms_user set userPassword = ? where id = ?";
            //将修改后的id和密码存储在Object下的params数组内
            Object[] params = {password, id};
            //调用BaseDao的执行方法(参数一定不能漏,顺序也不可以错)   最后将执行完的方法返回至一个新的参数
            result = BaseDao.execute(connection, pstm, sql, params);
            //关闭BaseDao的资源
            BaseDao.closeResource(null, pstm, null);
        }
        return result;
    }

    6.3 UserService层接口(针对业务的功能)

    //用户修改密码
    public boolean updatePassword(int id, String userPassword);

    6.4 修改密码的UserService接口实现类

    //用户修改密码
    @Override
    public boolean updatePassword(int id, String userPassword) {
        //传数据库的连接,并获取数据库的url
        Connection connection = null;
        //定义一个布尔值的标记符,用于记录是否修改成功
        Boolean flag = false;
        try {
            //通过调用BaseDao类的对象获取数据库url的值
            connection = BaseDao.getConnection();
            //加入判断,如果dao层修改成功返回的参数值为1,失败则为0,所以需要判断其值
            if (userDao.updatePassword(connection, id, userPassword) > 0) {
                flag = true;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //最后需要关闭BaseDao,以避免浪费资源
            BaseDao.closeResource(connection, null, null);
        }
        //最后返回修改结果
        return flag;
    }

    6.5 UserServlet类的实现

    本小节遇到了诸多问题:

    1. 首先是导包问题,必须是Jakarta.servlet的包才能让sql数据库进行实现

    2. 用于接收sql语句所得信息的数组,必须与sql语句的参数顺序一致

    3. 进行旧密码的校验

     package com.mao.servlet.user;
     ​
     ​
     import com.alibaba.fastjson.JSONArray;
     import com.mao.pojo.User;
     import com.mao.service.user.UserService;
     import com.mao.service.user.UserServiceImpl;
     import com.mao.util.Constants;
     import com.mysql.cj.util.StringUtils;
     import com.mysql.cj.xdevapi.JsonArray;
     import jakarta.servlet.ServletException;
     import jakarta.servlet.http.HttpServlet;
     import jakarta.servlet.http.HttpServletRequest;
     import jakarta.servlet.http.HttpServletResponse;
     ​
     ​
     import java.io.IOException;
     import java.io.PrintWriter;
     import java.util.HashMap;
     import java.util.Map;
     ​
     import static com.mysql.cj.xdevapi.JsonArray.*;
     ​
     //实现Servlet的复用(将方法单独写出来,然后在doGet中调用即可)
     public class UserServlet extends HttpServlet {
         //需要在doGet中调用自己所写的方法,才能实现相应的操作
         @Override
         protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
             String method = req.getParameter("method");
             //点保存修改密码后,跳转至此类中的修改密码方法
             if (method.equals("savepwd") && method != null) {
                 this.updatePwd(req, resp);
             } else if (method.equals("pwdmodify") && method != null) {//修改密码前的密码验证,跳转至此类中的密码验证方法
                 this.pwdModify(req, resp);
             }
         }
     ​
         @Override
         protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
             doGet(req, resp);
         }
     ​
         //修改密码
         public void updatePwd(HttpServletRequest req, HttpServletResponse resp) {
             //从Session中拿到用户信息(User_Session中包含了用户的所有信息)
             Object object = req.getSession().getAttribute(Constants.User_Session);
             //获取新密码,用于判断密码是否为空,或者是新输入的密码是否相等
             String newpassword = req.getParameter("newpassword");
             System.out.println("UserServlet: " + newpassword);
             //定义一个标记符,用于返回修改是否成功的结果
             boolean flag = false;
             System.out.println("String的状态:" + !(StringUtils.isNullOrEmpty(newpassword)));
             //判断获取的信息是否为空,或者密码是否为空
             //这里需要用到一个jdbc已经定义好的StirngUtils
             if (object != null && !(StringUtils.isNullOrEmpty(newpassword))) {
                 System.out.println("我进入Servlet层了");
                 //不为空则可以开始调用service层以及接口进行密码的更新操作,实现抽象方法
                 UserService userService = new UserServiceImpl();
                 //调用接口后,去实现具体的方法(通过id去修改密码,有两个参数),因为updatePassword最后返回的结果是布尔值,所以需要利用标记符
                 //同时这里需要把object强制转换为User类对象,才能去调用它的get方法,获取其id,newPassword不需要是因为在这个类就可以获取到
                 flag = userService.updatePwd(((User) object).getId(), newpassword);
                 System.out.println("flag的状态:" + flag);
                 //若修改成功,则告知用户成功,并移除已经存在的Session
                 if (flag) {
                     System.out.println("我成功修改了!");
                     req.setAttribute("message", "密码修改成功,请退出,使用新密码登录");
                     //移除Session信息
                     req.getSession().removeAttribute(Constants.User_Session);
                 } else {//若失败,告知失败,
                     System.out.println("我修改失败了!");
                     req.setAttribute("message", "密码修改失败!");
                 }
             } else {
                 System.out.println("我压根进不去!");
                 req.setAttribute("message", "新密码有误");
             }
             //修改后则跳转页面,做出转发操作,跳转到修改密码的界面(其实自我认为应该跳转到登录页面)
             try {
                 req.getRequestDispatcher("pwdmodify.jsp").forward(req, resp);
             } catch (ServletException e) {
                 throw new RuntimeException(e);
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
         }
     ​
         //验证旧密码,session中有用户的密码
         public void pwdModify(HttpServletRequest req, HttpServletResponse resp) {
             //从Session中拿到ID
             Object object = req.getSession().getAttribute(Constants.User_Session);
             //从前端页面拿到旧密码
             String oldpassword = req.getParameter("oldpassword");
     ​
             //万能的Map类:结果集
             Map<String, String> resultMap = new HashMap<String, String>();
     ​
             if (object == null) {//Session失效了,Session过期了
                 resultMap.put("result", "sessionerror");
             } else if (StringUtils.isNullOrEmpty(oldpassword)) {//如果旧密码为空
                 resultMap.put("result", "error");
             } else {
                 String userPassword = ((User) object).getUserPassword();//Session中用户的密码
                 if(oldpassword.equals(userPassword)){
                     resultMap.put("result", "true");//比对成功
                 }else {
                     resultMap.put("result", "false");
                 }
             }
             try {
                 resp.setContentType("application/json");
                 PrintWriter writer = resp.getWriter();
                 //JSONArray     阿里巴巴的JSON工具类,转换格式
                 /*
                 resultMap = ["result","sessionerror","result","error"]
                 Json格式 = {key: value}
                 * */
                 writer.write(JSONArray.toJSONString(resultMap));
                 writer.flush();
                 writer.close();
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
         }
     }

5、用户管理层实现

image-20250330143256998

1. 导入分页的工具类

 package com.mao.util;
 ​
 ​
 public class PageSupport {
     //当前页码-来自于用户输入
     private int currentPageNo = 1;
 ​
     //总数量(表)
     private int totalCount = 0;
 ​
     //页面容量
     private int pageSize = 0;
 ​
     //总页数-totalCount/pageSize(+1)
     private int totalPageCount = 1;
 ​
     public int getCurrentPageNo() {
         return currentPageNo;
     }
 ​
     public void setCurrentPageNo(int currentPageNo) {
         if(currentPageNo > 0){
             this.currentPageNo = currentPageNo;
         }
     }
 ​
     public int getTotalCount() {
         return totalCount;
     }
 ​
     public void setTotalCount(int totalCount) {
         if(totalCount > 0){
             this.totalCount = totalCount;
             //设置总页数
             this.setTotalPageCountByRs();
         }
     }
     public int getPageSize() {
         return pageSize;
     }
 ​
     public void setPageSize(int pageSize) {
         if(pageSize > 0){
             this.pageSize = pageSize;
         }
     }
 ​
     public int getTotalPageCount() {
         return totalPageCount;
     }
 ​
     public void setTotalPageCount(int totalPageCount) {
         this.totalPageCount = totalPageCount;
     }
 ​
     public void setTotalPageCountByRs(){
         if(this.totalCount % this.pageSize == 0){
             this.totalPageCount = this.totalCount / this.pageSize;
         }else if(this.totalCount % this.pageSize > 0){
             this.totalPageCount = this.totalCount / this.pageSize + 1;
         }else{
             this.totalPageCount = 0;
         }
     }
 ​
 }

2. 用户列表页面的导入

count(1)比count(*)要高效,前者是查一个列表,后者则是查所有列表

3. 查询用户总数功能

(1) Dao接口的抽象方法
//查询用户总数
public int getUserCount(Connection connection,String userName,int userRole);
(2) Dao接口实现类
//根据用户名或者角色查询用户总数【最难理解的SQL语句】
@Override
public int getUserCount(Connection connection, String userName, int userRole) {
    //预编译
    PreparedStatement pstm = null;
    ResultSet rs = null;
    int count = 0;

    if (connection != null) {
        //StringBuffer在执行字符串拼接或修改操作时更加高效,这里我们要将sql语句转为此类的作用是,sql语句需要拼接
        StringBuffer sql = new StringBuffer();
        //append(String str): 将指定的字符串追加到此字符序列(接下来使用多表查询)
        sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id");
        //存放我们的参数列表,ArrayList 是一个可以动态调整大小的数组。它实现了 List 接口,可以存储重复的元素。
        ArrayList<Object> list = new ArrayList<Object>();
        //接下来进行判断
        if (!StringUtils.isNullOrEmpty(userName)) {
            sql.append("and u.userName like ?");
            list.add("%" + userName + "%");//此处list的index为0
        }
        if (userRole > 0) {
            sql.append("and u.userRole = ?");
            list.add(userRole);//此处list的index为1
        }
        //怎么把List转换为数组
        Object[] params = list.toArray();
        //输出完整的sql语句用于调试
        System.out.println("UserDaoImpl -> : " + sql.toString());
        try {
            //执行底层BaseDao的方法
            rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
            if (rs.next()) {
                //从结果集中获取最终的数量
                count = rs.getInt("count");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }
    BaseDao.closeResource(null, pstm, rs);
    return count;
}
(3) Service业务层调用Dao层进行查询操作
  1. Service层接口

//查询用户总数
public int getUserCount(String userName,int userRole);
  1. 接口实现类

@Override
public int getUserCount(String userName, int userRole) {
    //调用dao层即可,先建立连接,获取数据库连接
    Connection connection = null;
    connection = BaseDao.getConnection();
    int count = 0;
    //连接完数据库后,可以进行接口方法的调用了
    count = userDao.getUserCount(connection, userName, userRole);
    //查询完毕后,关闭资源即可
    BaseDao.closeResource(connection, null, null);
    return count;
}
  1. 单元测试

//测试是否能够根据userRole的值获取其总数(测试成功)
@Test
public void test() {
    //首先需要将此类进行实例化,才能获取方法
    UserServiceImpl userService = new UserServiceImpl();
    int count = userService.getUserCount(null, 0);//这里放的参数意思是根据userRole等于1来查询,可随意更改
    System.out.println(count);
}

4. 根据条件查询用户列表

(1) Dao接口的抽象方法
 //根据条件查询用户列表(Dao层接口)
    public List getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize) throws SQLException;
(2) Dao接口的实现类
//Dao层的接口实现类:
//根据条件查询用户列表
    @Override
    public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize) throws SQLException {
        //执行sql语句的地方,先预编译
        PreparedStatement pstm = null;
        ResultSet rs = null;
        //使用List动态存储数组(动态页)
        List<User> userList = new ArrayList<User>();
//      连接成功后,即连接不为空的情况下,继续向下走
        if (connection != null) {
            //将sql语句转换为字符流的形式,便于增加修改操作
			//实现动态拼接,若不需要则直接把sql写死
            StringBuffer sql = new StringBuffer();
            sql.append("select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole = r.id");
            //使用动态数组,存储获取到的动态人员信息(为什么需要list,一个原因是可能存在多个角色、这里需要动态的更新)最后只需要将自己add进去即可
            ArrayList<Object> list = new ArrayList<>();
            //查询所有人(只要用户名不为空则查询出来)
            if(!StringUtils.isNullOrEmpty(userName)) {
                sql.append(" and u.userName like ?");
                list.add("%" + userName + "%");
            }
            //根据用户的id来查询(区分用户角色)append用于追加sql的查询条件,限制级
            if (userRole > 0) {
                sql.append(" and u.userRole = ?");
            }
            //接下来是数据库的分页查询操作,分页使用
            //limit  startIndex  pageSize
            //当前数据包含页                  (当前页  -  1 ) * 页面大小
            // 0,5(0,1,2,3,4)                   1  0      (1-1)*5
            // 5,5(5,6,7,8,9)                   2  5      (2-1)*5
            // 10,5(10,11,12,13,14)             3  10     (3-1)*5
            sql.append("order by creationDate desc limit ?,?");//根据用户创建时间降序排序(limit限制页面展示数据从?到?)
            //那么当前页面要如何计算
            currentPageNo = (currentPageNo - 1) * pageSize;//也就是上面的公式
            list.add(currentPageNo);//将当前页存储至list动态数组中
            list.add(pageSize);//将页面大小也存储进去

            Object[] params = list.toArray();//将list对象转换为数组对象,因为我们定义的是数组对象,这样才能输出
            System.out.println("UserDaoImpl -> : " + sql.toString());//用于debug当前sql语句是否有误
            //接收Base处理的sql语句结果集
            rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
            //接收后,开始依次写入获取,用于后续的输出展示
            while (rs.next()) {
                //从数据库中读取,然后通过set方法写入user对象
                User user = new User();
                user.setId(rs.getInt("id"));
                user.setUserCode(rs.getString("userCode"));
                user.setUserName(rs.getString("userName"));
                user.setGender(rs.getInt("gender"));
                user.setBirthday(rs.getDate("birthday"));
                user.setPhone(rs.getString("phone"));
                user.setUserRole(rs.getInt("userRole"));
                user.setUserRoleName(rs.getString("userRoleName"));//role表的字段,用于对比
                //最后将user对象的值添加到userList动态数组中
                userList.add(user);
            }
            //释放资源
            BaseDao.closeResource(null, pstm, rs);
        }
        //最后返回动态数组
        return userList;
    }
(3) 业务层Service去dao层调用获取结果到页面
//根据条件查询用户列表(Service层接口)
    public List<User> getUserList(String queryUserName,int queryUserRole,int currentPage,int pageSize);
//根据条件查询用户列表(分页)
    @Override
    public List<User> getUserList(String queryUserName, int queryUserRole, int currentPage, int pageSize) {
        //预定义连接为空,后再赋值
        Connection connection = null;
        List<User> userList = null;
        System.out.println("queryUserName ---- > " + queryUserName);
        System.out.println("queryUserRole ---- > " + queryUserRole);
        System.out.println("currentPage ---- > " + currentPage);
        System.out.println("pageSize ---- > " + pageSize);
        try {
            //将BaseDao中处理的数据用connection接收
            connection = BaseDao.getConnection();
            userList = userDao.getUserList(connection, queryUserName, queryUserRole, currentPage, pageSize);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        //关闭资源
        BaseDao.closeResource(connection, null, null);
        return userList;
    }

5、获取角色列表

(1) dao层接口的定义与接口实现
package com.mao.dao.role;

import com.mao.pojo.Role;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

public interface RoleDao {
    //获取角色列表,只需要连接即可,抽象方法
    public List<Role> getRoleList(Connection connection) throws SQLException;
}
package com.mao.dao.role;

import com.mao.dao.BaseDao;
import com.mao.pojo.Role;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class RoleDaoImpl implements RoleDao {
    //获取角色列表
    @Override
    public List<Role> getRoleList(Connection connection) throws SQLException {
        //预编译
        PreparedStatement pstm = null;
        //结果集
        ResultSet rs = null;
        //多角色列表需要List集合存储
        ArrayList<Role> roleList = new ArrayList<>();
        //如果连接不为空,即连接上数据库
        if (connection != null) {
            //这里不需要去给sql进行扩展操作,直接写死就可以
            String sql = "select * from smbms_role";
            //需要一个数组进行存储从数据库中所获取的信息,初始值为空
            Object[] params = {};
            //去BaseDao底层执行sql语句再返回结果集,dao层接触底层,所以是执行sql,而service则是过来获取
            rs = BaseDao.execute(connection, pstm, rs, sql, params);
            //开始读取写入到网页端,反馈数据
            while (rs.next()) {
                Role role = new Role();
                role.setId(rs.getInt("id"));
                role.setRoleName(rs.getString("roleName"));
                role.setRoleCode(rs.getString("roleCode"));
                //最后把自己这个对象添加到结果集
                roleList.add(role);
            }
            //关闭资源
            BaseDao.closeResource(null, pstm, rs);
        }
        return roleList;
    }
}
(2) Service层(接口与实现)
package com.mao.service.role;

import com.mao.pojo.Role;

import java.util.List;

public interface RoleService {
    //与dao层的抽象方法相对应,只是少了connection
    //查询角色列表
    public List<Role> getRoleList();
}
package com.mao.service.role;

import com.mao.dao.BaseDao;
import com.mao.dao.role.RoleDao;
import com.mao.dao.role.RoleDaoImpl;
import com.mao.pojo.Role;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class RoleServiceImpl implements RoleService {
    //实例化RoleService,再通过一个构造函数去访问dao层,引入dao层
    private RoleDao roleDao;

    public RoleServiceImpl(RoleDao roleDao) {
        //这里的赋值不能是简单的this指向,而是需要去调用接口
        roleDao = new RoleDaoImpl();
    }

    //实现抽象方法(获取角色列表)
    public List<Role> getRoleList() {
        //连接数据库执行操作
        Connection connection = null;
        ResultSet rs = null;
        List<Role> roleList = null;
        try {
            //利用service层去dao层获取数据库的连接
            connection = BaseDao.getConnection();
            //获取数据库的连接后去调用想要使用的方法
            roleList = roleDao.getRoleList(connection);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {//最后关闭资源
            BaseDao.closeResource(connection, null, null);
        }
        return roleList;
    }
}

6、用户管理功能的实现(Servlet层)【重难点】

else if (method.equals("query") && method != null) {//对应前端页面head.jsp中的点击事件,响应其方法
    //跳转当前类中的方法
    this.query(req, resp);
}
  1. 引入PageSupport.java,与前端的method --- name相对应

  2. 获取用户前端的数据(查询)

  3. 判断请求是否需要执行,看参数的值进行判断

  4. 为了实现分页,需要计算出当前页面和总页面,页面大小

  5. 用户列表展示

  6. 最后返回前端

//查询用户列表(方法体传入请求、相应参数)
public void query(HttpServletRequest req, HttpServletResponse resp) {
    //每次的数据是单次获取的,而不是在session中获取(否则每次点到这个页面都需要清除再相应)
    /*额外的请求:
              属性从前端进行获取(获取关键信息,如用户编码、用户名称即可,因为都有一个额外的请求)
              根据用户名查询用户、根据用户角色查询用户、根据页面页码跳转页面、根据总记录数获取总共页数,所以需要以下几个属性
              做了个表单的操作,文本框那些,req.getParameter() 的参数是前端元素的 name 属性。
   */
    String queryName = req.getParameter("queryname");//后面解析的参数必须与前端输入框的name属性值进行对应
    String queryUserRoleTemp = req.getParameter("queryUserRole");//这三个变量都是初始化加载,反映在前端的数据
    String pageIndex = req.getParameter("pageIndex");//从前端获取的当前页码
    //默认定义当前角色为0,即系统管理员(主要是防止系统报错)
    int queryUserRole = 0;

    //获取用户列表(需要去service中业务拿取,然后在业务层中,又会去主动调用dao层进行连接数据库获取信息)
    UserService userService = new UserServiceImpl();
    List<User> userList = null;//需要一个动态数组去存储未知容量的数据

    //第一次走这个请求,一定是第一页,页面大小是固定的
    int pageSize = 5;//如果用户的需求不是每页5个数据展示,可以将这个字段定义在配置文件中,用户就可以不用通过更改代码来达到其目的
    int currentPageNo = 1;//进入管理页面,默认第一页

    //这三个if判断,对应的是前端查询页面的,用户名文本框、用户角色下拉框以及当前页面
    if (queryName == null) {//如果前端获取的用户名为null,那么则赋空字符串,也就是进入页面后,看到文本框是空的
        queryName = "请键入数据";
    }
    if (queryUserRoleTemp != null && !queryUserRoleTemp.equals("")) {
        //如果用户在下拉框进行选择了,那就进入判断,将前端传来的数据进行解析,给到我们想要的结果返回在前端页面,如userRole为0,1,2,3
        queryUserRole = Integer.parseInt(queryUserRoleTemp);
    }
    if (pageIndex != null) {
        currentPageNo = Integer.parseInt(pageIndex);//解析前端的页码给后端
    }

    //获取用户的总数(分页:上一页,下一页的情况)
    int totalCount = userService.getUserCount(queryName, queryUserRole);
    //总页数支持
    PageSupport pageSupport = new PageSupport();
    pageSupport.setCurrentPageNo(currentPageNo);//设置当前的页码值
    pageSupport.setPageSize(pageSize);//设置当前页面大小
    pageSupport.setTotalCount(totalCount);//设置当前总页数

    int totalPageCount = pageSupport.getTotalPageCount();//获取总页面数

    //控制首页和尾页
    //如果页面要小于1了,就显示第一页的东西
    if (currentPageNo < 1) {
        currentPageNo = 1;
    } else if (currentPageNo > totalPageCount) {//当前页面大于了最后一页,即显示最后一页
        currentPageNo = totalPageCount;
    }

    //获取用户列表展示(根据条件查询用户列表时,同样页面要展示其他几个数据)
    userList = userService.getUserList(queryName, queryUserRole, currentPageNo, pageSize);
    req.setAttribute("userList", userList);//引号内是后续通过它来获取数据的
    //调用service层,再间接调用dao层
    RoleService roleService = new RoleServiceImpl();
    //获取角色列表
    List<Role> roleList = null;
    roleList = roleService.getRoleList();
    req.setAttribute("roleList", roleList);
    req.setAttribute("queryName", queryName);
    req.setAttribute("queryUserRole", queryUserRole);
    req.setAttribute("totalPageCount", totalPageCount);
    req.setAttribute("currentPageNo", currentPageNo);
    req.setAttribute("totalCount", totalCount);

    //返回前端
    try {
        req.getRequestDispatcher("userlist.jsp").forward(req,resp);
    } catch (ServletException e) {
        throw new RuntimeException(e);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值