在現代Web應用開發中,前后端分離架構已經成為主流模式。本文將通過一個完整的用戶管理系統案例,詳細介紹如何使用Vue.js + Element UI構建前端界面,結合Spring Boot實現后端服務,實現前后端分離開發。該系統包含用戶信息的增刪改查、批量操作、導入導出等常見功能,是一個典型的企業級管理系統模塊。
一、技術棧介紹
1.1 前端技術棧
Vue.js:漸進式JavaScript框架,用于構建用戶界面
Element UI:基于Vue.js的桌面端組件庫,提供豐富的UI組件
Axios:基于Promise的HTTP客戶端,用于前后端通信
Vue Router:Vue.js官方的路由管理器
1.2 后端技術棧
Spring Boot:簡化Spring應用初始搭建和開發過程的框架
MyBatis-Plus:MyBatis的增強工具,簡化CRUD操作
Hutool:Java工具類庫,提供Excel導入導出等功能
JWT:用于身份驗證的JSON Web Token
二、前端實現詳解
2.1 項目結構與配置
前端項目采用Vue CLI搭建,主要目錄結構如下:
src/ ├── views/ │ └── User.vue # 用戶管理主頁面 ├── router/ # 路由配置 ├── api/ # API請求封裝 └── public/config.js # 全局配置
在public/config.js
中配置后端服務地址:
window.WHITE_IP = "your-server-ip:port";
2.2 用戶管理頁面布局
用戶管理頁面主要分為以下幾個部分:
搜索區域:提供用戶名搜索和重置功能
操作按鈕區域:新增、批量刪除、導入導出等功能按鈕
表格展示區域:用戶數據列表展示
分頁組件:數據分頁控制
彈窗表單:新增/編輯用戶信息
<div class="User-container"><!-- 搜索區域 --><div style="margin: 10px 0"><el-input v-model="send.name" placeholder="請輸入用戶名"></el-input><el-button @click="selectListPage">搜索</el-button><el-button @click="reset">重置</el-button><!-- 操作按鈕 --><el-button @click="insertWindow">新增</el-button><el-popconfirm @confirm="confirmRemoveIdList"><el-button slot="reference">批量刪除</el-button></el-popconfirm><el-button @click="list_export">導出</el-button></div><!-- 表格區域 --><el-table :data="list" @selection-change="onSelectChange"><!-- 表格列定義 --></el-table><!-- 分頁組件 --><el-pagination@size-change="onSizeChange"@current-change="onCurrentChange":current-page="send.currentPage":page-size="send.pageSize":total="send.total"></el-pagination><!-- 彈窗表單 --><el-dialog :visible.sync="sendFormFlag"><el-form><!-- 表單字段 --></el-form></el-dialog> </div>
2.3 核心功能實現
2.3.1 分頁查詢
分頁查詢是管理系統的核心功能,前端需要維護當前頁碼、每頁條數等參數:
data() {return {send: {currentPage: 1,pageSize: 10,total: 0,name: ''},list: []} }, methods: {// 分頁查詢selectListPage() {this.$http.post("/user/list_page", this.send).then(res => {if (res.data.code === "200") {this.send.total = res.data.object.totalthis.list = res.data.object.data}})},// 分頁大小變化onSizeChange(pageSize) {this.send.pageSize = pageSizethis.selectListPage()},// 當前頁變化onCurrentChange(currentPage) {this.send.currentPage = currentPagethis.selectListPage()} }
2.3.2 新增與編輯用戶
通過同一個彈窗表單實現新增和編輯功能:
methods: {// 打開新增窗口insertWindow() {this.sendFormFlag = truethis.sendForm = {}},// 打開編輯窗口updateWindow(row) {this.sendFormFlag = truethis.sendForm = JSON.parse(JSON.stringify(row))},// 確認保存confirmInsertOrUpdate() {this.$http.post("/user/insertOrUpdate", this.sendForm).then(res => {if (res.data.code === "200") {this.$message.success('保存成功')this.selectListPage()}})} }
2.3.3 批量操作
批量操作需要處理表格的多選功能:
methods: {// 多選變化onSelectChange(val) {this.sendForm.removeIdList = val},// 確認批量刪除confirmRemoveIdList() {this.sendForm.removeIdList = this.sendForm.removeIdList.map(v => v.id)this.$http.post("user/list_delete", this.sendForm).then(res => {this.selectListPage()})} }
2.3.4 導入導出功能
導入導出是管理系統常見功能,使用Element UI的Upload組件實現:
methods: {// 導出list_export() {window.open(`https://${WHITE_IP}/user/list_export`)},// 導入成功回調onImportSuccess() {this.$message.success("文件導入成功")this.selectListPage()} }
三、后端實現詳解
3.1 項目結構
后端采用標準的Spring Boot項目結構:
src/main/java/ └── com.black├── controller # 控制器層├── mapper # 數據訪問層├── pojo # 實體類└── util # 工具類
3.2 核心控制器實現
用戶控制器處理所有用戶相關的請求:
@RestController @RequestMapping("/user") public class UserController {@ResourceUserMapper userMapper;// 新增或更新用戶@PostMapping("/insertOrUpdate")public Res insertOrUpdate(@RequestBody User user) {if (user.getId() != null) {userMapper.updateById(user);} else {user.setPassword(MyUtils.getSHA256StrJava("123456"));userMapper.insert(user);}return Res.success(null);}// 分頁查詢@PostMapping("/list_page")public Res list_page(@RequestBody User user) {QueryWrapper<User> queryWrapper = new QueryWrapper<>();if (StringUtils.isNotBlank(user.getName())) {queryWrapper.like("name", user.getName());}int total = userMapper.selectCount(queryWrapper);queryWrapper.last("limit " + user.getStart() + "," + user.getEnd());List<User> dataList = userMapper.selectList(queryWrapper);Map<String, Object> result = new HashMap<>();result.put("total", total);result.put("data", dataList);return Res.success(result);}// 導出Excel@GetMapping("/list_export")public void list_export(HttpServletResponse response) throws Exception {List<User> list = userMapper.selectList(null);ExcelWriter writer = ExcelUtil.getWriter(true);// 設置標題別名writer.addHeaderAlias("id", "ID");writer.addHeaderAlias("name", "用戶名");// ...其他字段writer.write(list, true);response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");String fileName = URLEncoder.encode("用戶信息", "UTF-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");ServletOutputStream out = response.getOutputStream();writer.flush(out, true);out.close();writer.close();} }
3.3 分頁查詢實現
后端分頁查詢使用MyBatis-Plus實現:
@PostMapping("/list_page") public Res list_page(@RequestBody User user) {// 1. 構建查詢條件QueryWrapper<User> queryWrapper = new QueryWrapper<>();if (StringUtils.isNotBlank(user.getName())) {queryWrapper.like("name", user.getName());}// 2. 獲取總數int total = userMapper.selectCount(queryWrapper);// 3. 計算分頁參數int start = (user.getCurrentPage() - 1) * user.getPageSize();int end = user.getPageSize();// 4. 執行分頁查詢queryWrapper.last("limit " + start + "," + end);List<User> dataList = userMapper.selectList(queryWrapper);// 5. 返回結果Map<String, Object> result = new HashMap<>();result.put("total", total);result.put("data", dataList);return Res.success(result); }
3.4 Excel導出實現
使用Hutool工具庫實現Excel導出:
@GetMapping("/list_export") public void list_export(HttpServletResponse response) throws Exception {// 1. 查詢數據List<User> list = userMapper.selectList(null);// 2. 創建Excel寫入器ExcelWriter writer = ExcelUtil.getWriter(true);// 3. 設置標題別名writer.addHeaderAlias("id", "ID");writer.addHeaderAlias("name", "用戶名");writer.addHeaderAlias("nick", "昵稱");// ...其他字段// 4. 寫入數據writer.write(list, true);// 5. 設置響應頭response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");String fileName = URLEncoder.encode("用戶信息", "UTF-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");// 6. 輸出流ServletOutputStream out = response.getOutputStream();writer.flush(out, true);out.close();writer.close(); }
四、前后端交互設計
4.1 API接口規范
系統采用RESTful風格設計API,主要接口如下:
請求方法 | 路徑 | 描述 |
---|---|---|
POST | /user/list_page | 分頁查詢用戶列表 |
POST | /user/insertOrUpdate | 新增或更新用戶 |
POST | /user/delete | 刪除用戶 |
POST | /user/list_delete | 批量刪除用戶 |
GET | /user/list_export | 導出用戶數據到Excel |
4.2 數據格式約定
前后端統一使用JSON格式交互,響應數據格式如下:
成功響應:
{"code": "200","message": "成功","object": {"total": 100,"data": [...]} }
錯誤響應:
{"code": "500","message": "服務器錯誤" }
4.3 Axios封裝
對Axios進行統一封裝,處理請求和響應:
import axios from 'axios' import router from '../router'// 創建axios實例 const service = axios.create({baseURL: process.env.BASE_API,timeout: 5000 })// 請求攔截器 service.interceptors.request.use(config => {// 在請求頭中添加tokenif (localStorage.token) {config.headers['Authorization'] = localStorage.token}return config},error => {return Promise.reject(error)} )// 響應攔截器 service.interceptors.response.use(response => {const res = response.dataif (res.code !== '200') {// token過期處理if (res.code === '401') {router.push('/login')}return Promise.reject(res)} else {return res.object}},error => {return Promise.reject(error)} )export default service
五、系統安全考慮
5.1 密碼安全
用戶密碼使用SHA256加密存儲:
public class MyUtils {public static String getSHA256StrJava(String str) {try {MessageDigest digest = MessageDigest.getInstance("SHA-256");byte[] hash = digest.digest(str.getBytes(StandardCharsets.UTF_8));StringBuilder hexString = new StringBuilder();for (byte b : hash) {String hex = Integer.toHexString(0xff & b);if (hex.length() == 1) hexString.append('0');hexString.append(hex);}return hexString.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return null;} }
5.2 接口權限控制
使用JWT進行接口權限驗證:
public class JwtInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String token = request.getHeader("Authorization");if (token == null) {throw new RuntimeException("無token,請重新登錄");}// 驗證tokenClaims claims = JwtUtil.parseToken(token);if (claims == null) {throw new RuntimeException("token不合法");}// 將用戶信息存入requestrequest.setAttribute("userInfo", claims.get("userInfo"));return true;} }
5.3 XSS防護
對用戶輸入進行過濾,防止XSS攻擊:
public class XssFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(httpRequest);chain.doFilter(xssRequest, response);} }public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {public XssHttpServletRequestWrapper(HttpServletRequest request) {super(request);}@Overridepublic String getParameter(String name) {String value = super.getParameter(name);return cleanXSS(value);}private String cleanXSS(String value) {if (value == null) return null;return HtmlUtils.htmlEscape(value);} }
六、性能優化實踐
6.1 前端性能優化
組件懶加載:路由組件按需加載
表格虛擬滾動:大數據量表格使用虛擬滾動
請求防抖:搜索框輸入使用防抖處理
// 防抖處理 debounceSelectListPage: _.debounce(function() {this.selectListPage() }, 500)
6.2 后端性能優化
MyBatis二級緩存:啟用MyBatis二級緩存減少數據庫查詢
分頁優化:使用更高效的分頁查詢方式
批量操作:使用批量插入代替循環單條插入
// 批量插入示例 public void batchInsert(List<User> userList) {SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);UserMapper mapper = session.getMapper(UserMapper.class);for (User user : userList) {mapper.insert(user);}session.commit();session.clearCache();session.close(); }
七、總結與擴展
本文詳細介紹了基于Vue.js和Spring Boot的前后端分離用戶管理系統的實現。系統實現了用戶管理的常見功能,包括:
用戶信息的增刪改查
批量操作
數據導入導出
分頁查詢與條件過濾
系統安全防護
擴展方向
角色權限管理:實現更細粒度的權限控制
操作日志:記錄用戶操作日志
數據可視化:增加用戶數據統計圖表
消息通知:系統消息通知功能
移動端適配:開發響應式布局或單獨移動端應用
通過這個項目,開發者可以掌握前后端分離開發的核心技術棧,了解企業級應用開發的常見模式和最佳實踐。希望本文能為您的開發工作提供有價值的參考。