瑞吉外賣實戰專案全攻略——第一天
該系列將記錄一份完整的實戰專案的完成程序,該篇屬于第一天
案例來自B站黑馬程式員Java專案實戰《瑞吉外賣》,請結合課程資料閱讀以下內容
該篇我們將完成以下內容:
- 軟體開發整體介紹
- 瑞吉外賣專案介紹
- 開發環境搭建
- 后臺登錄系統功能開發
- 后臺退出系統功能開發
軟體開發整體介紹
這個專案屬于我的第一個完整專案,所以我們將從軟體開發的概念來開始介紹
軟體開發流程
軟體開發主要分為五個階段,每個階段帶有不同的需求:
- 需求分析
需求分析需要設計產品原型,產生需求規格說明書
- 設計
設計主要負責產品檔案,UI界面設計,概要設計,詳細設計,資料庫設計等設計資訊
- 編碼
編碼主要負責專案代碼以及單元測驗,也就是我們著重介紹的部分
- 測驗
測驗主要負責準備測驗用例,書寫測驗報告
- 上線運維
上線運維主要包括軟體環境安裝,配置等
角色分工
我們的公司中通常具有不同的崗位,這些崗位被稱為角色
每個角色都具有不同的專案作用:
- 專案經理
對整個專案負責,任務分配,把控進度
- 產品經理
進行需求調研,輸出需求調研檔案,產品原型等
- UI設計師
根據產品原型輸出界面效果圖
- 架構師
專案整體架構設計,技術選型等
- 開發工程師
代碼實作
- 測驗工程師
撰寫測驗用例,輸出測驗報告
- 運維工程師
軟體環境搭建,專案上線
軟體環境
我們的專案軟體在不同的情況下要處于不同的軟體環境下
軟體環境通常分為三種:
- 開發環境(development)
開發人員在開發階段使用的環境,一般外部用戶無法訪問
- 測驗環境(test)
專門給測驗人員使用的環境,用于測驗專案,一般外部用戶無法訪問
- 生產環境(production)
即上線環境,正式提供對外服務的環境
瑞吉外賣專案介紹
我們想要開發產品,就要對產品具有一定的了解
專案介紹
首先我們介紹專案本身:
-
本專案(瑞吉外賣)是專門為餐飲企業(餐廳、飯店)定制的一款軟體產 品,包括系統管理后臺和移動端應用兩部分,
-
其中系統管理后臺主要提供給餐飲企業內部員工使用,可以對餐廳的菜品、套餐、訂單等進行管理維護,
-
移動端應用主要提供給消費者使用,可以在線瀏覽菜品添加購物車、下單等,
再來介紹我們的開發計劃:
- 本專案共分為3期進行開發
- 第一期主要實作基本需求,其中移動端應用通過H5實作,用戶可以通過手機瀏覽器訪問,
- 第二期主要針對移動端應用進行改進,使用微信小程式實作,用戶使用起來更加方便,
- 第三期主要針對系統進行優化升級,提高系統的訪問性能,
產品原型展示
首先我們先來介紹產品原型:
- 產品原型就是一個產品成型前的簡單框架,將頁面的排版布局展現出來,使初步構思有一個可視化的展示
- 通過原型展示,可以更加直觀的了解專案的需求和提供的功能
注意點:
- 產品原型主要用于展示專案的功能,并不是最終的頁面效果
關于產品原型的展示我們不再展示,產品原型在資料中已全部提供~
技術選型
我們給出整個專案的技術堆疊展示:

功能架構
我們同樣給出整個專案需要實作的功能架構:

角色展示
我們需要將專案中所出現的相關角色同列出來
本專案中大概出現三類角色:
- 后臺系統管理員
登錄后臺系統,擁有后臺系統中的所有操作權限
- 后臺系統普通員工
登錄后臺系統,對菜品,套餐,訂單進行管理
- C端用戶
登錄移動端應用,可以瀏覽菜品,添加購物車,設定地址,在線下單等
開發環境搭建
在正式開始編程之前,我們需要將準備作業完成
我們需要從兩方面進行環境搭建,我們的資料庫使用MYSQL,開發工具采用IDEA
資料庫環境搭建
我們直接進入MYSQL資料庫,這里使用MYSQL便捷工具Navicat:
- 創建資料庫reggie

- 增添資料
# 資料中包含有我們所使用的資料,直接導包即可,因資料過長,這里不做展示
到這里我們的資料庫環境搭建就結束了
最后我們將匯入資料庫的表羅列出來進行一定說明展示:

Maven專案搭建
我們的代碼開發采用IDEA的Maven搭建:
- 創建maven(直接創建即可)

- pom.xml相對應依賴坐標匯入
<!--pom.xml資料也有提供,當然直接復制下列內容也可以-->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.qiuluo</groupId>
<artifactId>mydelivery</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!-- 將物件 轉化為JSON格式-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.23</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.4.5</version>
</plugin>
</plugins>
</build>
</project>
- yml組態檔匯入
server:
port: 8080
spring:
application:
name: reggie_take_out
datasource:
# 德魯伊mysql配置,根據自己資料庫狀況修改
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123456
mybatis-plus:
configuration:
#在映射物體或者屬性時,將資料庫中表名和欄位名中的下劃線去掉,按照駝峰命名法映射,默認情況下開啟(這里僅做科普)
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: ASSIGN_ID
- 書寫主方法
// 在我們的java檔案夾下創建相對應的包
// 我創建的是com.qiuluo
package com.qiuluo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// 我們添加注解@Slf4j,可以使用log的方法添加日志,便于程式管理
@Slf4j
// @SpringBootApplication表示是程式的啟動類
@SpringBootApplication
public class ReggieApplication {
public static void main(String[] args) {
// 啟動程式的關鍵代碼
SpringApplication.run(ReggieApplication.class,args);
// 日志輸出
log.info("專案啟動成功");
}
}
- 前端頁面匯入
// 我們該專案主要側重后端開發,前端知識我們直接采用資料中所給資料即可
// 前端頁面:backend和front檔案,我們放置于resources檔案夾下即可
- 書寫配置類設定靜態資源
// 正常情況下,我們的頁面訪問時會被Contoller攔截下來回傳資料,這時我們就需要設定靜態資源的轉發路徑
package com.qiuluo.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
// @Configuration設定為配置類,讓Spring可以讀取到該配置類
@Slf4j
@Configuration
// 注意:主要繼承WebMvcConfigurationSupport成為配置類
public class WebMvcConfig extends WebMvcConfigurationSupport {
// 設定靜態資源的映射關系,繼承方法addResourceHandlers即可
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
// 日志輸出
log.info("即將進行靜態資源的映射:");
// 將請求路徑 /backend/** 映射到 專案靜態資源目錄 resources/backend 下
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
}
- 查看網頁是否映射成功
// 注意:需要先對專案整體進行clean操作后,再查看頁面,否則可能無法查看
后臺登錄功能開發
我們在進行功能開發時一般分為三個步驟進行開發
需求分析
首先我們需要得知,登錄是在前端哪個頁面通過什么方法請求資料
我們打開頁面后,通過F12來查看點擊相關功能后所進行的頁面請求或者直接在后端查看請求
頁面F12獲取請求:(這里由于我這里已經完成功能,點擊后直接跳轉,無法獲得資料)

后端查看請求:
function loginApi(data) {
return $axios({
'url': '/employee/login',
'method': 'post',
data
})
}
通過查詢后我們可以發現點擊登錄后發送請求格式為下列:
URL:http://localhost:8080/employee/login
Request Method:POST
因此我們需要書寫Controller來完成該請求的相對應代碼
另一方面,我們都知道我們前端和后端在互動時會通過一個固定的格式來回傳請求
我們可以通過查詢相關代碼來確定回傳格式:
methods: {
async handleLogin() {
this.$refs.loginForm.validate(async (valid) => {
if (valid) {
this.loading = true
let res = await loginApi(this.loginForm)
if (String(res.code) === '1') {
localStorage.setItem('userInfo',JSON.stringify(res.data))
window.location.href= 'https://www.cnblogs.com/backend/index.html'
} else {
this.$message.error(res.msg)
this.loading = false
}
}
})
}
}
// 我們可以發現res屬性包含有code,data,msg等屬性
那么我們在后端代碼中需要規定一個物體類來充當回傳引數類
代碼開發
下面我們來到IDEA中書寫我們前面所需要的內容:
- 構造物體類Employee
// 我們創建entity檔案夾專門書寫物體類(資料中包含有物體類構造代碼)
// Employee是我們的員工表,相當于我們的賬號和密碼的主體類
package com.qiuluo.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String name;
private String password;
private String phone;
private String sex;
private String idNumber;
private Integer status;
private LocalDateTime createTime;
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
}
- 構造資料層
package com.qiuluo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qiuluo.entity.Employee;
import org.apache.ibatis.annotations.Mapper;
// @Mapper幫助Spring自動識別資料層,采用全權代理開發
@Mapper
// 繼承BaseMapper<Employee>,其中包括有許多基本資料庫方法
public interface EmployeeMapper extends BaseMapper<Employee> {
}
- 構造業務層介面
package com.qiuluo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qiuluo.entity.Employee;
// 繼承IService<Employee>實作多種方法
public interface EmployerService extends IService<Employee> {
}
- 構造業務層
package com.qiuluo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiuluo.entity.Employee;
import com.qiuluo.mapper.EmployeeMapper;
import com.qiuluo.service.EmployerService;
import org.springframework.stereotype.Service;
// @Service幫助Spring自動識別
@Service
// 繼承ServiceImpl<EmployeeMapper,Employee>中的各種方法,第一個引數是Mapper,第二個引數是物體類
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper,Employee> implements EmployerService {
}
- 構造服務層
package com.qiuluo.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qiuluo.common.R;
import com.qiuluo.entity.Employee;
import com.qiuluo.service.EmployerService;
import com.qiuluo.service.impl.EmployeeServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
// 書寫基本注解
// 日志注解
@Slf4j
// REST形式的Controller
@RestController
// 設定整體映射地址
@RequestMapping("/employee")
public class EmployeeController {
// 自動裝配employeeService
@Autowired
private EmployeeServiceImpl employeeService;
}
- 構造回傳結構類R
// 我們構造一個回傳結構類作為回傳型別
package com.qiuluo.common;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
@Data
public class R<T> {
private Integer code; //編碼:1成功,0和其它數字為失敗
private String msg; //錯誤資訊
private T data; //資料
private Map map = new HashMap(); //動態資料
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = https://www.cnblogs.com/qiuluoyuweiliang/p/object;
r.code = 1;
return r;
}
public static R error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R add(String key, Object value) {
this.map.put(key, value);
return this;
}
}
- 邏輯分析前端需求并實作
package com.qiuluo.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qiuluo.common.R;
import com.qiuluo.entity.Employee;
import com.qiuluo.service.EmployerService;
import com.qiuluo.service.impl.EmployeeServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeServiceImpl employeeService;
/**
* 員工登錄
* */
@PostMapping("/login")
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){
// 1. 將頁面提交的密碼經過md5加密(DigestUtils.md5DigestAsHex方法需要byte引數)
String password = employee.getPassword();
password = DigestUtils.md5DigestAsHex(password.getBytes());
// 2.根據頁面提交的用戶名username查詢資料庫(采用LambdaQueryWrapper進行條件篩選)
LambdaQueryWrapper<Employee> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(Employee::getUsername,employee.getUsername());
Employee emp = employeeService.getOne(lambdaQueryWrapper);
// 3.如果沒有查詢到,判定失敗
if (emp == null){
return R.error("登陸失敗");
}
// 4.密碼比對,密碼不一致失敗
if (!emp.getPassword().equals(password)){
return R.error("登陸失敗");
}
// 5.查看員工狀態
if (emp.getStatus() == 0){
return R.error("賬戶已禁用");
}
// 6.登錄成功,并將員工id存入Session并回傳登錄成功結果
request.getSession().setAttribute("employee",employee.getId());
return R.success(emp);
}
}
- 前端登錄測驗
# 測驗時盡量將代碼中書寫的各種情況都測驗一遍確保無誤
后臺退出功能開發
我們在進行功能開發時一般分為三個步驟進行開發
需求分析
員工登錄成功后,頁面跳轉到系統首頁頁面(backend/index.html),此時顯示當前用戶名
當我們點擊退出時,直接點擊退出按鈕即可退出頁面,回到登錄頁面
同樣我們采用F12或者后臺請求查看:
URL:http://localhost:8080/employee/logout
Request Method:POST
代碼開發
我們回到EmployeeController程式中開發請求地址為employee/logout的POST請求即可
具體步驟包括有:
- 清理Session中的id
- 回傳結果
我們的實際開發步驟分為兩步:
- 在EmployeeController中開發相對應的功能
package com.qiuluo.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qiuluo.common.R;
import com.qiuluo.entity.Employee;
import com.qiuluo.service.EmployerService;
import com.qiuluo.service.impl.EmployeeServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeServiceImpl employeeService;
/**
* 員工登錄
* */
@PostMapping("/login")
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){
// 1. 將頁面提交的密碼經過md5加密(DigestUtils.md5DigestAsHex方法需要byte引數)
String password = employee.getPassword();
password = DigestUtils.md5DigestAsHex(password.getBytes());
// 2.根據頁面提交的用戶名username查詢資料庫(采用LambdaQueryWrapper進行比對)
LambdaQueryWrapper<Employee> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(Employee::getUsername,employee.getUsername());
Employee emp = employeeService.getOne(lambdaQueryWrapper);
// 3.如果沒有查詢到,判定失敗
if (emp == null){
return R.error("登陸失敗");
}
// 4.密碼比對,密碼不一致失敗
if (!emp.getPassword().equals(password)){
return R.error("登陸失敗");
}
// 5.查看員工狀態
if (emp.getStatus() == 0){
return R.error("賬戶已禁用");
}
// 6.登錄成功,并將員工id存入Session并回傳登錄成功結果
request.getSession().setAttribute("employee",employee.getId());
return R.success(emp);
}
/**
* 退出管理員
* */
@PostMapping("/logout")
public R<String> logout(HttpServletRequest request){
// 1. 將用戶id從Session中刪去
request.getSession().removeAttribute("employee");
// 2. 回傳推出成功的資訊即可
return R.success("退出成功");
}
}
- 實際測驗(點擊退出鍵回傳登錄頁面即可)

易錯點
在這里我們會點出該專案目前容易出錯的位置,當然是對于我來說可能~
設定靜態資源映射
易錯點位置:
- 開發環境搭建中的Maven專案搭建
易錯原因:
- 書寫過少,內容不夠了解
易錯點:
- 設定靜態映射屬于配置類,需要添加@Configuration注解
- 該類本身不具有配置功能,需要繼承WebMvcConfigurationSupport類實作其方法
- 設定靜態類的方法為addResourceHandlers方法,采用內置引數registry的相關方法
- registry的方法addResourceHandler后跟請求路徑,addResourceLocations后跟映射的靜態資源路徑
// 正常情況下,我們的頁面訪問時會被Contoller攔截下來回傳資料,這時我們就需要設定靜態資源的轉發路徑
package com.qiuluo.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
// @Configuration設定為配置類,讓Spring可以讀取到該配置類
@Slf4j
@Configuration
// 注意:主要繼承WebMvcConfigurationSupport成為配置類
public class WebMvcConfig extends WebMvcConfigurationSupport {
// 設定靜態資源的映射關系,繼承方法addResourceHandlers即可
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
// 日志輸出
log.info("即將進行靜態資源的映射:");
// 將請求路徑 /backend/** 映射到 專案靜態資源目錄 resources/backend 下
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
}
結束語
該篇內容到這里就結束了,希望能為你帶來幫助~
附錄
該文章屬于學習內容,具體參考B站黑馬程式員的Java專案實戰《瑞吉外賣》
這里附上視頻鏈接:業務開發Day1-01-本章內容介紹_嗶哩嗶哩_bilibili
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/517744.html
標籤:Java
