学成在线第二天-查询课程、查询课程分类、新增课程接口实现以及跨域的处理思路和全局异常处理的使用以及面试题

news2024/11/15 15:55:39

目录

一、接口的实现

二、跨域的处理思路

三、全局异常处理

四、面试题

五、总结


一、接口的实现

1. 查询课程接口

思路:

典型的分页查询 + 按需查询 + 模糊查询的查询

controller:

@ApiOperation(value = "课程列表", notes = "课程列表")
    @PostMapping("/list")
    public PageResult<CourseBase> courses(PageParams pageParams, @RequestBody CourseBaseInfoDto courseBaseInfoDto) {
        PageResult<CourseBase> pageResult = courseBaseService.courses(pageParams, courseBaseInfoDto);
        return pageResult;
    }

service接口及其实现;

public interface CourseBaseService extends IService<CourseBase> {

    PageResult courses(PageParams pageParams, CourseBaseInfoDto courseBaseInfoDto);
}
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase>
    implements CourseBaseService{

    @Autowired
    private CourseMarketService courseMarketService;

    @Override
    public PageResult<CourseBase> courses(PageParams pageParams, CourseBaseInfoDto courseBaseInfoDto) {
        Page<CourseBase> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());

        LambdaQueryWrapper<CourseBase> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(courseBaseInfoDto.getCourseName()),CourseBase::getName,courseBaseInfoDto.getCourseName());
        wrapper.eq(StringUtils.hasText(courseBaseInfoDto.getAuditStatus()),CourseBase::getAuditStatus,courseBaseInfoDto.getAuditStatus());
        wrapper.eq(StringUtils.hasText(courseBaseInfoDto.getPublishStatus()),CourseBase::getStatus,courseBaseInfoDto.getPublishStatus());
        page(page,wrapper);
        List<CourseBase> records = page.getRecords();
        PageResult<CourseBase> pageResult = PageResult.ok(records, page.getTotal());
        return pageResult;
    }
}

2. 查询课程分类接口

典型的对树形数据结构的查询

通过数据库中的parentId字段,就能实现

@Service
public class CourseCategoryServiceImpl extends ServiceImpl<CourseCategoryMapper, CourseCategory>
    implements CourseCategoryService{


    /**
     * 获取分类树
     * @return
     */
    @Override
    public List<CourseCategoryNode> courseCategoryTreeNodes() {

        //1. 先查出所有节点
        List<CourseCategory> categories = list();
        List<CourseCategoryNode> courseCategoryNodes = BeanUtil.copyToList(categories, CourseCategoryNode.class);
        List<CourseCategoryNode> collect  = Collections.EMPTY_LIST;
        if(courseCategoryNodes!=null && courseCategoryNodes.size()>0){
            collect = courseCategoryNodes.stream().filter(category-> category.getParentid().equals("1")).map(categoryNode -> {
                List<CourseCategoryNode> childrenTreeNodes = children(categoryNode.getId(), courseCategoryNodes);
                categoryNode.setChildrenTreeNodes(childrenTreeNodes);
                return categoryNode;
            }).sorted((category1, category2) -> category1.getOrderby() == null? 0 : category1.getOrderby() - (category2.getOrderby() == null? 0 : category2.getOrderby())).collect(Collectors.toList());
        }
        return collect;
    }

    private List<CourseCategoryNode> children(String id, List<CourseCategoryNode> categories) {
        List<CourseCategoryNode> collect  = Collections.EMPTY_LIST;
        //注意判空
        if (categories != null && categories.size() > 0) {
            //1. 遍历所有节点 找到其节点的一级子节点
            collect = categories.stream().filter(category -> category.getParentid().equals(id)).map(category -> {
                //2. 再对一级子节点进行递归查找子节点
                category.setChildrenTreeNodes(children(category.getId(), categories));
                return category;
            }).sorted((category1, category2) -> category1.getOrderby() == null? 0 : category1.getOrderby() - (category2.getOrderby() == null? 0 : category2.getOrderby())).collect(Collectors.toList());
        }
        return collect;
    }
}

注意:

1. courseCategoryNodes.stream().filter(category-> category.getParentid().equals("1"))

这个是确保第一级就是 真正的第一级同级  而不会出现  第二级也作为父节点

2. 可以使用map 看似这里其实只是一个简单的set而并没有真正的将其对象进行转换,所以可以直接使用foreach,但是因为这里还有一个sort的后续对流的操作,所以可以使用map,使用map就能连续的对流进行处理

3. 注意避免空指针

要有这种意识,一旦对数组使用stream来操作,数组一定不能为null

还有就是在流处理中,通常可以获取到对象,而去调用对象的get方法,此时就需要主要判空

3. 新增课程信息接口

典型的多表新增  并且必须新增完上一个才能新增下一个也就是关联新增

还有就是新增和修改是一个接口,需要判断是新增还是修改

可以通过标识位判断,另外还可以查看数据库中数据是否存在的方法...老师写的有点问题

这里下面的营销信息是基于上面的基本信息,所以说下面一定是新增

正确的做法应该是再添加一个专门的修改方法

这里建议是不要将修改和添加合并

二、跨域的处理思路

1. 前端使用JSONP的方式

2. 使用过滤器 或者是拦截器 适用于单体服务

拦截器:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    /**
     * 配置跨域
     *
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 设置允许跨域的路径
        registry.addMapping("/**")
                // 设置允许跨域请求的域名
                .allowedOriginPatterns("*")
                // 是否允许cookie
                .allowCredentials(true)
                // 设置允许的请求方式
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 设置允许的header属性
                .allowedHeaders("*")
                // 跨域允许时间
                .maxAge(3600);
        // 设置可被访问的响应头
        //.exposedHeaders("jieiwi");
    }
}

过滤器:

 @Configuration
 public class GlobalCorsConfig {

  /**
   * 允许跨域调用的过滤器
   */
  @Bean
  public CorsFilter corsFilter() {
   CorsConfiguration config = new CorsConfiguration();
   //允许白名单域名进行跨域调用
   config.addAllowedOrigin("*");
   //允许跨越发送cookie
   config.setAllowCredentials(true);
   //放行全部原始头信息
   config.addAllowedHeader("*");
   //允许所有请求方法跨域调用
   config.addAllowedMethod("*");
   UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
   source.registerCorsConfiguration("/**", config);
   return new CorsFilter(source);
  }
 }

 还可以添加@CrossOrigin的方式

3. 在网关中配置

    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedMethods: # 支持的方法
              - GET
              - POST
              - PUT
              - DELETE

4. 使用nginx反向代理

由于浏览器直接访问对应的服务会跨域,那么可以不让浏览器直接访问服务,而是先将请求发给nginx,再由nigix代理给对应的服务

其实就是将浏览器环境变成了ngixn环境

因为在nginx中配置前端静态资源是很方便的,那么就可以利用ngixn,直接在浏览器中访问到nginx中的静态资源,这里是不会跨域的,这是由nginx的特点所决定的,nginx本来就可以实现动静分离 然后再在nginx中进行反向代理  将请求代理给服务集群

 参考:http://t.csdnimg.cn/i2nS9

三、全局异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = PriceException.class)
    public RestErrorResponse handlePriceException(PriceException e) {
        return new RestErrorResponse(e.getMessage());
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public RestErrorResponse handleArgsException(MethodArgumentNotValidException e) {
        List<String> collect = e.getBindingResult().getFieldErrors().stream().map(fieldError -> {
            return fieldError.getField()+fieldError.getDefaultMessage();
        }).collect(Collectors.toList());
        return new RestErrorResponse(StrUtil.join(",", collect));
    }

    @ExceptionHandler(value = Exception.class)
    public RestErrorResponse handException(){
        return new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());
    }

}

这个最终肯定是要返回前端以标准的响应体返回的,这样前端才能拿到异常信息,进行显示

至于这个返回给前端的异常信息到底是怎样的,可以直接 在抛出异常的时候指定好错误,然后在全局异常处理中直接调用异常对象的方法获取到异常信息

return new RestErrorResponse(e.getMessage());

 也可以不使用那里的,而是再全局异常中再去自己指定。另外这里的异常信息推荐使用将其封装成枚举 比如下面这样:

return new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());

反正也就是响应类和枚举类之间的玩法 

四、面试题

1. mybais中的分页插件的原理

其实就是将分页参数放到ThreadLocal中,然后根据不同的数据库类型添加对应的分页语句重写sql,例如将select * from table where a=xx 将其重写为  select count(*) from table where a = xx求出总数,然后还有一条select * from table where a = xx limit  ,  获取到数据

2. 异常处理

使用全局异常处理机制进行处理

@RestControllerAdvice注解和@ExceptionHandle可以处理自定义异常和系统异常 返回自己的异常信息

五、总结

还是几个常见接口的实现 现在来说应该说不能有难度了

分页查询、树形查询....新增和修改....

还是跨域和异常处理 但是学到了更多的处理跨域问题的解决办法

再就是知道mybatis分页插件的原理

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字节码进阶之java Instrumentation原理详解

文章目录 0. 前言1. 基础2. Java Instrumentation API使用示例 3. Java Agent4. 字节码操作库5. 实际应用6. 注意事项和最佳实践 0. 前言 Java Instrumentation是Java API的一部分&#xff0c;它允许开发人员在运行时修改类的字节码。使用此功能&#xff0c;可以实现许多高级操…

记录一次线下渗透电气照明系统(分析与实战)

项目地址:https://github.com/MartinxMax/S-Clustr 注意 本次行动未造成任何设备损坏,并在道德允许范围内测试 >ethical hacking< 发现过程 在路途中,发现一个未锁的配电柜,身为一个电工自然免不了好奇心(非专业人士请勿模仿,操作不当的话220V人就直了) 根据照片,简…

c++踩坑点,类型转换

std::string转换到PVOID std::string转换到PVOID的方式如下 这样的话成功转换 “const char *” 类型的实参与 “WCHAR *” “const char *” 类型的实参与 “WCHAR *” 类型的形参不兼容 可以看到这种报错&#xff0c;可以直接强转如下&#xff1a; 但是在我们这里不适…

论文总结:EXPRESSIVE SPEECH-DRIVEN FACIAL ANIMATION WITH CONTROLLABLE EMOTIONS

存在的问题:现有的语音驱动面部动画方法可以产生令人满意的嘴部运动和嘴唇同步,但在情感表达和情感控制方面存在不足。 作者使用wav2vec2.0和transformer encoder来获取文本向量和全局风格向量。将其拼接起来通过Auido2FLAME模块来预测flame的参数,Auido2FLAME由多层CNN组成…

大厂秋招真题【贪心】大疆20230813秋招T1-矩形田地

题目描述与示例 题目描述 给定一个矩形田地&#xff0c;其高度为 h 且宽度为 w。同时&#xff0c;你将获得两个整数数组 horizontalCutting 和 verticalCutting&#xff0c;其中 horizontalCutting[i] 表示从矩形田地顶部到第 i 个水平切口的距离&#xff0c;verticalCutting…

【二维差分】ICPC南京 A

https://codeforces.com/gym/104128/problem/A 题意 思路 二维差分经典模型 考虑如果没有洞那么经历操作之后会剩下什么样子的袋鼠。发现上下左右移动可以看成是边界在移动&#xff0c;边界一直保持一个原初的矩形形状&#xff0c;而且上下移动和左右移动没有任何关系。一旦…

自然语言处理---Transformer机制详解之GPT模型介绍

1 GPT介绍 GPT是OpenAI公司提出的一种语言预训练模型.OpenAI在论文<< Improving Language Understanding by Generative Pre-Training >>中提出GPT模型.OpenAI后续又在论文<< Language Models are Unsupervised Multitask Learners >>中提出GPT2模型.…

自然语言处理---RNN、LSTM、GRU模型

RNN模型 RNN模型概述 RNN(Recurrent Neural Network)&#xff0c;中文称作循环神经网络&#xff0c;它一般以序列数据为输入&#xff0c;通过网络内部的结构设计有效捕捉序列之间的关系特征&#xff0c;一般也是以序列形式进行输出。RNN的循环机制使模型隐层上一时间步产生的…

MIPS指令集摘要

目录 MIPS指令R I J三种格式 MIPS五种寻址方式 立即数寻址 寄存器寻址 基址寻址 PC相对寻址 伪直接寻址 WinMIPS64汇编指令 助记 从内存中加载数据 lb lbu lh lhu lw lwu ld l.d lui 存储数据到内存 sb sh sw sd s.d 算术运算 daddi daddui dadd…

自然语言处理---Transformer机制详解之GPT2模型介绍

1 GPT2的架构 从模型架构上看, GPT2并没有特别新颖的架构, 它和只带有解码器模块的Transformer很像. 所谓语言模型, 作用就是根据已有句子的一部分, 来预测下一个单词会是什么. 现实应用中大家最熟悉的一个语言模型应用, 就是智能手机上的输入法, 它可以根据当前输入的内容智…

hdlbits系列verilog解答(向量)-11

文章目录 一、问题描述二、verilog源码三、仿真结果一、问题描述 向量用于使用一个名称对相关信号进行分组,以使其更易于操作。例如,声明一个名为 8 位向量, wire [7:0] w; 该向量在 w 功能上等效于具有 8 个单独的线网(wire w0, w1, w2, w3, w4, w5, w6, w7)。 与C语言…

【Ubuntu系统搭建STM32开发环境(国内镜像全程快速配置)】

源于本人失败的经历苦心研究 虚拟机安装ubuntu换源VScode安装安装Java环境安装cubemx安装 arm-Linux-gcc安装gdb server安装OpenOCD 虚拟机安装ubuntu 系统镜像可以在阿里云镜像站且下载速度很快。 选择安装的版本。 我选择的是&#xff1a;ubuntu-22.10-desktop-amd64.iso。…

Hadoop3教程(三十四):(生产调优篇)MapReduce生产经验汇总

文章目录 &#xff08;164&#xff09;MR跑得慢的原因&#xff08;165&#xff09;MR常用调优参数Map阶段Reduce阶段 &#xff08;166&#xff09;MR数据倾斜问题参考文献 &#xff08;164&#xff09;MR跑得慢的原因 MR程序执行效率的瓶颈&#xff0c;或者说当你觉得你的MR程…

json-server工具准备后端接口服务环境

1.安装全局工具json-server&#xff08;全局工具仅需要安装一次&#xff09; 官网&#xff1a;json-server - npm 点击Getting started可以查看使用方法 在终端中输入yarn global add json-server或npm i json-server -g 2.代码根目录新建一个db目录 3.在db目录下创建index…

061:mapboxGL利用fitBounds同时将多个点放在可视范围内

第061个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中加载geojson数据,利用fitBounds同时将多个点放在可视范围内。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共134行)相关API参考:专栏目标示例…

linux性能分析(四)如何学习linux性能优化

一 如何学习linux性能优化 强调&#xff1a; 由于知识记忆曲线以及某些知识点不常用,所以一定要注重复习思考&#xff1a; 如何进行能力转义以及能力嫁接? --> 真正站在巨人的肩膀上性能调优的目的&#xff1a; 不影响系统稳定性的资源最大利用化补充&#xff1a; 性能…

【Spring Cloud】如何确定微服务项目的Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本

文章目录 1. 版本选择2. 用脚手架快速生成微服务的pom.xml3. 创建一个父工程4. 代码地址 本文描述如何确定微服务项目的Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本。 1. 版本选择 我们知道Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本选择一致性非常重…

CSS常见的预处理器有哪些?

CSS常见的预处理器有以下几种&#xff1a; 1&#xff1a;Sass&#xff08;Syntactically Awesome Style Sheets&#xff09;&#xff1a;Sass是一种成熟且广泛使用的CSS预处理器。它提供了许多功能&#xff0c;如变量、嵌套规则、混合&#xff08;Mixins&#xff09;、继承&am…

RT-Thread学习笔记(四):RT-Thread Studio工具使用

RT-Thread Studio工具使用 官网详细资料实用操作1. 查看 RT-Thread RTOS API 文档2.打开已创建的工程3.添加头文件路径4. 如何设置生成hex文件5.新建工程 官网详细资料 RT-Thread Studio 用户手册 实用操作 1. 查看 RT-Thread RTOS API 文档 2.打开已创建的工程 如果打开项目…

库的操作【MySQL】

文章目录 创建数据库字符集和校验规则概念分类例子 查看数据库显示创建语句修改数据库删除数据库备份和恢复备份恢复 创建数据库 SQL: CREATE DATABASE [IF NOT EXISTS] db_name [[DEFAULT] CHARSETcharset_name] [[DEFAULT] COLLATEcollation_name];其中&#xff0c;大写的单…