本笔记源自黑马程序员的视频课程——《瑞吉外卖》,总结了课程笔记、相关知识点以及可能遇到的问题解决方案,并且增加了课程中未实现的功能,供读者参考。笔记全面且条理清晰,希望帮助读者学习和理解这个外卖项目。
本项目全部笔记见:外卖项目笔记合集

1. 读写分离

问题说明

图片

以两台数据库为例:

图片

读写分离,降低单台数据库的访问压力。

1.1 MySQL主从复制

1.1.1 介绍

MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库自带的二进制日志功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制然后再解析日志并应用到自身,最终实现从库的数据和主库的数据保持一致。MySQL主从复制是MySQL数据库自带功能,无需借助第三方工具。

图片

MySQL复制过程分成三步:

  • master将改变记录到二进制日志(binary log)
  • slave将master的binary log拷贝到它的中继日志(relay log)
  • slave重做中继日志中的事件,将改变应用到自己的数据库中

1.1.2 配置-前置条件

克隆虚拟机的方法见此笔记

提前准备好两台服务器,分别安装Mysql并启动服务、用navicat连接上。

登录mysql:mysql -u root -p

navicat连接方法:

  • 打开navicat,新建连接(Connection - mySQL),连接名任意,主机或IP地址填虚拟机端的IP地址196.168.xxx.xxx,用户名root,密码xxx。
  • 将虚拟机端端口3306开放,firewall-cmd --zone=public --add-port=3306/tcp --permanent以及firewall-cmd --reload
  • 在navicat双击新建的连接,即可连接上。

1.1.3 配置-主库Master

第一步:修改Mysql数据库的配置文件 vim /etc/my.cnf

Read more »

本笔记源自黑马程序员的视频课程——《瑞吉外卖》,总结了课程笔记、相关知识点以及可能遇到的问题解决方案,并且增加了课程中未实现的功能,供读者参考。笔记全面且条理清晰,希望帮助读者学习和理解这个外卖项目。
本项目全部笔记见:外卖项目笔记合集

问题:用户数量多,系统访问量大。频繁访问数据库,系统性能下降,用户体验差。解决方法:使用缓存。用户点链接后,服务端先看缓存中有没有相应数据。如果有数据,不用再查数据库。

1. 使用git管理代码

在gitee上新建仓库,名称和当前项目名相同,权限为私有仓库。

1.1 将本地代码推送到仓库

  • 复制远程仓库链接。

  • 打开IDEA,在菜单选中VCS,选择Import into version control,选择create git repository,选中项目。

  • .gitignore文件中,排除一些文件(除了IDEA自动生成的,还添加了以下的)

    1
    2
    3
    4
    5
    6
    7
    8
    .git
    logs
    rebel.xml
    target/
    !.mvn/wrapper/maven-wrapper.jar
    log.path_IS_UNDEFINED
    .DS_Store
    offline_user.md
  • 右键项目,点击Git,点击Add。

  • 点击IDEA上方工具的Commit,可以加入注释“加入redis,缓存验证码和菜品”,点击Commit and Push

  • push时,点击Define remote,将刚才复制的远程仓库链接粘到url中,配置远程仓库。

1.2 创建新的分支,把缓存相关优化都放在新的分支上

点击IDEA右下角的分支,新建分支命名为v1.0。

将v1.0分支也推送到远程仓库,当前代码没有改,直接点工具中的Push即可。

2. 环境搭建

2.1 maven坐标

在项目的pom. xml文件中,导入spring data redis的maven坐标:

1
2
3
4
5
<!--导入Redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.2 配置文件

在项目的application.yml中加入redis相关配置:

1
2
3
4
5
6
spring:
redis:
host: localhost # 本地ip或者虚拟机IP。此处使用了本地的
port: 6379
password:
database: 0 # 默认使用0号数据库

2.3 配置类

Read more »

本笔记源自黑马程序员的视频课程——《瑞吉外卖》,总结了课程笔记、相关知识点以及可能遇到的问题解决方案,并且增加了课程中未实现的功能,供读者参考。笔记全面且条理清晰,希望帮助读者学习和理解这个外卖项目。
本项目全部笔记见:外卖项目笔记合集

1. 个人页面功能开发

1.1 地址管理

1.1.1 需求分析

地址簿,指的是移动端消费者用户的地址信息,用户登录成功后可以维护自己的地址信息。同一个用户可以有多个地址信息,但是只能有一个默认地址。

图片

1.1.2 数据模型

用户的地址信息会存储在address_book表,即地址簿表中。具体表结构如下:

图片

1.1.3 准备工作

Read more »

本笔记源自黑马程序员的视频课程——《瑞吉外卖》,总结了课程笔记、相关知识点以及可能遇到的问题解决方案,并且增加了课程中未实现的功能,供读者参考。笔记全面且条理清晰,希望帮助读者学习和理解这个外卖项目。
本项目全部笔记见:外卖项目笔记合集

1. 套餐管理业务开发

1.1 新增套餐

1.1.1 需求分析

套餐就是菜品的集合。

后台系统中可以管理套餐信息,通过”新增套餐”功能来添加一个新的套餐,在添加套餐时,需要选择当前套餐所属的套餐分类和包含的菜品,并且需要上传套餐对应的图片,在移动端会按照套餐分类来展示对应的套餐。

图片

1.1.2 数据模型

新增套餐,其实就是将新增页面录入的套餐信息插入到setmeal表,还需要向setmeal_dish表插入套餐和菜品关联数据。所以在新增套餐时,涉及到两个表:

1、setmeal表(套餐表)

图片

2、setmeal_dish表(套餐-菜品关系表)

图片

1.1.3 准备工作

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

1、实体类SetmealDish(从课程资料中导入,Setmeal实体类前面已经导入过了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Data
public class SetmealDish implements Serializable {

private static final long serialVersionUID = 1L;

private Long id;

//套餐id-和setmeal表关联
private Long setmealId;

//菜品id-和dish表关联
private Long dishId;

//菜品名称-和dish表关联(冗余字段 可以没有 可以根据dish_id从dish表里现场查,也可以存在setmeal_dish表里)
private String name;
@Data
public class SetmealDto extends Setmeal {

private List<SetmealDish> setmealDishes;

private String categoryName;
}
//菜品原价
private BigDecimal price;

//份数
private Integer copies;

//排序
private Integer sort;

@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;

@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;

@TableField(fill = FieldFill.INSERT)
private Long createUser;

@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;

//是否删除
private Integer isDeleted;
}
Read more »

本笔记源自黑马程序员的视频课程——《瑞吉外卖》,总结了课程笔记、相关知识点以及可能遇到的问题解决方案,并且增加了课程中未实现的功能,供读者参考。笔记全面且条理清晰,希望帮助读者学习和理解这个外卖项目。
本项目全部笔记见:外卖项目笔记合集

1. 菜品管理业务开发

1.1 文件上传下载

1.1.1 文件上传介绍

文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。

文件上传时,需要使用form表单上传文件,且对页面的form表单有如下要求:

  • method=”post” method为post
  • enctype=”multipart/form-data” form表单的enctype属性值为”multipart/form-data”
  • type=”file” form标签中使用input type=”file”添加上传的文件

1

目前一些前端组件库也提供了相应的上传组件,但是底层原理还是基于form表单的文件上传。例如ElementUI中提供的upload上传组件:

2

服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件:

  • commons-fileupload
  • commons-io

Spring框架在spring-web包中对“文件上传”进行了封装,大大简化了服务端代码。

我们只需要在Controller的方法中,声明一个MultipartFile类型的参数,即可接收上传的文件。

步骤为:

1、新建一个控制器类CommonController,专门负责文件上传和下载

2、在upload()方法的形参位置,声明MultipartFile类型的参数,对象名与「html页面传来的form表单中的name」一致,也就是和浏览器请求体form-data处的name值一致。

具体实现在1.1.3中。

1.1.2 文件下载介绍

文件下载,也称为download,是指将文件从服务器传输到本地计算机的过程。通过浏览器进行文件下载,通常有两种表现形式:

Read more »

本笔记源自黑马程序员的视频课程——《瑞吉外卖》,总结了课程笔记、相关知识点以及可能遇到的问题解决方案,并且增加了课程中未实现的功能,供读者参考。笔记全面且条理清晰,希望帮助读者学习和理解这个外卖项目。
本项目全部笔记见:外卖项目笔记合集

1. 分类管理业务开发

1.1 公共字段自动填充

1.1.1 问题分析

前面我们已经完成了后台系统的员工管理功能开发,在新增员工时需要设置创建时间、创建人、修改时间、修改人等字段,在编辑员工时需要设置修改时间和修改人等字段。这些字段属于公共字段,也就是很多表中都有这些字段,如下:

1

2

能不能对于这些公共字段在某个地方统一处理,来简化开发呢?答案就是使用Mybatis Plus提供的公共字段自动填充功能。

1.1.2 代码实现

Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候,为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。

实现步骤:

1、在实体类的属性上加入@TableField注解,指定自动填充的策略

2、按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandler接口

具体实现:

1、在实体类的属性上加入@TableField注解,指定自动填充的策略

1
2
3
4
5
6
7
8
9
10
11
@TableField(fill = FieldFill.INSERT)//插入的时候,填充字段的值
private LocalDateTime createTime;

@TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充字段的值
private LocalDateTime updateTime;

@TableField(fill = FieldFill.INSERT)
private Long createUser;

@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
Read more »

本笔记源自黑马程序员的视频课程——《瑞吉外卖》,总结了课程笔记、相关知识点以及可能遇到的问题解决方案,并且增加了课程中未实现的功能,供读者参考。笔记全面且条理清晰,希望帮助读者学习和理解这个外卖项目。
本项目全部笔记见:外卖项目笔记合集

1. 完善登录功能

1.1 问题分析

前面我们已经完成了后台系统的员工登录功能开发,但是还存在一个问题:用户如果不登录,直接访问系统首页面,照样可以正常访问。

这种设计并不合理,我们希望看到的效果应该是,只有登录后才能访问后台管理页面如果没有登录,则跳转到登录页面。

那么,具体应该怎么实现呢?

答案就是使用过滤器或者拦截器,在过滤器或者拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面。

1.2 代码实现

1.2.1 实现思路

  1. 创建自定义过滤器LoginCheckFilter
  2. 在启动类上加入注解@ServletComponentScan
  3. 完善过滤器的处理逻辑

1.2.2 具体实现

1、创建filter包,在其中创建LoginCheckFilter类,实现Filter接口,并重写doFilter()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 登录检查过滤器(也可以用拦截器interceptor实现,此项目中用过滤器实现)
* 检查用户是否已经完成登录
*/
@WebFilter(filterName = "LoginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest) servletRequest;
HttpServletResponse response=(HttpServletResponse) servletResponse;
log.info("拦截到请求:{}",request.getRequestURI());
filterChain.doFilter(request,response); // 放行
}
}

说明:

  1. @WebFilter替代web.xml配置过滤器。filterName指定过滤器名称(随意);urlPatterns指定拦截的请求。urlPatterns = "/*"表示工程路径下所有请求路径都拦截。
  2. 继承Filter时不要导错包,import javax.servlet.*

2、在启动类上加入注解@ServletComponentScan

加上这个注解后,才会扫描@WebFilter注解,使得过滤器生效。

1
2
3
4
5
6
7
8
9
@Slf4j
@SpringBootApplication
@ServletComponentScan
public class ReggieApplication {
public static void main(String[] args) {
SpringApplication.run(ReggieApplication.class,args);
log.info("项目启动成功");
}
}
Read more »

这是一个使用Springboot+SSM的实战练习项目,实现了一个外卖系统的前后台功能。

本笔记源自黑马程序员的视频课程——《瑞吉外卖》,总结了课程笔记、相关知识点以及可能遇到的问题解决方案,并且增加了课程中未实现的功能,供读者参考。笔记全面且条理清晰,希望帮助读者学习和理解这个外卖项目。
本项目全部笔记见:外卖项目笔记合集

下图是项目效果展示,左侧是移动端的效果,右侧是管理后台的效果。

1

1. 软件开发整体介绍

1.1 软件开发流程

2

1.2 角色分工

3

1.3 软件环境

4

2. 外卖项目介绍

2.1 项目介绍

本外卖项目是专门为餐饮企业(餐厅、饭店)定制的一款软件产品,包括系统管理后台和移动端应用两部分。其中系统管理后台主要提供给餐饮企业内部员工使用,可以对餐厅的菜品、套餐、订单等进行管理维护。移动端应用主要提供给消费者使用,可以在线浏览菜品、添加购物车、下单等。

本项目共分为3期进行开发:

第一期主要实现基本需求,其中移动端应用通过H5实现,用户可以通过手机浏览器访问。

第二期主要针对移动端应用进行改进,使用微信小程序实现,用户使用起来更加方便。

第三期主要针对系统进行优化升级,提高系统的访问性能。

Read more »

插入图片的方法

在完成了博客搭建、发布文章后,如果我们想在文章中插入图片,该怎么做呢?
在使用网上的方法上传图片之后,我仍然遇到“图片无法显示”的问题,查阅官方文档并自己实践后,终于解决了,现将几种插入图片方法的步骤整理如下。

如果图片保存在本地

方法一:全局资源文件夹

即,将所有文章的资源统一用一个全局资源文件夹管理。
此方法的优点是比较简便,并且当多篇文章需要引用同一资源时,也比较方便。缺点是当文章很多时,各个文章的图片都在同一文件夹,不便管理
具体方法:
在hexo文件夹下的source目录下,新建一个文件夹叫images(名字随意),将要插入的图片放在该文件夹中。
md文档内,使用![图片](图片链接地址 "图片title")的格式,圆括号内的链接地址写(/images/name.jpeg)。
这里的 / 指的是根目录,对于hexo,资源文件的根目录就是source。
例如,在md文档中写:
![图片](/images/20.jpeg "甘雨")
同时将“20.jpeg”这个图片文件放在hexo文件夹/source/images下。
则图片可以上传到博客,效果为:

Read more »

发布文章到Hexo博客上

1. 将文章添加到hexo文件夹下的source/_posts目录

有两种方法:
方法一:
较为简单。直接把编辑好的.md格式的文件,复制到hexo文件夹下的source/_posts文件夹。

方法二:
便于结构化的管理图片等资源。使用hexo new [layout] <title> 命令创建新文章,此时会自动创建一个文件夹和.md文件。
例如,执行hexo new "如何发布文章到hexo博客上(含插入图片的方法)",如下:
创建新文章
会在source/_post文件夹下生成一个”如何发布文章到hexo博客上(含插入图片的方法).md”文件。如下:
生成md文件和同名文件夹
可以看到,同时还生成了一个同名的资源文件夹。
我们可以将所有与该文章有关的资源(包括图片)放在这个关联文件夹中,再通过相对路径来引用它们。
例如,将“1.jpeg”这个图片资源放在该文件夹中,并在.md文件中像这样引用图片:![图片](1.jpeg),这个方法在资源较多时方便管理。
有关插入图片的具体方法和可能遇到的问题,可以参考这篇博客文章:在hexo博客中插入图片的方法及问题总结

2. 编辑文章标题、分类、标签

Read more »
0%