瑞吉外卖项目

外卖项目


本项目来自黑马视频

一、软件开发整体介绍

  • 在学完springboot和mybitasPlus之后,为了更好地掌握于是来找这个项目加深一下。下面就正式开始这个外卖项目。
  • 一个软件开发是很复杂的,一般情况下是由多个人共同完成的。通过不同的流程,以及不同流程的分工,从而各司其职完成一个软件的开发。

1.1、软件开发流程

  • 软件开发流程一般分为以下几个步骤。不同流程一般由不同的人来完成。尤其是在大公司,他们会有严格分工。但是在小厂也许你一个人要负责好几个部分。
    在这里插入图片描述

1.2、角色分工

  • 下面是每个角色需要做的事情。
    在这里插入图片描述

1.3、软件环境

  • 下面是软件环境,不同角色的员工使用的环境不同。像我们开发人员,一般就是使用开发环境。
    在这里插入图片描述
    在这里插入图片描述

二、外卖项目介绍

2.1、项目介绍

  • 现在开始进入主题,我们本次是来做一个外面项目。是专门为餐饮企业定制的一款软件产品。他一共分为系统管理部分和移动端两个部分。其中系统管理部分主要是提供给餐饮企业内部员工使用,可以对菜品、套餐、订单等进行管理维护。移动端主要是给消费者使用,可以在线浏览菜品、添加购物车、下单等。

2.2、项目分期

  • 本项目一共分为三期进行开发:
    (1)第一期主要实现基本需求,其中移动端应用通过H5实现,客户可以通过浏览器访问。
    (2)第二期主要针对移动端进行改进,使用微信小程序实现,用户使用起来更加方便。
    (3)第三期主要针对系统进行优化升级,提高系统的访问性能。

2.3、产品原型展示

  • 产品原型就是一款产品成型之前的一个简单框架,就是将页面的排版布局展现出来,使产品的初步构思有一个可视化的展示。通过展示,可以更加直观的了解项目的需求和提供的功能。注意:产品原型主要是用于展示项目功能,并不是最终的页面效果

2.4、技术选型

  • 在开发一个项目的时候,我们首先需要知道自己需要用到哪些技术,这一步骤一般由架构师来完成。技术的选型是一个很具有技术含量的工作。有的人可能就说,这有啥技术,不就是选个框架吗,它也可以。技术选型往往需要你对这个技术的优缺点以及实现原理掌握的十分清楚,这是很多年的开发经验积累下来的,不是我们想的那么简单。下面我放了一张本项目的技术选型的图片。
    在这里插入图片描述

2.5、开发环境搭建

2.5.1、数据库环境搭建

  • 在设计数据时,一般大公司会有专门负责的人来完成。我们一般只需要了解这些表之间有什么关系就行。下面我将通过两种方式完成数据库的搭建。
  • 第一种,我们通过可视化的工具来完成(我使用的是SQLyag),不同人选用的可能不太一样,但是没啥太大的区别。先创建一个数据源,然后右键选择导入选择导入外部数据库即可。如下图所示。
    在这里插入图片描述
  • 上面是第一种,可能有人找不到这些免费的可视化操作工具。下面我们就来看看使用命令操作。一样的,首先,我们先创建一个数据源:create database XXX;然后切换到该数据源上:user XXX;最后将sql文件导入:source【空格】sql文件的全路径;这里需要注意的是,将要导入的sql文件不要放在含有中文名称的目录下。
  • 下面就是数据库里面每一张表的说明。
    在这里插入图片描述

2.5.2、maven项目的搭建

  • 上面我们将数据库的环境搭建好了,下面我们来搭建一下项目。首先使用idea搭建一个maven项目。如果有人不会可以参考这篇文章:链接。如果会搭建springboot项目就直接搭建springboot项目。

2.5.3、导入本项目需要用到的坐标

  • 下面就是需要用到的坐标
    在这里插入图片描述
    在这里插入图片描述
  • 到这里,我们的开发环境就算是搭建好了。

三、后台开发

3.1、后台登录开发

  • 每一个功能的开发都需要遵循这三步,需求分析、代码分析、功能测试。接下来我们就开始开发后台登录功能。

3.1.1、需求分析

  • 后台登录主要是给餐饮企业的员工使用。下面就来看看处理的逻辑。

  • 在写处理逻辑之前,我们先来创建一个Employee实体类,该类主要是用于封装员工的信息,如下图所示:
    在这里插入图片描述

  • 员工在登录时,是从前端页面进行密码和账号的输入。所以我们首先需要在controller里面创建登录方法中接收前端的账号密码,并且将接收到的信息封装到Employee类中。也就是说,该登录方法需要一个Employee类的参数。接下来我们开始登录,首先将获取到的密码进行md5加密,因为我们在数据库里面不是直接存储用户密码,而是将密码加密后进行存储。其次根据页面提交的用户名查询数据库,如果没有查询到则返回登陆失败结果。如果存在则进行密码对比,如果不一致则返回登录失败,最后就是查看该用户的状态,如果已经被禁用,则返回员工已经被禁用。最后,登录成功,将员工的id存入Session中,所以,该登录方法还需要一个HttpServletReques成员。具体运行逻辑可以参考下图:
    在这里插入图片描述

3.1.2、代码开发

  • 在进行页面开发时,我们需要知道前端登录时使用的时是那种请求方式以及请求的url和该请求携带的参数是什么?

  • 所以通常是抓取前端登录的数据头信息,通过分析就可以知道这些信息是怎么样的。然后就可以使用相应的方式来完成。比如该登录功能抓取的数据如下图:从其中就可以知道后端需要使用post以及参数有密码和账号。

  • 然后根据获取到信息进行代码书写。注意:我们是将前端的密码和账号封装到Employee类中,并且前端是以json格式发送的数据,所以需要给Employee参数加上@RequestBoby注解。然后就是代码书写。按照上面分析的逻辑去写就行。
    在这里插入图片描述

3.1.3、功能测试

  • 在上述代码书写完成之后,需要对起进行检测。我们打开前端页面,进行登录尝试。首先,先使用数据库里面已经存保存好的用户进行登录,看是否能登录成功。然后在使用错误的数据进行登录,看是否登录失败。

3.1.4、测试遇到的问题

  • 这一块在测试时遇到一个报错,Error in created hook: “SyntaxError: Unexpected token u in JSON at position 0。这是数据转化出了问题,自己找了很久,后来发现是前端在使用后台返回的数据名称和后台不一样,前端用的是data名称,而后端使用的是date,所以导致了该问题。

3.2、后台退出功能

3.2.1、功能分析

  • 上面我们将登录功能完成了。但是我们在经常使用一些系统的时候都会有退出这个功能,所以,我们就接着将退出功能完成。
  • 逻辑很简单,点击页面的退出按钮,发送请求,请求地址为/employee/logout,请求方式是post。我们只需要在controller中创建对应的处理方法即可。具体的逻辑是:
    (1)清除Session中的用户id
    (2)返回结果

3.2.2、代码实现

  • 上面已经分析了逻辑,所以我们就根据上面的分析来完成下面的代码。
    在这里插入图片描述

3.3、完善登录功能——拦截器

  • 上面我们已经将登录和退出功能完成了,但是仍然存在一些问题。就是用户不登录,直接访问系统页面,照样可以正常访问,这显然是不允许出现的。我们希望看到的效果是,只有登录成功之后才可以访问系统中的页面,如果没有登录,则跳转到登录页面。下面我就来处理一下这个问题。

3.3.1、问题分析处理

  • 针对上述的问题,我们可以使用拦截器或者过滤器,在拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面。

3.3.2、实现步骤

  • 创建自定义的过滤器;我们需要在这个类上添加@WebFilter注解,第一个属性值是拦截器名称,可以随便写。第二个属性是对那些请求url进行拦截,我配置的是对所以的请求都进行拦截。
  • 下面来看看这个类,该类实现Filter接口,并且实现该接口的doFilter方法。首先,我们先对数据做一个向下类型转换。然后获取到请求时发送的URI。然后这个数组里面存储的是不需要进行拦截的URI,所以,通过check检查获取到的URI就可以知道是否需要进行拦截。然后判断用户的登录状态,如果已经登录则放行。如果还未登录,则返回未登录,并且处于登录页面。具体的逻辑图可以参考下图
    在这里插入图片描述
/**
 * 检查用户是否已经完成登录
 */
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {

//    路径匹配器,
    public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

//        1、获取请求的uri
        String requestURI = request.getRequestURI();

        log.info("拦截到请求:{}", requestURI);

//        定义不需要处理的请求路径
        String[] urls = {
                "/employee/login",//登录请求
                "/employee/logout",//退出请求
                "/backend/**",//静态资源
                "/front/**"
        };

//        2、判断本次请求是否需要去处理
        boolean check = check(urls, requestURI);

//        3、如果不需要处理则直接放行
        if (check) {
            log.info("本次请求{}不需要处理", requestURI);
            filterChain.doFilter(request,response);
            return;
        }

//        4、判断登录状态,如果已经登录则放行
        if (request.getSession().getAttribute("employee") != null) {
            log.info("用户已登录,用户id为:{}", request.getSession().getAttribute("employee"));
            filterChain.doFilter(request,response);
            return;
        }

//        5、如果未登录,则返回未登录结果
        log.info("用户未登录");
        response.getWriter().write(JSON.toJSONString(ReturnResultType.error("NOTLOGIN")));
        return;
    }

    /**
     * 路径匹配,检查本次请求是否需要放行
     *
     * @param urls
     * @param requestURI
     * @return
     */
    public boolean check(String[] urls, String requestURI) {

        for (String url : urls) {
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match) {
                return true;
            }
        }

        return false;
    }

}

  • 代码在完成之后,还需要在启动类上添加@ServletComponentScan注解。如下图所示
    在这里插入图片描述
  • 到此,拦截器功能就完成了。

3.4、新增员工功能

3.4.1、需求分析

  • 在后台系统中可以管理员工信息,通过新增员工来添加后台系统用户。点击【添加员工】按钮就可以跳转到新增页面。
  • 新增员工其实就是将我们新添加页面的员工信息保存到employee表里面。需要注意的是该表中的username字段添加了唯一约束,因为username是员工的登录账号,必须是唯一的。所以通过该方式保证用户的唯一性
  • 其次就是status字段,该字段是用来判断该员工账号是否已经被禁用。该字段设置的默认值是1,也就是正常状态。
  • 然后给每一个新添加的员工设置一个初始密码。后期可以自行更改。

3.4.2、代码实现

  • 在开发代码之前,需要梳理一下整个程序的执行流程。
    (1)页面发送ajax请求,将新增员工页面输入的数据以jason的形式提交到服务器;
    (2)服务器Controller接收页面提交的数据并调用service将数据进行保存;
    (3)service调用mapper操作数据库,保存数据;
  • 我们将前端提交的数据封装到Employee类当中。并进行保存,如下图所示:
    在这里插入图片描述

3.4.3、功能完善

  • 在上面3.4.1中,我们提到了每个用户的username都是唯一的,所以在新增员工时,如果出现username一样时,则会抛出一个异常信息。所以我们需要将异常捕获进行处理。
  • 处理方式有两种:
    (1)在controller方法中添加try-catch进行异常处理;
    (2)使用异常处理器进行全局异常捕获;
  • 在这里我们使用第二种方式来解决这个问题。首先,定义一个全局异常处理器类,并在该类上添加@ControllerAdvice注解,然后再在方法上添加@ExceptionHandle注解,该注解里面有异常类型,只要是Controller类里面出现了该类型的异常,就可以被这个方法拦截到。
    在这里插入图片描述

3.5、运功信息分页查询

3.5.1、需求分析

  • 系统中的员工很多的时候,为了方便查看,一般的系统都会使用分页的方式来展示列表数据。

3.5.2、代码实现

  • 在开发代码前,需要梳理一下整个程序的执行过程。
    (1)页面发送ajax请求,将分页查询参数page、pagesize、name提交到服务端;
    (2)服务端Controller接收页面提交的数据并调用Service查询数据;
    (3)Service调用Mapper操作数据库,查询分页数据
    (4)Controller将查询到的分页数据响应给页面;
    (5)页面接收到分页数据并通过ElementUI的Table组件展示到页面上;
  • 接下来,我们看看代码是如何实现的;
  • 首先,我们先配置一个分页查询插件。
    在这里插入图片描述
  • 响应前端查询的后台代码;
    在这里插入图片描述

3.6、启动、禁用功能

3.6.1、需求分析

  • 在员工管理页面,管理员可以对任何一个员工账号进行启用或者禁用操作。账号被禁用的员工不能登录系统,启用后的员工可以正常登录。需要注意的是只有管理员才可以对普通用户进行启用、禁用操作,所以普通用户登陆系统后禁用按钮不显示

在这里插入图片描述

  • 在上面我们说了,只有管理员登录才会显示禁用按钮,而普通员工登录是不会显示的。那这是如何做到的呢?其实也很简单,当用户登陆时,服务端会将当前登录用户的信息发送到前端。前端通过username字段信息判断当前用户是否是管理员,如果是则显示,如果不是则不显示。具体实现可以参考下图
    在这里插入图片描述

3.6.2、代码开发

  • 在代码开发之前一定要梳理一下整个程序的执行过程。
    (1)页面发送ajax请求,将参数(id、status)提交到服务端;
    (2)服务端Controller接收页面提交的数据并调用Service更新数据;
    (3)Service调用Mapper操作数据库;
  • 启用、禁用员工账号,本质上就是一个更新操作,也就是对status字段值进行更改。在Controller中创建update方法,来修改员工status字段的值。
    在这里插入图片描述

3.6.3、测试遇到的问题

3.6.3.1、问题分析
  • 点击禁用之后,发现并没有达到我们所预料的功能。通过抓取数据分析,前端先从数据库获取数据,然后再将获取到的id数据返回给数据库去查询,但是前端返回的数据和它从服务端获取到的id数据不一致。这是因为出现了精度损失。因为页面中js处理Long类型数据只能精确到前16位,所以最终通过ajax请求提交给服务端得时候id值发生精度损失。从而查询不到需要禁用的用户。在这里插入图片描述
3.6.3.2、代码修复
  • 通过前面的分析,我们已经发现了问题产生的原因,即就是js在处理数据的时候出现了精度损失,导致提交的id和数据库中存储的id不一致。解决的方法如下:在服务端给页面响应jason数据时将long类型的数据统一转换为String字符串。但是如何做才能实现这样的效果。使用对象转换器即可
  • 具体的实现步骤:
    (1)提供对象转换器,基于Jackson进行Java对象到jason数据的转换。注意:下面这个转换器不仅将id转换,而且将日期也进行了转换。
    在这里插入图片描述
    (2)在WebMvcConfig配置类中扩展Spring mvc的消息转换器,在此消息转换器中使用提供的对象转换器进行Java对象到jason数据的转换。
    在这里插入图片描述
  • 至此,该问题就得到解决。

3.7、员工信息的编辑

3.7.1、需求分析

  • 在员工管理页面点击编辑按钮,跳转到编辑页面,在编辑页面回显员工信息并进行修改,最后点击保存按钮完成编辑操作。

3.7.1、代码开发

  • 先来梳理一下操作过程和对应程序的执行流程:
    (1)点击编辑按钮,页面跳转到add.html,并url中携带参数【员工id】;
    (2)在add.html页面获取url中的员工id;
    (3)发送ajax请求,请求服务端,同时提交员工id;
    (4)服务端接受请求,并根据员工id查询员工信息,将员工信息以json形式响应给页面;
    在这里插入图片描述
    (5)页面接收到服务端响应的json数据,并将该数据回显到页面;
    (6)点击保存按钮,发送ajax请求,将页面中的员工信息以json方式提交给服务端;
    (7)服务端接收员工信息,并进行处理,完成后给页面响应;
    (8)页面接收到服务端响应信息后进行相应的处理;
    注意:add.html页面为公共页面,新增员工和编辑员工都是在此页面操作;所以会导致这里存在一个逻辑问题;
  • 在更修改员工数据时使用的是新增员工的那个方法,所以如果员工将初始密码进行更改,那么在执行信息更改后员工改变之后的密码就会变成初始密码。结局方案如下图所示:在设置密码这里进行一个判断即可;
    在这里插入图片描述

3.8、公共字段填充

3.8.1、需求分析

  • 在前面我们已经完成后台系统的员工管理功能开发,在新增员工时需要设置创建时间、创建人、修改时间、修改人等字段,在编辑员工时需要设置修改时间和修改人等字段。这些字段属于公共字段,也就是说很多表里面都有这些字段。那么以后在开发时一旦碰到这种需要修改这些公共字段的字段就得编写相应的修改代码。那可以不可以只将修改代码写一次,以后只要碰到修改就会自动去执行这个修改代码。这就的用到mybatisPlus的公共字段填充

3.8.2、代码实现

  • mybatisPlus公共字段自动进行填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免重复代码。
  • 实现步骤:
    (1)在实体类的属性上添加@TableField注解,指定自动填充的策略。
    在这里插入图片描述
    (2)按照框架要求,编写原数据处理器,在此类中统一为公共字段赋值,此类需要实现MateObjectHandle接口。下面就是当有插入或者保存操作时就会自动执行公共字段填充。
    在这里插入图片描述

3.8.3、功能完善

  • 前面我们已经完成了公共字段填充,但是在开发时碰到一个问题,就是在填充createUser和updateUser时设置的用户id该如何获取,之前我们是通过HttpServiceRequest类对象来获取,现在没有该对象了那该怎么办?可以使用ThreadLocal来解决这个问题。

  • 在学习ThreadLocal类之前,我们需要先确认一个事情,客户端每次发送http请求,对应的在服务端都会分配一个新的线程来处理,在处理过程中会涉及到LoginCheckFilter的doFilter方法、EmployeeController类的update方法、MyMetaObjectHandler类中的updateFile方法都属于相同的一个线程。下面就来看看什么是ThreadLocal
    在这里插入图片描述

  • 下面就来进行代码完善;
    (1)编写BaseContext工具类,基于ThreadLocal封装的工具类;
    在这里插入图片描述
    (2)在LocalCheckFilter的doFilter方法中调用BaseContext来设置当前用户登录的id;
    在这里插入图片描述
    (3)在MyMetaObjectHandler的方法中调用BaseContext获取登陆用户的id;
    在这里插入图片描述

3.9、新增分类

3.9.1、需求分析

  • 后台系统的分类管理中可以管理两类信息,分别是菜品分类和套餐分类。当我们在后台系统中添加餐品时需要选择一个菜品分类,当我们在后台系统中添加一个套餐时需要选择一个套餐分类,在移动端也会按照餐品分类和套餐分类来展示对应的菜品和套餐。

3.9.2、代码开发

  • 在开发业务之前,需要将Category的实体类和相关的mapper层、service层、controller层的代码完成。
  • 在开发之前,需要先梳理一下整个程序的执行过程:
    (1)页面发送ajax请求,将新增分类窗口输入的数据以json形式提交到服务端;
    (2)服务端controller接收页面提交的数据并调用Service将数据进行保存;
    (3)Service调用Mapper操作数据库,保存数据。
    在这里插入图片描述

3.10、分类管理页面数据分页

  • 和之前的页面分页操作一样,这里就不在写了;

3.11、分类删除

3.11.1、需求分析

  • 在分类管理列表页面,可以对某个分类进行删除操作。需要注意的是当分类关联了菜品或者套餐时,此时分类不允许删除。

3.11.2、代码实现

  • 在代码开发之前,需要先梳理一下整个程序执行的流程:
    (1)页面发送ajax请求,将参数id提交到服务端;
    (2)服务端controller接受页面提交的数据并调用Service删除数据;
    (3)Service调用mapper操作数据库;
  • 这里调用mapper里面的删除函数是我们自己实现的。下面就来分析一下实现过程:首先,先在service接口里面定义一个根据id删除的函数,然后在该接口的实现类里面实现具体过程。在删除时必须得判断该分类是否还有关联数据(这里就得完成菜品和套餐的mapper、service等等那一套东西),如果有就不能删除,直接抛出业务异常信息。具体实现如下图:
    在这里插入图片描述
  • 在实现完自定义的删除功能之后,就可以在controller层进行操作;
    在这里插入图片描述

3.12、更改分类数据

3.12.1、需求分析

  • 在分类管理列表页面,可以对某个分类进行更改操作。

3.12.2、代码实现

在这里插入图片描述

3.13、文件上传下载

3.13.1、文件上传介绍;

  • 在我们这个项目中,需要对图片进行大量的上传和下载。
    在这里插入图片描述

3.13.2、代码开发

  • Spring框架在spring-web包中对文件上传进行了封装,在很大程度上简化了服务端代码的开发,我们只需要在Controller的方法中声明一个MultiparrtFile类型的参数即可接收上传的文件。
    在这里插入图片描述

3.13.3、文件下载介绍

  • 文集下载,指的就是将文件从服务器传输到本地计算机的过程。
  • 具体的介绍请参考下图。
    在这里插入图片描述

3.13.4、代码实现

在这里插入图片描述

3.14、新增菜品

3.14.1、需求分析和数据模型分析

  • 具体请看下图。
    在这里插入图片描述
    在这里插入图片描述

3.14.2、代码开发

  • 首先,先建立好需要用到的类和接口创建好,具体参考下图。
    在这里插入图片描述
  • 在代码开发之前先将整个过程梳理清楚,具体请看下图。
    在这里插入图片描述
  • 在这里我们得先介绍一种DTO类型的类。接下来我们根据下面代码进行分析。
  • 我们在新增菜品时,不仅会传输该菜品的基本信息,并且还会有该菜的分类信息以及口味信息,所以仅仅靠Dish这一个类已经不能完成前端信息的封装,所以我们必须得对Dish这个类进行扩展,而扩展出来得这个类就称为DTO类型的类。
    在这里插入图片描述
  • 在完成上面这些之后,就可以接收前端发送的数据了。
  • 首先,我们得明确这个过程需要操作两张数据表,所以我们不能直接使用mybatisPlus直接提供的方法来完成多表的操作。必须的自己写这个过程。如下图所示。
    在这里插入图片描述
  • 然后再来写与前端交互的controller类的方法。如下图所示。
    在这里插入图片描述

3.15、菜品信息分页查询

3.15.1、需求分析

  • 具体分析请参考下图。
    在这里插入图片描述

3.15.2、代码开发

  • 在开发代码之前一定要先对整个流程分析清除。如下图所示。需要多说一点的就是,在访问菜品数据的同时还会进行图片的访问,这个请求是前端来发送的,直接调用后端的上传方法即可。我们之前已经将上传方法已经写好了,所以会直接都拿来使用。
    在这里插入图片描述
  • 下面就是具体的前后端代码交互过程。需要注意的就是这个需要用到DTO类,为了在前端显示该菜品的类型名称。所以需要用到DTO类了。
    在这里插入图片描述

3.16、修改菜品信息

3.16.1、需求分析

  • 具体分析如下
    在这里插入图片描述

3.16.2、代码开发

  • 在开发之前我们得先梳理一下思路,如下图所示。
    在这里插入图片描述
  • 在修改信息之前,我们需要先对信息进行一个回显,这个就需要根据菜品id查询到该菜品的信息并回显回来。 在修改菜品信息时需要牵扯到两张表菜品信息表菜品口味表。所以,我们得自己编写相应得实现方法。如下图所示:
    在这里插入图片描述

3.17、新增套餐

3.17.1、需求分析

在这里插入图片描述

3.17.2、数据模型分析

在这里插入图片描述

3.17.3、代码开发

  • 首先,我们先将需要用到的基本结构创建好,如下图所示。
    在这里插入图片描述
  • 在开发之前我们先来对整个过程进行分析。
    在这里插入图片描述
  • 在对过程过程分析清楚之后,就开始对代码的书写。首先,我们得明确这是需要操作两张表,即套餐基本信息表和套餐里面所包含的菜品信息表。下面我们就来看看具体的代码实现。由于前端发送过的菜品信息里面并不会包含它所属套餐的id,所以我们需要自己将这个id设置进去。这样才会将套餐和菜品联系起来。
    在这里插入图片描述

3.18、套餐信息分页查询

3.18.1、需求分析

在这里插入图片描述

3.18.2、代码开发

  • 在开发代码之前,我们先来对整个过程梳理清楚。
    在这里插入图片描述
  • 在将业务分析清楚之后,就开始前后端的代码开发。
    在这里插入图片描述

3.19、删除套餐

3.19.1、需求分析

在这里插入图片描述

3.19.2、代码开发

  • 先来分析一下整个执行过程。
    在这里插入图片描述
  • 在将业务分析清楚之后,就开始前后端的代码开发。在删除套餐时,我们需要知道不仅需要操作套餐表,还需要操作保存套餐菜品信息的表。下面就来看看代码的开发。
    在这里插入图片描述
  • 然后再来看看前后端的交互代码。
    在这里插入图片描述

四、客户端开发

  • 在做完后端开发之后,现在应该来看看客户端的功能需求。

4.1、手机验证码发送功能

4.1.1、短信服务介绍

在这里插入图片描述

  • 这里我们用阿里的短信服务平台。
    在这里插入图片描述

4.1.2、代码开发

  • 任何一个服务商的平台都会提供响应的使用文档,参考官方文档即可完成。
  • 首先,我们先来导入坐标。

在这里插入图片描述

  • 然后调用相应的API就行。这个代码就是直接从官网复制下来,然后对参数稍加更改就行。然后再在前端调用这个就行。
    在这里插入图片描述
  • 在做完发送功能之后,就可以做前后端交互开发了,如下图所示。
    在这里插入图片描述

4.2、手机验证码登录

在这里插入图片描述

4.2.1、需求分析

在这里插入图片描述

4.2.2、代码开发

  • 首先我们先对过程进行梳理。
    在这里插入图片描述
  • 在前面我们做过一个过滤器,他会最所以的请求都进行拦截,但是发送短信和登录功能不能进行拦截,所以需要放行。
    在这里插入图片描述
    在这里插入图片描述

4.3、添加用户地址信息

4.3.1、需求分析

在这里插入图片描述

4.3.2、代码开发

  • 首先先将基本架构搭建起来。
    在这里插入图片描述
  • 这就是添加新的地址。
    在这里插入图片描述

4.4、菜品展示

4.4.1、需求分析

在这里插入图片描述

4.4.2、代码开发

  • 首先先来梳理一下整个过程。
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.5、用户下单

4.5.1、需求分析

在这里插入图片描述
在这里插入图片描述

4.5.2、代码开发

在这里插入图片描述

五、Git学习

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

六、项目优化

6.1、使用Redis进行缓存短信验证码

6.1.1、需求分析

  • 以前我们是将验证码保存在session里面,现在将验证码保存到redis里面。使用缓存效率会提高,并且设置过期策略方便,符合验证码使用场景。
    在这里插入图片描述

6.1.2、代码开发

  • 首先,使用redis需要先导进去相关的坐标。
    在这里插入图片描述
  • 然后编写redis的序列器。注意:使用idea编写时出现了下图的爆红。不用关它,这是idea的问题
    在这里插入图片描述
  • 然后就可以在需要使用redis的类里面注入RedisTemplate类。并且在需要使用缓存的地方使用redis即可。例如下图:
    在这里插入图片描述

6.2、餐单数据的缓存

6.1.1、不使用缓存所存在的问题

  • 当用户数量多,系统的访问量就会变大。频繁的访问数据库,会造成系统性能下降,用户体验变差。所以如果将数据缓存在redis,那么在获取数据时就可以直接从缓存中获取,而不用在从数据库里面获取。避免了频繁的访问数据库这个问题。
    在这里插入图片描述

6.1.2、代码开发

  • 之前我们是直接从数据库里面获取我们需要的数据,但是为了减少数据库的访问次数,我们现在使用redis来优化这个问题。下面是实现的思路。但是需要注意的是,当菜品数据发生更新之后,需要马上清除缓存,以防出现脏读。
    在这里插入图片描述
  • 下面就是相关缓存的代码。
    在这里插入图片描述
    在这里插入图片描述

6.3、springCache

6.3.1、需求分析

  • 上面我们已经使用redis进行了优化,但是相关的缓存逻辑还是得自己来实现。但是为了更加方便的使用缓存,我们可以使用springCache来进行优化。下面就来学习一下springCache的使用。
    在这里插入图片描述

6.3.2、springCache的注解讲解

  • 在上面我们是自己完成了缓存的一系列操作。但是为了更加方便的使用缓存,springCache为我们提供了这些注解来实现那些缓存的逻辑功能。具体使用如下图所示
    在这里插入图片描述

6.3.3、代码实现

  • 具体的步骤参考下图。
    在这里插入图片描述

  • 加入缓存
    在这里插入图片描述

  • 删除缓存。#p0指的是第一个方法参数。
    在这里插入图片描述

  • 根据条件缓存数据。
    在这里插入图片描述

6.4、套餐的优化

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
主从复制
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值