🍊作者:計算機編程-吉哥
🍊簡介:專業從事JavaWeb程序開發,微信小程序開發,定制化項目、 源碼、代碼講解、文檔撰寫、ppt制作。做自己喜歡的事,生活就是快樂的。
🍊心愿:點贊 👍 收藏 ?評論 📝
🍅 文末獲取源碼聯系👇🏻 精彩專欄推薦訂閱 👇🏻 不然下次找不到喲~
Java畢業設計項目~熱門選題推薦《1000套》Python畢業設計精品項目《1000套》
微信小程序畢業設計精品項目《1000套》
大數據/機器學習畢業設計精品項目《1000套》
【看項目演示視頻,文末掃一下】
【看項目演示視頻,文末掃一下】
目錄
?1.技術選型
2.開發工具
2.1 Java
2.2 SpringBoot
2.3 MyBatisPlus
2.4 Vue
2.5 ElementUI
2.6 MySQL
2.7 Maven
3.功能
3.1【角色】
3.2【功能模塊】
4.項目演示截圖
4.1 前臺
4.2 后臺
5.核心代碼
5.1攔截器
5.2分頁工具類
5.3文件上傳下載
5.4前端請求
6.LW文檔參考
背景意義介紹:?
在當今社會,隨著人們生活節奏的加快以及生活品質追求的提升,家政保潔服務需求呈現出快速增長的趨勢。現代人工作繁忙,往往無暇顧及家庭清潔事務,而專業的家政保潔服務能夠有效解決這一問題,為人們創造整潔、舒適的居住環境。然而,傳統的家政保潔預約方式存在諸多弊端。一方面,用戶通常需要通過電話溝通來預約服務,這種方式不僅效率低下,容易出現信息傳遞不準確的情況,而且在高峰期還可能面臨占線、等待時間長等問題,給用戶帶來極大的不便。另一方面,對于家政服務提供商而言,難以對服務人員的工作安排、訂單狀態等進行有效管理和跟蹤,導致服務質量難以保證,資源分配不合理,進而影響企業的運營效率和競爭力。
與此同時,信息技術的飛速發展,尤其是互聯網技術的普及,為家政保潔行業帶來了新的發展機遇。在此背景下,基于Spring Boot框架開發一套家政保潔預約系統具有重要的現實意義。Spring Boot以其快速開發、簡化配置、易于集成等優勢,成為眾多企業級應用開發的首選框架。利用Spring Boot技術構建家政保潔預約系統,能夠充分利用其強大的功能特性,為家政服務行業打造一個高效、便捷、智能的信息化平臺。
1.技術選型
- 框架:springboot、mybatisplus、vue、elementui、html、css、js、mysql、jdk1.8
- 工具:idea、Navicat
2.開發工具
2.1 Java
Java是一種廣泛使用的高級編程語言,以其跨平臺兼容性、面向對象的特性和豐富的庫支持而聞名。它在系統開發中被廣泛應用,特別是在需要高度可移植性和網絡功能的場景中。Java的虛擬機(JVM)允許程序在多種操作系統上運行,無需修改代碼。它的強類型系統和自動垃圾回收機制減少了內存泄漏和程序崩潰的風險。此外,Java提供了強大的網絡編程支持,使得開發分布式系統和網絡應用變得容易。它還擁有大量的開源庫和框架,如Spring和Hibernate,這些庫和框架進一步簡化了復雜問題的解決,如數據庫操作和企業級應用開發。因此,Java在構建可擴展、安全且高效的系統中扮演了關鍵角色。
2.2 SpringBoot
Spring Boot是一個輕量級的Java框架,旨在簡化Spring應用的創建和部署。它通過自動配置和“約定優于配置”的原則,極大地減少了開發者在配置上的負擔。Spring Boot內置了Tomcat、Jetty等Web服務器,使得應用無需部署WAR文件即可快速啟動。此外,它還提供了豐富的Starters,幫助開發者輕松集成數據庫、消息隊列、安全框架等。Spring Boot的Actuator模塊為應用提供了監控和管理功能,增強了系統的可維護性。通過這些特性,Spring Boot使得開發微服務架構和云原生應用變得更加高效和簡單。
2.3 MyBatisPlus
MyBatis-Plus是一個對MyBatis框架的增強工具,它通過簡化數據庫操作和減少模板代碼,極大地提升了開發效率。它提供了自動生成的CRUD接口,使得開發者無需編寫繁瑣的SQL語句,同時支持Lambda表達式和條件構造器,讓查詢條件構建變得簡潔明了。內置的分頁插件簡化了分頁操作,而靈活的主鍵策略和代碼生成器進一步加速了開發流程。MyBatis-Plus的無侵入性和對現有工程的兼容性,使其成為提升數據庫操作效率和簡化開發流程的有力工具。
2.4 Vue
Vue.js是一個漸進式JavaScript框架,專注于構建用戶界面。它易于上手,同時提供了強大的功能來幫助開發者構建復雜的單頁應用。Vue的核心特點包括響應式數據綁定、組件系統和虛擬DOM。響應式數據綁定讓數據更新變得簡單直觀,開發者只需關注數據本身,視圖會自動更新。組件系統允許開發者將界面分割成可復用的組件,每個組件管理自己的狀態和邏輯,使得代碼更加模塊化和可維護。虛擬DOM提高了性能,因為它減少了直接操作DOM的次數,通過計算最小更新量來實現高效的DOM更新。Vue還提供了豐富的生態系統,包括Vuex狀態管理和Vue Router路由管理,使得構建大型應用變得更加簡單。此外,Vue的輕量級特性使其成為快速開發中小型項目的優選。在系統開發中,Vue通過這些特點,提供了快速開發、高可維護性和良好的用戶體驗,特別適合于需要快速迭代和動態內容更新的應用場景。
2.5 ElementUI
Element UI是一個專為Vue.js設計的開源前端組件庫,由餓了么前端團隊開發。它以“簡潔、實用、高效”為核心設計理念,遵循Material Design等國際通行的設計規范,提供了一套直觀易用且符合人類直覺交互習慣的UI組件。Element UI的組件庫豐富,包括表格、表單、對話框、菜單、按鈕等,這些組件都基于響應式設計,自動適應不同設備的屏幕大小,提供一致的用戶體驗。
使用Element UI可以大大提高開發效率,它提供了一套全面的預置組件,涵蓋了幾乎所有的基礎和復雜UI需求。例如,它的表單驗證、下拉選擇器、日期選擇器等功能模塊均經過精心設計,兼顧了功能性和美觀性,提升了用戶體驗。此外,Element UI的組件封裝簡單,開發人員可以輕松地在Vue.js應用程序中使用,同時支持高度可定制性,在保持默認外觀的前提下,可以通過CSS、主題等來自定義組件樣式,支持按需加載。
Element UI還提供了完善的文檔和示例代碼,方便開發者學習和使用,同時擁有一個活躍的社區,為開發者提供了豐富的資源和支持。它的設計和實現考慮了開發者的實際需求,使得在構建現代Web應用程序時,Element UI成為一個受歡迎的選擇。
2.6 MySQL
MySQL是一個流行的關系型數據庫管理系統,廣泛用于各種應用場景。它以其高性能、可靠性和易用性而聞名。MySQL支持SQL語言,允許開發者通過標準的查詢語句來操作數據。它提供了強大的數據類型,包括整數、浮點數、字符串和日期時間等,以滿足不同數據存儲需求。
MySQL的索引機制優化了查詢性能,通過B+樹等數據結構,加快了數據檢索速度。它的事務處理能力保證了數據的一致性和完整性,支持ACID(原子性、一致性、隔離性、持久性)屬性,適合需要高可靠性的業務場景。
此外,MySQL的復制功能支持數據的分布式存儲,提高了數據的可用性和容錯性。其靈活的存儲引擎,如InnoDB和MyISAM,提供了不同的性能和功能特點,以適應不同的應用需求。MySQL還提供了豐富的管理工具和監控功能,方便數據庫的維護和優化。
在系統開發中,MySQL通過其高性能、可靠性、易用性和靈活性,為數據存儲和管理提供了強大的支持。它的社區版免費且開源,降低了開發和維護成本,使其成為許多項目的首選數據庫解決方案。
2.7 Maven
Maven是一個強大的項目管理和構建自動化工具,它通過提供一個標準化的項目管理方法,簡化了Java項目的構建過程。Maven的核心優勢在于其依賴管理能力,它允許開發者在項目的`pom.xml`文件中聲明依賴,然后自動從遠程倉庫中獲取所需的庫,從而避免了手動下載和配置依賴的繁瑣工作。
Maven還強制執行了一致的項目結構,這不僅促進了團隊成員之間的協作,還簡化了代碼的整合和重用。它定義了一系列構建生命周期和階段,使得開發者可以按照預定義的順序執行各種任務,如編譯、測試、打包和部署。
此外,Maven支持構建配置文件,允許開發者為不同環境定義不同的構建配置,這對于在多個環境中部署應用程序(如開發、測試和生產環境)非常有用。Maven的可擴展性也是其一大特點,開發者可以創建Maven插件來添加額外的目標或定制現有目標,以滿足特定需求。
在系統應用中,Maven通過自動化構建流程、管理項目依賴、提供一致的項目結構、支持自動化測試、允許構建配置文件和高度可擴展性,極大地提高了開發效率和項目的可維護性。這些特性使得Maven成為Java項目開發中不可或缺的工具之一。
3.功能
3.1【角色】
管理員、家政公司、保潔阿姨、用戶
3.2【功能模塊】
管理員:系統首頁、用戶管理、個人中心、家政公司管理、保潔阿姨管理、服務類型管理、家政服務管理、服務記錄管理、服務評價管理、系統管理
家政公司:系統首頁、個人中心、保潔阿姨管理、家政服務管理、服務預約管理、服務記錄管理、服務評價管理
保潔阿姨:系統首頁、個人中心、服務分配管理、服務記錄管理、服務評價管理
用戶:系統首頁、家政服務、公告資訊、個人中心、我的收藏
4.項目演示截圖
4.1 前臺
4.2 后臺
5.核心代碼
5.1攔截器
package com.interceptor;import com.alibaba.fastjson.JSONObject;
import com.annotation.IgnoreAuth;
import com.entity.TokenEntity;
import com.service.TokenService;
import com.utils.R;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;/*** 權限(Token)驗證*/
@Component
public class AuthorizationInterceptor implements HandlerInterceptor {public static final String LOGIN_TOKEN_KEY = "Token";@Autowiredprivate TokenService tokenService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//支持跨域請求response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");response.setHeader("Access-Control-Max-Age", "3600");response.setHeader("Access-Control-Allow-Credentials", "true");response.setHeader("Access-Control-Allow-Headers", "x-requested-with,request-source,Token, Origin,imgType, Content-Type, cache-control,postman-token,Cookie, Accept,authorization");response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));// 跨域時會首先發送一個OPTIONS請求,這里我們給OPTIONS請求直接返回正常狀態if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {response.setStatus(HttpStatus.OK.value());return false;}IgnoreAuth annotation;if (handler instanceof HandlerMethod) {annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class);} else {return true;}//從header中獲取tokenString token = request.getHeader(LOGIN_TOKEN_KEY);/*** 不需要驗證權限的方法直接放過*/if(annotation!=null) {return true;}TokenEntity tokenEntity = null;if(StringUtils.isNotBlank(token)) {tokenEntity = tokenService.getTokenEntity(token);}if(tokenEntity != null) {request.getSession().setAttribute("userId", tokenEntity.getUserid());request.getSession().setAttribute("role", tokenEntity.getRole());request.getSession().setAttribute("tableName", tokenEntity.getTablename());request.getSession().setAttribute("username", tokenEntity.getUsername());return true;}PrintWriter writer = null;response.setCharacterEncoding("UTF-8");response.setContentType("application/json; charset=utf-8");try {writer = response.getWriter();writer.print(JSONObject.toJSONString(R.error(401, "請先登錄")));} finally {if(writer != null){writer.close();}}return false;}
}
5.2分頁工具類
package com.utils;import java.io.Serializable;
import java.util.List;
import java.util.Map;import com.baomidou.mybatisplus.plugins.Page;/*** 分頁工具類*/
public class PageUtils implements Serializable {private static final long serialVersionUID = 1L;//總記錄數private long total;//每頁記錄數private int pageSize;//總頁數private long totalPage;//當前頁數private int currPage;//列表數據private List<?> list;/*** 分頁* @param list 列表數據* @param totalCount 總記錄數* @param pageSize 每頁記錄數* @param currPage 當前頁數*/public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {this.list = list;this.total = totalCount;this.pageSize = pageSize;this.currPage = currPage;this.totalPage = (int)Math.ceil((double)totalCount/pageSize);}/*** 分頁*/public PageUtils(Page<?> page) {this.list = page.getRecords();this.total = page.getTotal();this.pageSize = page.getSize();this.currPage = page.getCurrent();this.totalPage = page.getPages();}/** 空數據的分頁*/public PageUtils(Map<String, Object> params) {Page page =new Query(params).getPage();new PageUtils(page);}public int getPageSize() {return pageSize;}public void setPageSize(int pageSize) {this.pageSize = pageSize;}public int getCurrPage() {return currPage;}public void setCurrPage(int currPage) {this.currPage = currPage;}public List<?> getList() {return list;}public void setList(List<?> list) {this.list = list;}public long getTotalPage() {return totalPage;}public void setTotalPage(long totalPage) {this.totalPage = totalPage;}public long getTotal() {return total;}public void setTotal(long total) {this.total = total;}}
5.3文件上傳下載
package com.controller;import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.ConfigEntity;
import com.entity.EIException;
import com.service.ConfigService;
import com.utils.R;/*** 上傳文件映射表*/
@RestController
@RequestMapping("file")
@SuppressWarnings({"unchecked","rawtypes"})
public class FileController{@Autowiredprivate ConfigService configService;/*** 上傳文件*/@RequestMapping("/upload")@IgnoreAuthpublic R upload(@RequestParam("file") MultipartFile file,String type) throws Exception {if (file.isEmpty()) {throw new EIException("上傳文件不能為空");}String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);File path = new File(ResourceUtils.getURL("classpath:static").getPath());if(!path.exists()) {path = new File("");}File upload = new File(path.getAbsolutePath(),"/upload/");if(!upload.exists()) {upload.mkdirs();}String fileName = new Date().getTime()+"."+fileExt;File dest = new File(upload.getAbsolutePath()+"/"+fileName);file.transferTo(dest);if(StringUtils.isNotBlank(type) && type.equals("1")) {ConfigEntity configEntity = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "faceFile"));if(configEntity==null) {configEntity = new ConfigEntity();configEntity.setName("faceFile");configEntity.setValue(fileName);} else {configEntity.setValue(fileName);}configService.insertOrUpdate(configEntity);}return R.ok().put("file", fileName);}/*** 下載文件*/@IgnoreAuth@RequestMapping("/download")public ResponseEntity<byte[]> download(@RequestParam String fileName) {try {File path = new File(ResourceUtils.getURL("classpath:static").getPath());if(!path.exists()) {path = new File("");}File upload = new File(path.getAbsolutePath(),"/upload/");if(!upload.exists()) {upload.mkdirs();}File file = new File(upload.getAbsolutePath()+"/"+fileName);if(file.exists()){HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", fileName); return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);}} catch (IOException e) {e.printStackTrace();}return new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR);}}
5.4前端請求
import axios from 'axios'
import router from '@/router/router-static'
import storage from '@/utils/storage'const http = axios.create({timeout: 1000 * 86400,withCredentials: true,baseURL: '/furniture',headers: {'Content-Type': 'application/json; charset=utf-8'}
})
// 請求攔截
http.interceptors.request.use(config => {config.headers['Token'] = storage.get('Token') // 請求頭帶上tokenreturn config
}, error => {return Promise.reject(error)
})
// 響應攔截
http.interceptors.response.use(response => {if (response.data && response.data.code === 401) { // 401, token失效router.push({ name: 'login' })}return response
}, error => {return Promise.reject(error)
})
export default http
6.LW文檔參考
?具體LW如何寫法,可以咨詢博主,耐心分享!
你可能還有感興趣的項目👇🏻👇🏻👇🏻
更多項目推薦:計算機畢業設計項目
Python畢業設計精品項目《1000套》
微信小程序畢業設計精品項目《1000套》
大數據/機器學習畢業設計精品項目《1000套》
如果大家有任何疑慮,請在下方咨詢或評論