瑞吉外卖实战-笔记

软件开发的流程
在这里插入图片描述

角色分工
在这里插入图片描述

软件环境
在这里插入图片描述

开发环境的搭建

数据库环境

maven环境
1.创建完成后,需要检查一下编码、maven仓库、jdk等

<parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.7.12</version>
</parent>
//注意:3.0版本以下使用的java版本是11,

2.导入pom

 <dependencies>
<!--sb的起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
<!--sb的测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
<!--springboot的web使用依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>compile</scope>
        </dependency>
<!--mybatisplus的起步依赖-->
        <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>
            <version>8.0.33</version>
        </dependency>
<!--数据源的依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.23</version>
        </dependency>
<!--阿里云的短信服务-->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.0.3</version>
        </dependency>

        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
            <version>1.1.0</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>

1.Filter-过滤器

作用:用于登录校验,未登录禁止访问

@WebFilter(filterName = "EmployeeLoginFilter",urlPatterns = "/*"),申明过滤器,名称自取,拦截路径为所有路径
想要使用过滤器,需要在启动类添加 @ServletComponentScan 注解

实现逻辑

  1. 创建一个类,实现Filter
  2. 重写doFilter方法
  3. 定义放行的路径数组
String[] url=new String[]
{ "/employee/login","/employee/logout","/common/**","/user/sendMsg","/user/login","/backend/**","/front/**"
};
//"/employee/login","/employee/logout"这是controller中的路径
//"/backend/**""/common/**",静态资源路径,即前端页面代码,路径从resources第一个包开始

4.获取前端请求路径,与以上的放行路径进行对比

HttpServletRequest httpServletRequest= (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse= (HttpServletResponse) servletResponse;
String requestURI = httpServletRequest.getRequestURI();//获取前端请求路径

5.遍历对比信息

public static final AntPathMatcher antPathMatcher=new AntPathMatcher();//路径对比器
public boolean pathmatch(String[] url,String requesturl)//自定义对比方法
    {
        for (String path:url
             ) {
            boolean match = antPathMatcher.match(path, requesturl);
            if(match)
            {
                return true;
            }
        }
        return false;
    }

6.调用自定义的方法,boolean pathmatch = this.pathmatch(url, requestURI);如果为true,则匹配成功,放行, filterChain.doFilter(httpServletRequest,httpServletResponse);这两个参数为doFilter的参数
7.如果没有进行前后端分离的话,在跳转到登录命令的controller后,需要设置一个session属性,用于判断是否登录

//Longincontroller,方法中需要自定义一个HttpServletRequest对象
request.getSession().setAttribute("employee",one.getId());

8.判断session是否存在,不存在则表示未登录
Object employee = httpServletRequest.getSession().getAttribute(“employee”);

2.MybatisPlus的分页查询-Pageconfig

作用:自定义分页,无需手动构造分页内容

@Configuration
public class PageConfig {

    @Bean
   public MybatisPlusInterceptor mybatisPlusInterceptor()
   {
       MybatisPlusInterceptor mybatisPlusInterceptor=new MybatisPlusInterceptor();
       mybatisPlusInterceptor.addInnerInterceptor( new PaginationInnerInterceptor());
       return mybatisPlusInterceptor;
   }
}
//通过Page<Object> page=new Page<>(起始页,每页条数)可直接使用

3.公共字段填充-MetaObjectHander

作用:数据表发生变化时,自动添加某些字段

实现逻辑
1.自定义类实现MetaObjectHandler类
2.重写insertFill方法/updateFill方法
3.添加公共参数

metaObject.setValue("updateTime", LocalDateTime.now())//第一个参数为数据表字段名称;

4.MybatisPlus

作用:mybatis的升级,不用手动编写sql

注意:使用mybatisplus,数据层与业务层有所不同

`
//数据层
@Mapper
public interface Mapper extends BaseMapper<实体类名>
//业务层接口
public interface Service extends IService<实体类名> {}
//业务层实现类
@Service
public class ServiceImpl extends ServiceImpl<Mapper,实体类名> implements Service {}`

想要使用mybatisplus自带的命令
1.构造一个条件对象
LambdaQueryWrapper<实体类> queryWrapper=new LambdaQueryWrapper<>();查找条件
LambdaUpdateWrapper<实体类> updateWrapper=new LambdaUpdateWrapper<>();条件更新
2.通过条件对象进行sql操作

5.数据传输对象-Dto

作用:将多个表单对象封装到一起,用于前端展示
步骤
1.创建表单类A、B
2.自定义一个类,继承A类
3.在自定义类中定义其他属性(集合/字符串/整形等)
4.集合中的参数为表单类B

@Data
public class DishDto extends Dish {

    private List<DishFlavor> flavors = new ArrayList<>();

    private String categoryName;

    private Integer copies;
}

6.后端响应结果集

将后端的发送的数据进行封装,在前端页面展示

//结果类包含的内容
private Integer code;//用于表示后端处理成功或失败
private String msg;//用于对后端处理结果的描述
private T data;//定义一个泛型,用于将后端处理后的数据传到前端

自定义泛型类
public class R<T> {
    // 类成员和方法的定义
}

泛型类的构造方法,返回值是一个泛型
public static <T>R<T>success(T obj)
    {
        R<T> r=new R<T>();
        r.data=obj;
        r.code=1;
        return r;
    }
    public static <T>R<T>error(String msg)
    {
        R r=new R();
        r.msg=msg;
        r.code=0;
        return r;
    }

7.自定义异常类

作用:捕获后端异常,当后端发生异常时,能够及时通知到前端

1.自定义异常类
//根据需要,继承想要展示的异常
public class CustomException extends RuntimeException{
public CustomException(String msg)
{
super(msg);		//调用父类的构造方法
}
}

2.定义异常处理类-ExceptionHandler
//@RestControllerAdvice通常与ExceptionHandler注解连用
@RestControllerAdvice(annotations = RestController.class)//=@Responsebody+@ControllerAdvice,参数为被拦截的错误来源
@Slf4j
public class ExceptionHandler {
    @org.springframework.web.bind.annotation.ExceptionHandler(CustomException.class)//处理异常类
    //SQLIntegrityConstraintViolationException e
    public R<String> ex(SQLIntegrityConstraintViolationException e)
    {
    log.info("异常处理");
    if(e.getMessage().contains("Duplicate entry"))//e.getmessage,就能获取到自定义错误的信息
    {
        System.out.println(e.getMessage());
        String[] errstr= e.getMessage().split(" ");
        for (String s:errstr
             ) {
            System.out.println(s);
        }
        String msg=errstr[2]+"已存在";
        log.info(msg);
        return R.error(msg);
    }
    return R.error("失败了");
    }

8.多线程-ThreadLocal

作用
1.跟踪请求处理过程中的数据:如将用户的标识(比如用户ID)存储在 threadLocal 中,这样在整个请求处理过程中都可以方便地获取和使用它
2.线程隔离的数据存储:一些数据在多线程环境中是线程私有的,并且不同线程之间的数据不应该相互干扰,可以使用 ThreadLocal 来实现数据的线程隔离。

//一般在校验登录的时候就为其赋值,将初始化的session赋给threadLocal,对象.方法调用即可
public class BaseContext {
    private static ThreadLocal<Long> threadLocal=new ThreadLocal<>();//通过这个方法就能随时获取sessionid,不用构建HttpServletRequest参数对象
    public static void setThreadLocal(Long integer)
    {
        threadLocal.set(integer);
    }
    public static Long getThreadLocal()
    {
        return threadLocal.get();
    }
}

10.文件上传下载-文件存储与本地,数据库只存储文件名

文件上传
1.获取上传的文件后缀名称
2.生成唯一的文件名称
3.校验存储位置的文件夹是否存在
4.转存到对应的文件夹

@Value("${reggie.path}")//配置文件自定义文件夹路径
    private String path;
    @PostMapping("/upload")
    public R<String> upload(MultipartFile file) throws IOException //上传的文件对象参数名,必须与前端的input框的name名字一致,且文件对象必须是MultipartFile
    {
        //上传的file文件是一个临时文件,需要转存,不然本次操作后,该文件就会销毁消失
        String originalFilename = file.getOriginalFilename(); //获取文件上传时的名称
        log.info(originalFilename);
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));//获取上传文件的后缀
        log.info(file+"这是前端的对象信息");
        String filename = UUID.randomUUID().toString()+suffix;//UUID生成一个唯一的名字
        log.info(filename);
        /**
         * 判断配置文件 @Value("${reggie.path}")的目录是否存在,没有就创建
         */

        File dir=new File(path);
        log.info("dir"+dir);
        if(!dir.exists())
        {
            log.info("创建文件");
            dir.mkdirs();//创建@Value("${reggie.path}")的文件夹
        }

        file.transferTo(new File(path+"/"+filename));   //将临时文件转存到该路径
        return R.success(filename);
    }

文件下载

@GetMapping("/download")
    public void download(String name, HttpServletResponse response)//name为图片存储地址
    {
        //下载文件需要经过两个步骤,读数据流,写数据流
        try {
            FileInputStream fileInputStream=new FileInputStream(new File(path+"/"+name));//输入流,将文件地址写入
            ServletOutputStream outputStream = response.getOutputStream();//输出流,因为这里需要将数据流显示到前端,所以用HttpServletResponse
            response.setContentType("image/jpeg");//设置传输到前端的数据格式
            int len=0;
            byte[] bytes=new byte[1024];
            while((len=fileInputStream.read(bytes))!=-1)//len是每次读取的字节数,bytes是存储读出字节的内容,fileInputStream.read是读取输入流,当读取完最后一个数时,len=-1
            {
                outputStream.write(bytes,0,len);//输出流,outputStream = response.getOutputStream(),写入bytes数组中的内容,从0开始写入,长度是len
                outputStream.flush();//刷新数据流
            }
            outputStream.close();//关闭输出流
            fileInputStream.close();//关闭输入流
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/58784.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pytorch 中 view 和reshape的区别

在 PyTorch&#xff08;一个流行的深度学习框架&#xff09;中&#xff0c; reshape 和 view 都是用于改变张量&#xff08;tensor&#xff09;形状的方法&#xff0c;但它们在实现方式和使用上有一些区别。下面是它们之间的主要区别&#xff1a; 实现方式&#xff1a; reshap…

机器学习--课后作业--hw1

机器学习(课后作业–hw1) 本篇文章全文参考这篇blog 网上找了很多教程&#xff0c;这个是相对来说清楚的&#xff0c;代码可能是一模一样&#xff0c;只是进行了一些微调&#xff0c;但是一定要理解这个模型具体的处理方法&#xff0c;这个模型我认为最巧妙的它对于数据的处理…

HTTP(超文本传输协议)学习

关于HTTP补学 一、HTTP能干什么 通过下图能够直观的看出&#xff1a;“交换数据 ” 二、HTTP请求例子 一个 HTTP 方法&#xff0c;通常是由一个动词&#xff0c;像 GET、POST 等&#xff0c;或者一个名词&#xff0c;像 OPTIONS、HEAD 等&#xff0c;来定义客户端执行的动作。…

Django之JWT库与SimpleJWT库的使用

Django之JWT库与SimpleJWT库的使用 JWTJWT概述头部(header)载荷(payload)签名(signature) Django使用JWT说明jwt库的使用安装依赖库配置settings.py文件配置urls.py文件创建视图配置权限 SimpleJWT库的使用安装SimpleJWT库配置Django项目配置路由创建用户接口测试身份认证自定义…

MP的开发流程-2

RESTful的实现等级 0级&#xff1a;传统的RPC&#xff0c;基于SOAP的WS&#xff0c;调用的服务名&#xff0c;参数放在HTTP协议的body里面&#xff0c;同时必须以POST方式提交&#xff0c;问题在于你必须清楚的知道所有服务&#xff0c;子服务&#xff0c;及其参数的信息&…

FileZilla Server同时共享多个目录(手把手教你使用FileZilla Server同时设置多个目录)

网上的基本全是一句话带过怎么共享多个目录&#xff0c;没图很烦&#xff0c;所以我自己就写一个过程 目录 1、创建ftp用户并设置密码 1.1、进入用户管理 1.2、新建用户 1.3、设置密码 2、添加共享的目录 2.1、选择用户添加目录 2.2、给予用户访问权限 2.2.1、客户端访…

长相思·罚站墙Vue

优化前 看效果图 Vue长相思 刚学Vue&#xff0c;正好在追剧&#xff0c;看到这个小案例觉得挺好玩的&#xff0c;第一天学&#xff0c;代码太简陋了 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta…

windows环境下安装elasticsearch、kibana

通过本文可以快速在windows系统上安装elasticsearch、kibana环境。 当你用Integer类型的时候&#xff0c;要非常小心&#xff0c;因为100等于100、但是200不等于200&#xff0c;当然&#xff0c;如果你会一点小花招&#xff0c;也可以让100不等于100、让200等于200。(运算符比较…

全球十大知名看黄金即时行情的软件名单(综合榜单)

在当今的数字化时代&#xff0c;黄金投资已成为一种受欢迎的投资方式。为了获取即时的黄金行情信息&#xff0c;许多投资者开始使用黄金即时行情软件。然而&#xff0c;选择一款合适的软件并不是一件容易的事情。那么&#xff0c;如何选适合自己需求的软件呢&#xff1f;首先&a…

LeetCode344.反转字符串

344.反转字符串 题目描述 解题思路 这是字符串专题的第一题 在之前反转链表的题目中&#xff0c;我们使用了双指针法来进行反转链表 这道题同样的&#xff0c;也使用双指针&#xff0c;对于字符串的反转&#xff0c;比链表更为简单 因为字符串本质上是一种数组&#xff0c…

【嵌入式学习笔记】嵌入式入门5——窗口看门狗WWDG

1.WWDG简介 WWDG的全称&#xff1a;Window watchdog&#xff0c;即窗口看门狗WWDG的本质&#xff1a;能产生系统复位信号和提前唤醒中断的计数器WWDG的特性&#xff1a;递减的计数器&#xff0c;当递减计数器值从 0x40减到0x3F时复位&#xff08;即T6位跳变到0&#xff09;&am…

性能优化-react路由懒加载和组件懒加载

背景 随着项目越来越大&#xff0c;打包后的包体积也越来越大&#xff0c;严重影响了首屏加载速度&#xff0c;需要对路由和组件做懒加载处理 主要用到了react中的lazy和Suspense。 废话不多说&#xff0c;直接上干货 路由懒加载 核心代码 import React, { lazy, Suspens…

三款AI写作宝介绍,教你玩转AI写作

AI写作宝是一款利用人工智能技术自动生成文章的工具。它采用先进的自然语言处理算法&#xff0c;可以在短时间内生成高质量的文章。与传统的写作方式相比&#xff0c;AI写作宝有着更快的速度、更高的准确性和更低的成本&#xff0c;成为了许多人工智能爱好者和写作从业者的首选…

写字楼门禁如何管理?最最新方法来了!

在现代社会&#xff0c;随着城市化和商务发展的蓬勃推进&#xff0c;大厦写字楼作为繁忙的商业中心和办公场所&#xff0c;其安全管理和员工考勤变得尤为重要。为了应对这一挑战&#xff0c;人脸门禁考勤机应运而生&#xff0c;成为大厦写字楼的安全保障和工时管理的关键工具。…

【数模】聚类模型

分类和聚类 分类&#xff1a;最终类别是确认的&#xff0c;把各样本分到已有的类别中聚类&#xff1a;最终类别是未知的&#xff0c;把所有样本划分出最终类别 一、K-means聚类算法 1.1 K-means算法了解 算法流程&#xff08;推荐使用流程图&#xff1a;更简洁&#xff0c;且…

Mybatis引出的一系列问题-JDBC 的探究

1 引入对JDBC的理解-1 一般来说&#xff0c;Java应用程序访问数据库的过程是&#xff1a; 装载数据库驱动程序&#xff1b;通过jdbc建立数据库连接&#xff1b;访问数据库&#xff0c;执行sql语句&#xff1b;断开数据库连接。 Public void FindAllUsers(){//1、装载sqlserve…

synchronized总结

目录 一、synchronized的特性 1.1 原子性 1.2 可见性 1.3 有序性 1.4 可重入性 二、synchronized的使用 2.1 修饰普通方法 2.2 修饰静态方法 2.3 修饰代码块 三、synchronized的锁机制 3.1 偏向锁 3.2 轻量级锁 3.3 重量级锁 一、synchronized的特性 1.1 原子性 原子性是指一…

Eclipse进行debug

目录 基本步骤三种执行方式 -- 键盘快捷键variables面板移除debug过的项目通过eclipse调用具有软件界面的项目进行debug各个variable颜色具有的意义 基本步骤 点击eclipse右上角debug按钮 调出debug面板 点击小蜘蛛图标&#xff08;不是点绿色三角的Run&#xff09; 此时会进…

华为流程体系:流程架构「OES方法」

目录 内容简介 OES方法 端到端的流程 专栏列表 CSDN学院 作者简介 内容简介 今天继续来谈谈华为流程体系中的流程架构。 在前期的内容已经介绍过 POS 流程架构的方法。 这里就先回顾一下 POS 方法的相关内容&#xff1a; 关于 POS&#xff0c;大家可以参看上面的这张图…

实现天气预报走势图

实现效果&#xff1a; 这里我用的天气接口是网上开源的&#xff0c;可以自己找一下。 稍微简单封装了一下axiso以及接口 封装的axios&#xff1a; // import { useUserStore } from /stores/user import axios from axios import router from /router import { ElMessage } f…