【狂神说】SMBMS
本项目基于狂神说Java
的SMBMS项目,用于个人学习。
开发工具
IntelliJ IDEA 2022.2.3 MySQL9.0 Tomcat 9
项目架构:
项目主要分为四个核心模块
-
登录注销 -
用户管理 -
订单管理 -
供应商管理
1、数据库表
项目需要用到以下数据表,读者朋友可在公众号后台回复sql
获得创建所有数据库表的sql。
该表通过smbms.sql
一键生成
1.1、用户表
1.2、角色表
1.3、地址表
1.4、账单表
1.5、供应商表
2、搭建项目
2.1、创建webapp项目(Maven)
注意:勾选的原型是maven-archetype-webapp
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. 完善项目的包结构
完善项目结构
java
dao:数据持久化层,用于操作数据库 filter:过滤器 pojo:实体类 service:业务层,调用dao层处理业务 servlet:调用service层处理业务 util:工具类 resources:存放资源文件 webapp:项目资源
2.3、配置tomcat
选择war包
修改路径为/smbms
启动tomcat服务,访问成功,注意这个路径就是我们前面配置tomcat时设置的路径。
2.4、在idea中连接数据库
datasource选择MySQL
填写数据库配置,测试连接。
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
目录下
3、功能开发
需要开发的功能
登录注销功能(权限拦截) 密码修改功能 用户管理功能 本次开发聚焦于后端开发,因此前端页面直接用已经实现好的页面。
开发方式:自顶向下分析,自底向上实现
3.1、登录功能
登录功能的架构设计如下所示:
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>
3. DAO层
Dao层主要是实现与数据库交互,根据userCode
在数据库中完成查询,找到userCode
对应的用户。这里我们在dao下新建目录user
,在其中定义UserDao接口和接口的实现类。
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层。
UserService接口
定义
login
方法,通过校验userCode
和password
,来返回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, null, null);
}
return user;
}
}
5. Servlet层
Servlet层需要处理前端的登录请求,调用service层完成用户验证,并完成视图跳转。
用户登录成功:将该用户存储在 Session中,重定向到后台页面
用户登录失败:设置提醒,通过请求转发到登录页
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>
导入资源
这里需要注意前端文件中的路径。
输入错误密码,提示:
登录成功,跳转到后台管理页面
这里顺便修复一个小bug:在登录完成跳转到后台后,并没有显示用户名。这里通过查看frame.jsp
的源代码可以发现,jsp页面中使用的Session名应该为userSession
,将util.Constants
中的常量进行修改,即可正常显示用户名。
这里如果出现显示时间出现乱码的问题,可以使用以下方法:
在IDEA中将time.js
修改为add bom
,然后ctrl+shift+del
删除浏览器缓存,或者ctrl+F5
强制刷新,然后重新启动服务器。如下图所示,页面出现乱码可以通过该方法解决。
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中处理请求,并重新跳转页面。
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, null, null);
}
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>
密码修改成功页面如下所示:
碰到的一个问题,密码修改之后提交请求,报错
经过排查,实际上是前面BaseDao
代码有误,executeUpdate()
不需要传递参数。
3.4、用户分页查询
在我们点击用户管理时,实际上就是发送请求,然后在数据库中进行查询的功能,可以通过用户名进行查询(模糊匹配)或者通过用户角色进行查询。具体的架构设计如下图所示:
查询效果如下:
在进行用户分页列表查询时,需要从数据库中查询以下数值:
-
用户列表 -
角色列表 -
记录数
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
接口,因为用户管理页面中需要呈现用户的基本信息和用户角色,所以需要连表查询(user
和role
)。这里需要传递的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, null, null);
}
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
接口,因为用户管理页面中需要呈现用户的基本信息和用户角色,所以需要连表查询(user
和role
)。这里也需要拼接sql,sql语句如下:select count(1) as cnt
from smbms_user u, smbms_role r
where u.userRole = r.id
and u.userName like '%username%'
and r.userRole = userRole其中
username
和userRole
是我们需要传递的参数,我们将其放在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, null, null);
}
return count;
}
}
3. 查询角色列表
查询角色相关信息需要用到Role
表,在dao层中主要是对Role
表进行操作,因此新建包dao.role
, service.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, null, null);
}
return roles;
}
}
4. servlet层
在前端页面,我们是通过点击用户管理来实现跳转到用户查询页面的,我们可以分析下userlist.jsp
,前端会返回三个参数:queryUserName
,queryUserRole
,pageIndex
,分别表示查询用户名,查询用户角色,页码,通过这三个参数我们可以获取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,删除)。我们按照这样的顺序来实现相关功能。以上功能统一集成在用户管理页面中,如下所示。
1.增
增加用户功能页面如下所示:当点击添加用户
按钮,即可跳转到页面http://localhost:8080/smbms/jsp/useradd.jsp
,填入信息,完成用户添加。我们可以看到这里除了用户相关信息外,还需要从用户角色列表中进行选择。
功能实现流程:用户从前端发送请求访问页面,填写用户相关参数,将前端的参数返回到后端,后端根据用户参数创建用户对象,并且将用户插入到用户表中。
接下来,我们仍然按照自底向上的方式实现功能。根据我们上面的流程,我们其实是直接向数据库传递User
对象。
在实现用户增加功能时,需要考虑以下问题:
-
对于新建的用户,需要验证是否在数据库中已经有重复的编码——对应到的方法是使用ajax验证,绑定 ucexist
方法 -
新增用户需要设置角色,就需要我们获得用户列表 -
在servlet层需要更新用户创建的时间以及创建者,创建者可以从 Session
中获得当前User
的id
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, null, null);
}
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, null, null);
}
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();
}
}
在选择用户角色的时候,会出现上图的问题,主要是我们未能获取到用户角色列表。
2.删
删除用户的话,其实并不需要页面,我们只需要在构造ajax请求的时候传递用户id就可以直接在用户管理页面进行删除。
访问页面user.do?method=deluser&uid=49
,来实现删除功能。
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, null, null);
}
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请求,修改用户信息
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, null, null);
}
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, null, null);
}
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,查询用户信息
还记得吗,我们前面其实已经定义了根据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
获取~
4. 小结
这个项目前前后后花了差不多一个月的时间,虽然前端部分是直接copy的,但是通过这样一个简单的javaweb项目,对mvc架构有了简单的了解,当然这个项目问题还是比较多的。在我学完mybatis之后,我才回头补充这部分的文档,不由得还是感慨框架的效率,比jdbc确实是快太多了。接下来的任务就是开始学习spring全家桶了,期待在下一个Java项目与大家相见~
原文始发于微信公众号(多肉罗罗):JavaWeb项目SMBMS(二)——需求实现
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/186294.html