JavaWeb项目SMBMS(二)——需求实现

【狂神说】SMBMS

本项目基于狂神说Java的SMBMS项目,用于个人学习。

开发工具

  • IntelliJ IDEA 2022.2.3
  • MySQL9.0
  • Tomcat 9

项目架构:

项目主要分为四个核心模块

  • 登录注销
  • 用户管理
  • 订单管理
  • 供应商管理

JavaWeb项目SMBMS(二)——需求实现

1、数据库表

项目需要用到以下数据表,读者朋友可在公众号后台回复sql获得创建所有数据库表的sql。

JavaWeb项目SMBMS(二)——需求实现

该表通过smbms.sql一键生成

1.1、用户表

JavaWeb项目SMBMS(二)——需求实现

1.2、角色表

JavaWeb项目SMBMS(二)——需求实现

1.3、地址表

JavaWeb项目SMBMS(二)——需求实现

1.4、账单表

JavaWeb项目SMBMS(二)——需求实现

1.5、供应商表

JavaWeb项目SMBMS(二)——需求实现

2、搭建项目

2.1、创建webapp项目(Maven)

注意:勾选的原型是maven-archetype-webapp

JavaWeb项目SMBMS(二)——需求实现

2.2、完善项目结构

1. 更新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. 在pom.xml中导入依赖包

  • jsp
  • servlet
  • 数据库连接
  • jstl
  • standard
 <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!--servlet依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!--jsp依赖-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>

        <!--jstl依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</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.31</version>
        </dependency>
    </dependencies>

3. 完善项目的包结构

完善项目结构

  1. java
    • dao:数据持久化层,用于操作数据库
    • filter:过滤器
    • pojo:实体类
    • service:业务层,调用dao层处理业务
    • servlet:调用service层处理业务
    • util:工具类
  2. resources:存放资源文件
  3. webapp:项目资源

JavaWeb项目SMBMS(二)——需求实现

2.3、配置tomcat

选择war包

JavaWeb项目SMBMS(二)——需求实现

修改路径为/smbms

JavaWeb项目SMBMS(二)——需求实现JavaWeb项目SMBMS(二)——需求实现

启动tomcat服务,访问成功,注意这个路径就是我们前面配置tomcat时设置的路径。

JavaWeb项目SMBMS(二)——需求实现

2.4、在idea中连接数据库

datasource选择MySQL

JavaWeb项目SMBMS(二)——需求实现

填写数据库配置,测试连接。

JavaWeb项目SMBMS(二)——需求实现

2.5、创建实体类

ORM映射,表->类。由于地址表并没有具体含义,因此只需要创建四张表的实体类。

1. User

pojo-User.java

除了User表的字段,这里还增加了两个字段:age(年龄)和userRoleName(用户角色名称)字段。其中年龄字段通过当前时间-出生时间获得,用户角色名称字段是为了匹配用户角色表。其他字段的get和set方法直接通过IDEA快速创建(篇幅原因省略这部分代码)。

package com.thomas.pojo;

import java.util.Date;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 11:12
 * @Description User用户表实体类
 * @Since version-1.0
 */

public class User {
    private Integer id; //用户id
    private String userCode; //用户编码
    private String userName; //用户名称
    private String userPassword; //用户密码
    private Integer gender; //用户性别(1:女、2:男)
    private Date birthday; //出生日期
    private String phone; //手机号码
    private String address; //用户地址
    private Integer userRole; //用户角色(取自角色表-角色id)
    private Integer createdBy; //创建者(userId)
    private Date creationDate; //创建时间
    private Integer modifyBy; //更新者(userId)
    private Date modifyDate; //修改时间

    private Integer age; //年龄 通过当前时间-出生年份得出
    private String userRoleName; //用户角色名称

    public String getUserRoleName() {
        return userRoleName;
    }

    public void setUserRoleName(String userRoleName) {
        this.userRoleName = userRoleName;
    }

    public Integer getAge() {
        Date date = new Date();
        Integer age = date.getYear() - birthday.getYear();
        return age;
    }
 ...
}

2. Role

pojo-Role.java

直接参照Role表的字段生成实体类,所有字段的get和set方法直接通过IDEA快速创建(篇幅原因省略这部分代码)。

package com.thomas.pojo;

import java.util.Date;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 11:34
 * @Description Role实体类
 * @Since version-1.0
 */


public class Role {
    private Integer id; //id
    private String roleCode; //用户编码
    private Integer createdBy; //创建者
    private Date creationDate; //创建时间
    private Integer modifyBy; //修改者
    private Date modifyDate; //修改时间

    ...
}

3. Provider

pojo-Provider.java

直接参照Provider表的字段生成实体类,所有字段的get和set方法直接通过IDEA快速创建(篇幅原因省略这部分代码)。

package com.thomas.pojo;

import java.util.Date;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 11:38
 * @Description 供应商实体类
 * @Since version-1.0
 */


public class Provider {
    private Integer id; //id
    private String proCode; //供应商编码
    private String proName; //供应商名称
    private String proDesc; //供应商详细描述
    private String proContact; //供应商联系人
    private String proPhone; //联系电话
    private String proFax; //传真
    private Integer createdBy; //创建者(userId)
    private Date creationDate; //创建时间
    private Integer modifyBy; //更新者(userId)
    private Date modifyDate; //修改时间

    ...
}

4. Bill

pojo-Bill.java

除了Bill表的字段,这里还增加了providerName(供应商名字)字段。所有字段的get和set方法直接通过IDEA快速创建(篇幅原因省略这部分代码)。

package com.thomas.pojo;

import java.math.BigDecimal;
import java.util.Date;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 11:44
 * @Description 订单表实体类
 * @Since version-1.0
 */


public class Bill {
    private Integer id; //id
    private String billCode; //账单编码
    private String productName; //商品名称
    private String productDesc; //商品描述
    private String productUnit; //商品单位
    private BigDecimal productCount; //商品数量
    private BigDecimal totalPrice; //商品总额
    private Integer isPayment; //是否支付(1-未支付 2-已支付)
    private Integer createdBy; //创建者(userId)
    private Date creationDate; //创建时间
    private Integer modifyBy; //更新者(userId)
    private Date modifyDate; //修改时间

    private String providerName; //供应商名字

    ...
}

2.6、编写BaseDao

1. 创建数据库配置文件

resources目录下创建db.properties,写入数据库配置

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?userUnicode=true%characterEncoding=utf-8
username=root
password=密码

2. 编写公共方法

编写公共方法,便于其他Dao直接调用

  • 加载驱动(使用静态代码块)
  • 获取数据库连接
  • 执行SQL语句(增删改查)
  • 关闭相关连接

dao-BaseDao.java

package com.thomas.dao;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 13:30
 * @Description 操作数据库的公共类
 * @Since version-1.0
 */

public class BaseDao {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;
    
    //静态代码块,类加载的时候就初始化了
    static {
        Properties prop = new Properties();
        //通过类加载器读取对应的资源
        InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
        try {
            prop.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }

        driver = prop.getProperty("driver");
        url = prop.getProperty("url");
        username = prop.getProperty("username");
        password = prop.getProperty("password");
    }

    /**
     * @Author GeekThomas
     * @Date 2023/1/12 13:39
     * @Description 获取数据库的连接
     * @Param
     * @Return {@link Connection}
     * @Since version-1.0
     */


    public static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return connection;
    }

    /**
     * @Author GeekThomas
     * @Date 2023/1/12 13:45
     * @Description 查询公共方法
     * @Param connection
     * @Param preparedStatement
     * @Param resultSet
     * @Param sql
     * @Param params 查询sql中的参数
     * @Return {@link ResultSet}
     * @Since version-1.0
     */


     public static ResultSet execute(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet, String sql, Object[] params) throws SQLException {
        preparedStatement = connection.prepareStatement(sql);

        for (int i = 0; i < params.length; i++) {
            //占位符从1开始,数组从0开始!
            preparedStatement.setObject(i + 1, params[i]);
        }
        resultSet = preparedStatement.executeQuery();
        return resultSet;
    }
    
    /**
     * @Author GeekThomas
     * @Date 2023/1/12 13:52
     * @Description 编写增删改的公共方法
     * @Param connection
     * @Param preparedStatement
     * @Param sql
     * @Param params
     * @Return {@link int}
     * @Since version-1.0
     */


    public static int execute(Connection connection, PreparedStatement preparedStatement, String sql, Object[] params) throws SQLException {
        preparedStatement = connection.prepareStatement(sql);

        for (int i = 0; i < params.length; i++) {
            //占位符从1开始,数组从0开始!
            preparedStatement.setObject(i + 1, params[i]);
        }
        int updateRows = preparedStatement.executeUpdate();
        return updateRows;
    }

    /**
     * @Author GeekThomas
     * @Date 2023/1/12 13:58
     * @Description 关闭资源
     * @Param preparedStatement
     * @Param resultSet
     * @Return {@link boolean}
     * @Since version-1.0
     */


    public static boolean closeResources(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {
        boolean flag = true;

        if (resultSet != null) {
            try {
                resultSet.close();
                //GC回收
                resultSet = null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
        }

        if (preparedStatement != null) {
            try {
                preparedStatement.close();
                //GC回收
                preparedStatement = null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
        }

        if (connection != null) {
            try {
                connection.close();
                //GC回收
                connection = null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
        }

        return flag;
    }
}

2.7、过滤器

编写过滤器,解决乱码问题(这里有个大坑,可以看下功能开发-用户管理-增中对这部分的扩充内容)

filter-CharacterEncodingFilter.java

package com.thomas.filter;

import javax.servlet.*;
import java.io.IOException;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 14:29
 * @Description 处理乱码过滤器
 * @Since version-1.0
 */


public class CharacterEncodingFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");

        filterChain.doFilter(servletRequest, servletResponse);
    }

    public void destroy() {
    }
}

注册Filter

web.xml

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.thomas.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/smbms/*</url-pattern>
    </filter-mapping>

2.8、导入资源

导入以下静态资源,注意要放在webapp目录下

JavaWeb项目SMBMS(二)——需求实现

3、功能开发

需要开发的功能

  • 登录注销功能(权限拦截)
  • 密码修改功能
  • 用户管理功能

本次开发聚焦于后端开发,因此前端页面直接用已经实现好的页面。

开发方式:自顶向下分析,自底向上实现

3.1、登录功能

登录功能的架构设计如下所示:

JavaWeb项目SMBMS(二)——需求实现

1. 编写前端页面

在webapp下新建login.jsp,这里我们直接用写好的

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/1/27
  Time: 12:31
  To change this template use File | Settings | File Templates.
--%>
<%@ 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}/css/style.css">
    <script>

    </script>
</head>
<body class="login_bg">
<section class="loginBox">
    <header class="loginHeader">
        <h1>超市订单管理系统</h1>
    </header>
    <section class="loginCont">
        <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>

2. 设置首页

web.xml中设置欢迎页,这样就不会自动跳转到index.jsp

    <!--设置欢迎页面-->
    <welcome-file-list>
        <welcome-file>/login.jsp</welcome-file>
    </welcome-file-list>

JavaWeb项目SMBMS(二)——需求实现

3. DAO层

Dao层主要是实现与数据库交互,根据userCode在数据库中完成查询,找到userCode对应的用户。这里我们在dao下新建目录user,在其中定义UserDao接口和接口的实现类。

JavaWeb项目SMBMS(二)——需求实现

UserDao接口

定义getLoginUser方法,在数据库中完成查询,返回要登录的User对象。

package com.thomas.dao.user;

import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:49
 * @Description 用户接口类
 * @Since version-1.0
 */


public interface UserDao {
    //得到要登录的用户
    public User getLoginUser(Connection connection, String userCode) throws SQLException;
}

实现UserDao接口

package com.thomas.dao.user;

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

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:50
 * @Description 实现用户接口UserDao
 * @Since version-1.0
 */


public class UserDaoImpl implements UserDao {
    /**
     * @Author GeekThomas
     * @Date 2023/1/12 16:50
     * @Description 在数据库中根据userCode查询登录用户
     * @Param connection
     * @Param userCode
     * @Return {@link User}
     * @Since version-1.0
     */

    
    public User getLoginUser(Connection connection, String userCode) throws SQLException {
        PreparedStatement ps = null;
        ResultSet rs = null;
        Object[] params = {userCode};

        User user = null;

        //如果拿到了数据库连接
        if (connection != null) {
            String sql = "select * from smbms_user where userCode = ?;";
            rs = BaseDao.execute(connection, ps, rs, sql, params);

            if (rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setUserCode(userCode);
                user.setUserPassword(rs.getString("userPassword"));
                user.setUserName(rs.getString("userName"));
                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.setCreatedBy(rs.getInt("createdBy"));
                user.setCreationDate(rs.getTimestamp("creationDate"));
                user.setModifyBy(rs.getInt("modifyBy"));
                user.setModifyDate(rs.getTimestamp("modifyDate"));
            }
            BaseDao.closeResources(null, ps, rs);
        }
        return user;
    }
}

4. Service层

service层也需要定义接口和实现接口的类,由于service层是实现业务的层,因此这里需要调用dao层。

JavaWeb项目SMBMS(二)——需求实现

UserService接口

定义login方法,通过校验userCodepassword,来返回User对象

package com.thomas.service.user;

import com.thomas.pojo.User;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:31
 * @Description 用户业务类
 * @Since version-1.0
 */


public interface UserService {
    public User login(String userCode, String password);
}

实现UserService接口

package com.thomas.service.user;

import com.thomas.dao.BaseDao;
import com.thomas.dao.user.UserDao;
import com.thomas.dao.user.UserDaoImpl;
import com.thomas.pojo.User;
import org.junit.Test;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:33
 * @Description 实现用户service接口
 * @Since version-1.0
 */


public class UserServiceImpl implements UserService {
    //业务层会调用dao层,所以需要引入dao
    private UserDao userDao;

    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }

    /**
     * @Author GeekThomas
     * @Date 2023/1/12 17:33
     * @Description 业务层调用dao层,获取登录的用户,并对用户名密码进行验证
     * @Param userCode
     * @Param password
     * @Return {@link User}
     * @Since version-1.0
     */


    public User login(String userCode, String password) {
        Connection connection = null;
        User user = null;

        try {
            connection = BaseDao.getConnection();
            //通过业务层调用对应的具体的数据库操作
            user = userDao.getLoginUser(connection, userCode);
            System.out.println((user != null) && password.equals(user.getUserPassword()));
            //验证用户名和密码,如果未查询到user或者密码错误,则返回空
            if (user == null || !password.equals(user.getUserPassword())) {
                user = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return user;
    }
}

5. Servlet层

Servlet层需要处理前端的登录请求,调用service层完成用户验证,并完成视图跳转。

用户登录成功:将该用户存储在 Session中,重定向到后台页面

用户登录失败:设置提醒,通过请求转发到登录页

JavaWeb项目SMBMS(二)——需求实现

LoginServlet

Constants类定义需要用到的常量。

package com.thomas.servlet.user;

import com.thomas.pojo.User;
import com.thomas.service.user.UserServiceImpl;
import com.thomas.util.Constants;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String userCode = req.getParameter("userCode");
        String password = req.getParameter("userPassword");

        UserServiceImpl userService = new UserServiceImpl();
        User user = userService.login(userCode, password);

        if (user != null) {
            //将用户保存到Session
            req.getSession().setAttribute(Constants.USER_SESSION, user);
            //重定向到后台主页
            resp.sendRedirect("jsp/frame.jsp");
        } else {
            //通过请求转发携带参数
            req.setAttribute("error""用户名或密码错误");
            //请求转发到登录页面
            req.getRequestDispatcher("login.jsp").forward(req, resp);
        }
    }

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

在web.xml中完成注册

<!--登录Servlet-->
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.thomas.servlet.user.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login.do</url-pattern>
    </servlet-mapping>

导入资源

这里需要注意前端文件中的路径。

JavaWeb项目SMBMS(二)——需求实现

输入错误密码,提示:

JavaWeb项目SMBMS(二)——需求实现

登录成功,跳转到后台管理页面

JavaWeb项目SMBMS(二)——需求实现

这里顺便修复一个小bug:在登录完成跳转到后台后,并没有显示用户名。这里通过查看frame.jsp的源代码可以发现,jsp页面中使用的Session名应该为userSession,将util.Constants中的常量进行修改,即可正常显示用户名。

JavaWeb项目SMBMS(二)——需求实现

这里如果出现显示时间出现乱码的问题,可以使用以下方法:

在IDEA中将time.js修改为add bom,然后ctrl+shift+del删除浏览器缓存,或者ctrl+F5强制刷新,然后重新启动服务器。如下图所示,页面出现乱码可以通过该方法解决。

JavaWeb项目SMBMS(二)——需求实现

3.2、登录功能优化

1. 注销登录功能

LogoutServlet

定义注销登录服务

servlet.user-LogoutServlet

package com.thomas.servlet.user;

import com.thomas.util.Constants;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //注销直接移除Session中定义的变量
        Object userSession = req.getSession().getAttribute(Constants.USER_SESSION);
        if (userSession != null) {
            req.getSession().removeAttribute(Constants.USER_SESSION);
            //重定向到登录页面
            resp.sendRedirect("login.jsp");
        }
    }

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

在web.xml中完成注册

    <!--注销登录-->
    <servlet>
        <servlet-name>LogoutServlet</servlet-name>
        <servlet-class>com.thomas.servlet.user.LogoutServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LogoutServlet</servlet-name>
        <url-pattern>/logout.do</url-pattern>
    </servlet-mapping>

2. 权限过滤

在退出界面之后,我们返回到登录页面,可以发现还是能直接访问到localhost:8080/smbms/jsp/frame.jsp,因此我们需要做权限过滤。通过过滤器将未登录的请求进行拦截。

编写过滤器,进行权限过滤,拦截未登录用户请求

filter-SysFilter.java

package com.thomas.filter;

import com.thomas.util.Constants;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class SysFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //将req和resp转成HttpServletRequest和HttpServletResponse
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        Object userSession = request.getSession().getAttribute(Constants.USER_SESSION);
        //如果用户未登录或者已注销
        if (userSession == null) {
            response.sendRedirect(request.getContextPath() + "/error.jsp");
        }

        filterChain.doFilter(request, response);
    }

    public void destroy() {
    }
}

在web.xml中注册Filter

<!--权限验证-未登录拦截-->
<filter>
    <filter-name>SysFilter</filter-name>
    <filter-class>com.thomas.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SysFilter</filter-name>
    <url-pattern>/jsp/*</url-pattern>
</filter-mapping>

用户在未登录状态下访问管理页面,则跳转到error.jsp

3.3、修改密码

修改密码的架构图如下:客户从前端发送修改密码的请求,Servlet接收请求,调用service层的服务,对密码进行修改。而service层则是通过调用dao层,实现在数据库中修改密码。

我们遵循从底层到顶层的开发原则,先编写Dao接口,然后实现在数据库中修改密码的方法。在service层调用dao层,判断密码是否修改成功。如果修改成功,则在servlet中处理请求,并重新跳转页面。

JavaWeb项目SMBMS(二)——需求实现

1. DAO层

在UserDao接口中定义修改用户密码方法,接收参数为:数据库连接,用户id,要修改的新密码

public interface UserDao {
    //得到要登录的用户
    public User getLoginUser(Connection connection, String userCode) throws SQLException;

    //修改用户密码
    public int modifyPassword(Connection connection, int id, String newPassword) throws SQLException;
}

在UserDaoImpl类中实现接口的修改密码方法,编写sql,根据用户id查询到唯一用户完成密码修改。

package com.thomas.dao.user;

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

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:50
 * @Description 实现用户接口UserDao
 * @Since version-1.0
 */


public class UserDaoImpl implements UserDao {
 ...

    /**
     * @Author GeekThomas
     * @Date 2023/1/14 18:34
     * @Description 修改数据库中用户密码
     * @Param connection
     * @Param id
     * @Param newPassword
     * @Return {@link int}
     * @Since version-1.0
     */


    public int modifyPassword(Connection connection, int id, String newPassword) throws SQLException {
        PreparedStatement ps = null;
        int execute = 0;

        if (connection != null) {
            String sql = "update smbms_user set userPassword = ? where id = ?";
            Object params[] = {newPassword, id};
            execute = BaseDao.execute(connection, ps, sql, params);
            BaseDao.closeResources(null, ps, null);
        }

        return execute;
    }
}

2. Service层

在UserService接口中定义修改用户密码方法,接收参数为:用户id,要修改的新密码

public interface UserService {
    public User login(String userCode, String password);

    public boolean modifyPassword(int id, String password);
}

在UserServiceImpl类中实现修改用户密码方法,在service层处理业务,这里主要就是判断更新密码是否成功。

package com.thomas.service.user;

import com.thomas.dao.BaseDao;
import com.thomas.dao.user.UserDao;
import com.thomas.dao.user.UserDaoImpl;
import com.thomas.pojo.User;
import org.junit.Test;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:33
 * @Description 实现用户service接口
 * @Since version-1.0
 */


public class UserServiceImpl implements UserService {
    //业务层会调用dao层,所以需要引入dao
    private UserDao userDao;

    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }

 ...

    /**
     * @Author GeekThomas
     * @Date 2023/1/14 18:36
     * @Description 业务层调用dao层,判断是否更新成功,如果更新失败,业务层需要回滚事务
     * @Param id
     * @Param password
     * @Return {@link boolean}
     * @Since version-1.0
     */

    
    public boolean modifyPassword(int id, String password) {
        Connection connection = null;
        boolean flag = false;

        try {
            connection = BaseDao.getConnection();
            int i = userDao.modifyPassword(connection, id, password);
            if (i > 0) {
                flag = true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return flag;
    }
}

3. Servlet层

本项目中,多个页面用到 UserServlet,只是调用的方法不同;

考虑到复用性,抽取方法。判断页面发送的是哪个请求,再调用相应方法。

UserServlet实现服务器端密码验证

这里需要对前端调用的方法进行验证,因为修改密码首先要验证旧密码,然后再修改新密码,所以这里其实需要验证两个方法。

package com.thomas.servlet.user;

import com.alibaba.fastjson.JSONArray;
import com.mysql.cj.util.StringUtils;
import com.thomas.pojo.User;
import com.thomas.service.user.UserServiceImpl;
import com.thomas.util.Constants;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");
        if (method != null && "savepwd".equals(method)) {
            this.modifyPassword(req, resp);
        } else if (method != null && "pwdmodify".equals(method)) {
            this.verifyPassword(req, resp);
        }
    }
}
验证旧密码

这里我们使用ajax提交请求,因此需要向前端传递一个json对象。用户的旧密码只需要从Session中就能获得。

    /**
     * @Author GeekThomas
     * @Date 2023/1/14 19:24
     * @Description 验证旧密码,从Session中获取旧密码
     * @Param req
     * @Param resp
     * @Return
     * @Since version-1.0
     */


    public void verifyPassword(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object o = req.getSession().getAttribute(Constants.USER_SESSION);
        String oldPassword = req.getParameter("oldpassword");

        Map<String, String> resultMap = new HashMap<String, String>();
        resultMap.put("method""pwdmodify");
        if (o == null) {
            //用户未登录
            resultMap.put("result""sessionerror");
        } else if (StringUtils.isNullOrEmpty(oldPassword)) {
            //密码输入为空
            resultMap.put("result""error");
        } else {
            String password = ((User) o).getUserPassword();
            if (oldPassword.equals(password)) {
                //密码输入正确
                resultMap.put("result""true");
            } else {
                //密码输入失败
                resultMap.put("result""false");
            }
        }

        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(JSONArray.toJSONString(resultMap));
        writer.flush();
        writer.close();
    }

对应的前端代码pwdmodify.js构造的ajax请求:

$.ajax({
    type:"GET",
    url:path+"/jsp/user.do",
    data:{method:"pwdmodify",oldpassword:oldpassword.val()},
    dataType:"json",
    success:function(data){
    if(data.result == "true"){//旧密码正确
     validateTip(oldpassword.next(),{"color":"green"},imgYes,true);
    }else if(data.result == "false"){//旧密码输入不正确
     validateTip(oldpassword.next(),{"color":"red"},imgNo + " 原密码输入不正确",false);
    }else if(data.result == "sessionerror"){//当前用户session过期,请重新登录
     validateTip(oldpassword.next(),{"color":"red"},imgNo + " 当前用户session过期,请重新登录",false);
    }else if(data.result == "error"){//旧密码输入为空
    v alidateTip(oldpassword.next(),{"color":"red"},imgNo + " 请输入旧密码",false);
    }
    },
    error:function(data){
    //请求出错
     validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请求错误",false);
    }
});
修改新密码

调用业务层的修改密码代码,如果修改成功,则重新登录

/**
 * @Author GeekThomas
 * @Date 2023/1/14 19:20
 * @Description 调用service层的修改密码,完成密码修改,若修改成功,则重新登录
 * @Param req
 * @Param resp
 * @Return
 * @Since version-1.0
 */


public void modifyPassword(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String newPassword = req.getParameter("newpassword");
    Object o = req.getSession().getAttribute(Constants.USER_SESSION);

    //获取到用户和新密码
    if (o != null && !StringUtils.isNullOrEmpty(newPassword)) {
        UserServiceImpl userService = new UserServiceImpl();
        User user = (User) o;
        Integer id = user.getId();
        boolean flag = userService.modifyPassword(id, newPassword);
        //密码修改成功
        if (flag) {
            req.setAttribute(Constants.MESSAGE, "密码修改成功,请使用新密码重新登录");
            req.getSession().removeAttribute(Constants.USER_SESSION);
        } else {
            req.setAttribute(Constants.MESSAGE, "密码修改失败");
        }
    } else {
        req.setAttribute(Constants.MESSAGE, "新密码输入错误");
    }
    req.getRequestDispatcher("pwdmodify.jsp").forward(req, resp);
}

在web.xml中注册:修改密码的UserServlet以及设置会话过期时间

    <!--修改密码-->
    <servlet>
        <servlet-name>UserServlet</servlet-name>
        <servlet-class>com.thomas.servlet.user.UserServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>UserServlet</servlet-name>
        <url-pattern>/jsp/user.do</url-pattern>
    </servlet-mapping>

 <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

密码修改成功页面如下所示:

JavaWeb项目SMBMS(二)——需求实现

碰到的一个问题,密码修改之后提交请求,报错

JavaWeb项目SMBMS(二)——需求实现JavaWeb项目SMBMS(二)——需求实现

经过排查,实际上是前面BaseDao代码有误,executeUpdate()不需要传递参数。

JavaWeb项目SMBMS(二)——需求实现

3.4、用户分页查询

在我们点击用户管理时,实际上就是发送请求,然后在数据库中进行查询的功能,可以通过用户名进行查询(模糊匹配)或者通过用户角色进行查询。具体的架构设计如下图所示:

JavaWeb项目SMBMS(二)——需求实现
image-20230119214303401

查询效果如下:

JavaWeb项目SMBMS(二)——需求实现

在进行用户分页列表查询时,需要从数据库中查询以下数值:

  • 用户列表
  • 角色列表
  • 记录数

1. 查询用户列表

DAO层

dao-user.UserDao.java

可以通过用户名或者用户角色来进行查询,所以需要传递username以及userRole参数;同时还可以分页查询,这里需要用到currentPageNo(当前页码)和pageSize(页面容量)

package com.thomas.dao.user;

import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:49
 * @Description 用户接口类
 * @Since version-1.0
 */


public interface UserDao {
    ...

    //获取用户列表
    public List<User> getUserList(Connection connection, String username, int userRole, int currentPageNo, int pageSize) throws SQLException;
}

UserDaoImpl中实现UserDao接口,因为用户管理页面中需要呈现用户的基本信息和用户角色,所以需要连表查询(userrole)。

这里需要传递的sql如下所示:

select u.*, r.roleName 
from smbms_user u, smbms_role r 
where u.userRole = r.id 
and u.userName like '%username%'
and r.id = userRole
limit a, b

这里我们需要拼接sql,传入参数列表。同时需要传递当前页面的起始记录,当前页面从1开始计算。

currentNo = pageSize * (currentPageNo - 1)

对查询的结果集进行遍历,将用户信息存储到用户列表。

package com.thomas.dao.user;

import com.mysql.cj.util.StringUtils;
import com.thomas.dao.BaseDao;
import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:50
 * @Description 实现用户接口UserDao
 * @Since version-1.0
 */


public class UserDaoImpl implements UserDao {
 ...

    /**
     * @Author GeekThomas
     * @Date 2023/1/17 23:44
     * @Description 获取用户列表(可能会需要根据用户名,用户角色筛选)
     * @Param connection
     * @Param username
     * @Param userRole
     * @Param currentPageNo
     * @Param pageSize
     * @Return {@link List< User>}
     * @Since version-1.0
     */


    public List<User> getUserList(Connection connection, String username, int userRole, int currentPageNo, int pageSize) throws SQLException {
        PreparedStatement ps = null;
        ResultSet rs = null;
        //存储分页查询的用户列表
        ArrayList<User> users = new ArrayList<User>();
        if (connection != null) {
            StringBuffer sql = new StringBuffer();
            sql.append("select u.*, r.roleName from smbms_user u, smbms_role r where u.userRole = r.id");
            List<Object> paramList = new ArrayList<Object>();

            //增加用户名字的筛选
            if (!StringUtils.isNullOrEmpty(username)) {
                sql.append(" and u.userName like ?");
                paramList.add("%" + username + "%");
            }

            //增加用户角色的筛选
            if (userRole > 0) {
                sql.append(" and r.id = ?");
                paramList.add(userRole);
            }

            //实现分页的功能
            sql.append(" order by u.creationDate limit ?, ?");
            //当前页面的起始记录,如果页面容量为5,那么就是
            //limit 0, 5(第一页)
            //limit 5, 5(第二页)
            int currentNo = (currentPageNo - 1) * pageSize;
            paramList.add(currentNo);
            paramList.add(pageSize);

            Object[] params = paramList.toArray();
            System.out.println("sql ---> " + sql.toString());
            rs = BaseDao.execute(connection, ps, rs, sql.toString(), params);

            while (rs.next()) {
                User _user = new User();
                _user.setId(rs.getInt("id"));
                _user.setUserCode(rs.getString("userCode"));
                _user.setUserPassword(rs.getString("userPassword"));
                _user.setUserName(rs.getString("userName"));
                _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.setCreatedBy(rs.getInt("createdBy"));
                _user.setCreationDate(rs.getTimestamp("creationDate"));
                _user.setModifyBy(rs.getInt("modifyBy"));
                _user.setModifyDate(rs.getTimestamp("modifyDate"));
                _user.setUserRoleName(rs.getString("roleName"));
                users.add(_user);
            }

            BaseDao.closeResources(null, ps, rs);
        }
        return users;
    }
}
service层

在UserService接口中定义获取用户列表方法,接收参数为:用户名,用户角色,当前页面,页面容量。

package com.thomas.service.user;

import com.thomas.pojo.User;

import java.util.List;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:31
 * @Description 用户业务类
 * @Since version-1.0
 */


public interface UserService {
    ...
    public List<User> getUserList(String username, int userRole, int currentPageNo, int pageSize);
}

在UserServiceImpl类中实现获取用户列表方法,在service层处理业务

package com.thomas.service.user;

import com.thomas.dao.BaseDao;
import com.thomas.dao.user.UserDao;
import com.thomas.dao.user.UserDaoImpl;
import com.thomas.pojo.User;
import org.junit.Test;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:33
 * @Description 实现用户service接口
 * @Since version-1.0
 */


public class UserServiceImpl implements UserService {
    //业务层会调用dao层,所以需要引入dao
    private UserDao userDao;

    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }

    ...
        
    public List<User> getUserList(String username, int userRole, int currentPageNo, int pageSize) {
        Connection connection = null;
        List<User> users = new ArrayList<User>();
        System.out.println("queryUserName ---> " + username);
        System.out.println("queryUserRole ---> " + userRole);
        System.out.println("queryCurrentPageNo ---> " + currentPageNo);
        System.out.println("queryPageSize ---> " + pageSize);
        try {
            connection = BaseDao.getConnection();
            users = userDao.getUserList(connection, username, userRole, currentPageNo, pageSize);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return users;
    }
}

2. 查询用户总数

DAO层

dao.user-UserDao.java

可以通过用户名或者用户角色来进行查询,所以需要传递username以及userRole参数,但是不需要考虑分页的情况。

package com.thomas.dao.user;

import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:49
 * @Description 用户接口类
 * @Since version-1.0
 */


public interface UserDao {
    //根据用户名或用户角色获取用户总数
    public int getUserCount(Connection connection, String username, int userRole) throws SQLException;
}

user.dao-UserImpl.java

UserDaoImpl中实现UserDao接口,因为用户管理页面中需要呈现用户的基本信息和用户角色,所以需要连表查询(userrole)。这里也需要拼接sql,sql语句如下:

select count(1as cnt
from smbms_user u, smbms_role r
where u.userRole = r.id
  and u.userName like '%username%'
  and r.userRole = userRole

其中usernameuserRole是我们需要传递的参数,我们将其放在ArrayList中,实现动态增加参数。

package com.thomas.dao.user;

import com.mysql.cj.util.StringUtils;
import com.thomas.dao.BaseDao;
import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:50
 * @Description 实现用户接口UserDao
 * @Since version-1.0
 */


public class UserDaoImpl implements UserDao {
    /**
     * @Author GeekThomas
     * @Date 2023/1/17 22:40
     * @Description 根据用户名或者用户角色获取用户总数,需要拼接sql,动态添加参数!!!
     * @Param connection
     * @Param username
     * @Param userRole
     * @Return {@link int}
     * @Since version-1.0
     */


    public int getUserCount(Connection connection, String username, int userRole) throws SQLException {
        PreparedStatement ps = null;
        ResultSet rs = null;
        int count = 0;
        if (connection != null) {
            StringBuffer sql = new StringBuffer();
            sql.append("select count(1) as cnt from smbms_user u, smbms_role r where u.userRole = r.id");

            //用一个可变长度的List来存储动态的参数
            ArrayList<Object> paramList = new ArrayList<Object>();

            //输入用户名,则在where条件里添加条件,注意空格
            if (!StringUtils.isNullOrEmpty(username)) {
                sql.append(" and u.userName like ?");
                //"select count(1) as cnt from smbms_user u, smbms_role r
                // where u.userRole = r.id
                // and u.userName like %李%
                // "
                //参数实际上应该是%username%
                paramList.add("%" + username + "%");
            }

            //输入角色,则在where条件里添加条件,注意空格
            if (userRole > 0) {
                sql.append(" and r.id = ?");
                //"select count(1) as cnt from smbms_user u, smbms_role r
                // where u.userRole = r.id
                // and r.useRole = 1
                // "
                //参数实际上应该是userRole
                paramList.add(userRole);
            }

            //把List转为数组
            Object[] params = paramList.toArray();

            System.out.println("UserDaoImpl--->getUserCount:n" + sql.toString()); //输出完整的sql
            rs = BaseDao.execute(connection, ps, rs, sql.toString(), params);
            
            if (rs.next()) {
                count = rs.getInt("cnt"); //从结果集中获取数量
            }

            //关闭资源
            BaseDao.closeResources(null, ps, rs);
        }

        return count;
    }
}
service层

在UserService接口中定义获取用户列表方法,接收参数为:用户名,用户角色。

package com.thomas.service.user;

import com.thomas.pojo.User;

import java.util.List;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:31
 * @Description 用户业务类
 * @Since version-1.0
 */


public interface UserService {
    public int getUserCount(String username, int userRole);
}

在UserServiceImpl类中实现获取用户列表方法,在service层处理业务

package com.thomas.service.user;

import com.thomas.dao.BaseDao;
import com.thomas.dao.user.UserDao;
import com.thomas.dao.user.UserDaoImpl;
import com.thomas.pojo.User;
import org.junit.Test;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:33
 * @Description 实现用户service接口
 * @Since version-1.0
 */


public class UserServiceImpl implements UserService {
    //业务层会调用dao层,所以需要引入dao
    private UserDao userDao;

    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }

    /**
     * @Author GeekThomas
     * @Date 2023/1/17 23:10
     * @Description 根据用户名或者用户角色进行查询,获取总数,也就是所有页面数据的总条数
     * @Param username
     * @Param userRole
     * @Return {@link int}
     * @Since version-1.0
     */


    public int getUserCount(String username, int userRole) {
        Connection connection = null;
        int count = 0;
        try {
            connection = BaseDao.getConnection();
            count = userDao.getUserCount(connection, username, userRole);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return count;
    }
}

3. 查询角色列表

查询角色相关信息需要用到Role表,在dao层中主要是对Role表进行操作,因此新建包dao.roleservice.role

DAO层

需要查询到所有的用户角色

dao.role-RoleDao.java

package com.thomas.dao.role;

import com.thomas.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;
}

RoleDaoImpl中实现RoleDao接口。

这里需要传递的sql如下所示:

select * from smbms_role

currentNo = pageSize * (currentPageNo - 1)

对查询的结果集进行遍历,将客户信息存储到用户列表。

package com.thomas.dao.role;

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

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

/**
 * @Author GeekThomas
 * @Date 2023/1/19 20:49
 * @Description 实现角色接口RoleDao
 * @Since version-1.0
 */


public class RoleDaoImpl implements RoleDao {
    /**
     * @Author GeekThomas
     * @Date 2023/1/19 20:50
     * @Description 获得用户角色列表
     * @Param connection
     * @Param userRole
     * @Return {@link List< Role>}
     * @Since version-1.0
     */


    public List<Role> getRoleList(Connection connection) throws SQLException {
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<Role> roles = new ArrayList<Role>();

        if (connection != null) {
            String sql = "select * from smbms_role";
            Object[] params = {};
            rs = BaseDao.execute(connection, ps, rs, sql, params);
            while (rs.next()) {
                Role role = new Role();
                role.setId(rs.getInt("id"));
                role.setRoleCode(rs.getString("roleCode"));
                role.setRoleName(rs.getString("roleName"));
                roles.add(role);
            }
            BaseDao.closeResources(null, ps, rs);
        }
        return roles;
    }
}
service层

service.role-UserService.java接口中定义获取角色列表方法。

package com.thomas.service.role;

import com.thomas.pojo.Role;

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

public interface RoleService {
    public List<Role> getRoleList() throws SQLException;
}

service.role-UserServiceImpl.java类中实现获取角色列表方法,在service层处理业务

package com.thomas.service.role;

import com.thomas.dao.BaseDao;
import com.thomas.dao.role.RoleDao;
import com.thomas.dao.role.RoleDaoImpl;
import com.thomas.pojo.Role;
import org.junit.Test;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/19 21:08
 * @Description 实现RoleService接口
 * @Since version-1.0
 */


public class RoleServiceImpl implements RoleService {
    private RoleDao roleDao;

    public RoleServiceImpl() {
        roleDao = new RoleDaoImpl();
    }

    /**
     * @Author GeekThomas
     * @Date 2023/1/19 21:08
     * @Description 调用RoleDao,实现查询用户角色列表
     * @Param
     * @Return {@link List< Role>}
     * @Since version-1.0
     */


    public List<Role> getRoleList() {
        Connection connection = null;
        List<Role> roles = new ArrayList<Role>();
        try {
            connection = BaseDao.getConnection();
            roles = roleDao.getRoleList(connection);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return roles;
    }
}

4. servlet层

在前端页面,我们是通过点击用户管理来实现跳转到用户查询页面的,我们可以分析下userlist.jsp,前端会返回三个参数:queryUserNamequeryUserRolepageIndex,分别表示查询用户名,查询用户角色,页码,通过这三个参数我们可以获取dao中sql查询的相关参数。

package com.thomas.servlet.user;

import com.alibaba.fastjson.JSONArray;
import com.mysql.cj.util.StringUtils;
import com.thomas.pojo.Role;
import com.thomas.pojo.User;
import com.thomas.service.role.RoleServiceImpl;
import com.thomas.service.user.UserServiceImpl;
import com.thomas.util.Constants;
import com.thomas.util.PageSupport;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");
        if (method != null && "savepwd".equals(method)) {
            this.modifyPassword(req, resp);
        } else if (method != null && "pwdmodify".equals(method)) {
            this.verifyPassword(req, resp);
        } else if (method != null && "query".equals(method)) {
            this.query(req, resp);
        }
    }

   ...

    /**
     * @Author GeekThomas
     * @Date 2023/1/19 21:58
     * @Description 查询用户列表
     * @Param req
     * @Param resp
     * @Return
     * @Since version-1.0
     */


    public void query(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException  {
        //获取前端页面的参数
        String queryUserName = req.getParameter("queryname"); //查询的用户名
        String temp = req.getParameter("queryUserRole"); //查询的用户角色
        String pageIndex = req.getParameter("pageIndex"); //查询的当前页面
        int queryUserRole = 0;

        //与页面有关的参数
        int pageSize = 5;
        int currentPageNo = 1//默认从第一页开始

        //对前端获取的参数进行处理
        if (queryUserName == null) {
            queryUserName = "";
        }

        if (temp != null && !"".equals(temp)) {
            queryUserRole = Integer.parseInt(temp); //使用前端查询的参数赋值
        }

        if (pageIndex != null) {
            currentPageNo = Integer.parseInt(pageIndex);
        }

        UserServiceImpl userService = new UserServiceImpl();
        List<User> userList = null;

        //查询用户总数
        int totalCount = userService.getUserCount(queryUserName, queryUserRole);

        PageSupport pageSupport = new PageSupport();
        pageSupport.setPageSize(pageSize);
        pageSupport.setCurrentPageNo(currentPageNo);
        pageSupport.setTotalCount(totalCount);

        int totalPageCount = pageSupport.getTotalPageCount();

        //控制首页和尾页
        if (totalPageCount < 1) {
            currentPageNo = 1;
        } else if (currentPageNo > totalPageCount) {
            currentPageNo = totalPageCount;
        }

        //查询用户列表
        userList = userService.getUserList(queryUserName, queryUserRole, currentPageNo, pageSize);

        //查询角色列表
        RoleServiceImpl roleService = new RoleServiceImpl();
        List<Role> roleList = roleService.getRoleList();

        //向前端传递参数
        req.setAttribute("userList", userList);
        req.setAttribute("roleList", roleList);
        req.setAttribute("currentPageNo", currentPageNo);
        req.setAttribute("totalCount", totalCount);
        req.setAttribute("totalPageCount", totalPageCount);

        //请求转发
        req.getRequestDispatcher("userlist.jsp").forward(req, resp);
    }
}

注意这里定义了一个PageSupport工具类,通过这个工具类,我们可以根据数据条数动态计算总页面。

util-PageSupport.java

package com.thomas.util;

/**
 * @Author GeekThomas
 * @Date 2023/1/17 21:03
 * @Description 分页工具类,实现分页功能
 * @Since version-1.0
 */


public class PageSupport {
    //当前页码(用户输入)
    private int currentPageNo = 1;
    //总数(某张表)
    private int totalCount = 0;
    //页面容量
    private int pageSize = 0;
    //总页数
    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;
        }
    }
}

3.5、用户管理

接下来我们继续项目,来实现用户管理模块中的增删改查功能,也就是常说的C(Create,创建/增加)R(Retrieve,读取查询)U(Update,更新)D(Delete,删除)。我们按照这样的顺序来实现相关功能。以上功能统一集成在用户管理页面中,如下所示。

JavaWeb项目SMBMS(二)——需求实现

1.增

增加用户功能页面如下所示:当点击添加用户按钮,即可跳转到页面http://localhost:8080/smbms/jsp/useradd.jsp,填入信息,完成用户添加。我们可以看到这里除了用户相关信息外,还需要从用户角色列表中进行选择。

JavaWeb项目SMBMS(二)——需求实现

功能实现流程:用户从前端发送请求访问页面,填写用户相关参数,将前端的参数返回到后端,后端根据用户参数创建用户对象,并且将用户插入到用户表中。

JavaWeb项目SMBMS(二)——需求实现

接下来,我们仍然按照自底向上的方式实现功能。根据我们上面的流程,我们其实是直接向数据库传递User对象。

在实现用户增加功能时,需要考虑以下问题:

  • 对于新建的用户,需要验证是否在数据库中已经有重复的编码——对应到的方法是使用ajax验证,绑定ucexist方法
  • 新增用户需要设置角色,就需要我们获得用户列表
  • 在servlet层需要更新用户创建的时间以及创建者,创建者可以从Session中获得当前Userid
DAO层

user-UserDao.java

在DAO层我们主要是对数据库进行操作,在UserDao接口中定义增加用户方法。

package com.thomas.dao.user;

import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:49
 * @Description 用户接口类
 * @Since version-1.0
 */


public interface UserDao {
 ...
    //增加用户
    public int addUser(Connection connection, User user) throws SQLException;
}

user-UserDaoImpl.java

实现UserDao中的增加用户方法,这里其实就是向数据库中插入新数据。

insert into smbms_user(userCode, userName, userPassword, gender, birthday, phone, address, userRole, createdBy, creationDate)
values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

其中问号为占位符,代表的就是User对象的属性(在pojo.user中已经定义)

package com.thomas.dao.user;

import com.mysql.cj.util.StringUtils;
import com.thomas.dao.BaseDao;
import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:50
 * @Description 实现用户接口UserDao
 * @Since version-1.0
 */


public class UserDaoImpl implements UserDao {
 ...

    /**
     * @Author GeekThomas
     * @Date 2023/1/20 22:06
     * @Description 增加用户,如果新增成功,则返回1
     * @Param connection
     * @Param user
     * @Return {@link int}
     * @Since version-1.0
     */


    public int addUser(Connection connection, User user) throws SQLException {
        PreparedStatement ps = null;
        int updatedRows = 0;

        if (connection != null) {
            String sql = "insert into smbms_user(userCode, userName, userPassword, gender, birthday, phone, address, " +
                    "userRole, createdBy, creationDate) " +
                    "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
            Object[] params = {user.getUserCode(), user.getUserName(), user.getUserPassword(), user.getGender(),
                    user.getBirthday(), user.getPhone(), user.getAddress(), user.getUserRole(), user.getCreatedBy(),
                    user.getCreationDate()};
            updatedRows = BaseDao.execute(connection, ps, sql, params);
            BaseDao.closeResources(null, ps, null);
        }
        return updatedRows;
    }
}
service层

在service层我们主要是通过调用dao层,来实现对数据库的操作。

user-UserService.java

在service层中新建增加用户方法,参数为User对象,返回是否增加成功(boolean)

package com.thomas.service.user;

import com.thomas.pojo.User;

import java.util.List;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:31
 * @Description 用户业务类
 * @Since version-1.0
 */


public interface UserService {
 ...
    public User selectUserCodeExist(String userCode);
    
    public boolean addUser(User user);
}

user-UserServiceImpl.java

实现增加用户方法。由于是增加新用户,我们需要考虑如果增加用户过程中程序报错,需要将事务回滚。

package com.thomas.service.user;

import com.thomas.dao.BaseDao;
import com.thomas.dao.user.UserDao;
import com.thomas.dao.user.UserDaoImpl;
import com.thomas.pojo.User;
import org.junit.Test;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:33
 * @Description 实现用户service接口
 * @Since version-1.0
 */


public class UserServiceImpl implements UserService {
    //业务层会调用dao层,所以需要引入dao
    private UserDao userDao;

    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }

 ...

    /**
     * @Author GeekThomas
     * @Date 2023/1/20 22:16
     * @Description 调用dao层代码,添加新用户
     * @Param user
     * @Return {@link int}
     * @Since version-1.0
     */


    public boolean addUser(User user) {
        Connection connection = null;
        boolean flag = false;

        try {
            connection = BaseDao.getConnection();
            connection.setAutoCommit(false); //开启jdbc事务管理
            int updatedRows = userDao.addUser(connection, user);
            connection.commit();
            if (updatedRows > 0) {
                flag = true;
                System.out.println("add user succeed");
            } else {
                System.out.println("add user failed");
            }
        } catch (Exception e) {
            e.printStackTrace();
            //事务回滚
            try {
                System.out.println("rollback-------->");
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return flag;
    }
    
    /**
     * @Author GeekThomas
     * @Date 2023/1/21 0:50
     * @Description 通过用户编码查询用户
     * @Param userCode
     * @Return {@link User}
     * @Since version-1.0
     */


    public User selectUserCodeExist(String userCode) {
        Connection connection = null;
        User user = null;
        try {
            connection = BaseDao.getConnection();
            user = userDao.getLoginUser(connection, userCode);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return user;
    }
}
servlet层
package com.thomas.servlet.user;

import com.alibaba.fastjson.JSONArray;
import com.mysql.cj.util.StringUtils;
import com.thomas.pojo.Role;
import com.thomas.pojo.User;
import com.thomas.service.role.RoleServiceImpl;
import com.thomas.service.user.UserServiceImpl;
import com.thomas.util.Constants;
import com.thomas.util.PageSupport;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;

public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");
        if (method != null && "savepwd".equals(method)) {
            this.modifyPassword(req, resp);
        } else if (method != null && "pwdmodify".equals(method)) {
            this.verifyPassword(req, resp);
        } else if (method != null && "query".equals(method)) {
            this.query(req, resp);
        } else if (method != null && "view".equals(method)) {
            this.view(req, resp);
        } else if (method != null && "add".equals(method)) {
            this.addUser(req, resp);
        } else if (method != null && "getrolelist".equals(method)) {
            this.getRoleList(req, resp);
        } else if (method != null && "ucexist".equals(method)) {
            this.userCodeExists(req, resp);
        } else if (method != null && "deluser".equals(method)) {
            this.deleteUser(req, resp);
        } else if (method != null && "modify".equals(method)) {
            this.getUserById(req, resp);
        } else if (method != null && "modifyexe".equals(method)) {
            this.modifyUser(req, resp);
        }
    }

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

    public void addUser(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String userCode = req.getParameter("userCode");
        String userName = req.getParameter("userName");
        String userPassword = req.getParameter("userPassword");
        String genderTemp = req.getParameter("gender");
        String birthdayTemp = req.getParameter("birthday");
        String phone = req.getParameter("phone");
        String address = req.getParameter("address");
        String userRoleTemp = req.getParameter("userRole");
        int gender = 0;
        Date birthday = null;
        int userRole = 0;

        //根据在数据库中的内容进行格式转换
        //1.转换性别
        if (genderTemp != null && !"".equals(genderTemp)) {
            gender = Integer.parseInt(genderTemp);
        }
        //2.转换日期
        if (birthdayTemp != null && !"".equals(birthdayTemp)) {
            try {
                birthday = new SimpleDateFormat("yyyy-mm-dd").parse(birthdayTemp);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        //3.转换用户角色
        if (userRoleTemp != null && !"".equals(userRoleTemp)) {
            userRole = Integer.parseInt(userRoleTemp);
        }

        //新建一个User,并设置属性
        User user = new User();
        user.setUserCode(userCode);
        user.setUserName(userName);
        user.setUserPassword(userPassword);
        user.setGender(gender);
        user.setBirthday(birthday);
        user.setPhone(phone);
        user.setAddress(address);
        user.setUserRole(userRole);
        //设置创建者,就是当前用户
        user.setCreatedBy(((User) req.getSession().getAttribute(Constants.USER_SESSION)).getId());
        //设置创建日期,使用当前时间
        user.setCreationDate(new Date());

        UserServiceImpl userService = new UserServiceImpl();
        boolean flag = userService.addUser(user);
        if (flag) {
            resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
        } else {
            req.getRequestDispatcher("useradd.jsp").forward(req, resp);
        }
    }

    public void getRoleList(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<Role> roleList = null;
        RoleServiceImpl roleService = new RoleServiceImpl();
        roleList = roleService.getRoleList();
        System.out.println(req.getRequestURL());

        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(JSONArray.toJSONString(roleList));
        writer.flush();
        writer.close();
    }

    private void userCodeExists(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String userCode = req.getParameter("userCode");
        Map<String, String> resultMap = new HashMap<String, String>();
        resultMap.put("method""ucexist");
        UserServiceImpl userService = new UserServiceImpl();
        User user = userService.selectUserCodeExist(userCode);
        if (StringUtils.isNullOrEmpty(userCode)) {
            resultMap.put("userCode""exist");
        } else {
            if (user != null) {
                resultMap.put("userCode""exist");
            } else {
                resultMap.put("userCode""nonExist");
            }
        }

        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(JSONArray.toJSONString(resultMap));
        writer.flush();
        writer.close();
    }
}

JavaWeb项目SMBMS(二)——需求实现

在选择用户角色的时候,会出现上图的问题,主要是我们未能获取到用户角色列表。

2.删

删除用户的话,其实并不需要页面,我们只需要在构造ajax请求的时候传递用户id就可以直接在用户管理页面进行删除。

访问页面user.do?method=deluser&uid=49,来实现删除功能。

JavaWeb项目SMBMS(二)——需求实现

DAO层

user-UserDao.java

在DAO层我们主要是对数据库进行操作,在UserDao接口中定义删除用户方法。

package com.thomas.dao.user;

import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:49
 * @Description 用户接口类
 * @Since version-1.0
 */

public interface UserDao {
    //删除用户
    public int deleteUserById(Connection connection, int userId) throws SQLException;
}

user-UserDaoImpl.java

实现UserDao中的删除用户方法,这里其实就是在数据库中根据用户id数据。

delete from smbms_user where id = ?

其中问号为占位符,代表的就是User对象的属性(在pojo.user中已经定义)

package com.thomas.dao.user;

import com.mysql.cj.util.StringUtils;
import com.thomas.dao.BaseDao;
import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:50
 * @Description 实现用户接口UserDao
 * @Since version-1.0
 */


public class UserDaoImpl implements UserDao {
    /**
     * @Author GeekThomas
     * @Date 2023/1/21 10:31
     * @Description 根据用户id删除用户
     * @Param connection
     * @Param userId
     * @Return {@link int}
     * @Since version-1.0
     */


    public int deleteUserById(Connection connection, int userId) throws SQLException {
        PreparedStatement ps = null;
        int updatedRows = 0;

        if (connection != null) {
            String sql = "delete from smbms_user where id = ?";
            Object[] params = {userId};
            updatedRows = BaseDao.execute(connection, ps, sql, params);
            BaseDao.closeResources(null, ps, null);
        }

        return updatedRows;
    }
}
service层

在service层我们主要是通过调用dao层,来实现对数据库的操作。

user-UserService.java

在service层中新建删除用户方法,参数为User对象的id,返回是否增加成功(boolean)

package com.thomas.service.user;

import com.thomas.pojo.User;

import java.util.List;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:31
 * @Description 用户业务类
 * @Since version-1.0
 */


public interface UserService {
    public boolean deleteUserById(int userId);
}

user-UserServiceImpl.java

实现删除用户方法。

package com.thomas.service.user;

import com.thomas.dao.BaseDao;
import com.thomas.dao.user.UserDao;
import com.thomas.dao.user.UserDaoImpl;
import com.thomas.pojo.User;
import org.junit.Test;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:33
 * @Description 实现用户service接口
 * @Since version-1.0
 */


public class UserServiceImpl implements UserService {
    //业务层会调用dao层,所以需要引入dao
    private UserDao userDao;

    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }

    public boolean deleteUserById(int userId) {
        Connection connection = null;
        boolean flag = false;
        try {
            connection = BaseDao.getConnection();
            int updatedRows = userDao.deleteUserById(connection, userId);
            if (updatedRows > 0) {
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return flag;
    }
}
servlet层

前端获得用户id,构造ajax请求删除用户

package com.thomas.servlet.user;

import com.alibaba.fastjson.JSONArray;
import com.mysql.cj.util.StringUtils;
import com.thomas.pojo.Role;
import com.thomas.pojo.User;
import com.thomas.service.role.RoleServiceImpl;
import com.thomas.service.user.UserServiceImpl;
import com.thomas.util.Constants;
import com.thomas.util.PageSupport;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;

public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");
        if (method != null && "savepwd".equals(method)) {
            this.modifyPassword(req, resp);
        } else if (method != null && "pwdmodify".equals(method)) {
            this.verifyPassword(req, resp);
        } else if (method != null && "query".equals(method)) {
            this.query(req, resp);
        } else if (method != null && "view".equals(method)) {
            this.view(req, resp);
        } else if (method != null && "add".equals(method)) {
            this.addUser(req, resp);
        } else if (method != null && "getrolelist".equals(method)) {
            this.getRoleList(req, resp);
        } else if (method != null && "ucexist".equals(method)) {
            this.userCodeExists(req, resp);
        } else if (method != null && "deluser".equals(method)) {
            this.deleteUser(req, resp);
        } else if (method != null && "modify".equals(method)) {
            this.getUserById(req, resp);
        } else if (method != null && "modifyexe".equals(method)) {
            this.modifyUser(req, resp);
        }
    }

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

    public void deleteUser(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uid = req.getParameter("uid");
        int userId = 0;
        if (!StringUtils.isNullOrEmpty(uid)) {
            userId = Integer.parseInt(uid);
        }

        Map<String, String> resultMap = new HashMap<String, String>();
        resultMap.put("method""deluser");
        if (userId <= 0) {
            resultMap.put("delResult""notexist");
        } else {
            UserServiceImpl userService = new UserServiceImpl();
            boolean flag = userService.deleteUserById(userId);
            if (flag) {
                resultMap.put("delResult""true"); //删除成功
            } else {
                resultMap.put("delResult""false"); //删除失败
            }
        }

        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(JSONArray.toJSONString(resultMap));
        writer.flush();
        writer.close();
    }
}

3. 改

修改用户其实就是要先根据用户id选出用户,然后再给该用户更新属性。这里会涉及到两个请求,

http://localhost:8080/smbms/jsp/user.do?method=modify&uid=58:从前端页面获得用户

localhost:8080/smbms/jsp/user.do?method=modifyexe:发送ajax请求,修改用户信息

JavaWeb项目SMBMS(二)——需求实现

DAO层

user-UserDao.java

在DAO层我们主要是对数据库进行操作,在UserDao接口中定义根据id获取用户和修改用户方法。

package com.thomas.dao.user;

import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:49
 * @Description 用户接口类
 * @Since version-1.0
 */


public interface UserDao {

    //根据用户id查询用户信息
    public User getUserById(Connection connection, int id) throws SQLException;

    //修改用户
    public int modifyUser(Connection connection, User user) throws SQLException;
}

user-UserDaoImpl.java

实现UserDao中的根据id查询用户、修改用户方法,对应的sql如下:

  • 根据id查询用户
select * from smbms_user where id = ?
  • 更新用户信息
update smbms_user
set userName=?,gender=?,birthday=?,phone=?,address=?,userRole=? where id = ?

其中问号为占位符,代表的就是User对象的属性(在pojo.user中已经定义)

package com.thomas.dao.user;

import com.mysql.cj.util.StringUtils;
import com.thomas.dao.BaseDao;
import com.thomas.pojo.User;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 16:50
 * @Description 实现用户接口UserDao
 * @Since version-1.0
 */


public class UserDaoImpl implements UserDao {
    /**
     * @Author GeekThomas
     * @Date 2023/1/20 12:08
     * @Description 根据用户Id查询用户
     * @Param connection
     * @Param id
     * @Return {@link User}
     * @Since version-1.0
     */


    public User getUserById(Connection connection, int id) throws SQLException {
        PreparedStatement ps = null;
        ResultSet rs = null;
        User user = null;

        if (connection != null) {
            String sql = "select u.*, r.roleName from smbms_user u, smbms_role r where u.userRole = r.id and u.id = ?";
            Object[] params = {id};
            rs = BaseDao.execute(connection, ps, rs, sql, params);

            if (rs.next()) {
                user = new User();
                user.setId(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.setAddress(rs.getString("address"));
                user.setUserRoleName(rs.getString("roleName"));
            }
            BaseDao.closeResources(null, ps, rs);
        }
        return user;
    }

    /**
     * @Author GeekThomas
     * @Date 2023/1/21 15:47
     * @Description 修改用户信息
     * @Param connection
     * @Param user
     * @Return {@link int}
     * @Since version-1.0
     */

    public int modifyUser(Connection connection, User user) throws SQLException {
        PreparedStatement ps = null;
        int updatedRows = 0;

        if (connection != null) {
            String sql = "update smbms_usern" +
                    "set userName=?,gender=?,birthday=?,phone=?,address=?,userRole=? where id = ?";
            Object[] params = {user.getUserName(), user.getGender(), user.getBirthday(), user.getPhone(), user.getAddress(),
                    user.getUserRole(), user.getId()};
            updatedRows = BaseDao.execute(connection, ps, sql, params);
            BaseDao.closeResources(null, ps, null);
        }
        return updatedRows;
    }
}
service层

在service层我们主要是通过调用dao层,来实现对数据库的操作。

user-UserService.java

在service层中新建根据id查询用户和更新用户信息方法

package com.thomas.service.user;

import com.thomas.pojo.User;

import java.util.List;

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:31
 * @Description 用户业务类
 * @Since version-1.0
 */


public interface UserService {
    public User getUserById(int id);

    public boolean modifyUser(User user);
}

user-UserServiceImpl.java

实现相关的用户方法。

package com.thomas.service.user;

import com.thomas.dao.BaseDao;
import com.thomas.dao.user.UserDao;
import com.thomas.dao.user.UserDaoImpl;
import com.thomas.pojo.User;
import org.junit.Test;

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

/**
 * @Author GeekThomas
 * @Date 2023/1/12 17:33
 * @Description 实现用户service接口
 * @Since version-1.0
 */


public class UserServiceImpl implements UserService {
    //业务层会调用dao层,所以需要引入dao
    private UserDao userDao;

    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }

    public User getUserById(int id)  {
        Connection connection = null;
        User user = null;
        try {
            connection = BaseDao.getConnection();
            user = userDao.getUserById(connection, id);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return user;
    }

    public boolean modifyUser(User user) {
        Connection connection = null;
        boolean flag = false;
        try {
            connection = BaseDao.getConnection();
            int updateRows = userDao.modifyUser(connection, user);
            if (updateRows > 0) {
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResources(connection, nullnull);
        }
        return flag;
    }
}
servlet层
  • 前端获得用户id,获得用户,携带用户请求转发
  • 修改用户信息
package com.thomas.servlet.user;

import com.alibaba.fastjson.JSONArray;
import com.mysql.cj.util.StringUtils;
import com.thomas.pojo.Role;
import com.thomas.pojo.User;
import com.thomas.service.role.RoleServiceImpl;
import com.thomas.service.user.UserServiceImpl;
import com.thomas.util.Constants;
import com.thomas.util.PageSupport;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;

public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");
        if (method != null && "savepwd".equals(method)) {
            this.modifyPassword(req, resp);
        } else if (method != null && "pwdmodify".equals(method)) {
            this.verifyPassword(req, resp);
        } else if (method != null && "query".equals(method)) {
            this.query(req, resp);
        } else if (method != null && "view".equals(method)) {
            this.view(req, resp);
        } else if (method != null && "add".equals(method)) {
            this.addUser(req, resp);
        } else if (method != null && "getrolelist".equals(method)) {
            this.getRoleList(req, resp);
        } else if (method != null && "ucexist".equals(method)) {
            this.userCodeExists(req, resp);
        } else if (method != null && "deluser".equals(method)) {
            this.deleteUser(req, resp);
        } else if (method != null && "modify".equals(method)) {
            this.getUserById(req, resp);
        } else if (method != null && "modifyexe".equals(method)) {
            this.modifyUser(req, resp);
        }
    }

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

    /**
     * @Author GeekThomas
     * @Date 2023/1/23 23:29
     * @Description 在对用户进行修改时,需要先获得用户
     * @Param req
     * @Param resp
     * @Return
     * @Since version-1.0
     */


    public void getUserById(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uid = req.getParameter("uid");
        int userId = 0;
        if (!StringUtils.isNullOrEmpty(uid)) {
            userId = Integer.parseInt(uid);
        }
        //获取需要修改的用户
        UserServiceImpl userService = new UserServiceImpl();
        User modifyUser = userService.getUserById(userId);
        if (modifyUser != null) {
            req.setAttribute("user", modifyUser);
            req.getRequestDispatcher("usermodify.jsp").forward(req, resp);
        }

    }

    /**
     * @Author GeekThomas
     * @Date 2023/1/23 22:53
     * @Description 修改用户
     * @Param req
     * @Param resp
     * @Return
     * @Since version-1.0
     */


    public void modifyUser(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String userId = req.getParameter("uid");
        String userName = req.getParameter("userName");
        String genderTemp = req.getParameter("gender");
        String birthdayTemp = req.getParameter("birthday");
        String phone = req.getParameter("phone");
        String address = req.getParameter("address");
        String userRoleTemp = req.getParameter("userRole");

        int uid = 0;
        int gender = 0;
        Date birthday = null;
        int userRole = 0;

        //转换格式
        if (!StringUtils.isNullOrEmpty(userId)) {
            uid = Integer.parseInt(userId);
        }

        if (!StringUtils.isNullOrEmpty(genderTemp)) {
            gender = Integer.parseInt(genderTemp);
        }

        if (!StringUtils.isNullOrEmpty(birthdayTemp)) {
            try {
                birthday = new SimpleDateFormat("yyyy-mm-dd").parse(birthdayTemp);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        if (!StringUtils.isNullOrEmpty(userRoleTemp)) {
            userRole = Integer.parseInt(userRoleTemp);
        }

        //使用前端传递的参数,创建新用户
        User user = new User();
        user.setId(uid);
        user.setUserName(userName);
        user.setGender(gender);
        user.setBirthday(birthday);
        user.setPhone(phone);
        user.setAddress(address);
        user.setUserRole(userRole);

        //设置修改人和修改信息
        user.setModifyBy(((User) req.getSession().getAttribute(Constants.USER_SESSION)).getId());
        user.setModifyDate(new Date());

        //提交请求
        UserServiceImpl userService = new UserServiceImpl();
        boolean flag = userService.modifyUser(user);
        if (flag) {
            resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
        } else {
            req.getRequestDispatcher("usermodify.jsp").forward(req, resp);
        }
    }
}

4. 查

通过id,查询用户信息

JavaWeb项目SMBMS(二)——需求实现

还记得吗,我们前面其实已经定义了根据id获取用户信息的方法。所以我们只用修改servlet实现即可。根据id查询用户,并携带这个用户进行请求转发。

package com.thomas.servlet.user;

import com.alibaba.fastjson.JSONArray;
import com.mysql.cj.util.StringUtils;
import com.thomas.pojo.Role;
import com.thomas.pojo.User;
import com.thomas.service.role.RoleServiceImpl;
import com.thomas.service.user.UserServiceImpl;
import com.thomas.util.Constants;
import com.thomas.util.PageSupport;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;

public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getParameter("method");
        if (method != null && "savepwd".equals(method)) {
            this.modifyPassword(req, resp);
        } else if (method != null && "pwdmodify".equals(method)) {
            this.verifyPassword(req, resp);
        } else if (method != null && "query".equals(method)) {
            this.query(req, resp);
        } else if (method != null && "view".equals(method)) {
            this.view(req, resp);
        } else if (method != null && "add".equals(method)) {
            this.addUser(req, resp);
        } else if (method != null && "getrolelist".equals(method)) {
            this.getRoleList(req, resp);
        } else if (method != null && "ucexist".equals(method)) {
            this.userCodeExists(req, resp);
        } else if (method != null && "deluser".equals(method)) {
            this.deleteUser(req, resp);
        } else if (method != null && "modify".equals(method)) {
            this.getUserById(req, resp);
        } else if (method != null && "modifyexe".equals(method)) {
            this.modifyUser(req, resp);
        }
    }

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

    public void view(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uid = req.getParameter("uid");
        int userId = 0;

        if (!StringUtils.isNullOrEmpty(uid)) {
            userId = Integer.parseInt(uid);
        }

        UserServiceImpl userService = new UserServiceImpl();
        User user = userService.getUserById(userId);
        System.out.println(user.getUserName());

        if (user != null) {
            req.setAttribute("user", user);
            req.getRequestDispatcher("userview.jsp").forward(req, resp);
        }
    }
}

至此,关于用户层的增删改查已经搞定了。实际上狂神的B站课程也只是实现到了这一步,不过我参照用户层的思路,将供应商以及订单的管理也都全部实现了,这部分CRUD其实有很大的重复性,所以在文章里就不赘述啦。相关的代码我稍后会打包好,有需要的朋友可以直接在公众号后台回复smbms获取~

JavaWeb项目SMBMS(二)——需求实现

4. 小结

这个项目前前后后花了差不多一个月的时间,虽然前端部分是直接copy的,但是通过这样一个简单的javaweb项目,对mvc架构有了简单的了解,当然这个项目问题还是比较多的。在我学完mybatis之后,我才回头补充这部分的文档,不由得还是感慨框架的效率,比jdbc确实是快太多了。接下来的任务就是开始学习spring全家桶了,期待在下一个Java项目与大家相见~


原文始发于微信公众号(多肉罗罗):JavaWeb项目SMBMS(二)——需求实现

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/186294.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!