准备工作
需要的文件我已经打包好了:
链接:https://pan.baidu.com/s/1gTIi2nTHHv3bfcy5khKxgw
提取码:i2al
- 前端页面:可参考此篇文章 Element 入门教程 自行编写,也可以直接使用我准备好的模板
- sql 文件 ```sql -- 创建数据库 create database db1 character set utf8; use db1;
-- 删除tb_brand表
代码语言:txt复制drop table if exists tb_brand;
代码语言:txt复制-- 创建tb_brand表
代码语言:txt复制create table tb_brand
代码语言:txt复制(
代码语言:txt复制 -- id 主键
代码语言:txt复制 id int primary key auto_increment,
代码语言:txt复制 -- 品牌名称
代码语言:txt复制 brand_name varchar(20),
代码语言:txt复制 -- 企业名称
代码语言:txt复制 company_name varchar(20),
代码语言:txt复制 -- 排序字段
代码语言:txt复制 ordered int,
代码语言:txt复制 -- 描述信息
代码语言:txt复制 description varchar(100),
代码语言:txt复制 -- 状态:0:禁用 1:启用
代码语言:txt复制 status int
代码语言:txt复制);
代码语言:txt复制-- 添加数据
代码语言:txt复制insert into tb_brand (brand_name, company_name, ordered, description, status)
代码语言:txt复制values
代码语言:txt复制 ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制 ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制 ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制 ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制 ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制 ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制 ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制 ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制 ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
代码语言:txt复制 ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制 ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制 ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制 ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制 ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制 ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制 ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制 ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制 ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制 ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制 ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制 ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制 ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制 ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制 ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制 ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
代码语言:txt复制 ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制 ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制 ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制 ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制 ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制 ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制 ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制 ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制 ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制 ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制 ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制 ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制 ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制 ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
代码语言:txt复制 ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制 ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
代码语言:txt复制 ('华为', '华为技术有限公司', 100, '万物互联', 1),
代码语言:txt复制 ('小米', '小米科技有限公司', 50, 'are you ok', 1),
代码语言:txt复制 ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
代码语言:txt复制 ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
代码语言:txt复制 ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
代码语言:txt复制 ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
代码语言:txt复制 ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1)
代码语言:txt复制 ;
代码语言:txt复制SELECT * FROM tb_brand;
代码语言:txt复制```
业务 - 查询所有
后端
BrandMapper.java
:这里要注意实体类属性名称和数据库表名称不一致,使用 resultMap 映射 ```java /** * 查询所有 * @return */ @Select("select * from tb_brand") @ResultMap("brandResultMap") List<Brand> selectAll(); ```- service
- service 接口:
BrandService.java
```java package com.ruochen.service;
import com.ruochen.pojo.Brand;
代码语言:txt复制import java.util.List;
代码语言:txt复制public interface BrandService {
代码语言:txt复制 /**
代码语言:txt复制 * 查询所有
* @return
*/
List<Brand> selectAll();
}
```
- service 实现类:`BrandServiceImpl.java`
```java
package com.ruochen.service.impl;
代码语言:txt复制import com.ruochen.mapper.BrandMapper;
代码语言:txt复制import com.ruochen.pojo.Brand;
代码语言:txt复制import com.ruochen.service.BrandService;
代码语言:txt复制import com.ruochen.util.SqlSessionFactoryUtils;
代码语言:txt复制import org.apache.ibatis.session.SqlSession;
代码语言:txt复制import org.apache.ibatis.session.SqlSessionFactory;
代码语言:txt复制import java.util.List;
代码语言:txt复制public class BrandServiceImpl implements BrandService {
代码语言:txt复制 // 1. 创建 SqlSessionFactory 工厂对象
代码语言:txt复制 SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
代码语言:txt复制 @Override
代码语言:txt复制 public List<Brand> selectAll() {
代码语言:txt复制 // 2. 获取 SqlSession 对象
代码语言:txt复制 SqlSession sqlSession = factory.openSession();
代码语言:txt复制 // 3. 获取 BrandMapper
代码语言:txt复制 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制 // 4. 调用方法
代码语言:txt复制 List<Brand> brands = brandMapper.selectAll();
代码语言:txt复制 // 5. 释放资源
代码语言:txt复制 sqlSession.close();
代码语言:txt复制 return brands;
代码语言:txt复制 }
代码语言:txt复制}
代码语言:txt复制```
SelectAllServlet.java
```java package com.ruochen.web.servlet;
import com.alibaba.fastjson.JSON;
代码语言:txt复制import com.ruochen.pojo.Brand;
代码语言:txt复制import com.ruochen.service.BrandService;
代码语言:txt复制import com.ruochen.service.impl.BrandServiceImpl;
代码语言:txt复制import javax.servlet.*;
代码语言:txt复制import javax.servlet.http.*;
代码语言:txt复制import javax.servlet.annotation.*;
代码语言:txt复制import java.io.IOException;
代码语言:txt复制import java.util.List;
代码语言:txt复制@WebServlet("/selectAllServlet")
代码语言:txt复制public class SelectAllServlet extends HttpServlet {
代码语言:txt复制 private BrandService brandService = new BrandServiceImpl();
代码语言:txt复制 @Override
代码语言:txt复制 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
代码语言:txt复制 // 1. 调用 service 查询
代码语言:txt复制 List<Brand> brands = brandService.selectAll();
代码语言:txt复制 // 2. 数据转为 JSON
代码语言:txt复制 String jsonString = JSON.toJSONString(brands);
代码语言:txt复制 // 3. 写数据
代码语言:txt复制 // 数据存在中文
代码语言:txt复制 response.setContentType("text/json;charset=utf-8");
代码语言:txt复制 response.getWriter().write(jsonString);
代码语言:txt复制 }
代码语言:txt复制 @Override
代码语言:txt复制 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
代码语言:txt复制 this.doGet(request, response);
代码语言:txt复制 }
代码语言:txt复制}
代码语言:txt复制```
- 测试
前端
- 页面加载完成后,发送异步请求,获取数据,绑定表格上模型
tableData
```js mounted() { // 当页面加载完成后,发送异步请求,获取数据 var _this = this; axios({ method: "get", url: "http://localhost:8080/brand-case/selectAllServlet" }).then(function (resp) { _this.tableData = resp.data; }) }, ``` - 测试 业务 - 新增品牌
后端
BrandMapper.java
```java /** * 添加数据 * @param brand */ @Insert("insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status})") void add(Brand brand); ```- service
- service 接口:
BrandService.java
```java /** * 添加数据 * @param brand */ void add(Brand brand); ``` - service 实现类:`BrandServiceImpl.java` ```java @Override public void add(Brand brand) { // 2. 获取 SqlSession 对象 SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 brandMapper.add(brand); // 5. 提交事务 sqlSession.commit(); // 6. 释放资源 sqlSession.close(); } } ``` AddServlet.java
```java package com.ruochen.web.servlet;
import com.alibaba.fastjson.JSON;
代码语言:txt复制import com.ruochen.pojo.Brand;
代码语言:txt复制import com.ruochen.service.BrandService;
代码语言:txt复制import com.ruochen.service.impl.BrandServiceImpl;
代码语言:txt复制import javax.servlet.ServletException;
代码语言:txt复制import javax.servlet.annotation.WebServlet;
代码语言:txt复制import javax.servlet.http.HttpServlet;
代码语言:txt复制import javax.servlet.http.HttpServletRequest;
代码语言:txt复制import javax.servlet.http.HttpServletResponse;
代码语言:txt复制import java.io.BufferedReader;
代码语言:txt复制import java.io.IOException;
代码语言:txt复制import java.util.List;
代码语言:txt复制@WebServlet("/addServlet")
代码语言:txt复制public class AddServlet extends HttpServlet {
代码语言:txt复制 private BrandService brandService = new BrandServiceImpl();
代码语言:txt复制 @Override
代码语言:txt复制 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
代码语言:txt复制 // 1. 接收品牌数据
代码语言:txt复制 BufferedReader br = request.getReader();
代码语言:txt复制 String params = br.readLine(); // json 字符串
代码语言:txt复制 // JSON 字符串转为 brand 对象
代码语言:txt复制 Brand brand = JSON.parseObject(params, Brand.class);
代码语言:txt复制 // 2. 调用 service 添加
代码语言:txt复制 brandService.add(brand);
代码语言:txt复制 // 3. 响应成功标识
代码语言:txt复制 response.getWriter().write("success");
代码语言:txt复制 }
代码语言:txt复制 @Override
代码语言:txt复制 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
代码语言:txt复制 this.doGet(request, response);
代码语言:txt复制 }
代码语言:txt复制}
代码语言:txt复制```
前端
- 我们先将上一个功能中查询所有数据 ajax 请求封装为一个方法,方便调用 ```js // 查询所有数据 selectAll() { // 当页面加载完成后,发送异步请求,获取数据 var _this = this; axios({ method: "get", url: "http://localhost:8080/brand-case/selectAllServlet" }).then(function (resp) { _this.tableData = resp.data; }) }, ```
- 提交按钮绑定了
addBrand
方法,点击提交按钮时发送 ajax 请求,添加数据(数据由模型 brand 绑定获得) ```js // 添加数据 addBrand() { var _this = this; // 发送 ajax 请求,添加数据 axios({ method: "post", url: "http://localhost:8080/brand-case/addServlet", data: _this.brand }).then(function (resp) { if (resp.data == 'success') { // 添加成功 // 关闭窗口 _this.dialogVisible = false; // 查询数据 _this.selectAll();
// 弹出消息提示
代码语言:txt复制 _this.$message({
代码语言:txt复制 message: '恭喜你,添加成功',
代码语言:txt复制 type: 'success'
代码语言:txt复制 });
代码语言:txt复制 }
代码语言:txt复制 })
代码语言:txt复制},
代码语言:txt复制```
Servlet 优化
- 查看文章:Javaweb 自定义 Servlet 实现按照访问路径转发
业务 - 批量删除
后端
- Dao 层
-
BrandMapper.java
```java /** * 批量删除 * @param ids */ void deleteByIds(@Param("ids") int[] ids); ``` - `BrandMapper.xml` ```xml <!--批量删除--> <delete id="deleteByIds"> delete from tb_brand where id in <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> </delete> ``` - Service 层
- Service 接口:
BrandService.java
```java /** * 批量删除 * @param ids */ void deleteByIds(int[] ids); ``` - Service 实现类:`BrandServiceImpl.java` ```java @Override public void deleteByIds(int[] ids) { // 2. 获取 SqlSession 对象 SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 brandMapper.deleteByIds(ids); // 5. 提交事务 sqlSession.commit(); // 6. 释放资源 sqlSession.close(); } ``` - Web 层:
BrandServlet.java
```java /** * 批量删除 * * @param request * @param response * @throws ServletException * @throws IOException */ public void deleteByIds(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收数据 [1,2,...] BufferedReader br = request.getReader(); String params = br.readLine(); // json 字符串
// 转为 int[]
代码语言:txt复制 int[] ids = JSON.parseObject(params, int[].class);
代码语言:txt复制 // 2. 调用 service 添加
代码语言:txt复制 brandService.deleteByIds(ids);
代码语言:txt复制 // 3. 响应成功标识
代码语言:txt复制 response.getWriter().write("success");
代码语言:txt复制 }
代码语言:txt复制```
前端
- 首先要给批量删除按钮添加点击事件 ```html <el-button type="danger" plain @click="deleteByIds">批量删除</el-button> ```
- 在编写
deleteByIds
方法之前,我们要想办法获取到选中的 id,复选框选中后会执行一个handleSelectionChange
回调方法,我们可以通过该方法中的this.multipleSelection
获取到选中的对象数组 ```js // 复选框选中后执行的方法 handleSelectionChange(val) { this.multipleSelection = val;
// console.log(this.multipleSelection)
代码语言:txt复制},
代码语言:txt复制```
- 然后我们再写一个模型
multipleSelection
用于存放从this.multipleSelection
获取到的 id ```js // 复选框选中数据集合 multipleSelection: [], ``` - 现在我们编写
deleteByIds
方法 ```js // 批量删除 deleteByIds() { // 弹出确认提示框 this.$confirm('此操作将删除该数据, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { // 用户点击确认按钮 // 1. 创建id 数组 从 this.multipleSelection 获取即可 for (let selectionElement of this.multipleSelection) { this.selectedIds.push(selectionElement.id); } // 2. 发送 ajax 请求,携带 ID var _this = this; // 发送 ajax 请求,添加数据 axios({ method: "post", url: "http://localhost:8080/brand-case/brand/deleteByIds", data: _this.selectedIds }).then(function (resp) { if (resp.data == 'success') { // 删除成功 // 重新查询数据 _this.selectAll();
// 弹出消息提示
代码语言:txt复制 _this.$message({
代码语言:txt复制 message: '恭喜你,删除成功',
代码语言:txt复制 type: 'success'
代码语言:txt复制 });
代码语言:txt复制 }
代码语言:txt复制 })
代码语言:txt复制 }).catch(() => {
代码语言:txt复制 // 用户点击取消按钮
代码语言:txt复制 this.$message({
代码语言:txt复制 type: 'info',
代码语言:txt复制 message: '已取消删除'
代码语言:txt复制 });
代码语言:txt复制 });
代码语言:txt复制}
代码语言:txt复制```
业务 - 分页查询
分析
- SQL Limit 查询语句 - 参数1:开始索引 - 参数2:查询的条目数
- 页面传递的参数 - 当前页码 - 每页显示条数
- 计算 - 开始索引 = (当前页码 - 1) * 每页显示条数 - 查询的条目数 = 每页显示条数
后端
- 创建 JavaBean:
PageBean.java
```java package com.ruochen.pojo;
import java.util.List;
代码语言:txt复制// 分页查询的 JavaBean
代码语言:txt复制public class PageBean<T> {
代码语言:txt复制 // 总记录数
代码语言:txt复制 private int totalCount;
代码语言:txt复制 // 当前页数据
代码语言:txt复制 private List<T> rows;
代码语言:txt复制 public int getTotalCount() {
代码语言:txt复制 return totalCount;
代码语言:txt复制 }
代码语言:txt复制 public void setTotalCount(int totalCount) {
代码语言:txt复制 this.totalCount = totalCount;
代码语言:txt复制 }
代码语言:txt复制 public List<T> getRows() {
代码语言:txt复制 return rows;
代码语言:txt复制 }
代码语言:txt复制 public void setRows(List<T> rows) {
代码语言:txt复制 this.rows = rows;
代码语言:txt复制 }
代码语言:txt复制}
代码语言:txt复制```
- Dao 层:
BrandMapper.java
```java /** * 分页查询 * * @param begin 开始索引 * @param size 查询数据条数 * @return */ @Select("select * from tb_brand limit #{begin}, #{size}") @ResultMap("brandResultMap") List<Brand> selectByPage(@Param("begin") int begin, @Param("size") int size);
/**
代码语言:txt复制 * 查询总记录数
*
* @return
*/
@Select("select count(*) from tb_brand")
int selectTotalCount();
```Service 层
- Service 接口类:
代码语言:txt复制 // 4. 计算 开始索引 和 查询条目数
代码语言:txt复制 int begin = (currentPage - 1) * pageSize;
代码语言:txt复制 int size = pageSize;
代码语言:txt复制 // 5. 查询当前页数据
代码语言:txt复制 List<Brand> rows = brandMapper.selectByPage(begin, size);
代码语言:txt复制 // 6. 查询总记录数
代码语言:txt复制 int totalCount = brandMapper.selectTotalCount();
代码语言:txt复制 // 7. 封装 pageBean 对象
代码语言:txt复制 PageBean<Brand> pageBean = new PageBean<>();
代码语言:txt复制 pageBean.setRows(rows);
代码语言:txt复制 pageBean.setTotalCount(totalCount);
代码语言:txt复制 // 8. 释放资源
代码语言:txt复制 sqlSession.close();
代码语言:txt复制 return pageBean;
代码语言:txt复制 }
代码语言:txt复制```
- Web 层:
BrandServlet.java
```java /** * 分页查询 * * @param request * @param response * @throws ServletException * @throws IOException */ public void selectByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收 当前页码 和 每页展示条数 url?currentPage=1&pageSize=5 String _currentPage = request.getParameter("currentPage"); String _pageSize = request.getParameter("pageSize");
// 转换为 int 类型
代码语言:txt复制 int currentPage = Integer.parseInt(_currentPage);
代码语言:txt复制 int pageSize = Integer.parseInt(_pageSize);
代码语言:txt复制 // 2. 调用 Service 查询
代码语言:txt复制 PageBean<Brand> pageBean = brandService.selectByPage(currentPage, pageSize);
代码语言:txt复制 // 2. 数据转为 JSON
代码语言:txt复制 String jsonString = JSON.toJSONString(pageBean);
代码语言:txt复制 // 3. 写数据
代码语言:txt复制 // 数据存在中文
代码语言:txt复制 response.setContentType("text/json;charset=utf-8");
代码语言:txt复制 response.getWriter().write(jsonString);
代码语言:txt复制 }
代码语言:txt复制```
- 测试 前端
- 设置模型总记录数:
totalCount
,初值设为100,在selectAll方法中赋值 - 当前页码模型 currentPage 初值设置为1
- 每页条数模型 pageSize,默认值为 5 ```js // 每页显示条数 pageSize: 5, // 总记录数 totalCount: 100, // 当前页码 currentPage: 1, ```
- currentPage 和 pageSize 动态拼接到 selectAll url 中
- selectAll 方法改为查询分页 ```java // 查询分页数据 var _this = this; axios({ method: "get", url: "http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" this.currentPage "&pageSize=" this.pageSize, }).then(function (resp) { // 设置表格数据 _this.tableData = resp.data.rows; // 设置总记录数 _this.totalCount = resp.data.totalCount; }) ```
- 分页工具条绑定了
handleCurrentChange
和handleSizeChange
方法,方法中将值设置到模型中,再调用selectAll
方法即可 ```js //分页 handleSizeChange(val) { // console.log(`每页 ${val} 条`); // 重新设置每页显示条数 this.pageSize = val; // 重新查询 this.selectAll(); }, handleCurrentChange(val) { // console.log(`当前页: ${val}`); // 重新设置当前页码 this.currentPage = val; // 重新查询 this.selectAll(); }, ```
业务 - 条件查询
后端
- Dao 层
-
BrandMapper.java
```java /** * 分页条件查询 * * @param begin 开始索引 * @param size 查询数据条数 * @param brand 查询条件 * @return */ @ResultMap("brandResultMap") List<Brand> selectByPageAndCondition(@Param("begin") int begin, @Param("size") int size, @Param("brand") Brand brand);
/**
代码语言:txt复制 * 根据条件查询总记录数
*
* @param brand 查询条件
* @return
*/
int selectTotalCountByCondition(Brand brand);
```
- `BrandMapper.xml`
```xml
<select id="selectByPageAndCondition" resultMap="brandResultMap">
select *
from tb_brand
<where>
<if test="brand.brandName != null and brand.brandName != ''">
and brand_name like #{brand.brandName}
</if>
<if test="brand.companyName != null and brand.companyName != ''">
and company_name like #{brand.companyName}
</if>
<if test="brand.status != null">
and status like #{brand.status}
</if>
</where>
limit #{begin}, #{size}
</select>
代码语言:txt复制 <select id="selectTotalCountByCondition" resultType="java.lang.Integer">
代码语言:txt复制 select count(*)
代码语言:txt复制 from tb_brand
代码语言:txt复制 <where>
代码语言:txt复制 <if test="brandName != null and brandName != ''">
代码语言:txt复制 and brand_name like #{brandName}
代码语言:txt复制 </if>
代码语言:txt复制 <if test="companyName != null and companyName != ''">
代码语言:txt复制 and company_name like #{companyName}
代码语言:txt复制 </if>
代码语言:txt复制 <if test="status != null">
代码语言:txt复制 and status like #{status}
代码语言:txt复制 </if>
代码语言:txt复制 </where>
代码语言:txt复制 </select>
代码语言:txt复制```
- Service 层
- Service 接口类:
BrandService.java
```java /** * 分页条件查询 * * @param currentPage * @param pageSize * @param brand * @return */ PageBean<Brand> selectByPageAndCondition(int currentPage, int pageSize, Brand brand); ```
- Service 实现类:`BrandServiceImpl.java`
```java
@Override
public PageBean<Brand> selectByPageAndCondition(int currentPage, int pageSize, Brand brand) {
// 2. 获取 SqlSession 对象
SqlSession sqlSession = factory.openSession();
// 3. 获取 BrandMapper
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
代码语言:txt复制 // 4. 计算 开始索引 和 查询条目数
代码语言:txt复制 int begin = (currentPage - 1) * pageSize;
代码语言:txt复制 int size = pageSize;
代码语言:txt复制 // 处理 brand 条件,模糊表达式
代码语言:txt复制 String brandName = brand.getBrandName();
代码语言:txt复制 if (brandName != null && brandName.length() > 0) {
代码语言:txt复制 brand.setBrandName("%" brandName "%");
代码语言:txt复制 }
代码语言:txt复制 String companyName = brand.getCompanyName();
代码语言:txt复制 if (companyName != null && companyName.length() > 0) {
代码语言:txt复制 brand.setCompanyName("%" companyName "%");
代码语言:txt复制 }
代码语言:txt复制 // 5. 查询当前页数据
代码语言:txt复制 List<Brand> rows = brandMapper.selectByPageAndCondition(begin, size, brand);
代码语言:txt复制 // 6. 查询总记录数
代码语言:txt复制 int totalCount = brandMapper.selectTotalCountByCondition(brand);
代码语言:txt复制 // 7. 封装 pageBean 对象
代码语言:txt复制 PageBean<Brand> pageBean = new PageBean<>();
代码语言:txt复制 pageBean.setRows(rows);
代码语言:txt复制 pageBean.setTotalCount(totalCount);
代码语言:txt复制 // 8. 释放资源
代码语言:txt复制 sqlSession.close();
代码语言:txt复制 return pageBean;
代码语言:txt复制 }
代码语言:txt复制```
- Web 层:
BrandServlet.java
```java /** * 分页条件查询 * * @param request * @param response * @throws ServletException * @throws IOException */ public void selectByPageAndCondition(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收 当前页码 和 每页展示条数 url?currentPage=1&pageSize=5 String _currentPage = request.getParameter("currentPage"); String _pageSize = request.getParameter("pageSize");
// 转换为 int 类型
代码语言:txt复制 int currentPage = Integer.parseInt(_currentPage);
代码语言:txt复制 int pageSize = Integer.parseInt(_pageSize);
代码语言:txt复制 // 获取查询条件对象
代码语言:txt复制 BufferedReader br = request.getReader();
代码语言:txt复制 String params = br.readLine(); // json 字符串
代码语言:txt复制 // 转为 brand 对象
代码语言:txt复制 Brand brand = JSON.parseObject(params, Brand.class);
代码语言:txt复制 // 2. 调用 Service 查询
代码语言:txt复制 PageBean<Brand> pageBean = brandService.selectByPageAndCondition(currentPage, pageSize, brand);
代码语言:txt复制 // 2. 数据转为 JSON
代码语言:txt复制 String jsonString = JSON.toJSONString(pageBean);
代码语言:txt复制 // 3. 写数据
代码语言:txt复制 // 数据存在中文
代码语言:txt复制 response.setContentType("text/json;charset=utf-8");
代码语言:txt复制 response.getWriter().write(jsonString);
代码语言:txt复制 }
代码语言:txt复制```
前端
- 搜索框绑定模型 brand ```html <!--搜索表单--> <el-form :inline="true" :model="brand" class="demo-form-inline"> ```
- 给按钮绑定单击事件 onSubmit ,调用 selectAll 方法,这里我们就要给后台携带
brand
参数(post 方式),但是我们还需要在 url 中携带 currentPage 和 pageSize 参数(get方式),需要同时传输 post 和 get 数据,所以把请求方式改为 post ```js // 查询分页数据 var _this = this; axios({ method: "post", url: "http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" this.currentPage "&pageSize=" this.pageSize, data: this.brand }).then(function (resp) { // 设置表格数据 _this.tableData = resp.data.rows; // 设置总记录数 _this.totalCount = resp.data.totalCount; }) ``` onSubmit
```js this.currentPage = 1; ```- 最后,测试时我们发现 status 显示的仍然是数字,我们要让其显示
启动/禁用
,我们在Brand.java
里面有逻辑视图getStatusStr
,所以在前端页面表格中当前状态prpo
取statusStr
即可 ```html <el-table-column prop="statusStr" align="center" label="当前状态"> </el-table-column> ```
业务 - 删除功能
后端
- Dao 层:
BrandMapper.java
```java /** * 删除操作 * @param id */ @Delete("delete from tb_brand where id = #{id}") void deleteById(int id); ``` - Service 层
- Service 接口类:
BrandService.java
```java /** * 删除 * @param id */ void deleteById(int id); ``` - Service 实现类:`BrandServiceImpl.java` ```java @Override public void deleteById(int id) { // 2. 获取 SqlSession 对象 SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 brandMapper.deleteById(id); // 5. 提交事务 sqlSession.commit(); // 6. 释放资源 sqlSession.close(); } ``` - Web 层:
BrandServlet.java
,这里我们不需要单独编写根据 id 删除的 servlet,直接调用deleteByIdIds
即可前端 - 删除操作前端要返回给后端删除数据的 id,这里我们通过
template
参数scope
可以获取到当前行的数据,然后从数据中取出 id,携带 id 通过 axios 向后端发起请求即可 ```html <el-table-column align="center" label="操作"> <template slot-scope="scope"> <el-row> <el-button type="primary">修改</el-button> <el-button type="danger" @click="deleteById(scope.row)">删除</el-button> </el-row> </template> </el-table-column> ``` ```js // 根据Id 删除 deleteById(row) { this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { // 用户点击确认按钮 let rowId = [row.id]; // 发送 ajax 请求,携带 id axios({ method: "pose", url: "http://localhost:8080/brand-case/brand/deleteByIds", data: rowId }).then(resp => { if (resp.data == 'success') { // 删除成功 // 重新查询数据 this.selectAll();
// 弹出消息提示
代码语言:txt复制 this.$message({
代码语言:txt复制 message: '恭喜你,删除成功',
代码语言:txt复制 type: 'success'
代码语言:txt复制 });
代码语言:txt复制 }
代码语言:txt复制 })
代码语言:txt复制 }).catch(() => {
代码语言:txt复制 this.$message({
代码语言:txt复制 type: 'info',
代码语言:txt复制 message: '已取消删除'
代码语言:txt复制 });
代码语言:txt复制 });
代码语言:txt复制}
代码语言:txt复制```
业务 - 修改功能
后端
- Dao 层:
BrandMapper.java
```java /** * 更新操作 * * @param brand */ @Update("update tb_brand set brand_name = #{brandName}, company_name = #{companyName}, ordered = #{ordered}, " "description = #{description}, status = #{status} where id = #{id}") void update(Brand brand); ``` - Service 层
- Service 接口类:
BrandService.java
```java /** * 修改 * @param brand */ void update(Brand brand); ``` - Service 实现类:`BrandServiceImpl.java` ```java @Override public void update(Brand brand) { // 2. 获取 SqlSession 对象 SqlSession sqlSession = factory.openSession(); // 3. 获取 BrandMapper BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); // 4. 调用方法 brandMapper.update(brand); // 5. 提交事务 sqlSession.commit(); // 6. 释放资源 sqlSession.close(); } ``` - Web 层:`BrandServlet.java` ```java /** * 更新操作 * * @param request * @param response * @throws ServletException * @throws IOException */ public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 接收品牌数据 BufferedReader br = request.getReader(); String params = br.readLine(); // json 字符串
// JSON 字符串转为 brand 对象
代码语言:txt复制 Brand brand = JSON.parseObject(params, Brand.class);
代码语言:txt复制 // 2. 调用 service 添加
代码语言:txt复制 brandService.update(brand);
代码语言:txt复制 // 3. 响应成功标识
代码语言:txt复制 response.getWriter().write("success");
代码语言:txt复制 }
代码语言:txt复制```
前端
- 首先,我们要新建一个 dialog 来进行数据回显(不用直接用新增数据的 dialog 的原因是新增 dialog 绑定的模型 brand 在搜索框也有绑定,直接使用会出现乱七八糟的问题),同时绑定模型
updateBrand
```html <!--更新数据对话框表单--> <el-dialog title="更新品牌" :visible.sync="updateVisible" width="30%" >
<el-form ref="form" :model="updateBrand" label-width="80px">
代码语言:txt复制 <el-form-item label="品牌名称">
代码语言:txt复制 <el-input v-model="updateBrand.brandName"></el-input>
代码语言:txt复制 </el-form-item>
代码语言:txt复制 <el-form-item label="企业名称">
代码语言:txt复制 <el-input v-model="updateBrand.companyName"></el-input>
代码语言:txt复制 </el-form-item>
代码语言:txt复制 <el-form-item label="排序">
代码语言:txt复制 <el-input v-model="updateBrand.ordered"></el-input>
代码语言:txt复制 </el-form-item>
代码语言:txt复制 <el-form-item label="备注">
代码语言:txt复制 <el-input type="textarea" v-model="updateBrand.description"></el-input>
代码语言:txt复制 </el-form-item>
代码语言:txt复制 <el-form-item label="状态">
代码语言:txt复制 <el-switch v-model="updateBrand.status"
代码语言:txt复制 active-value="1"
代码语言:txt复制 inactive-value="0"
代码语言:txt复制 ></el-switch>
代码语言:txt复制 </el-form-item>
代码语言:txt复制 <el-form-item>
代码语言:txt复制 <el-button type="primary" @click="updateByBrand">提交</el-button>
代码语言:txt复制 <el-button @click="updateVisible = false">取消</el-button>
代码语言:txt复制 </el-form-item>
代码语言:txt复制 </el-form>
代码语言:txt复制</el-dialog>
代码语言:txt复制```
- updateBrand 模型 和
updateVisible
定义如下 ```js // 更新brand updateBrand: { status: '', brandName: '', companyName: '', id: "", ordered: "", description: "" }, // 更新数据对话框是否展示的标记 updateVisible: false, ``` - 在修改按钮通过
slot-scope
的scope.row
获取选中行数据 ```html <el-table-column align="center" label="操作"> <template slot-scope="scope"> <el-row> <el-button type="primary" @click="update(scope.row)">修改</el-button> <el-button type="danger" @click="deleteById(scope.row)">删除</el-button> </el-row> </template> </el-table-column> ``` - 修改按钮绑定
update
方法,进行数据回显 ```js // 数据回显 update(row) { // 数据回显 this.updateBrand = { status: row.status, brandName: row.brandName, companyName: row.companyName, id: row.id, ordered: row.ordered, description: row.description }; // 打开窗口 this.updateVisible = true; }, ``` - update dialog 绑定
updateByBrand
方法,进行更新操作 ```js // 更新数据 updateByBrand() { // 发送 ajax 请求,添加数据 axios({ method: "post", url: "http://localhost:8080/brand-case/brand/update", data: this.updateBrand }).then(resp => { if (resp.data == 'success') { // 添加成功 // 关闭窗口 this.updateVisible = false; // 重新查询数据 this.selectAll();
// 弹出消息提示
代码语言:txt复制 this.$message({
代码语言:txt复制 message: '恭喜你,更新成功',
代码语言:txt复制 type: 'success'
代码语言:txt复制 });
代码语言:txt复制 }
代码语言:txt复制 })
代码语言:txt复制}
代码语言:txt复制```
问题:status(switch开关)回显有问题,目前不会实现
前端代码优化
- 最后,我们对 axios 进行一下优化,之前我们的异步请求代码是这样的 ```js var _this = this; axios({ method: "post", url: "http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" this.currentPage "&pageSize=" this.pageSize, data: this.brand }).then(function (resp) { // 设置表格数据 _this.tableData = resp.data.rows; // 设置总记录数 _this.totalCount = resp.data.totalCount; }) ```
- 因为在 axios 中 this 指代的是 axios 而不是 vue,我们每次都需要在 axios 外面先将指代 vue 的 this 赋值给 _this,然后在 axios 中使用 _this 调用 vue 中的模型,这样很不方便
- 我们可以将 axios then 的 function 改为箭头函数,箭头函数中 this 会根据上下文语义进行判断,这样就可以代表 vue 对象,修改如下```js axios({ method: "post", url: "http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" this.currentPage "&pageSize=" this.pageSize, data: this.brand }).then(resp => { // 设置表格数据 this.tableData = resp.data.rows; // 设置总记录数 this.totalCount = resp.data.totalCount; }) ```最后的成品我也打包放在了网盘,需要可以自行下载 链接:https://pan.baidu.com/s/1Ps3parEeOJtazS-Kv7bWEw 提取码:msjj
觉得本文还不错可以点个赞支持一下 :smile: