JavaWeb实战:基础CRUD+批量删除+分页+条件
目录技术栈及相关参考资料:
- Servlet基础
- MVC模式和三层架构
- Element
- 1、需求
- 2、环境准备
- 2.1 工程准备
- 2.2 创建表
- 3、查询所有功能
- 3.1 后端实现
- 3.1.1 Dao层方法实现
- 3.1.2 Service层方法实现
- 3.1.3 Servlet实现与Servlet优化
- 3.2 前端实现
- 3.1 后端实现
- 4、添加功能
- 4.1 后端实现
- 4.1.1 Dao层方法实现
- 4.1.2 Service层方法实现
- 4.1.3 Serlvet实现,在 BrandServlet 中添加方法
- 4.2 前端实现
- 4.1 后端实现
- 4、修改和删除功能
- 5、批量删除功能
- 6、分页功能
- 7、条件查询
1、需求
- 实现对品牌数据最基础的 CRUD 功能(文中仅演示了查询和添加)
- 实现在所有数据页面对数据的批量删除功能
- 实现分页展示功能
- 实现条件查询功能
2、环境准备
2.1 工程准备
-
vue.js 和 element-ui 依赖
-
引入 Axios.js 依赖
-
包结构
-
Maven 依赖 pom.xml
<?xml version="1.0" encoding="UTF-8"?>4.0.0 priv.dandelion brand-case 1.0-SNAPSHOT war 8 8 junit junit 4.11 test org.mybatis mybatis 3.5.5 mysql mysql-connector-java 5.1.46 org.slf4j slf4j-api 1.7.20 ch.qos.logback logback-classic 1.2.3 ch.qos.logback logback-core 1.2.3 javax.servlet javax.servlet-api 3.1.0 provided javax.servlet.jsp jsp-api 2.2 provided jstl jstl 1.2 taglibs standard 1.1.2 com.alibaba fastjson 1.2.62 org.apache.tomcat.maven tomcat7-maven-plugin 2.2 -
MyBatis 核心配置文件
<?xml version="1.0" encoding="UTF-8" ?> -
创建 SqlSession 工厂工具类
package priv.dandelion.utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; public class SqlSessionFactoryUtils { // 提升作用域,用于再方法内进行返回 private static SqlSessionFactory sqlSessionFactory; // 静态代码块会随着类的加载自动执行且只执行一次 static { String resource = "mybatis-config.xml"; InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } public static SqlSessionFactory getSqlSessionFactory() { return sqlSessionFactory; } } -
实体类 Brand.java
package priv.dandelion.entity; public class Brand { // id 主键 private Integer id; // 品牌名称 private String brandName; // 企业名称 private String companyName; // 排序字段 private Integer ordered; // 描述信息 private String description; // 状态:0:禁用 1:启用 private Integer status; public Brand() { } public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) { this.id = id; this.brandName = brandName; this.companyName = companyName; this.ordered = ordered; this.description = description; this.status = status; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBrandName() { return brandName; } public void setBrandName(String brandName) { this.brandName = brandName; } public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } public Integer getOrdered() { return ordered; } public void setOrdered(Integer ordered) { this.ordered = ordered; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } @Override public String toString() { return "Brand{" + "id=" + id + ", brand_name='" + brandName + '\'' + ", company_name='" + companyName + '\'' + ", ordered=" + ordered + ", description='" + description + '\'' + ", status=" + status + '}'; } } -
Mapper 映射文件和 Mapper 接口
<?xml version="1.0" encoding="UTF-8" ?> -
前端页面 brand.html
Title 查询 批量删除 新增 提交 取消 修改 删除
2.2 创建表
-
SQL脚本
-- 删除tb_brand表 drop table if exists tb_brand; -- 创建tb_brand表 create table tb_brand ( -- id 主键 id int primary key auto_increment, -- 品牌名称 brand_name varchar(20), -- 企业名称 company_name varchar(20), -- 排序字段 ordered int, -- 描述信息 description varchar(100), -- 状态:0:禁用 1:启用 status int ); -- 添加数据 insert into tb_brand (brand_name, company_name, ordered, description, status) values ('华为', '华为技术有限公司', 100, '万物互联', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1), ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1), ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1), ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0), ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0), ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1), ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0), ('华为', '华为技术有限公司', 100, '万物互联', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1), ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1), ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1), ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0), ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0), ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1), ('华为', '华为技术有限公司', 100, '万物互联', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1), ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1), ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1), ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0), ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0), ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1), ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0), ('华为', '华为技术有限公司', 100, '万物互联', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1), ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1), ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1), ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0), ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0), ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1), ('华为', '华为技术有限公司', 100, '万物互联', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1), ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1), ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1), ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0), ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0), ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1), ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0), ('华为', '华为技术有限公司', 100, '万物互联', 1), ('小米', '小米科技有限公司', 50, 'are you ok', 1), ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1), ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1), ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0), ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0), ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1) ; SELECT * FROM tb_brand;
3、查询所有功能
3.1 后端实现
3.1.1 Dao层方法实现
package priv.dandelion.dao;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Select;
import priv.dandelion.entity.Brand;
import java.util.List;
public interface BrandMapper {
// 解决数据库与实体类明明不一致问题
@ResultMap("brandResultMap")
@Select("select * from tb_brand")
List selectAll();
}
3.1.2 Service层方法实现
-
接口
package priv.dandelion.service; import priv.dandelion.entity.Brand; import java.util.List; public interface BrandService { /** * 查询所有 * @return */ ListselectAll(); } -
实现类
package priv.dandelion.service.impl; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import priv.dandelion.dao.BrandMapper; import priv.dandelion.entity.Brand; import priv.dandelion.service.BrandService; import priv.dandelion.utils.SqlSessionFactoryUtils; import java.util.List; public class BrandServiceImpl implements BrandService { SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory(); @Override public ListselectAll() { SqlSession sqlSession = sqlSessionFactory.openSession(); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); List brands = mapper.selectAll(); sqlSession.close(); return brands; } }
3.1.3 Servlet实现与Servlet优化
每个Servlet写一个类非常杂乱,不利于编写和管理
可以将其写到同一个类中,URL将更变为如
http://localhost:8080/brand-case/brand/selectAll的形式
- 获取最后一段路径,即方法名称
- 通过反射获取方法对象,执行方法
注:
- 不继承
HttpServlet而进行自定义,并手动实现使用请求路径进行方法分发- 注意代码中
this的使用方法(动态绑定)
-
BaseServlet 负责替换 HttpServlet ,根据请求的最后一段路径进行方法分发,是 Servlet的父类
package priv.dandelion.controller.servlet; 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.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 替换HttpServlet * * 根据请求的最后一段路径进行方法分发 */ public class BaseServlet extends HttpServlet { // 重写service,根据请求路径进行方法分发 @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1. 获取请求路径 String requestURI = req.getRequestURI(); // /brand-case/brand/selectAll // 获取请求路径的最后一段,即方法名 int index = requestURI.lastIndexOf('/'); // substring(index)截取字符串为左闭右开区间,不需要斜杠,index需要+1 String methodName = requestURI.substring(index + 1); // 2. 获取BrandServlet的字节码对象,并获取方法的Method对象 // 此处的this为动态绑定(Servlet入口在子类中,子类调用父类方法,程序执行到此处时,this代表调用父类方法的子类对象) Class<? extends BaseServlet> cls = this.getClass(); // 获取方法的Method对象 try { Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); // 3. 执行方法 method.invoke(this, req, resp); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } -
BrandServlet 关于 Brand 的 Servlet 类,将多个 Servlet 写在一个类中
package priv.dandelion.controller.servlet; import com.alibaba.fastjson.JSON; import priv.dandelion.entity.Brand; import priv.dandelion.service.BrandService; import priv.dandelion.service.impl.BrandServiceImpl; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; import java.util.List; @WebServlet("/brand/*") public class BrandServlet extends BaseServlet{ private BrandService brandService = new BrandServiceImpl(); public void selectAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Listbrands = brandService.selectAll(); // 将查询到的结果序列化为JSON String jsonString = JSON.toJSONString(brands); // 处理中文,使用utf-8 resp.setContentType("text/json;charset=utf-8"); // 写回数据 resp.getWriter().write(jsonString); } // ... }
3.2 前端实现
- 页面加载完成后发送异步请求,获取列表数据(需要引入 Axios 的 JS 文件)
- 将数据设置到模型上
-
代码