JavaWeb 练习 SMBMS

一、系统功能结构图

二、项目搭建前期准备

2.1 Maven 创建 web 项目

2.2 配置 pom.xml 并导入相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>smbms</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <!--Servlet 依赖-->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>5.0.0</version>
        </dependency>
        <!--JSP 依赖-->
        <dependency>
            <groupId>com.guicedee.services</groupId>
            <artifactId>jakarta.servlet.jsp-api</artifactId>
            <version>62</version>
        </dependency>
        <!--jstl 表达式依赖-->
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>jakarta.servlet.jsp.jstl</artifactId>
            <version>2.0.0</version>
        </dependency>
        <!--标签库依赖-->
        <dependency>
            <groupId>org.apache.taglibs</groupId>
            <artifactId>taglibs-standard-spec</artifactId>
            <version>1.2.5</version>
        </dependency>
        <!--MySQL 依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>       
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <!--fastjson 依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.79</version>
        </dependency>
    </dependencies>
</project>

2.3 IDEA 中配置 Tomcat

<!--修改为与Tomcat 10 一致-->
<!--去掉 metadata-complete="true",开启注解-->
<?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_5_0.xsd"
         version="5.0">
    <!--设置首页-->
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
    <!--设置Session默认过期时间30分钟-->
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
</web-app>

2.4 创建项目包

  • 结构图:

2.5 创建并连接数据库

2.6 编写实体类

  • pojo 包下编写对应数据表的实体类:BillProviderRoleUser

  • IDEA 快捷方式创建实例类:

    • 连接数据库后,在数据表上右键点击;

    • 选择创建位置;

    • 修改包路径;

    • 根据需求修改文件名称;

  • Bill.java

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 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 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 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;
    }
}
  • Provider.java
public class Provider {
    private Integer id; // 主键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; // 创建者(userId)
    private Date creationDate;  // 创建时间
    private Date modifyDate; // 更新时间
    private Integer modifyBy; // 更新者(userId)
   
    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;
    }
}
  • Role.java
public class Role {
    private Integer id; // 主键ID
    private String roleCode; // 角色编码
    private String roleName; // 角色名称
    private Integer createdBy;  // 创建者
    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 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 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;
    }
}
  • User.java
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 Integer getAge() {
        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 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 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;
    }
}

2.7 编写基础公共类

  • resources 包下,新建 db.properties 文件:
# MySQL8
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456
  • 编写数据库的公共类:dao 包下创建 BaseDao.java
public class BaseDao {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;

    /**
     * 静态代码块,类加载的同时进行初始化
     * 从配置文件中获取数据库配置
     */
    static {
        // 创建属性集合
        Properties params = new Properties();
        String configFile = "db.properties";
        // 通过类加载器读取对应资源,读取数据库连接信息,得到输入流
        InputStream is = BaseDao.class.getClassLoader().getResourceAsStream(configFile);
        // 读取流
        try {
            params.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取数据库配置属性
        driver = params.getProperty("driver");
        url = params.getProperty("url");
        username = params.getProperty("username");
        password = params.getProperty("password");
    }

    /**
     * 获取数据库连接
     *
     * @return 数据库对象
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            // 加载驱动
            Class.forName(driver);
            // 获取数据库连接对象
            connection = DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 编写查询公共方法
     *
     * @param connection        数据连接对象
     * @param preparedStatement SQL的执行对象
     * @param resultSet         查询结果集
     * @param sql               sql语句
     * @param params            占位符
     * @return 查询结果集
     * @throws SQLException
     */
    public static ResultSet execute(Connection connection, PreparedStatement preparedStatement,
                                    ResultSet resultSet, String sql, Object[] params) throws SQLException {
        // 获取sql语句的执行对象 PreparedStatement(对SQL进行预编译)
        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;
    }

    /**
     * 编写增、删、改公共方法
     *
     * @param connection        数据连接对象
     * @param sql               sql语句
     * @param params            占位符
     * @param preparedStatement SQL的执行对象
     * @return updateRows 记录条数
     * @throws SQLException
     */
    public static int execute(Connection connection, PreparedStatement preparedStatement,
                              String sql, Object[] params) throws SQLException {
        // 获取sql语句的执行对象 PreparedStatement(对SQL进行预编译)
        preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            // 为占位符参数赋值,索引从1开始
            preparedStatement.setObject(i + 1, params[i]);
        }
        // 获取增、删、改,记录条数
        int updateRows = preparedStatement.executeUpdate();
        return updateRows;
    }

    /**
     * 释放资源,顺序:后开先关
     *
     * @param resultSet         结果集
     * @param preparedStatement 执行sql的对象
     * @param connection        数据库对象
     * @return flag 是否关闭成功
     */
    public static boolean closeResource(Connection connection,
                                        PreparedStatement preparedStatement,
                                        ResultSet resultSet) {
        boolean flag = true;
        // 关闭结果集
        if (resultSet != null) {
            try {
                resultSet.close();
                // GC回收
                resultSet = null;
            } catch (SQLException e) {
                e.printStackTrace();
                // 设置异常时为false
                flag = false;
            }
        }
        // 关闭 preparedStatement
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
                preparedStatement = null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
            System.out.println(flag);
        }
        // 关闭 connection
        if (connection != null) {
            try {
                connection.close();
                connection = null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
        }
        return flag;
    }
}

2.8 编写字符编码过滤器

  • filter 包下,创建过滤器文件:
/**
 * 编码过滤器:注意:过滤器继续执行的代码!!
 * 用注解的方式,过滤所有内容:也可以通过配置web.xml
 */
@WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");

        // 注意:过滤器继续执行!!
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
  • web.xml 中注册,也通过注解方式 @WebFilter("/*")

2.9 导入静态资源

  • 放在 webapp 目录下:

三、登录功能的实现

3.1 流程结构

3.2 导入前端页面

  • 导入登录页面 login.jsp 及其它 jsp 页面;
  • 将登录页面 login.jsp 设置为首页:在 web.xml 中配置;
<!--设置首页页面-->
<welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
</welcome-file-list>

3.3 编写后端文件

  1. 编写 dao 层:
  • 功能:操作数据库
    • 通过 userCode 查询,业务层传递的 登录用户 是否存在;
  • dao 中新建 user 包,创建 UserDao 接口类:
public interface UserDao {
    /**
     * 得到要登录的用户
     *
     * @param connection 数据库连接对象
     * @param userCode   用户名
     * @return 登录用户
     */
    public User getLoginUser(Connection connection, String userCode) throws SQLException;
}
  • 编写 UserDao 接口的实现类 UserDaoImpl
public class UserDaoImpl implements UserDao {
    /**
     * 得到要登录的用户
     *
     * @param connection 数据库连接对象
     * @param userCode   用户名
     * @return User
     * @throws SQLException
     */
    @Override
    public User getLoginUser(Connection connection, String userCode) throws SQLException {
        PreparedStatement pstm = null;
        ResultSet rs = null;
        User user = null;

        // 判断数据库是否连接成功,
        if (connection != null) {
            // 创建SQL
            String sql = "select * from `smbms_user` where `userCode`=?";
            Object[] params = {userCode};
            // 执行SQL
            rs = BaseDao.execute(connection, pstm, rs, sql, params);
            while (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.setCreatedBy(rs.getInt("createdBy"));
                user.setCreationDate(rs.getTimestamp("creationDate"));
                user.setModifyBy(rs.getInt("modifyBy"));
                user.setModifyDate(rs.getTimestamp("modifyDate"));
            }
            BaseDao.closeResource(null, pstm, rs);
        }
        return user;
    }
}
  1. 编写业务层
  • 功能:调用 dao 层
    • 通过前端传递的用户编码 userCode,调用 dao 层,查询用户是否存在;
  • service 下新建 user 包,创建 UserService 接口:
public interface UserService {
    // 用户登录
    public User login(String userCode, String password);
}
  • 编写业务层接口的实现类
    • 业务层调用 dao 层,必须先引入 dao 层;
    • 引入方式:在构造函数中将其实例化
public class UserServiceImpl implements UserService {
    // 业务层都会调用dao层,所以需要引入dao层
    private UserDao userDao;

    // 通过构造函数,类实例化时,创建UserDao的实例
    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }

    /**
     * 用户登录
     *
     * @param userCode
     * @param password
     * @return
     */
    @Override
    public User login(String userCode, String password) {
        Connection connection = null;
        User user = null;
        try {
            connection = BaseDao.getConnection();
            // 业务层调用dao层:对应具体的数据库操作
            user = userDao.getLoginUser(connection, userCode);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResource(connection, null, null);
        }
        return user;
    }
}
  1. 编写 Servlet(控制层)
  • 功能:调用业务层
    • 获取前端输入的用户名、密码和数据库查询的内容做比对;
  • util 包下,创建 Constants 类,存储常量:
public class Constants {
    public final static String USER_SESSION = "userSession";
}
  • servlet 包中新建 user 包,创建 LoginServlet 类:
// 通过注解方式,注册servlet,也可通过web.xml配置
@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
    // Servlet:控制层,调用业务层
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("login.do=========LoginServlet start...");
        // 从前端获取输入的用户名、密码
        String userCode = req.getParameter("userCode");
        String userPassword = req.getParameter("userPassword");
        // 调用业务层:和数据库中密码进行对比
        UserService userService = new UserServiceImpl();
        // 得到登录人信息
        User user = userService.login(userCode, userPassword);

        // 如果用户存在,且密码正确,可以登录
        if (user != null && userPassword.equals(user.getUserPassword())) {             // 将用户信息存储到Session
            req.getSession().setAttribute(Constants.USER_SESSION, user);
            // 跳转到主页
            resp.sendRedirect(req.getContextPath() + "/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);
    }
}
  • 注册 servlet:可以配置 web.xml 或注解方式:@WebServlet("/login.do")
<!--注册登录页面的Servlet-->
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>类名</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login.do</url-pattern>
</servlet-mapping>
  • 测试访问,查看以上功能是否可以正常运行;

四、登录功能的优化

4.1 注销功能

  • 移除 session,返回登录页面:servlet.user 下创建 LogoutServlet 类:
// 注解方式,注册servlet
@WebServlet("/jsp/logout.do")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 移除用户的Session
        req.getSession().removeAttribute(Constants.USER_SESSION);
        // 返回登页面
        resp.sendRedirect(req.getContextPath() + "/login.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  • 注册 servlet:web.xml 或注解方式;

4.2 登录拦截器

  • 功能:未登录状态下,不能访问 jsp 目录下的所有页面;
  • filter 下创建 SysFilter 类:
    • 注意:执行完过滤内容,必须添加让过滤器继续往下执行的代码
      • chain.doFilter(req, resp);
// 注册过滤器
@WebFilter("/jsp/*")
public class SysFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        // 类型转换:获取session、重定向
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        // 从session中获取用户
        User user = (User) request.getSession().getAttribute(Constants.USER_SESSION);
        // 如果session为空(注销或未登录),跳转到错误页面
        if (user == null) {
            response.sendRedirect(request.getContextPath() + "/error.jsp");
        }
        // 过滤器继续执行!!
        chain.doFilter(req, resp);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
  • 注册过滤器:web.xml 中或注解方式:@WebFilter("/jsp/*")
<filter>
    <filter-name>Sysfilter</filter-name>
    <filter-class>类名</filter-class>
</filter>
<filter-mapping>
    <filter-name>Sysfilter</filter-name>
    <url-pattern>/jsp/*</url-pattern>
</filter-mapping>

4.3 密码修改

思路:自顶向下设计,自底向上实现

  • 先写基本逻辑,前端在测试后端时,逐渐完善:

    • 需要自底向上,逐一实现功能,修改密码需要更新数据库,需要到 dao 层,进行增、删、改、查;

    • dao 层需要的信息,比如:用户名、当前的密码、要修改的密码,需要从 Service 层获取;

    • Service 层,需要负责把从 Servlet 层传过来的数据,进行相应的处理、验证、核算,然后将最终的信息,传递给 dao 层;

    • Servlet 直接与前端接触,返回当前页面上传递过来的,用户输入触发的 参数,转发到不同的页面,交给不同的 Service 来处理这些请求;

  • 意味着,先从 dao 层开始写分模块,先写接口,再写接口的实现类,依次写 Serviceservlet ,最后注册 Servlet,然后测试并完善前端页面;

  1. 编写 dao 层
  • dao.user.UserDao 的接口下增加,用户修改密码接口:
/**
 * 修改当前用户密码
 *
 * @param connection 数据库连接对象
 * @param id         用户Id
 * @param password   新密码
 * @return 更新记录数
 * @throws SQLException
 */
public int updatePwd(Connection connection, int id, String password) throws SQLException;
  • 编写接口实现类:UserDaoImpl 中增加:
/**
 * 修改当前用户密码
 *
 * @param connection 数据库连接对象
 * @param id         用户Id
 * @param password   新密码
 * @return updateRows
 * @throws SQLException
 */
@Override
public int updatePwd(Connection connection, int id, String password) throws SQLException {
    PreparedStatement pstm = null;
    int updateRows = 0;
    if (connection != null) {
        String sql = "update `smbms_user` set `userPassword`=? where id=?";
        Object[] params = {password, id};
        updateRows = BaseDao.execute(connection, pstm, sql, params);
        BaseDao.closeResource(null, pstm, null);
    }
    return updateRows;
}
  1. 编写业务层 Service
  • 添加接口:在 UserService 接口类下增加:
// 根据用户Id,修改密码
public boolean updatePwd(int id, String pwd);
  • 接口实现类:在 UserServiceImpl 下增加:
/**
 * 根据用户Id,修改密码
 *
 * @param id  用户Id
 * @param pwd 新密码
 * @return boolean
 */
@Override
public boolean updatePwd(int id, String pwd) {
    boolean flag = false;
    Connection connection = null;
    try {
        connection = BaseDao.getConnection();
        if (userDao.updatePwd(connection, id, pwd) > 0) {
            flag = true;
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return flag;
}
  1. 编写 Servlet
  • servlet.user 包下,创建 UserServlet 类:
    • 通过前端传递的 method 值,做判断,去执行操作,实现 servlet 复用;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 实现servlet复用,实现复用需要提取出方法,然后在doGet函数中调用即可
    String method = req.getParameter("method");
    // 修改密码
    if (method.equals("savepwd") && method != null) {
        this.updatePwd(req, resp);   
    }
}

// 在doGet外添加复用方法
/**
 * 修改密码
 *
 * @param req
 * @param resp
 */
private void updatePwd(HttpServletRequest req, HttpServletResponse resp) {
    // 获取session
    Object o = req.getSession().getAttribute(Constants.USER_SESSION);
    String newpassword = req.getParameter("newpassword");
    // 设置标志位
    boolean flag = false;
    if (o != null && newpassword != null && newpassword.length() != 0) {
        // 调用业务层
        UserService userService = new UserServiceImpl();
        // 如果修改成功,返回true
        flag = userService.updatePwd(((User) o).getId(), newpassword);
        if (flag) {
            // 设置属性:返回前端
            req.setAttribute("message", "修改密码成功,请退出,使用新密码登录");
            // 移除session
            req.getSession().removeAttribute(Constants.USER_SESSION);
        } else {
            // 密码修改失败
            req.setAttribute("message", "修改密码失败");
        }
    } else {
        // 密码有问题
        req.setAttribute("message", "密码有问题");
    }

    try {
        resp.sendRedirect(req.getContextPath() + "/jsp/pwdmodify.jsp");
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • 注册 servlet:web.xml 中或注解方式 @WebServlet("/jsp/user.do")

4.4 使用 Ajax 优化密码修改

  • Json 转换依赖:

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.79</version>
    </dependency>
    
  • UserServlet 中创建 toJson 方法:

 /**
 * 转换为Json类型
 *
 * @param resp
 * @param object 需要转换的对象
 */
private void toJson(HttpServletResponse resp, Object object) {
    // 返回json类型
    resp.setContentType("application/json");
    try {
        // 输出流
        PrintWriter writer = resp.getWriter();
        // JSONArray工具类,转换格式
        // 将结果集,以json格式返回
        writer.write(JSONArray.toJSONString(object));
        // 刷新
        writer.flush();
        // 关闭流
        writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • 编写验证旧密码的 Servlet 类(方法复用):UserServlet 中增加
// doGet 方法中添加
// 验证旧密码
else if (method.equals("pwdmodify") && method != null) {
    this.pwdModify(req, resp);    
}

// 在doGet外添加复用方法
/**
 * Ajax验证旧密码:与session中的密码比对
 *
 * @param req
 * @param resp
 */
private void pwdModify(HttpServletRequest req, HttpServletResponse resp) {
    // 获取session
    Object o = req.getSession().getAttribute(Constants.USER_SESSION);
    String oldpassword = req.getParameter("oldpassword");
    // 万能的Map
    Map<String, String> resultMap = new HashMap<>();
    // Session过期
    if (o == null) {
        resultMap.put("result", "sessionerror");
        // 密码为空
    } else if (StringUtils.isNullOrEmpty(oldpassword)) {
        resultMap.put("result", "error");
        // 密码不正确
    } else {
        // session中的用户密码
        String userPassword = ((User) o).getUserPassword();
        if (userPassword.equals(oldpassword)) {
            resultMap.put("result", "true");
        } else {
            resultMap.put("result", "false");
        }
    }
    // 转换为json类型
    this.toJson(resp, resultMap);
}

五、用户管理模块

  • 结构流程图:

  • 导入分页的工具类:PageSupport.java

// 分页工具类
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;
    }

    // OOP三大特性:封装(属性私有、get/set、在set中限定一些不安全情况)
    public void setCurrentPageNo(int currentPageNo) {
        if (currentPageNo > 0) {
            this.currentPageNo = currentPageNo;
        }
    }

    public int getTotalCount() {
        return totalCount;
    }

    /**
     * 设置总记录数,获取页面总数
     *
     * @param 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;
        }
    }
}
  • 导入用户列表及相关 jsp 文件:

  • 按照自底向上的流程,编写:

    • Dao
    • DaoImpl
    • Service
    • ServiceImpl
    • Servlet

5.1 获取用户的数量

  • UserDao 接口,添加方法:
/**
 * 查询用户总数
 *
 * @param connection 数据库连接对象
 * @param userName   用户名
 * @param userRole   用户角色
 * @return int
 * @throws SQLException
 */
public int getUserCount(Connection connection, String userName, int userRole) throws SQLException;
  • UserDaoImpl 中添加实现方法:
/**
 * 根据用户名或角色,查询总数
 *
 * @param connection 数据库连接对象
 * @param userName   用户名
 * @param userRole   用户角色
 * @return count
 * @throws SQLException
 */
@Override
public int getUserCount(Connection connection, String userName, int userRole) throws SQLException {
    PreparedStatement pstm = null;
    ResultSet rs = null;
    int count = 0;
    if (connection != null) {
        StringBuffer sql = new StringBuffer();
        sql.append("select count(1) as count from `smbms_user` u,`smbms_role` r where u.`userRole`=r.`id`");
        // 存放参数
        ArrayList<Object> list = new ArrayList<>();
        if (!StringUtils.isNullOrEmpty(userName)) {
            sql.append(" and u.`userName` like ?");
            // index[0]
            list.add("%" + userName + "%");
        }
        if (userRole > 0) {
            sql.append(" and u.`userRole` = ?");
            // index[1]
            list.add(userRole);
        }
        // List 转换为数组
        Object[] params = list.toArray();
        System.out.println("UserDaoImpl-->getUserCount:" + sql.toString());
        rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
        if (rs.next()) {
            // 从结果集中获取最终的数量
            count = rs.getInt("count");
        }
        BaseDao.closeResource(null, pstm, rs);
    }
    return count;
}
  • UserService 接口中,添加方法:
// 查询用户数
public int getUserCount(String userName, int userRole);
  • UserServiceImpl 实现方法:
/**
 * 查询用户数
 *
 * @param userName 用户名
 * @param userRole 角色名
 * @return count
 */
@Override
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.closeResource(connection, null, null);
    }
    return count;
}

5.2 通过条件查询用户列表

  • UserDao 接口,添加方法:
/**
 * 通过条件查询用户列表
 *
 * @param connection    数据库连接对象
 * @param userName      用户名
 * @param userRole      用户角色
 * @param currentPageNo 当前页
 * @param pageSize      页面大小
 * @return List<User>
 * @throws SQLException
 */
public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize) throws SQLException;
  • UserDaoImpl 中添加实现方法:
/**
 * 通过条件查询用户列表
 *
 * @param connection    数据库连接对象
 * @param userName      用户名
 * @param userRole      用户角色
 * @param currentPageNo 当前页
 * @param pageSize      页面大小
 * @return List<User>
 */
@Override
public List<User> getUserList(Connection connection, String userName, int userRole,
                              int currentPageNo, int pageSize) throws SQLException {
    PreparedStatement pstm = null;
    ResultSet rs = null;
    // 用户列表
    List<User> userList = new ArrayList<>();
    if (connection != null) {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT u.*,r.`roleName` userRoleName FROM `smbms_user` u INNER JOIN `smbms_role` r ON u.`userRole`=r.`id`");
        ArrayList<Object> list = new ArrayList<>();
        if (!StringUtils.isNullOrEmpty(userName)) {
            sql.append(" and u.`userName` like ?");
            // index[0]
            list.add("%" + userName + "%");
        }
        if (userRole > 0) {
            sql.append(" and u.`userRole` = ?");
            // index[1]
            list.add(userRole);
        }
        // 分页
        sql.append(" ORDER BY `creationDate` DESC LIMIT ?,?");
        // 当前页
        currentPageNo = (currentPageNo - 1) * pageSize;
        list.add(currentPageNo);
        list.add(pageSize);
        // List 转换为数组
        Object[] params = list.toArray();
        System.out.println("UserDaoImpl-->getUserCount:" + sql.toString());
        rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
        while (rs.next()) {
            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"));
            userList.add(_user);
        }
        BaseDao.closeResource(null, pstm, rs);
    }
    return userList;
}
  • UserService 接口中,添加方法:
// 根据条件查询用户列表
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize);
  • UserServiceImpl 实现方法:
/**
 * 根据条件查询用户列表
 *
 * @param queryUserName 用户名
 * @param queryUserRole 用户角色
 * @param currentPageNo 当前页
 * @param pageSize      页面大小
 * @return List<User>
 */
@Override
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize) {
    Connection connection = null;
    List<User> userList = null;
    
    try {
        connection = BaseDao.getConnection();
        userList = userDao.getUserList(connection, queryUserName, queryUserRole, currentPageNo, pageSize);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return userList;
}

5.3 获取用户角色列表

  • dao 包下新建 role 目录,创建 RoleDao 接口:
public interface RoleDao {
    // 获取角色列表
    public List<Role> getRoleList(Connection connection) throws SQLException;
}
  • 创建 RoleDaoImpl 实现类:
public class RoleDaoImpl implements RoleDao {
    /**
     * 获取角色列表
     *
     * @param connection 数据库连接对象
     * @return List<Role>
     * @throws SQLException
     */
    @Override
    public List<Role> getRoleList(Connection connection) throws SQLException {
        PreparedStatement pstm = null;
        ResultSet rs = null;
        // 创建角色列表
        ArrayList<Role> roleList = new ArrayList<>();
        if (connection != null) {
            String sql = "select * from `smbms_role`";
            Object[] params = {};

            rs = BaseDao.execute(connection, pstm, 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"));
                roleList.add(_role);
            }
            BaseDao.closeResource(null, pstm, rs);
        }
        return roleList;
    }
}
  • service 包下,新建 role 目录,创建 RoleService 接口:
public interface RoleService {
    // 获取角色列表
    public List<Role> getRoleList();
}
  • 创建 RoleServiceImpl 实现类,实现方法:
    • 调用 dao 层,需要先引入;
public class RoleServiceImpl implements RoleService {
    // 引入dao
    private RoleDao roleDao;

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

    /**
     * 获取角色列表
     *
     * @return List<Role>
     */
    @Override
    public List<Role> getRoleList() {
        Connection connection = null;
        // 创建角色列表
        List<Role> roleList = null;
        try {
            connection = BaseDao.getConnection();
            // 获取角色列表
            roleList = roleDao.getRoleList(connection);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResource(connection, null, null);
        }
        return roleList;
    }
}

5.4 查询模块的 Servlet

  • UserServlet 中添加:
// doGet 方法中添加
// 用户管理
else if (method.equals("query") && method != null) {
    this.query(req, resp);            
}

/**
 * 用户管理(重点,难点):查询
 *
 * @param req
 * @param resp
 */
private void query(HttpServletRequest req, HttpServletResponse resp) {
    // 查询用户列表
    // 从前端获取数据
    String queryUserName = req.getParameter("queryname");
    String temp = req.getParameter("queryUserRole");
    String pageIndex = req.getParameter("pageIndex");
    // 设置默认的用户角色码,避免temp为空
    int queryUserRole = 0;

    // 获取用户列表
    UserService userService = new UserServiceImpl();
    List<User> userList = null;

    // 第一次请求,一定是第一页,页面大小固定
    // 页面大小:可以写配置文件,方便以后修改
    int pageSize = 5;
    // 默认起始页面
    int currentPageNo = 1;

    if (queryUserName == null) {
        queryUserName = "";
    }
    if (temp != null && !temp.equals("")) {
        // 给查询赋值 0、1、2、3
        queryUserRole = Integer.parseInt(temp);
    }
    if (pageIndex != null) {
        try {
            currentPageNo = Integer.parseInt(pageIndex);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }

    // 获取用户的总数(分页:上一页、下一页)
    int totalCount = userService.getUserCount(queryUserName, 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(queryUserName, queryUserRole, currentPageNo, pageSize);
    // 把用户列表传递给前端
    req.setAttribute("userList", userList);

    // 获取角色列表
    RoleServiceImpl roleService = new RoleServiceImpl();
    List<Role> roleList = roleService.getRoleList();
    // 把角色列表传递给前端
    req.setAttribute("roleList", roleList);

    // 给前端传递其它属性
    req.setAttribute("totalCount", totalCount);
    req.setAttribute("currentPageNo", currentPageNo);
    req.setAttribute("totalPageCount", totalPageCount);
    req.setAttribute("queryUserName", queryUserName);
    req.setAttribute("queryUserRole", queryUserRole);

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

5.5 用户管理模块的增、删、改、查(查看)

  • UserDao 中添加:
/**
 * 添加用户
 *
 * @param connection 数据库连接对象
 * @param user       用户对象
 * @return updateRows
 * @throws SQLException
 */
public int add(Connection connection, User user) throws SQLException;

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

// 修改用户信息
public int modify(Connection connection, User user) throws SQLException;

// 删除用户
public int delUser(Connection connection, int id) throws SQLException;
  • UserDaoImpl 中添加:
/**
 * 添加用户
 *
 * @param connection 数据库连接对象
 * @param user       用户对象
 * @return updateRows
 * @throws SQLException
 */
@Override
public int add(Connection connection, User user) throws SQLException {
    PreparedStatement pstm = null;
    int updateRows = 0;
    if (connection != null) {
        String sql = "INSERT INTO `smbms_user` (`userCode`,`userName`,`userPassword`," +
                "`gender`,`birthday`,`phone`,`address`,`userRole`,`createdBy`," +
                "`creationDate`) VALUE (?,?,?,?,?,?,?,?,?,?)";
        Object[] params = {user.getUserCode(), user.getUserName(), user.getUserPassword(),
                user.getGender(), user.getBirthday(), user.getPhone(), user.getAddress(),
                user.getUserRole(), user.getCreatedBy(), user.getCreationDate()};
        updateRows = BaseDao.execute(connection, pstm, sql, params);
        BaseDao.closeResource(null, pstm, null);
    }
    return updateRows;
}

/**
 * 根据id查看用户
 *
 * @param connection 数据库连接对象
 * @param id         用户id
 * @return User
 * @throws SQLException
 */
@Override
public User getUserById(Connection connection, int id) throws SQLException {
    PreparedStatement pstm = null;
    ResultSet rs = null;
    User _user = null;
    if (connection != null) {
        String sql = "SELECT u.*,`roleName` userRoleName FROM `smbms_user` u " +
                "INNER JOIN `smbms_role` r ON u.`userRole`= r.`id` WHERE u.`id`=?";
        Object[] params = {id};
        rs = BaseDao.execute(connection, pstm, rs, sql, params);
        while (rs.next()) {
            _user = new User();
            // id必须添加,否则修改时无法获取id
            _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.setAddress(rs.getString("address"));
            _user.setUserRole(rs.getInt("userRole"));
            _user.setUserRoleName(rs.getString("userRoleName"));
        }
        BaseDao.closeResource(null, pstm, rs);
    }
    return _user;
}

/**
 * 修改用户信息
 *
 * @param connection 数据库连接对象
 * @param user       用户对象
 * @return updateRows
 * @throws SQLException
 */
@Override
public int modify(Connection connection, User user) throws SQLException {
    PreparedStatement pstm = null;
    int updateRows = 0;
    if (connection != null) {
        String sql = "UPDATE `smbms_user` SET `userName`=?,`gender`=?,`birthday`=?," +
                "`phone`=?,`address`=?,`userRole`=?,`modifyBy`=?,`modifyDate`=? WHERE `id`=?";
        Object[] params = {user.getUserName(), user.getGender(), user.getBirthday(),
                user.getPhone(), user.getAddress(), user.getUserRole(),
                user.getModifyBy(), user.getModifyDate(), user.getId()};
        updateRows = BaseDao.execute(connection, pstm, sql, params);
        BaseDao.closeResource(null, pstm, null);
    }
    return updateRows;
}

// 删除用户
@Override
public int delUser(Connection connection, int id) throws SQLException {
    PreparedStatement pstm = null;
    int updateRows = 0;
    if (connection != null) {
        String sql = "DELETE FROM `smbms_user` WHERE `id`=?";
        Object[] params = {id};
        updateRows = BaseDao.execute(connection, pstm, sql, params);
        BaseDao.closeResource(null, pstm, null);
    }
    return updateRows;
}
  • UserService 中添加:
// 添加用户
public boolean add(User user);

// 查询用户编码:用户登录login,也可以实现功能
public User selectUserCodeExist(String userCode) throws SQLException;

// 根据id查看用户
public User getUserById(int id);

// 修改用户信息
public boolean modify(User user);

// 删除用户
public boolean delUser(int id);
  • UserServiceImpl 里添加:
/**
 * 添加用户
 *
 * @param user 用户对象
 * @return boolean
 */
@Override
public boolean add(User user) {
    boolean flag = false;
    Connection connection = null;
    try {
        connection = BaseDao.getConnection();
        // 开启事务
        connection.setAutoCommit(false);
        int updateRows = userDao.add(connection, user);
        // 提交事务
        connection.commit();
        if (updateRows > 0) {
            flag = true;
            System.out.println("用户添加成功");
        } else {
            System.out.println("用户添加失败");
        }
    } catch (SQLException e) {
        e.printStackTrace();
        try {
            System.out.println("rollback==========");
            // 手动通知,事务回滚(可去掉,失败后自动回滚)
            connection.rollback();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return flag;
}

/**
 * 查询用户编码是否存在:与login功能相同,可以通用
 *
 * @param userCode 用户编码
 * @return User
 */
@Override
public User selectUserCodeExist(String userCode) {
    Connection connection = null;
    User user = null;
    try {
        connection = BaseDao.getConnection();
        user = userDao.getLoginUser(connection, userCode);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return user;
}

/**
 * 根据id查看用户
 *
 * @param id 用户id
 * @return 用户对象
 */
@Override
public User getUserById(int id) {
    Connection connection = null;
    User user = null;
    try {
        connection = BaseDao.getConnection();
        user = userDao.getUserById(connection, id);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return user;
}

/**
 * 修改用户信息
 *
 * @param user 用户对象
 * @return boolean
 */
@Override
public boolean modify(User user) {
    boolean flag = false;
    Connection connection = null;
    try {
        connection = BaseDao.getConnection();
        // 开启事务
        connection.setAutoCommit(false);
        int updateRows = userDao.modify(connection, user);
        // 提交事务
        connection.commit();
        if (updateRows > 0) {
            flag = true;
        }
    } catch (SQLException e) {
        e.printStackTrace();
        try {
            // 手动通知事务回滚
            connection.rollback();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return flag;
}

/**
 * 删除用户
 *
 * @param id 用户id
 * @return boolean
 */
@Override
public boolean delUser(int id) {
    boolean flag = false;
    Connection connection = null;
    try {
        connection = BaseDao.getConnection();
        // 开启事务
        connection.setAutoCommit(false);
        int updateRows = userDao.delUser(connection, id);
        // 提交事务
        connection.commit();
        if (updateRows > 0) {
            flag = true;
        }
    } catch (SQLException e) {
        e.printStackTrace();
        try {
            // 手动通知事务回滚
            connection.rollback();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return flag;
}
  • UserServlet 整合文件:
// 通过注解方式,注册servlet
@WebServlet("/jsp/user.do")
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 实现servlet复用
        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);
            // 用户管理
        } else if (method.equals("query") && method != null) {
            this.query(req, resp);
            // 添加用户
        } else if (method.equals("add") && method != null) {
            this.add(req, resp);
            // 角色列表:添加用户时需获取
        } else if (method.equals("getrolelist") && method != null) {
            this.getRoleList(req, resp);
            // 查看用户编码是否重复
        } else if (method.equals("ucexist") && method != null) {
            this.userCodeExist(req, resp);
            // 查看用户
        } else if (method.equals("view") && method != null) {
            this.getUserById(req, resp, "userview.jsp");
            // 修改用户
        } else if (method.equals("modify") && method != null) {
            this.getUserById(req, resp, "usermodify.jsp");
            // 修改确认
        } else if (method.equals("modifyexe") && method != null) {
            this.modify(req, resp);
            // 删除用户
        } else if (method.equals("deluser") && method != null) {
            this.delUser(req, resp);
        }
    }

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

    /**
     * 修改密码
     *
     * @param req
     * @param resp
     */
    private void updatePwd(HttpServletRequest req, HttpServletResponse resp) {
        // 获取session
        Object o = req.getSession().getAttribute(Constants.USER_SESSION);
        String newpassword = req.getParameter("newpassword");
        // 设置标志位
        boolean flag = false;
        if (o != null && newpassword != null && newpassword.length() != 0) {
            // 调用业务层
            UserService userService = new UserServiceImpl();
            // 如果修改成功,返回true
            flag = userService.updatePwd(((User) o).getId(), newpassword);
            if (flag) {
                // 设置属性:返回前端
                req.setAttribute("message", "修改密码成功,请退出,使用新密码登录");
                // 移除session
                req.getSession().removeAttribute(Constants.USER_SESSION);
            } else {
                // 密码修改失败
                req.setAttribute("message", "修改密码失败");
            }
        } else {
            // 密码有问题
            req.setAttribute("message", "密码有问题");
        }

        try {
            resp.sendRedirect(req.getContextPath() + "/jsp/pwdmodify.jsp");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Ajax验证旧密码:与session中的密码比对
     *
     * @param req
     * @param resp
     */
    private void pwdModify(HttpServletRequest req, HttpServletResponse resp) {
        // 获取session
        Object o = req.getSession().getAttribute(Constants.USER_SESSION);
        String oldpassword = req.getParameter("oldpassword");
        // 万能的Map
        Map<String, String> resultMap = new HashMap<>();
        // Session过期
        if (o == null) {
            resultMap.put("result", "sessionerror");
            // 密码为空
        } else if (StringUtils.isNullOrEmpty(oldpassword)) {
            resultMap.put("result", "error");
            // 密码不正确
        } else {
            // session中的用户密码
            String userPassword = ((User) o).getUserPassword();
            if (userPassword.equals(oldpassword)) {
                resultMap.put("result", "true");
            } else {
                resultMap.put("result", "false");
            }
        }
        // 转换为json类型
        this.toJson(resp, resultMap);
    }

    /**
     * 用户管理(重点,难点):查询
     *
     * @param req
     * @param resp
     */
    private void query(HttpServletRequest req, HttpServletResponse resp) {
        // 查询用户列表
        // 从前端获取数据
        String queryUserName = req.getParameter("queryname");
        String temp = req.getParameter("queryUserRole");
        String pageIndex = req.getParameter("pageIndex");
        // 设置默认的用户角色码,避免temp为空
        int queryUserRole = 0;

        // 获取用户列表
        UserService userService = new UserServiceImpl();
        List<User> userList = null;

        // 第一次请求,一定是第一页,页面大小固定
        // 页面大小:可以写配置文件,方便以后修改
        int pageSize = 5;
        // 默认起始页面
        int currentPageNo = 1;

        if (queryUserName == null) {
            queryUserName = "";
        }
        if (temp != null && !temp.equals("")) {
            // 给查询赋值 0、1、2、3
            queryUserRole = Integer.parseInt(temp);
        }
        if (pageIndex != null) {
            try {
                currentPageNo = Integer.parseInt(pageIndex);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }

        // 获取用户的总数(分页:上一页、下一页)
        int totalCount = userService.getUserCount(queryUserName, 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(queryUserName, queryUserRole, currentPageNo, pageSize);
        // 把用户列表传递给前端
        req.setAttribute("userList", userList);

        // 获取角色列表
        RoleServiceImpl roleService = new RoleServiceImpl();
        List<Role> roleList = roleService.getRoleList();
        // 把角色列表传递给前端
        req.setAttribute("roleList", roleList);

        // 给前端传递其它属性
        req.setAttribute("totalCount", totalCount);
        req.setAttribute("currentPageNo", currentPageNo);
        req.setAttribute("totalPageCount", totalPageCount);
        req.setAttribute("queryUserName", queryUserName);
        req.setAttribute("queryUserRole", queryUserRole);

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

    /**
     * 添加用户:(需先获取角色列表)
     *
     * @param req
     * @param resp
     * @throws IOException
     * @throws ServletException
     */
    private void add(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        // 从前端获取属性
        String userCode = req.getParameter("userCode");
        String userName = req.getParameter("userName");
        String userPassword = req.getParameter("userPassword");
        String gender = (req.getParameter("gender"));
        String birthday = req.getParameter("birthday");
        String phone = req.getParameter("phone");
        String address = req.getParameter("address");
        String userRole = req.getParameter("userRole");

        // 创建用户对象,将前端的值存储到对象中
        User user = new User();
        user.setUserCode(userCode);
        user.setUserName(userName);
        user.setUserPassword(userPassword);
        user.setGender(Integer.valueOf(gender));
        try {
            user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setPhone(phone);
        user.setAddress(address);
        user.setUserRole(Integer.valueOf(userRole));
        user.setCreationDate(new Date());
        user.setCreatedBy(((User) req.getSession().getAttribute(Constants.USER_SESSION)).getId());

        // 调用业务层
        UserService userService = new UserServiceImpl();
        if (userService.add(user)) {
            resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
        } else {
            req.getRequestDispatcher("useradd.jsp").forward(req, resp);
        }
    }

    /**
     * 获取角色列表
     *
     * @param req
     * @param resp
     * @throws IOException
     */
    private void getRoleList(HttpServletRequest req, HttpServletResponse resp) {
        List<Role> roleList = null;
        RoleService roleService = new RoleServiceImpl();
        roleList = roleService.getRoleList();
        // 把roleList转换成json对象输出
        this.toJson(resp, roleList);
    }

    /**
     * 查看用户编码是否重复
     *
     * @param req
     * @param resp
     * @throws IOException
     */
    private void userCodeExist(HttpServletRequest req, HttpServletResponse resp) {
        String userCode = req.getParameter("userCode");
        Map<String, String> resultMap = new HashMap<>();
        if (StringUtils.isNullOrEmpty(userCode)) {
            resultMap.put("userCode", "exist");
        } else {
            UserService userService = new UserServiceImpl();
            User user = null;
            // 调用业务层
            // user = userService.selectUserCodeExist(userCode);
            // 业务层的login方法,功能相同
            user = userService.login(userCode, null);
            if (user != null) {
                resultMap.put("userCode", "exist");
            } else {
                resultMap.put("userCode", "notexist");
            }
        }
        // 转换为Json
        this.toJson(resp, resultMap);
    }

    /**
     * 转换为Json类型
     *
     * @param resp
     * @param object 需要转换的对象
     */
    private void toJson(HttpServletResponse resp, Object object) {
        // 返回json类型
        resp.setContentType("application/json");
        try {
            // 输出流
            PrintWriter writer = resp.getWriter();
            // JSONArray工具类,转换格式
            // 将结果集,以json格式返回
            writer.write(JSONArray.toJSONString(object));
            // 刷新
            writer.flush();
            // 关闭流
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据id查看用户
     *
     * @param req
     * @param resp
     * @param url  跳转网页地址
     * @throws ServletException
     * @throws IOException
     */
    private void getUserById(HttpServletRequest req, HttpServletResponse resp, String url) throws ServletException, IOException {
        String id = req.getParameter("uid");
        // id不为空
        if (!StringUtils.isNullOrEmpty(id)) {
            UserService userService = new UserServiceImpl();
            User user = userService.getUserById(Integer.parseInt(id));
            req.setAttribute("user", user);
            req.getRequestDispatcher(url).forward(req, resp);
        }
    }

    /**
     * 修改用户信息
     *
     * @param req
     * @param resp
     */
    private void modify(HttpServletRequest req, HttpServletResponse resp) {
        String id = req.getParameter("uid");
        String userName = req.getParameter("userName");
        String gender = req.getParameter("gender");
        String birthday = req.getParameter("birthday");
        String phone = req.getParameter("phone");
        String address = req.getParameter("address");
        String userRole = req.getParameter("userRole");

        User user = new User();
        user.setId(Integer.valueOf(id));
        user.setUserName(userName);
        user.setGender(Integer.valueOf(gender));
        try {
            user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setPhone(phone);
        user.setAddress(address);
        user.setUserRole(Integer.valueOf(userRole));
        user.setModifyBy(((User) req.getSession().getAttribute(Constants.USER_SESSION)).getId());
        user.setModifyDate(new Date());

        UserService userService = new UserServiceImpl();
        if (userService.modify(user)) {
            try {
                resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            try {
                req.getRequestDispatcher("usermodify.jsp").forward(req, resp);
            } catch (ServletException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    // 删除用户
    private void delUser(HttpServletRequest req, HttpServletResponse resp) {
        String id = req.getParameter("uid");
        Map<String, String> resultMap = new HashMap<>();
        if (StringUtils.isNullOrEmpty(id)) {
            resultMap.put("delResult", "notexist");
        } else {
            UserService userService = new UserServiceImpl();
            if (userService.delUser(Integer.parseInt(id))) {
                resultMap.put("delResult", "true");
            } else {
                resultMap.put("delResult", "false");
            }
        }
        // 转换为Json
        this.toJson(resp, resultMap);
    }
}

六、其它模块

  • 参照用户模块

  • 项目流程图

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容