前言
- 使用JSP回显用户列表,可以进行批量删除(有删除确认步骤),和修改用户数据(用户数据回显步骤)
- 使用servlet处理传递进来的请求参数,并调用dao处理数据并返回
- 使用mybatis,书写dao层,获取mysql数据库数据并返回到servlet
项目实现步骤
完整项结构
第一步:创建项目,配置pom.xml文件,导入相关工具类
pom.xml
<dependencies>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--mysql数据库连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<!---mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--jstl-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<finalName>project1</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.14.v20161028</version>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8080</port>
<path>/my_maven_pro</path>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 因为要使用mybatis,因此需要导入创建SqlSession的工具类,目的是创建sqlsession对象来发送sql,获取数据;
- 因为需要使用log4j日志,需要导入其配置文件相关设置;
- 因为mybatis配置了jdbc连接信息和mybatis配置信息分离,所以要jdbc.properties文件
SqlSessionFactoryUtil
public class SqlSessionFactoryUtil {
private static SqlSessionFactory factory;
private SqlSessionFactoryUtil(){}
static {
Reader reader=null;
try {
reader=reader= Resources.getResourceAsReader("mybatis.xml");
factory=new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static SqlSession getSessionSql(){
return factory.openSession(true);
}
}
openSession()方法参数为true,表示自动提交事务。
jdbc.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/csx_demo_925?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
username=root
password=root
jdbc的连接信息需要自己本地的mysql连接配置
log4j.properties
### set log levels ###
log4j.rootLogger = debug,stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d %p [%c] - %m%n
log4j.logger.com.ibatis=debug
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug,stdout
配置mybatis日志文件,在执行mybatis相关的sql时,可以看到sql语句的执行流程
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
</web-app>
web.xml配置的头信息,需要指定3.0版本以上,目的是可以在servlet中使用注解完成相关的映射配置
第二步:创建数据库表和对应实体类
数据库表
t_user用户表,包含字段为user_id(用户id),user_name(用户名),user_pic(用户头像),user_point(用户积分);这里用户头像暂时用不到
建表语句
create table if not exists t_user(
user_id int primary key auto_increment comment '用户id,主键',
user_name varchar(30) not null unique comment'用户名',
password varchar(30) not null comment'密码',
user_pic varchar(50) comment'用户头像',
user_point int default 0 comment'用户积分'
);
User
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private Integer userId;
private String userName;
private String password;
private String userPic;
private Integer userPoint;
}
属性名和字段名采用了小驼峰映射,需要在mybatis中手动配置类的属性和表中字段的映射关系。
第三步:创建Mybatis主配置文件,Dao层和mapper映射
mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<!--<settings>
<setting name="" value=""/>
</settings>-->
<typeAliases>
<package name="com.csx.entity"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver"
value="${driver}"/>
<property name="url"
value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
注意:
<properties resource="jdbc.properties"/>:配置了jdbc连接信息的路径,可以在mybatis.xml中使用${}引入jdbc.properties的配置信息 <typeAliases> <package name="com.csx.entity"/> </typeAliases>
- 设置别名,将entity包下的所有实体类,都设置别名,为类名或类名的全小写
- mappers标签中的mapper标签,需要先存在mappper映射文件才能配置其和主配置文件的绑定。
UserDao
public interface UserDao {
//查询所有用户
List<User> getUserList();
//根据id查询指定用户
User getUserById(int id);
//更新用户
int updateUser(User user);
//删除单个用户
int delUser(int id);
//批量删除用户
int delUsers(int[] ids);
}
项目需要的所有sql支持,从上到下分别为:查询所有用户数据;根据id查询指定用户;修改用户数据;删除用户数据(删除单个);批量删除用户数据
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.csx.dao.UserDao">
<resultMap id="userCols" type="user">
<id property="userId" column="user_id"/>
<result property="userName" column="user_name"/>
<result property="userPic" column="user_pic"/>
<result property="userPoint" column="user_point"/>
</resultMap>
<!--查询所有用户-->
<select id="getUserList" resultMap="userCols">
select * from t_user
</select>
<!--根据id查询指定用户-->
<select id="getUserById" parameterType="int" resultMap="userCols">
select * from t_user
where user_id = #{id}
</select>
<!--根据id修改用户名和积分-->
<update id="updateUser" parameterType="user">
update t_user set user_name = #{userName},user_point=#{userPoint}
where user_id = #{userId}
</update>
<!--删除单个用户数据-->
<delete id="delUser" parameterType="int">
delete from t_user where user_id = #{id}
</delete>
<!--批量删除用户数据,接收参数类型为数组-->
<delete id="delUsers">
delete from t_user where user_id in
<foreach collection="array" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
</mapper>
书写mapper.xml时需要注意使用 <resultMap>配置数据库字段和实体类的属性一一映射
第四步:创建service层
UserService
public interface UserService {
List<User> getUserList();
User getUserById(int id);
int updateUser(User user);
int delUser(int id);
int delUsers(String[] ids);
}
UserServiceImpl
public class UserServiceImpl implements UserService {
SqlSession session= SqlSessionFactoryUtil.getSessionSql();
UserDao userDao=session.getMapper(UserDao.class);
@Override
public List<User> getUserList() {
return userDao.getUserList();
}
@Override
public User getUserById(int id) {
return userDao.getUserById(id);
}
@Override
public int updateUser(User user) {
return userDao.updateUser(user);
}
@Override
public int delUser(int id) {
return userDao.delUser(id);
}
@Override
public int delUsers(String[] ids) {
//将字符串数组转换成int数组,需要判断null值
if (ids!=null){
int[] idss= Arrays.stream(ids).mapToInt(Integer::parseInt).toArray();
return userDao.delUsers(idss);
}
return 0;
}
}
service层,作用是调用dao的sql支持,完成业务逻辑,就像上面的类型转换的操作,实在service层实现的
第五步:创建前端页面和servlet
前端页面:执行逻辑--->当我们启动服务器时,在浏览器输入localhost:8080 默认访问的是index.html或index.jsp页面,因此我们可以直接在index.html页面完成跳转功能,跳转到我们的servlet进行逻辑处理(获取数据库中的数据,然后在页面展示)
index.html
<html>
<body>
<h2>Hello World!</h2>
</body>
<script>
location.href="toIndex";
</script>
</html>
在默认首页完成跳转到指定的servlet进行逻辑处理
ToIndexServlet
@WebServlet("/toIndex")
public class ToIndexServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
UserService userService=new UserServiceImpl();
//调用mybatis方法,获取所有用户数据
List<User> list= userService.getUserList();
//将存有用户数据的list集合放在request中
req.setAttribute("list",list);
//转发请求到list.jsp页面
req.getRequestDispatcher("list.jsp").forward(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
servlet的作用是获取所有用户信息,存放在list集合中,在存放到request作用域进行转发请求操作到list.jsp页面
list.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
<meta http-equiv="content-type" content="text/html;charset=utf-8" /><!-- /Added by HTTrack -->
<head>
<meta charset="UTF-8">
<meta name="description" content="">
<meta name="keywords" content="">
<title></title>
</head>
<body>
<table border="1px">
<tr>
<th></th>
<th>编号</th>
<th>姓名</th>
<th>积分</th>
<th>积分</th>
</tr>
<form action="subSelItem" method="post">
<c:forEach items="${list}" var="u">
<tr>
<td>
<input type="checkbox" name="selItems" value="${u.userId}">
</td>
<td>${u.userId}</td>
<td>${u.userName}</td>
<td>${u.userPoint}</td>
<td>
<a href="toUserDetail?userId=${u.userId}">修改</a>
<a href="delUser?userId=${u.userId}" onclick="return delUser()">删除</a>
</td>
</tr>
</c:forEach>
<input type="submit" value="删除所选" onclick="return delUser()">
</form>
</table>
</body>
<script>
function delUser(){
var ans= confirm("忍心删除吗?");
if(ans){
return true;
}else{
return false;
}
}
</script>
</html>
- 使用jstl标签库中的forEach标签,结合el表达式获取数据,遍历存放在request作用域中的list集合结合中的数据
- 通过两个超链接<a>,进行页面跳转和数据传递,处理修改和删除业务
- 通过表单包裹checkbox复选框,实现批量删除的请求;
注意:这里只展示了用户的id,用户名和用户积分
修改功能实现
修改逻辑的执行流程:
- 点击修改按钮,跳转到处理修改的/toUserDetail的servlet类,作用是获取当前用户信息,回显数据
- 由/toUserDetail的servlet跳转到修改页面userDetail.jsp,进行修改操作
- 将修改后的数据提交到另一个/updateUser的servlet中进行数据库更新操作
- 更新完成后,跳转到/toIndex的servlet获取数据库用户列表
- 获取完数据库用户数据后,跳转到list.jsp展示
ToUserDetailServlet
@WebServlet("/toUserDetail")
public class ToUserDetailServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id=Integer.parseInt(req.getParameter("userId"));
UserService userService=new UserServiceImpl();
User user= userService.getUserById(id);
req.setAttribute("user",user);
req.getRequestDispatcher("userDetail.jsp").forward(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
根据请求参数的用户id获取用户对象,将用户对象存放在request作用域,并转发请求到userDetail.jsp
userDetail.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML>
<html>
<meta http-equiv="content-type" content="text/html;charset=utf-8" /><!-- /Added by HTTrack -->
<head>
<meta charset="UTF-8">
<meta name="description" content="">
<meta name="keywords" content="">
<title>页面修改</title>
</head>
<body>
<form action="updateUser" method="post">
<input type="hidden" name="userId" value="${user.userId}">
姓名: <input type="text" name="userName" value="${user.userName}"> <br/>
积分: <input type="text" name="userPoint" value="${user.userPoint}"> <br/>
<input type="submit" value="确认修改">
</form>
</body>
</html>
进行页面回显操作,点击提交按钮,将数据提交到/updateUser的servlet类处理
UpdateUserServlet
@WebServlet("/updateUser")
public class UpdateUserServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id= Integer.parseInt(req.getParameter("userId"));
String user_name= req.getParameter("userName");
int score= Integer.parseInt(req.getParameter("userPoint"));
User user=new User();
user.setUserId(id);
user.setUserName(user_name);
user.setUserPoint(score);
UserService userService=new UserServiceImpl();
userService.updateUser(user);
resp.sendRedirect("toIndex");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
将提交数据更新到数据库中,然后回到/toIndex的servlet类中,重新获取数据库中的用户列表,然后跳转到list.jsp展示查看
删除单个功能
步骤:
- 在list.jsp中点击删除按钮,出现提示框,点击确认,跳转到delUser的servlet类中处理
- 在delUser的servlet类中进行删除操作,删除完毕后跳转到toIndex的servlet类中,重新获取数据库中的用户列表
- 跳转到list.jsp展示
DelUserServlet
@WebServlet("/delUser")
public class DelUserServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id= Integer.parseInt(req.getParameter("userId"));
UserService userService=new UserServiceImpl();
userService.delUser(id);
resp.sendRedirect("toIndex");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
批量删除功能
在list.jsp中使用表单包裹checkbox复选框,当选中多个提交时,在对应的servlet中使用
getParameterValues()方法接收到字符串数组,将字符串数组转换成int数组,底层通过mybatis的forEach标签进行批量删除
SubSelItemServlet
@WebServlet("/subSelItem")
public class SubSelItemServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String[] items= req.getParameterValues("selItems");
UserService userService=new UserServiceImpl();
userService.delUsers(items);
resp.sendRedirect("toIndex");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
业务处理:字符串数组转int数组
mybatis的sql处理:
总结
基于jsp+servlet+mybatis实现用户列表查看,用户修改,删除单个用户(确认步骤),批量删除用户等功能实现