JavaWeb實戰:基礎CRUD+批量刪除+分頁+條件
技術棧及相關參考資料:
1、需求
- 實現對品牌數據最基礎的 CRUD 功能(文中僅演示了查詢和添加)
- 實現在所有數據頁面對數據的批量刪除功能
- 實現分頁展示功能
- 實現條件查詢功能
2、環境準備
2.1 工程準備
-
vue.js 和 element-ui 依賴
-
引入 Axios.js 依賴
-
包結構
-
Maven 依賴 pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="//maven.apache.org/POM/4.0.0" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>priv.dandelion</groupId> <artifactId>brand-case</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <!-- junit單元測試依賴 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--mybatis 依賴--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <!--mysql 驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <!-- 添加slf4j日誌api --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.20</version> </dependency> <!-- 添加logback-classic依賴 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <!-- 添加logback-core依賴 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </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.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!-- JSTL依賴 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- JSTL標準標籤庫依賴 --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- JSON串和Java對象的相互轉換 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency> </dependencies> <build> <plugins> <plugin> <!-- tomcat插件 --> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> </plugins> </build> </project>
-
MyBatis 核心配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "//mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--起別名--> <typeAliases> <package name="priv.dandelion.entity"/> </typeAliases> <environments default="development"> <environment id="development"> <!-- 採用JDBC的事務管理方式 --> <transactionManager type="JDBC"/> <!-- 資料庫連接資訊 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <!-- value的值一定不能換行,一定!一定!不能換行 --> <property name="url" value="jdbc:mysql:///db1?useSSL=false&useUnicode=true&characterEncoding=utf-8&useServerPrepStmts=true"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!-- 掃描mapper,載入SQL映射文件 --> <mappers> <package name="priv.dandelion.dao"/> </mappers> </configuration>
-
創建 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" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "//mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="priv.dandelion.dao.BrandMapper"> <!-- 解決資料庫與實體類命名不一致問題 --> <resultMap id="brandResultMap" type="brand"> <result column="brand_name" property="brandName"></result> <result column="company_name" property="companyName"></result> </resultMap> </mapper>
-
前端頁面 brand.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .el-table .warning-row { background: oldlace; } .el-table .success-row { background: #f0f9eb; } </style> </head> <body> <div id="app"> <!--搜索表單--> <el-form :inline="true" :model="brand" class="demo-form-inline"> <el-form-item label="當前狀態"> <el-select v-model="brand.status" placeholder="當前狀態"> <el-option label="啟用" value="1"></el-option> <el-option label="禁用" value="0"></el-option> </el-select> </el-form-item> <el-form-item label="企業名稱"> <el-input v-model="brand.companyName" placeholder="企業名稱"></el-input> </el-form-item> <el-form-item label="品牌名稱"> <el-input v-model="brand.brandName" placeholder="品牌名稱"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">查詢</el-button> </el-form-item> </el-form> <!--按鈕--> <!-- @click="dialogVisible = true" 單擊時將dialogVisible設置為true,展示對話框 --> <el-row> <el-button type="danger" plain>批量刪除</el-button> <el-button type="primary" plain @click="dialogVisible = true">新增</el-button> </el-row> <!--添加數據對話框表單--> <el-dialog title="編輯品牌" :visible.sync="dialogVisible" width="30%"> <el-form ref="form" :model="brand" label-width="80px"> <el-form-item label="品牌名稱"> <el-input v-model="brand.brandName"></el-input> </el-form-item> <el-form-item label="企業名稱"> <el-input v-model="brand.companyName"></el-input> </el-form-item> <el-form-item label="排序"> <el-input v-model="brand.ordered"></el-input> </el-form-item> <el-form-item label="備註"> <el-input type="textarea" v-model="brand.description"></el-input> </el-form-item> <el-form-item label="狀態"> <el-switch v-model="brand.status" active-value="1" inactive-value="0" ></el-switch> </el-form-item> <el-form-item> <el-button type="primary" @click="addBrand">提交</el-button> <el-button @click="dialogVisible = false">取消</el-button> </el-form-item> </el-form> </el-dialog> <!--表格--> <!-- 其中<el-table-column></el-table-column>標籤的prop屬性值 需要和Vue核心對象返回tableData的對象屬性名一致 --> <template> <!-- @selection-change="handleSelectionChange" 監聽到複選框勾選時,獲取行的記錄 需要在Vue核心對象中實現handleSelectionChange函數 --> <el-table :data="tableData" style="width: 100%" :row-class-name="tableRowClassName" @selection-change="handleSelectionChange"> <!--表格複選框--> <el-table-column type="selection" width="55"> </el-table-column> <el-table-column type="index" width="50"> </el-table-column> <el-table-column prop="brandName" label="品牌名稱" align="center"> </el-table-column> <el-table-column prop="companyName" label="企業名稱" align="center"> </el-table-column> <el-table-column prop="ordered" align="center" label="排序"> </el-table-column> <el-table-column prop="status" align="center" label="當前狀態"> </el-table-column> <el-table-column align="center" label="操作"> <el-row> <el-button type="primary">修改</el-button> <el-button type="danger">刪除</el-button> </el-row> </el-table-column> </el-table> </template> <!--分頁工具條--> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[5, 10, 15, 20]" :page-size="5" layout="total, sizes, prev, pager, next, jumper" :total="400"> </el-pagination> </div> <script src="js/vue.js"></script> <script src="element-ui/lib/index.js"></script> <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script> new Vue({ el: "#app", methods: { tableRowClassName({row, rowIndex}) { if (rowIndex === 1) { return 'warning-row'; } else if (rowIndex === 3) { return 'success-row'; } return ''; }, // 複選框選中後執行的方法 handleSelectionChange(val) { this.multipleSelection = val; console.log(this.multipleSelection) }, // 查詢方法 onSubmit() { console.log(this.brand); }, // 添加數據 addBrand(){ console.log(this.brand); }, //分頁 handleSizeChange(val) { console.log(`每頁 ${val} 條`); }, handleCurrentChange(val) { console.log(`當前頁: ${val}`); } }, data() { return { // 當前頁碼 currentPage: 4, // 添加數據對話框是否展示的標記 dialogVisible: false, // 品牌模型數據 brand: { status: '', brandName: '', companyName: '', id:"", ordered:"", description:"" }, // 複選框選中數據集合 multipleSelection: [], // 表格數據 tableData: [{ brandName: '華為', companyName: '華為科技有限公司', ordered: '100', status: "1" }, { brandName: '華為', companyName: '華為科技有限公司', ordered: '100', status: "1" }, { brandName: '華為', companyName: '華為科技有限公司', ordered: '100', status: "1" }, { brandName: '華為', companyName: '華為科技有限公司', ordered: '100', status: "1" }] } } }) </script> </body> </html>
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<Brand> selectAll();
}
3.1.2 Service層方法實現
-
介面
package priv.dandelion.service; import priv.dandelion.entity.Brand; import java.util.List; public interface BrandService { /** * 查詢所有 * @return */ List<Brand> selectAll(); }
-
實現類
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 List<Brand> selectAll() { SqlSession sqlSession = sqlSessionFactory.openSession(); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); List<Brand> brands = mapper.selectAll(); sqlSession.close(); return brands; } }
3.1.3 Servlet實現與Servlet優化
每個Servlet寫一個類非常雜亂,不利於編寫和管理
可以將其寫到同一個類中,URL將更變為如
//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 { List<Brand> brands = 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 文件)
- 將數據設置到模型上
-
程式碼
<!-- ... --> <script src="js/axios-0.18.0.js"></script> <script> new Vue({ el: "#app", // 當頁面載入完成後發送非同步請求來獲取數據 mounted(){ // 原生的this不能在Axios中使用,提升其生命周期 var _this = this; // 使用Axios發送非同步請求 axios({ method:"get", url:"//localhost:8080/brand-case/selectAll" }).then(function (resp) { _this.tableData = resp.data; }) }, // ... // ... // ... }) </script> </body> </html>
4、添加功能
4.1 後端實現
4.1.1 Dao層方法實現
4.1.2 Service層方法實現
-
添加介面
/** * 添加數據 */ boolean addBrand(Brand brand);
-
實現介面
@Override public boolean addBrand(Brand brand) { // 自動提交事務 SqlSession sqlSession = sqlSessionFactory.openSession(true); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 判斷用戶名是否不存在 final boolean flag = (null == mapper.selectByBrandName(brand.getBrandName())); if (flag) mapper.addBrand(brand); sqlSession.close(); return flag; }
4.1.3 Serlvet實現,在 BrandServlet 中添加方法
public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
// 接收前端提交的數據
BufferedReader reader = req.getReader();
String params = reader.readLine();
// 反序列化為Brand對象
Brand brand = JSON.parseObject(params, Brand.class);
// 調用Service進行添加
if (brandService.addBrand(brand)) resp.getWriter().write("success");
}
4.2 前端實現
- 點擊提交按鈕時,發送AJAX請求攜帶表單數據
- 獲取數據,判斷添加是否成功,關閉窗口,重新載入數據
-
程式碼
<!-- ...... --> <!--按鈕--> <!-- @click="dialogVisible = true" 單擊時將dialogVisible設置為true,展示對話框 --> <el-row> <el-button type="danger" plain>批量刪除</el-button> <el-button type="primary" plain @click="dialogVisible = true">新增</el-button> </el-row> <!--添加數據對話框表單--> <el-dialog title="編輯品牌" :visible.sync="dialogVisible" width="30%"> <el-form ref="form" :model="brand" label-width="80px"> <el-form-item label="品牌名稱"> <el-input v-model="brand.brandName"></el-input> </el-form-item> <el-form-item label="企業名稱"> <el-input v-model="brand.companyName"></el-input> </el-form-item> <el-form-item label="排序"> <el-input v-model="brand.ordered"></el-input> </el-form-item> <el-form-item label="備註"> <el-input type="textarea" v-model="brand.description"></el-input> </el-form-item> <el-form-item label="狀態"> <el-switch v-model="brand.status" active-value="1" inactive-value="0" ></el-switch> </el-form-item> <el-form-item> <el-button type="primary" @click="addBrand">提交</el-button> <el-button @click="dialogVisible = false">取消</el-button> </el-form-item> </el-form> </el-dialog> <!-- ...... --> <script> new Vue({ // ... // ... methods: { // 查詢所有數據,抽出作為一個函數,降低耦合 selectAll() { // 原生的this不能在Axios中使用,提升其生命周期 var _this = this; // 使用Axios發送非同步請求 axios({ method:"get", url:"//localhost:8080/brand-case/selectAll" }).then(function (resp) { _this.tableData = resp.data; }) }, // ... // ... // ... // 添加數據 addBrand(){ //console.log(this.brand); // 檢驗數據是否合法,判空細節不表 var flag = true; // isNaN()函數 把空串 空格 以及NUll 按照0來處理,所以先去除。非數字類型返回true if (this.brand.ordered == '' || this.brand.ordered == null || isNaN(this.brand.ordered)) { flag = false; this.$message({ message: '警告:排序不可為空且必須為一個數字', type: 'warning' }); } // 原生的this不能在Axios中使用,提升其生命周期 var _this = this; // 發送AJAX非同步請求,添加數據 if (flag) { axios({ method:"post", url:"//localhost:8080/brand-case/addBrand", // Axios 內部不能使用原生的 this data:_this.brand }).then(function (resp){ if ("success" == resp.data) { // 添加成功 // 關閉窗口 _this.dialogVisible = false; // 重新查詢數據 _this.selectAll(); // 顯示成功提示 _this.$message({ message: '品牌數據添加成功', type: 'success' }); } else { // 顯示錯誤提示 _this.$message.error('該品牌已存在,添加失敗'); } }) } }, // ... // ... // ... </script> </body> </html>
4、修改和刪除功能
-
Dao
@Update("update tb_brand " + "set brand_name = #{brandName}," + "company_name = #{companyName}," + "ordered = #{ordered}," + "description = #{description}," + "status = #{status} " + "where id = #{id};") void updateBrand(Brand brand); @Delete("delete from tb_brand where id = #{id};") void deleteBrand(@Param("id") String id);
-
Service 新增介面方法並實現
@Override public boolean updateBrand(Brand brand) { // 自動提交事務 SqlSession sqlSession = sqlSessionFactory.openSession(true); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 判斷用戶名是否不存在 boolean flag = (null == mapper.selectByBrandName(brand.getBrandName())); if (flag) mapper.updateBrand(brand); sqlSession.close(); return flag; } @Override public void deleteBrand(String id) { // 自動提交事務 SqlSession sqlSession = sqlSessionFactory.openSession(true); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); mapper.deleteBrand(id); sqlSession.close(); }
-
Servlet
public void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ // 接收前端提交的數據 BufferedReader reader = req.getReader(); String params = reader.readLine(); // 反序列化為Brand對象 Brand brand = JSON.parseObject(params, Brand.class); // 調用Service進行修改 if (brandService.addBrand(brand)) resp.getWriter().write("success"); } public void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ // 接收前端提交的數據 String id = req.getParameter("id"); // 調用Service進行添加 brandService.deleteBrand(id); }
-
前端頁面
5、批量刪除功能
-
Dao
-
Mapper介面
void deleteByIds(@Param("ids") int[] ids);
-
Mapper映射文件
<!-- 批量刪除,動態SQL --> <delete id="deleteByIds"> <!-- delete from tb_brand where id in (?,?,...,?) --> delete from tb_brand where id in <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> </delete>
-
-
Service
@Override public void deleteByIds(int[] ids) { // 自動提交事務 SqlSession sqlSession = sqlSessionFactory.openSession(true); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); mapper.deleteByIds(ids); sqlSession.close(); }
-
Servlet
public void deleteByIds(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ // 接收前端提交的數據 BufferedReader reader = req.getReader(); String params = reader.readLine(); // 反序列化為Brand對象 int[] ids = JSON.parseObject(params, int[].class); brandService.deleteByIds(ids); resp.getWriter().write("success"); }
-
前端頁面
<!-- ... --> <div id="app"> <!-- ... --> <el-row> <el-button type="danger" plain @click="deleteByIds">批量刪除</el-button> <el-button type="primary" plain @click="dialogVisible = true">新增</el-button> </el-row> <!-- ... --> </div> <!-- ... --> <script> new Vue({ el: "#app", // 當頁面載入完成後發送非同步請求來獲取數據 mounted(){ this.selectAll(); }, methods: { // ... // ... // 批量刪除 deleteByIds() { this.$confirm('此操作將永久刪除該文件, 是否繼續?', '提示', { confirmButtonText: '確定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.$message({ type: 'success', message: '正在刪除...' }); // 將id數據寫入被選中的id數組模型 for (let i = 0; i < this.multipleSelection.length; i++) { let selectionElem = this.multipleSelection[i]; this.selectedIds[i] = selectionElem.id; } console.log(this.multipleSelection); console.log(this.selectedIds); // 發送AJAX請求 var _this = this; axios({ method:"post", url:"//localhost:8080/brand-case/brand/deleteByIds", // Axios 內部不能使用原生的 this data:_this.selectedIds }).then(function (resp){ if ("success" == resp.data) { // 重新查詢數據 _this.selectAll(); // 顯示成功提示 _this.$message({ message: '刪除成功', type: 'success' }); } else { // 顯示錯誤提示 _this.$message.error('刪除失敗'); } }) }).catch(() => { this.$message({ type: 'info', message: '已取消刪除' }); }); } }, data() { return { // ... // ... // 被選中的資料庫id數組 selectedIds:[] } } }) </script> </body> </html>
6、分頁功能
-
用於分頁查詢的 JavaBean
package priv.dandelion.entity; import java.util.List; /** * 分頁查詢的JavaBean */ public class PageBean<T> { // 總記錄數 private int totalCount; // 當前頁數據 private List<T> rows; public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } public List<T> getRows() { return rows; } public void setRows(List<T> rows) { this.rows = rows; } }
-
Dao
// limit 開始索引, 查詢的條目數 // select * from tb limit 0, 5 // 頁面傳遞的參數為 起始條數和每一頁顯示的條數 // 開始索引 = (當前頁碼 - 1) * 每一頁顯示的條數 @Select("select * from tb_brand limit #{begin}, #{pageSize}") List<Brand> selectByPage(@Param("begin") int begin, @Param("pageSize") int pageSize); @Select("select count(*) from tb_brand") int selectTotalCount();
-
Service
@Override public PageBean<Brand> selectByPage(int currentPage, int pageSize) { SqlSession sqlSession = sqlSessionFactory.openSession(); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 計算開始索引 int begin = (currentPage - 1) * pageSize; // 查詢數據 List<Brand> rows = mapper.selectByPage(begin, pageSize); int totalCount = mapper.selectTotalCount(); // 封裝數據 PageBean<Brand> brandPageBean = new PageBean<>(); brandPageBean.setRows(rows); brandPageBean.setTotalCount(totalCount); sqlSession.close(); return brandPageBean; }
-
Servlet
public void selectByPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ // 接收當前頁碼和每頁展示條數 int currentPage = Integer.parseInt(req.getParameter("currentPage")); int pageSize = Integer.parseInt(req.getParameter("pageSize")); // 調用對應的Service進行查詢 PageBean<Brand> brandPageBean = brandService.selectByPage(currentPage, pageSize); // 序列化為JSON String jsonString = JSON.toJSONString(brandPageBean); // 寫回數據 resp.setContentType("text/json;charset=utf-8"); resp.getWriter().write(jsonString); }
-
頁面
<!-- ... --> <!--分頁工具條,綁定Model--> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[5, 10, 15, 20]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="totalCount"> </el-pagination> <!-- ... --> <script> new Vue({ el: "#app", // 當頁面載入完成後發送非同步請求來獲取數據 mounted(){ this.selectAll(); }, methods: { // 查詢所有數據,抽出作為一個函數,降低耦合 selectAll() { // 原生的this不能在Axios中使用,提升其生命周期 var _this = this; // 使用Axios發送非同步請求 axios({ method:"get", // URL改為分頁查詢所需的URL url:"//localhost:8080/brand-case/brand/selectByPage?currentPage="+ _this.currentPage +"&pageSize="+ _this.pageSize }).then(function (resp) { _this.tableData = resp.data.rows; _this.totalCount = resp.data.totalCount; }) }, // ... // ... // ... }, data() { return { // 每頁記錄數 pageSize: 5, // 當前頁碼 currentPage: 1, // 總記錄數 totalCount: 100, // ... // ... } } }) </script> </body> </html>
7、條件查詢
-
Dao
-
Mapper介面
List<Brand> selectByPageAndCondition(@Param("begin") int begin, @Param("pageSize") int pageSize, @Param("brand") Brand brand); int selectTotalCount();
-
Mapper映射文件
<!-- 條件查詢 --> <select id="selectByPageAndCondition" resultMap="brandResultMap"> select * from tb_brand <where> <if test="brand.brandName != null and brand.brandName != ''"> 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 = #{brand.status} </if> </where> limit #{begin}, #{pageSize} </select> <select id="selectTotalCountByCondition" resultType="java.lang.Integer"> select count(*) from tb_brand <where> <if test="brand.brandName != null and brand.brandName != ''"> 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 = #{brand.status} </if> </where> </select>
-
-
Service
@Override public PageBean<Brand> selectByPageAndCondition(int currentPage, int pageSize, Brand brand) { SqlSession sqlSession = sqlSessionFactory.openSession(); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); // 計算開始索引 int begin = (currentPage - 1) * pageSize; // 模糊查詢準備 String brandName = brand.getBrandName(); String companyName = brand.getCompanyName(); if (brandName != null && brandName.length() > 0) brand.setBrandName("%"+ brandName +"%"); if (companyName != null && companyName.length() > 0) brand.setCompanyName("%"+ companyName +"%"); // 查詢數據 List<Brand> rows = mapper.selectByPageAndCondition(begin, pageSize, brand); int totalCountByCondition = mapper.selectTotalCountByCondition(brand); // 封裝數據 PageBean<Brand> brandPageBean = new PageBean<>(); brandPageBean.setRows(rows); brandPageBean.setTotalCount(totalCountByCondition); sqlSession.close(); return brandPageBean; }
-
Servlet
public void selectByPageAndCondition(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ // 接收當前頁碼和每頁展示條數 int currentPage = Integer.parseInt(req.getParameter("currentPage")); int pageSize = Integer.parseInt(req.getParameter("pageSize")); // 獲取查詢條件對象 BufferedReader reader = req.getReader(); String params = reader.readLine(); Brand brand = JSON.parseObject(params, Brand.class); // 調用對應的Service進行查詢 PageBean<Brand> brandPageBean = brandService.selectByPageAndCondition(currentPage, pageSize, brand); // 序列化為JSON String jsonString = JSON.toJSONString(brandPageBean); // 寫回數據 resp.setContentType("text/json;charset=utf-8"); resp.getWriter().write(jsonString); }
-
頁面
<!-- ... --> <div id="app"> <!--搜索表單--> <el-form :inline="true" :model="brand" class="demo-form-inline"> <!-- ... --> <el-form-item> <el-button type="primary" @click="onSubmit">查詢</el-button> </el-form-item> </el-form> <!-- ... --> </div> <!-- ... --> <script> new Vue({ el: "#app", // 當頁面載入完成後發送非同步請求來獲取數據 mounted(){ this.selectAll(); }, methods: { // 查詢所有數據,抽出作為一個函數,降低耦合 selectAll() { // 原生的this不能在Axios中使用,提升其生命周期 var _this = this; // 使用Axios發送非同步請求 axios({ method:"post", url:"//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() { this.selectAll(); }, // ... // ... }, // ... }) </script> </body> </html>