苍穹外卖随记(一)

黑马苍穹外卖逻辑和细节的问题和解决

1.后端查询到员工的日期信息,将信息进行json化传给前端时发生:前端收到的是不标准的日期json串。

解决: 1.注解进行json格式化(@JsonFormat)2. 在spring MVC中,通过消息转换器(重写configureMessageConverters方法),统一进行日期的标准json化

2.关于在设计接口时,返回值的Result是否带有泛型,主要取决于Result的data属性。data是我们给前端传输的数据,我们当设计到查询业务时,应该设定泛型

复制代码
3.//TODO:直接在接口测试传参数的时候发现,我们在进行员工信息修改时输入的信息并没有合法化,但是也能保存入数据库。因此会发现,当再次进行信息修改时,原本的信息会被判定为不合法

4.如何实现自动填充公共字段(逻辑思路:需要干什么?;怎么写?【熟悉反射等机制】)

解决: 解决代码重用问题,我们会想到aop,也就是切面思维。那么其底层的实现逻辑其实就是使用拦截器,去拦截需要对公共字段进行赋值的方法,然后对他进行赋值。那么有个问题是:如何让拦截器知道,我们需要拦截的方法是哪些呢?其实就是给一个标志。基于这个思路:我们的解决办法其实也就是 自定义注解AutoFill和自定义切面AutoFillAspect。最后在Mapper的方法上加入AutoFill注解

自定义注解 AutoFill,用于标识 出需要进行公共字段自动填充的方法

自定义切面 类AutoFillAspect,统一拦截 加入了AutoFill注解的方法,通过反射 为公共字段赋值

技术点:自定义注解、自定义切面、定义切入点、定义通知方法

5.借助 阿里云oss存储 上传文件

使用MultipartFile接口的参数,实现http文件上传

MultipartFile 是 Spring 框架中用于处理 HTTP 文件上传的一个接口。它定义了处理上传文件所需的基本操作,比如获取文件名、文件大小、文件类型以及最重要的,获取文件的字节流来读取文件内容。

6.Endpoint 通常包含地域信息和阿里云的服务标识,如 oss-cn-beijing.aliyuncs.com 中的 oss 表示对象存储服务,cn-beijing 表示中国北京地域。aliyuncs.com 是阿里云的顶级域名。

7.@ConditionalOnMissingBean 是一个 Spring 框架的注解,它用来确保当没有其他相同类型的 bean 存在于 Spring 容器中时,才创建并注册一个 bean。简单来说,它的作用就是:

  1. 如果系统中没有这个类型的 bean,就创建一个。

  2. 如果已经有了,就不创建了,避免重复。

这个注解通常用在自动配置类中,以提供一个默认的 bean 实现,让开发者可以根据自己的需要替换掉这个默认实现。

复制代码
//根据id修改菜品信息和对应的口味信息
    @Override
    public void updateWithFlavor(DishDTO dishDTO) {
        //菜品基本信息直接修改:菜品基本信息 直接dish类型,不需要dto
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        dishMapper.update(dish);
        //菜品口味由于多种可能:未改、追加、全部修改【不是简单的变量的数据修改】
        //删除原来的口味数据
        dishFlavorMapper.deleteByDishId(dishDTO.getId());
        //再用传来的参数重新新增口味
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if(flavors != null && !flavors.isEmpty()){
            //口味信息也可能是新增的口味,
            flavors.forEach(dishFlavor -> {
                dishFlavor.setDishId(dishDTO.getId());
            });
​
            dishFlavorMapper.insertBatch(flavors);
​
        }
​
    }

这里的:

复制代码
 //口味信息也可能是新增的口味,
            flavors.forEach(dishFlavor -> {
                dishFlavor.setDishId(dishDTO.getId());
            });

为什么还要重新设置id?没明白

我的想法:就是修改菜品id,菜品id已知,为什么还需要设置id?

9.sql经常出现的错误:赋值时:比如:update_user = #{updateUser},其中,update_user 是数据库表的字段 ;updateUser是参数

10.springData redis操作redis数据库:

  • 导入springData redis的maven坐标

  • 配置Redis数据源

  • 编写redis的配置类,创建redisTemplate对象

  • 通过redisTemplate操作redis数据库

11.编写redis的配置类:

作用:创建并初始化redisTemplate对象,并返回。(作为bean组件,创建以后可以直接注入)

步骤:

  1. 创建redisTemplate对象

  2. redisTemplate初始化:

    设置redis的连接对象工厂

    设置redis 中 key 的序列化器

  3. 返回redisTemplate对象

其他:

  1. redis的连接对象工厂RedisConnectionFactory是什么?有什么作用?

答: RedisConnectionFactory 是 Spring Data Redis 提供的一个接口,它的作用是创建与 Redis 服务器的连接。你可以把它想象成一个工厂,它的职责是制造(即创建)和管理 Redis 连接。

这个接口的主要目的是抽象化和封装创建 Redis 连接的细节,使得在 Spring 应用程序中使用 Redis 变得更加容易和统一。无论你使用的是哪种 Redis 客户端库(比如 Jedis 或 Lettuce),你都可以通过实现 RedisConnectionFactory 接口来提供连接。
RedisConnectionFactory 的作用包括:

  1. 创建连接 :它提供了创建新连接的方法。当你的应用程序需要与 Redis 服务器交互时,它可以通过 RedisConnectionFactory 获取一个连接。

  2. 配置连接 :你可以在 RedisConnectionFactory 实现中配置连接的各种参数,比如超时设置、密码认证、数据库选择等。

  3. 连接池管理 :在高并发的应用程序中,直接创建和关闭连接是非常耗费资源的。RedisConnectionFactory 可以配合连接池使用,复用连接,提高性能。

  4. 透明化连接管理 :开发者不需要关心连接的低级管理,如打开、关闭连接等,这些都由 RedisConnectionFactory 来处理。

在 Spring Boot 中,通常会有一个自动配置的 RedisConnectionFactory 实现,它根据你的 application.propertiesapplication.yml 文件中的配置来创建连接。如果你需要自定义连接的某些特定行为,你可以自己实现 RedisConnectionFactory 接口或者扩展现有的实现类。

简单来说,RedisConnectionFactory 就像是 Redis 连接的"制造商",它让应用程序能够方便地获取和使用 Redis 连接。

  1. StringRedisSerializer是什么?有什么用?

答: StringRedisSerializer 是 Spring Data Redis 中的一个序列化器,默认情况下,StringRedisSerializer 使用 Java 的 String 类型作为序列化和反序列化的对象。实际上可以接收Object的java类型;
StringRedisSerializer主要用途包括:

  • 键值序列化 :在 Redis 中存储键值对时,键和值都需要被序列化为字符串。StringRedisSerializer 可以确保键和值在存入 Redis 之前被正确地转换为字符串格式。

  • 字符串操作 :在执行需要字符串参数的 Redis 命令时(如 SETGET 等),StringRedisSerializer 可以确保传入的参数是正确序列化的。

  • 一致性:在分布式系统中,确保所有的 Java 对象在网络传输和存储时使用相同的序列化机制,可以避免数据不一致的问题。

12.关于redis数据库

复制代码
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    log.info("开始创建redis操作对象");
    RedisTemplate redisTemplate = new RedisTemplate();
    redisTemplate.setConnectionFactory(redisConnectionFactory);
    //redis的key的序列化是非常有必要的,否则查询很复杂
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    //但是考虑是否可以切换其他的序列化方法???????
    //因为得到的值仍然是“乱码”
    return redisTemplate;
}

13.在项目中有管理端和客户端和服务端,那么服务端是后端,管理端和客户端是前端,那么在设计接口时有这样的:/api/admin/applications,那么后端怎么根据这个接口开始开发呢?那个api怎么理解,或者说怎么替换?

在软件开发中,API(应用程序编程接口)是一组预定义的函数、协议和工具,用于构建软件应用程序。API 允许不同的软件系统相互交互。在您提到的 /api/admin/applications 接口中,api 通常是指应用程序编程接口的前缀,而后面的路径则定义了具体的资源和操作。

对于后端开发来说,设计和实现这样的接口通常涉及以下步骤:

  1. 理解需求 :首先,需要明确接口的目的和需求。在这个例子中,/api/admin/applications 可能意味着这是一个供管理员使用的接口,用于管理应用程序。

  2. 定义资源和操作:确定接口将处理哪些资源(在这个例子中是"applications")以及支持哪些操作(如获取列表、创建、更新、删除等)。

  3. 设计数据模型:根据接口的需求,设计数据库模型,确定需要存储哪些数据。

  4. 编写路由和控制器:在后端框架中,编写路由来匹配请求的URL,然后编写控制器来处理这些请求。例如,使用 Express.js 框架的 Node.js 应用可能会这样定义路由:

    复制代码
    app.get('/api/admin/applications', adminController.listApplications);
    app.post('/api/admin/applications', adminController.createApplication);
    // 其他路由...
  5. 实现业务逻辑:在控制器中实现具体的业务逻辑,比如从数据库中查询数据、验证数据、处理数据等。

  6. 错误处理:确保接口能够妥善处理错误,并返回适当的错误信息。

  7. 测试:编写单元测试和集成测试来验证接口的功能和性能。

  8. 文档:编写API文档,说明每个接口的用途、请求参数、响应格式和可能的错误代码。

至于"api"如何理解或替换,它通常是一个固定的前缀,用来标识这是一个API接口。在实际部署时,它可能会被替换为实际的域名或子域名,例如 https://api.yourdomain.com/admin/applications。这里的 api 可以被替换为任何符合项目命名规范的前缀,但通常保留 api 是为了明确表示这是一个供外部系统调用的接口。

在开发过程中,后端开发者需要与前端开发者紧密合作,确保接口的设计符合前端的需求,并且能够被前端正确地调用和处理。

14.如果接口都是这样设计的,那么我是不是可以全部取掉api?

在设计RESTful API时,使用 /api 作为前缀是一种常见的做法,它有助于区分API端点和其他类型的URL。然而,是否使用 /api 前缀并不是强制性的,它更多的是一个约定俗成的习惯。以下是一些考虑因素:

  1. 一致性 :如果你的团队或项目中已经采用了 /api 作为API端点的前缀,那么保持一致性是很重要的。这有助于团队成员理解和维护代码。

  2. 简洁性 :有些开发者和团队可能倾向于更简洁的URL,因此他们可能会选择不使用 /api 前缀。这在小型项目或者内部使用的应用中可能更常见。

  3. 版本控制 :在某些情况下,/api 后面可以跟版本号,如 /api/v1,这样可以在不更改现有API路径的情况下引入新版本的API。

  4. 部署考虑 :在某些部署环境中,可能需要将API部署在特定的路径下,这时 /api 前缀可以帮助明确API的部署路径。

  5. CORS(跨源资源共享) :如果你的API需要支持跨域请求,那么使用 /api 前缀可以帮助你更容易地配置CORS策略。

如果你决定不使用 /api 前缀,你的端点可能看起来像这样:

复制代码
GET /admin/applications
POST /admin/applications

在决定是否使用 /api 前缀时,你应该考虑你的项目需求、团队偏好以及未来的可维护性。如果你的项目规模较小,或者你预计不会有多个版本的API,那么省略 /api 前缀可能是合理的。但是,如果你预计项目会增长,或者你需要更清晰地区分API端点和非API端点,那么保留 /api 前缀可能是更好的选择。

最后,无论是否使用 /api 前缀,重要的是确保你的API设计遵循RESTful原则,如使用资源名称、HTTP方法和状态码来清晰地表达API的行为。

15.例如,非API端点可能包括:

/:网站的主页。 /login:用户登录页面。 /contact:联系我们页面。 /search:执行搜索的页面或端点。这样的话就是后端不需要对这些api进行开发?

实际上,即使是非API端点,后端通常也需要进行一定的开发工作,因为这些端点可能涉及到服务器端的逻辑处理、数据库交互、用户认证、数据检索等。以下是一些常见非API端点的后端开发任务:

  1. 主页(/)

    • 后端可能需要从数据库中检索特定的内容,如最新文章、推荐产品等。

    • 可能需要处理用户认证状态,以决定显示给用户的内容。

  2. 登录页面(/login)

    • 后端需要处理用户的登录请求,包括验证用户的凭证。

    • 可能需要与数据库交互,检索用户信息。

    • 需要处理会话管理和用户认证。

  3. 联系我们页面(/contact)

    • 后端可能需要处理用户提交的表单数据,如发送电子邮件或存储用户的联系信息。

    • 可能需要验证表单数据的有效性。

  4. 搜索页面或端点(/search)

    • 后端需要处理用户的搜索请求,可能涉及到复杂的查询逻辑和数据库搜索。

    • 需要优化搜索结果,提供相关性和性能。

即使这些端点不直接用于数据的CRUD操作,后端开发仍然需要确保这些端点能够正确地处理用户请求,并提供所需的功能。后端开发不仅仅是关于API端点的开发,它还包括了整个Web应用的后端逻辑,确保应用的稳定性、安全性和可用性。

此外,后端开发还涉及到服务器配置、安全性措施(如防止SQL注入、跨站脚本攻击等)、性能优化、错误处理和日志记录等方面。因此,即使是非API端点,后端开发也是不可或缺的一部分。

*16.在进行开发时会遇到controller同名的时候,这时如果不处理,那么在容器中,组件会发生冲突。具体说明冲突的原因,如何解决冲突?(除了给controller改名字)

17.在接口文档中,如何将用户端和管理端区分开?

在web的配置类中直接:

复制代码
/**
     * 通过knife4j生成管理端接口文档
     * @return
     */
    @Bean
    public Docket docket1() {
        log.info("准备生成接口文档:");
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("苍穹外卖项目接口文档")
                .version("2.0")
                .description("苍穹外卖项目接口文档")
                .build();
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName("管理端接口")
                .apiInfo(apiInfo)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.sky.controller.admin"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }

通过 groupName 进行分组,然后就可以在Swagger页面上展示:

相关推荐
晴子呀5 分钟前
Spring底层原理大致脉络
java·后端·spring
只吹45°风11 分钟前
Java-ArrayList和LinkedList区别
java·arraylist·linkedlist·区别
阿华的代码王国19 分钟前
【JavaEE】多线程编程引入——认识Thread类
java·开发语言·数据结构·mysql·java-ee
黑蛋同志19 分钟前
array和linked list的区别
java
andrew_121925 分钟前
腾讯 IEG 游戏前沿技术 一面复盘
java·redis·sql·面试
寻求出路的程序媛33 分钟前
JVM —— 类加载器的分类,双亲委派机制
java·jvm·面试
这孩子叫逆35 分钟前
35. MyBatis中的缓存失效机制是如何工作的?
java·spring·mybatis
骆晨学长35 分钟前
基于SpringBoot的校园失物招领系统
java·spring boot
汇匠源35 分钟前
零工市场小程序:保障灵活就业
java·小程序·零工市场
计算机编程-吉哥38 分钟前
计算机毕业设计 二手图书交易系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
java·spring boot·毕业设计·毕业论文·计算机毕业设计选题·计算机毕业设计开题报告·二手图书交易系统