1.介绍
学习完servlet 和 jsp 之后的第一个小demo
学习目的:第一次 打通 前端 后端 数据库 ,看到完整的javaweb 项目 基本流程
技术栈: servlet + jsp + jdbc + mysql + tomcat + maven + bootstrap +
2.准备工作:
准备数据库
/*
SQLyog Ultimate v11.33 (64 bit)
MySQL - 5.7.15 : Database - ssm
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`ssm` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
USE `ssm`;
/*Table structure for table `t_student` */
DROP TABLE IF EXISTS `t_student`;
CREATE TABLE `t_student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`sex` varchar(3) DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
`phone` varchar(32) DEFAULT NULL,
`address` varchar(32) DEFAULT NULL,
`hobby` varchar(200) DEFAULT NULL,
`pic` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=93 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
/*Data for the table `t_student` */
insert into `t_student`(`id`,`name`,`sex`,`birthday`,`phone`,`address`,`hobby`,`pic`) values (9,'李逍垚','男','2022-03-29 00:00:00','123333','郑州','coding','https://qf2201.oss-cn-beijing.aliyuncs.com/img/1650957654174.png'),(14,'刘洁','女','2022-03-14 00:00:00','123','郑州','coding','https://qf2201.oss-cn-beijing.aliyuncs.com/img/1651025986871.png'),(17,'刘洁','女','2022-03-08 00:00:00','12333334444','郑州','1113','https://qf2201.oss-cn-beijing.aliyuncs.com/img/1651026006687.png'),(18,'张文桧','男','2022-03-13 00:00:00','888','郑州111','听音乐','https://qf2201.oss-cn-beijing.aliyuncs.com/img/1651114571498.png'),(19,'胡图图123','男','2022-03-14 00:00:00','888','郑州','听音乐','https://qf2201.oss-cn-beijing.aliyuncs.com/img/1651114700812.png'),(25,'李孟阳123','女','2022-03-14 00:00:00','13511111','郑州','playgame',''),(27,'李垚','男','2022-03-15 16:43:03','1239','郑州','coding',NULL),(32,'张飞','男','2022-03-15 16:54:20','123','郑州','eating',NULL),(37,'张文桧','男','2022-03-15 17:20:18','888','郑州','听音乐',NULL),(40,'海龙战神','男','2022-03-15 17:52:57','111','郑州','貂蝉',NULL),(45,'哦哦','男','2022-03-15 18:34:37','123','郑州','郑州',NULL),(53,'张义博','男','2022-03-17 09:55:25','123','上海','coding',NULL),(55,'妲己222','女','2022-03-25 00:00:00','123','123','123',NULL),(66,'李垚','男','2022-04-24 00:00:00','111','222','写代码','https://qf2201.oss-cn-beijing.aliyuncs.com/img/1650794347858.png'),(73,'骚琦','男','2022-07-20 00:00:00','123','郑州','喊麦','https://java2207.oss-cn-hangzhou.aliyuncs.com/2207/saoqi.jpg'),(76,'晓雨3','女','2022-07-15 00:00:00','123','4567','play','https://java2207.oss-cn-hangzhou.aliyuncs.com/image/1658310400041.jpg'),(79,'zs','男','2022-10-11 00:00:00','123','123','123','123'),(80,'zszzzz','男','2022-10-11 00:00:00','123','123','123','123'),(81,'321','保密','2022-10-11 00:00:00','2222','zz','1232222','123'),(82,'afeng','男','2022-10-11 00:00:00','123','123','111','https://java2212.oss-cn-hangzhou.aliyuncs.com/image/1665474350740.jpg'),(83,'xiaomei','女','2022-10-12 00:00:00','123','123','123','https://java2212.oss-cn-hangzhou.aliyuncs.com/image/1665474464939.jpg'),(84,'222','保密','2022-10-12 00:00:00','222','222','222',''),(85,'张三','男','1999-11-11 00:00:00',NULL,'222','coding',NULL),(86,'李思思','女','1999-12-12 00:00:00',NULL,'222','coding',NULL),(87,'zzz','男','1999-11-11 00:00:00',NULL,'222','coding',NULL),(88,'qqqq','男','1999-11-11 00:00:00',NULL,'222','coding',NULL),(91,'zs','男','1999-11-11 00:00:00',NULL,NULL,'coding',NULL),(92,'ls','女','1999-12-12 00:00:00',NULL,NULL,'coding',NULL);
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
3.创建maven 形式的web 工程
1.先创建一个 empty project
2.创建module 以maven 的形式 使用骨架 创建web工程 注意 路径要放在刚才的project 下面
3.添加依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--添加servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- 引入jsp依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--druid连接池的依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.3</version>
</dependency>
<!--mysql驱动 注意 8 的驱动 对应的 url 和 driverClass 的写法-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
</dependencies>
4.修改web.xml
因为自动创建的web.xml 约束版本为2.3 ,修改如下
<?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">
</web-app>
5.创建基本的包 , 实体类 数据库配置文件
db.properties
driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/ssm?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username=root
password=123456
# ----- 加入druid的一些连接配置
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 60000毫秒/1000等于60秒 -->
maxWait=5000
DbUtil工具类
package com.glls.utils;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc
*/
public class DBUtil {
static Properties properties = new Properties( );
// 声明Druid连接池对象
private static DruidDataSource druidDataSource;
static {
try {
// 将配置文件读作输入流
InputStream stream = DBUtil.class.getResourceAsStream("/db.properties");
// properties对象加载流,即配置信息都在properties对象里面
properties.load(stream);
// 通过配置信息创建出druidDataSource数据源
druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace( );
}
}
/**
* 通过DruidDataSource获得连接
*/
public static Connection getConnection() {
Connection conn = null;
try {
// 2 获得连接
conn = druidDataSource.getConnection( );
} catch (Exception e) {
e.printStackTrace( );
}
return conn;
}
/**
* 抽取关流的方法
*/
public static void closeAll(Connection conn, Statement s) {
if (conn != null) {
try {
conn.close( );
} catch (SQLException e) {
e.printStackTrace( );
}
}
if (s != null) {
try {
s.close( );
} catch (SQLException e) {
e.printStackTrace( );
}
}
}
public static void closeAll(Connection conn, Statement s, ResultSet rs) {
if (conn != null) {
try {
conn.close( );
} catch (SQLException e) {
e.printStackTrace( );
}
}
if (s != null) {
try {
s.close( );
} catch (SQLException e) {
e.printStackTrace( );
}
}
if (rs != null) {
try {
rs.close( );
} catch (SQLException e) {
e.printStackTrace( );
}
}
}
/**
* 封装查询一个对象
*
* @param sql 有?的sql语句
* @param t 要封装的实体类字节码文件
* @param args 要给?赋值的值
* select * from tb_user where id = ?
*/
public static <T> T selectOne(String sql, Class<T> t, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
T target = null;
Field[] fields = t.getDeclaredFields( );
try {
conn = getConnection( );
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject((i + 1), args[i]);
}
rs = ps.executeQuery( );
if (rs.next( )) {
target = t.newInstance( );
for (Field field : fields) {
String name = field.getName( );
// 因为ORM,所以属性名就是列名
Object value = rs.getObject(name);
if (value == null) {
continue;
}
field.setAccessible(true);
field.set(target, value);
}
}
} catch (Exception e) {
e.printStackTrace( );
} finally {
closeAll(conn, ps, rs);
}
return target;
}
public static <T> List<T> selectAll(String sql, Class<T> t, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
T target = null;
Field[] fields = t.getDeclaredFields( );
ArrayList<T> list = new ArrayList<>( );
try {
conn = getConnection( );
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject((i + 1), args[i]);
}
rs = ps.executeQuery( );
while (rs.next( )) {
target = t.newInstance( );
for (Field field : fields) {
String name = field.getName( );
// 因为ORM,所以属性名就是列名
Object value = rs.getObject(name);
field.setAccessible(true);
if (value == null) {
continue;
}
field.set(target, value);
}
list.add(target);
}
} catch (Exception e) {
e.printStackTrace( );
} finally {
closeAll(conn, ps, rs);
}
return list;
}
/**
* 增删改设计成一个方法
*/
public static int update(String sql,Object... args) {
Connection conn = null;
PreparedStatement ps = null;
int num = 0;
try {
conn = getConnection( );
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject((i + 1), args[i]);
}
num = ps.executeUpdate( );
} catch (Exception e) {
e.printStackTrace( );
} finally {
closeAll(conn, ps);
}
return num;
}
public static void main(String[] args) {
System.out.println(getConnection());
}
}
前端页面准备
使用步骤:
在页面引入资源文件 ,这个资源文件 可以选择下载到本地 ,也可以选择直接引用线上的资源文件
这里 咱们资源文件的引入 放入 top.jsp 里面,别的页面只需要包含它即可
top.jsp
java<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <!-- 可选的 Bootstrap 主题文件(一般不用引入) --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous"> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) --> <%-- <script src="https://cdn.jsdelivr.cn/npm/jquery@1.12.4/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>--%> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Brand</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="${pageContext.request.contextPath}/studentList">学员管理 <span class="sr-only">(current)</span></a></li> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> <li role="separator" class="divider"></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="#"> ${currentUser.name} </a></li> <li><a href="${pageContext.request.contextPath}/logout"> 注销 </a></li> </ul> <form class="navbar-form navbar-right"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">Submit</button> </form> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav>
登录功能
登录页面
java<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <jsp:include page="common/top.jsp"></jsp:include> </head> <body> <p style="height: 50px"></p> <div class="container"> <h1 class="text-center"> 登录页面</h1> <form action="${pageContext.request.contextPath}/login" method="post" class="form-horizontal" role="form"> <div class="form-group"> <label for="firstname" class="col-sm-2 col-sm-offset-1 control-label">用户名</label> <div class="col-sm-6"> <input name="name" type="text" class="form-control" id="firstname" placeholder="请输入用户名"> </div> </div> <div class="form-group"> <label for="lastname" class="col-sm-2 col-sm-offset-1 control-label">密码</label> <div class="col-sm-6"> <input name="password" type="password" class="form-control" id="lastname" placeholder="请输入密码"> </div> </div> <%-- <div class="form-group">--%> <%-- <div class="col-sm-offset-2 col-sm-10">--%> <%-- <div class="checkbox">--%> <%-- <label>--%> <%-- <input type="checkbox"> 请记住我--%> <%-- </label>--%> <%-- </div>--%> <%-- </div>--%> <%-- </div>--%> <div class="form-group"> ${error} <div class="col-sm-offset-4 col-sm-6"> <button type="submit" class="btn btn-default">登录</button> <button type="button" class="btn btn-default">注册</button> </div> </div> </form> </div> </body> </html>
对应后端LoginServlet
javapackage com.glls.web; /** * @date 2023/3/29 * @desc */ import com.glls.pojo.Student; import com.glls.service.StudentService; import com.glls.service.impl.StudentServiceImpl; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet(name = "LoginServlet", value = "/login") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); //获取 用户名 密码 String name = request.getParameter("name"); String password = request.getParameter("password"); StudentService studentService = new StudentServiceImpl(); Student result = studentService.login(name,password); if(result!=null){ //用户名 密码是正确的 HttpSession session = request.getSession(); // 把查询出来的用户信息 存到session 域对象中 session.setAttribute("currentUser",result); response.sendRedirect(request.getServletContext().getContextPath() +"/main.jsp"); }else{ //用户名 密码 错误 request.setAttribute("error","用户名或密码错误"); request.getRequestDispatcher("/login.jsp").forward(request,response); } } }
对应的service 方法
java@Override public Student login(String name, String password) { Student student = studentDao.login(name, password); return student; }
对应的dao 方法
java@Override public Student login(String name, String password) { String sql = "select * from t_student where name = ? and password = ? "; Student student = DBUtil.selectOne(sql, Student.class, name, password); return student; }
登录成功之后 跳转到 main.jsp
java<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <jsp:include page="common/top.jsp"></jsp:include> <div class="container-fluid"> <div class="jumbotron"> <h1>Hello, JavaWeb!</h1> <p>纸上得来终觉浅</p> <p>绝知此事要躬行</p> <p>抬头 看看周围 大家都在努力</p> <p>你</p> <p>在干什么?</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> </div> <jsp:include page="common/footer.jsp"></jsp:include> </body> </html>
点击导航条上的 学员管理 查看学员列表
请求后端 StudentListServlet
package com.glls.web;
import com.glls.pojo.Student;
import com.glls.service.StudentService;
import com.glls.service.impl.StudentServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @date 2023/3/30
* @desc
*/
@WebServlet("/studentList")
public class StudentListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
// 准备好学生列表数据
StudentService studentService = new StudentServiceImpl();
List<Student> students = studentService.studentList();
//放在域对象中
req.setAttribute("students",students);
//跳转到页面上展示
req.getRequestDispatcher("/studentList.jsp").forward(req,resp);
}
}
对应的service 方法
@Override
public List<Student> studentList() {
List<Student> students = studentDao.studentList();
return students;
}
对应的dao 方法
@Override
public List<Student> studentList() {
String sql = "select * from t_student ";
List<Student> students = DBUtil.selectAll(sql, Student.class);
return students;
}
查询出来的数据 会在servlet 放入域对象 然后转发到studentList.jsp 使用el表达式和 jstl 标签 取数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:include page="common/top.jsp"></jsp:include>
<div class="page-header">
<small>
<a type="button" href="${pageContext.request.contextPath}/studentAdd.jsp" class="btn btn-info">学员添加</a>
</small>
</div>
<table class="table">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>生日</th>
<th>电话</th>
<th>地址</th>
<th>爱好</th>
<th>头像</th>
<th>操作</th>
</tr>
</thead>
<c:forEach items="${students}" var="stu">
<tr>
<td>${stu.id}</td>
<td>${stu.name}</td>
<td>${stu.sex}</td>
<td>
<fmt:formatDate value="${stu.birthday}" pattern="yyyy-MM-dd" ></fmt:formatDate>
</td>
<td>${stu.phone}</td>
<td>${stu.address}</td>
<td>${stu.hobby}</td>
<td>
<img width="50px" height="50px" src=" ${stu.pic}" alt="">
</td>
<td>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/studentUpdate?id=${stu.id}" role="button">编辑</a>
<a class="btn btn-warning" href="${pageContext.request.contextPath}/studentDelete?id=${stu.id}" role="button">删除</a>
</td>
</tr>
</c:forEach>
</table>
<jsp:include page="/common/footer.jsp"></jsp:include>
</body>
</html>
删除功能
对应的servlet
package com.glls.web;
import com.glls.service.StudentService;
import com.glls.service.impl.StudentServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/studentDelete")
public class StudentyDeleteServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String id = req.getParameter("id");
//创建service 对象
StudentService studentService = new StudentServiceImpl();
int result = studentService.deleteStudentById(Integer.parseInt(id));
if(result==1){
//删除成功 刷新下列表 这里咱么请求 列表数据的servlet
req.getRequestDispatcher("/studentList").forward(req,resp);
}else{
System.out.println("删除失败");
}
}
}
对应的service 的删除方法
@Override
public int deleteStudentById(Integer id) {
int result = studentDao.deleteStudentById(id);
return result;
}
对应的dao的删除方法
@Override
public int deleteStudentById(Integer id) {
String sql = "delete from t_student where id = ?";
int result = DBUtil.update(sql, id);
return result;
}
编辑功能
点页面上的编辑按钮
对应的servlet
package com.glls.web;
import com.glls.pojo.Student;
import com.glls.service.StudentService;
import com.glls.service.impl.StudentServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/studentUpdate")
public class StudentUpdateServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//接受要修改的记录的id
String id = req.getParameter("id");
//根据id 把要修改的记录查出来
StudentService studentService = new StudentServiceImpl();
Student stu = studentService.findStudentById(Integer.parseInt(id));
// 把要修改的数据 展示在页面上
req.setAttribute("stu",stu);
req.getRequestDispatcher("/studentUpdate.jsp").forward(req,resp);
}
}
service层代码
@Override
public Student findStudentById(int id) {
Student student = studentDao.findStudentById(id);
return student;
}
dao层代码
@Override
public Student findStudentById(int id) {
String sql = "select * from t_student where id = ?";
Student student = DBUtil.selectOne(sql, Student.class, id);
return student;
}
查询出来的要修改的记录 回显到表单上面
对应的页面 studentUpdate.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:include page="common/top.jsp"></jsp:include>
<form class="form-horizontal" method="post" action="${pageContext.request.contextPath}/doUpdate">
<div class="form-group">
<label for="id" class="col-sm-2 control-label">编号</label>
<div class="col-sm-10">
<input type="text" class="form-control" readonly id="id" placeholder="编号" name="id" value="${stu.id}">
</div>
</div>
<div class="form-group">
<label for="name" class="col-sm-2 control-label">学生姓名</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="name" placeholder="学生姓名" name="name" value="${stu.name}">
</div>
</div>
<div class="form-group">
<label for="sex" class="col-sm-2 control-label">性别</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="sex" placeholder="性别" name="gender" value="${stu.sex}">
</div>
</div>
<div class="form-group">
<label for="birthday" class="col-sm-2 control-label">生日</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="birthday" placeholder="生日" name="birthday" value="${stu.birthday}">
</div>
</div>
<div class="form-group">
<label for="phone" class="col-sm-2 control-label">电话</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="phone" placeholder="电话" name="phone" value="${stu.phone}">
</div>
</div>
<div class="form-group">
<label for="address" class="col-sm-2 control-label">住址</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="address" placeholder="住址" name="address" value="${stu.address}">
</div>
</div>
<div class="form-group">
<label for="hobby" class="col-sm-2 control-label">爱好</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="hobby" placeholder="爱好" name="hobby" value="${stu.hobby}">
</div>
</div>
<%-- //头像 先不做--%>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
</form>
<jsp:include page="/common/footer.jsp"></jsp:include>
</body>
</html>
在这个页面 提交 修改后的数据 到数据库 请求 DoUpdateStudentServlet
package com.glls.web;
import com.glls.pojo.Student;
import com.glls.service.StudentService;
import com.glls.service.impl.StudentServiceImpl;
import com.glls.utils.DateUtil;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* @date 2023/3/30
* @desc
*/
@WebServlet("/doUpdate")
public class DoUpdateStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//接受表单数据
String id = req.getParameter("id");
String name = req.getParameter("name");
String gender = req.getParameter("gender");
String birthday = req.getParameter("birthday");
String phone = req.getParameter("phone");
String address = req.getParameter("address");
String hobby = req.getParameter("hobby");
//封装到对象中
Student student = new Student();
student.setId(Integer.parseInt(id));
student.setName(name);
student.setSex(gender);
//前端传来的日期是一个字符串类型 而实体类中的日期是 Date 类型 所以这里需要转换
Date date = DateUtil.strToDate(birthday);
student.setBirthday(date);
student.setPhone(phone);
student.setAddress(address);
student.setHobby(hobby);
//调用service 去做修改
StudentService studentService = new StudentServiceImpl();
int result = studentService.updateStudentById(student);
// 修改成功 刷新页面列表
if(result==1){
req.getRequestDispatcher("/studentList").forward(req,resp);
}else{
req.setAttribute("error","编辑失败");
req.setAttribute("stu",student);
req.getRequestDispatcher("/studentUpdate.jsp").forward(req,resp);
}
}
}
添加功能
studentAdd.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:include page="common/top.jsp"></jsp:include>
<h1 class="text-center">添加学生</h1>
<form class="form-horizontal" method="post" action="${pageContext.request.contextPath}/studentAdd">
<div class="form-group">
<label for="name" class="col-sm-2 col-sm-offset-1 control-label">学生姓名</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="name" placeholder="学生姓名" name="name" >
</div>
</div>
<div class="form-group">
<label class="col-sm-2 col-sm-offset-1 control-label">性别</label>
<div class="col-sm-6">
<label class="radio-inline">
<input type="radio" name="gender" id="sex1" value="男"> 男
</label>
<label class="radio-inline">
<input type="radio" name="gender" id="sex2" value="女"> 女
</label>
</div>
</div>
<div class="form-group">
<label for="birthday" class="col-sm-2 col-sm-offset-1 control-label">生日</label>
<div class="col-sm-6">
<input type="date" class="form-control" id="birthday" placeholder="生日" name="birthday" >
</div>
</div>
<div class="form-group">
<label for="phone" class="col-sm-2 col-sm-offset-1 control-label">电话</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="phone" placeholder="电话" name="phone" >
</div>
</div>
<div class="form-group">
<label for="address" class="col-sm-2 col-sm-offset-1 control-label">住址</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="address" placeholder="住址" name="address" >
</div>
</div>
<div class="form-group">
<label for="hobby" class="col-sm-2 col-sm-offset-1 control-label">爱好</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="hobby" placeholder="爱好" name="hobby" >
</div>
</div>
<%-- //头像 先不做--%>
<div class="form-group">
<div class="col-sm-offset-5 col-sm-10">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
${error}
</form>
<jsp:include page="/common/footer.jsp"></jsp:include>
</body>
</html>
StudentAddServlet
// 自己实现添加功能
分页功能
背景: 当列表中的数据比较多的时候,在页面展示时 需要分页查询 ,mysql 的分页语句 要使用 limit 关键字
select 。。。。 from table where ..... limit start ,size; start 指的是从哪里开始取数据 size 指的是取多少条数据。 结合 功能的实现 前端需要传到后端 页码 就是 第几页 start = (页码 -1 ) * pageSize
思路: 还是 把分页数据 放在 域对象 然后跳转到页面 ,这就要求我们 不能再只放一个 集合了 ,需要设计一个数据结构 存放 页面上 分页列表数据 以及 分页的数据 比如 页码 总记录数 总页数等 那这个数据结构就是 pageBean
Page
package com.glls.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @date 2023/3/31
* @desc 封装分页的数据
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Page<T> {
// 分页列表数据
private List<T> pageData;
//页码
private Integer pageNum;
//一共多少页
private Integer totalPage;
//一共有多少记录
private Integer totalRecord;
//页面显示的起始页
private Integer startPageNum;
//页面显示的终止页
private Integer endPageNum;
}
在学生列表页面 咱们请求的就是 分页数据了
首先看 页面 ,需要使用 el + jstl 展示分页数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:include page="common/top.jsp"></jsp:include>
<div class="page-header">
<small>
<a type="button" href="${pageContext.request.contextPath}/studentAdd.jsp" class="btn btn-info">学员添加</a>
</small>
</div>
<table class="table">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>生日</th>
<th>电话</th>
<th>地址</th>
<th>爱好</th>
<th>头像</th>
<th>操作</th>
</tr>
</thead>
<c:forEach items="${page.pageData}" var="stu">
<tr>
<td>${stu.id}</td>
<td>${stu.name}</td>
<td>${stu.sex}</td>
<td>
<fmt:formatDate value="${stu.birthday}" pattern="yyyy-MM-dd" ></fmt:formatDate>
</td>
<td>${stu.phone}</td>
<td>${stu.address}</td>
<td>${stu.hobby}</td>
<td>
<img width="50px" height="50px" src=" ${stu.pic}" alt="">
</td>
<td>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/studentUpdate?id=${stu.id}" role="button">编辑</a>
<a class="btn btn-warning" href="${pageContext.request.contextPath}/studentDelete?id=${stu.id}" role="button">删除</a>
</td>
</tr>
</c:forEach>
</table>
<div align="center">
<nav aria-label="Page navigation">
<ul class="pagination">
<li class="disabled">
<a href=""> 当前第${page.pageNum}页</a>
</li>
<c:if test="${page.pageNum>1}">
<li>
<a href="${pageContext.request.contextPath}/studentList?pageNum=${page.pageNum-1}" aria-label="Previous">
<span aria-hidden="true">上一页</span>
</a>
</li>
</c:if>
<c:forEach var="num" begin="${page.startPageNum}" end="${page.endPageNum}">
<c:choose>
<c:when test="${num==page.pageNum}">
<li class="disabled"><a href="#"> ${num}</a></li>
</c:when>
<c:otherwise>
<li><a href="${pageContext.request.contextPath}/studentList?pageNum=${num}"> ${num}</a></li>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${page.pageNum<page.totalPage}">
<li>
<a href="${pageContext.request.contextPath}/studentList?pageNum=${page.pageNum+1}" aria-label="Next">
<span aria-hidden="true">下一页</span>
</a>
</li>
</c:if>
<li class="disabled">
<a href="">共${page.totalPage}页</a>
</li>
</ul>
</nav>
</div>
</body>
</html>
请求的后端servlet
package com.glls.web;
import com.glls.pojo.Page;
import com.glls.pojo.Student;
import com.glls.service.StudentService;
import com.glls.service.impl.StudentServiceImpl;
import com.mysql.cj.util.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @date 2023/3/30
* @desc
*/
@WebServlet("/studentList")
public class StudentListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//接受分页参数 第几页
String num = req.getParameter("pageNum");
Integer pageNum = 1;
if(!StringUtils.isNullOrEmpty(num)){
//如果传过来的页码不为空 接受传过来的页码
pageNum = Integer.parseInt(num);
}
//如果 传过来的页码为空 pageNum = 1
// 准备好分页数据
StudentService studentService = new StudentServiceImpl();
Page page = studentService.getPageData(pageNum);
//把 分页数据 放在域对象中
req.setAttribute("page",page);
//跳转到页面上展示
req.getRequestDispatcher("/studentList.jsp").forward(req,resp);
}
}
service 实现分页功能
@Override
public Page getPageData(Integer pageNum) {
Page<Student> studentPage = new Page<>();
studentPage.setPageNum(pageNum); //封装页码
Integer pageSize = 5; //每页显示的记录数
List<Student> pageData = studentDao.getPageData(pageNum,pageSize);
studentPage.setPageData(pageData); //封装分页的列表数据
Integer totalRecord = studentDao.getTotalRecord();
studentPage.setTotalRecord(totalRecord); // 封装总记录数
Integer totalPageNum = totalRecord%pageSize==0?(totalRecord/pageSize):(totalRecord/pageSize+1);
studentPage.setTotalPage(totalPageNum); // 封装总页数
//起始的页码 终止的页码 假设一共10 页
/**
* 1 2 3 4 5 第一页的时候
*
* 1 2 3 4 5 2
*
* 1 2 3 4 5 3
*
* 2 3 4 5 6 4
*
* 3 4 5 6 7 5
*
*
* 6 7 8 9 10 8
*
* 6 7 8 9 10 9
*
* 6 7 8 9 10 10
*
* */
Integer startPageNum = 1;
Integer endPageNum = 5;
//当页码 大于3 时 页面显示的 情况
if(pageNum-2>1){
startPageNum = pageNum-2;
endPageNum = pageNum + 2;
}
//当页面翻到 最后两页时
if(pageNum+2>totalPageNum){
startPageNum = totalPageNum-4;
endPageNum = totalPageNum;
}
//总页数 不到5 页 的情况
if(totalPageNum<5){
startPageNum = 1;
endPageNum = totalPageNum;
}
studentPage.setStartPageNum(startPageNum);
studentPage.setEndPageNum(endPageNum);
return studentPage;
}
对应dao方法
// 分页 查询 要查询出 分页列表数据
@Override
public List<Student> getPageData(Integer pageNum, Integer pageSize) {
//mysql 的分页语句 limit (pageNum-1)*pageSize, pageSize;
String sql = "select * from t_student limit ?,?";
Integer start = (pageNum-1) * pageSize;
List<Student> students = DBUtil.selectAll(sql, Student.class, start, pageSize);
return students;
}
//分页查询 也需要查询总记录数
@Override
public Integer getTotalRecord() {
String sql = "select * from t_student";
List<Student> students = DBUtil.selectAll(sql, Student.class);
Integer totalRecord = students.size();
return totalRecord;
}
模糊查询功能
页面输入查询条件, 点击查询按钮
查询 请求 还是 StudentListServlet , 需要在这servlet 中 接受 查询条件 ,这里 有两种思路
思路1 就是使用表单向后端发送模糊查询的条件
思路2 js 发送模糊查询的条件,这里咱们先试用js 来实现
<a type="button" onclick="findByCon()" class="btn btn-info">查询</a>
function findByCon(){
var s_name = $("#s_name").val();
var s_phone = $("#s_phone").val();
window.location.href="${pageContext.request.contextPath}/studentList?s_name="+s_name+"&s_phone="+s_phone;
}
</script>
后端 介绍查询条件,重构前面的分页查询方法 把service 和 dao 的 分页查询方法 加上模糊查询的条件
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//接受分页参数 第几页
String num = req.getParameter("pageNum");
Integer pageNum = 1;
if(!StringUtils.isNullOrEmpty(num)){
//如果传过来的页码不为空 接受传过来的页码
pageNum = Integer.parseInt(num);
}
//如果 传过来的页码为空 pageNum = 1
//获取模糊查询的条件
String s_name = req.getParameter("s_name");
String s_phone = req.getParameter("s_phone");
// 准备好分页数据
StudentService studentService = new StudentServiceImpl();
// 把模糊查询的条件 加上去
Page page = studentService.getPageData(pageNum,s_name,s_phone);
//把 分页数据 放在域对象中
req.setAttribute("page",page);
// 把查询条件带回去
req.setAttribute("s_name",s_name);
req.setAttribute("s_phone",s_phone);
//跳转到页面上展示
req.getRequestDispatcher("/studentList.jsp").forward(req,resp);
}
对应的service 实现 也是只需加上 模糊查询条件 s_name s_phone
List<Student> pageData = studentDao.getPageData(pageNum,pageSize,s_name,s_phone);
studentPage.setPageData(pageData); //封装分页的列表数据
Integer totalRecord = studentDao.getTotalRecord(s_name,s_phone);
需要注意的是 dao 层 sql 语句 怎么拼接
@Override
public List<Student> getPageData(Integer pageNum, Integer pageSize, String s_name, String s_phone) {
// 创建sb 对象 因为要拼接字符串
StringBuffer sb = new StringBuffer("select * from t_student ");
// s_name 不为空 需要把这个条件拼上去
if(!StringUtils.isNullOrEmpty(s_name)){
sb.append(" and name like '%"+s_name+"%' ");
}
// s_phone 不为空 需要把这个条件拼上去
if(!StringUtils.isNullOrEmpty(s_phone)){
sb.append(" and phone like '%"+s_phone+"%' ");
}
//mysql 的分页语句 limit (pageNum-1)*pageSize, pageSize;
sb.append( " limit ?, ?");
// 把 and 用 where 替换掉
String sql = sb.toString().replaceFirst("and" ," where");
Integer start = (pageNum-1) * pageSize;
List<Student> students = DBUtil.selectAll(sql, Student.class, start, pageSize);
return students;
}
@Override
public Integer getTotalRecord(String s_name, String s_phone) {
StringBuffer sb = new StringBuffer("select * from t_student ");
if(!StringUtils.isNullOrEmpty(s_name)){
sb.append(" and name like '%"+s_name+"%' ");
}
if(!StringUtils.isNullOrEmpty(s_phone)){
sb.append(" and phone like '%"+s_phone+"%' ");
}
String sql = sb.toString().replaceFirst("and" ," where");
List<Student> students = DBUtil.selectAll(sql, Student.class);
Integer totalRecord = students.size();
return totalRecord;
}
测试 模糊查询的效果