学成在线第二天-查询课程、查询课程分类、新增课程接口实现以及跨域的处理思路和全局异常处理的使用以及面试题
目录
一、接口的实现
二、跨域的处理思路
三、全局异常处理
四、面试题
五、总结
一、接口的实现
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{@Autowiredprivate CourseMarketService courseMarketService;@Overridepublic 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*/@Overridepublic 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*/@Overridepublic void addCorsMappings(CorsRegistry registry) {// 设置允许跨域的路径registry.addMapping("/**")// 设置允许跨域请求的域名.allowedOriginPatterns("*")// 是否允许cookie.allowCredentials(true)// 设置允许的请求方式.allowedMethods("GET", "POST", "DELETE", "PUT")// 设置允许的header属性.allowedHeaders("*")// 跨域允许时间.maxAge(3600);// 设置可被访问的响应头//.exposedHeaders("jieiwi");}
}
过滤器:
@Configurationpublic class GlobalCorsConfig {/*** 允许跨域调用的过滤器*/@Beanpublic CorsFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();//允许白名单域名进行跨域调用config.addAllowedOrigin("*");//允许跨越发送cookieconfig.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分页插件的原理
相关文章:

学成在线第二天-查询课程、查询课程分类、新增课程接口实现以及跨域的处理思路和全局异常处理的使用以及面试题
目录 一、接口的实现 二、跨域的处理思路 三、全局异常处理 四、面试题 五、总结 一、接口的实现 1. 查询课程接口 思路: 典型的分页查询 按需查询 模糊查询的查询 controller: ApiOperation(value "课程列表", notes "课程…...

【OpenCV概念】 11— 对象检测
一、说明 这都是关于物体识别的。物体识别是指通过计算机视觉技术,自动识别图像或视频中的物体及其属性和特征,是人工智能领域的一个分支。物体识别可应用于多个领域,包括工业自动化、智能家居、医疗、安防等。请随时阅读这篇文章:…...
TensorRT学习笔记--常用卷积、激活、池化和FC层算子API
目录 1--Tensor算子API 1-1--卷积算子 1-2--激活算子 1-3--池化算子 1-4--FC层算子 2--代码实例 3--编译运行 1--Tensor算子API TensorRT提供了卷积层、激活函数和池化层三种最常用算子的API: // 创建一个空的网络 nvinfer1::INetworkDefinition* network …...
【Edabit 算法 ★☆☆☆☆☆】 Less Than 100?
【Edabit 算法 ★☆☆☆☆☆】 Less Than 100? language_fundamentals math validation Instructions Given two numbers, return true if the sum of both numbers is less than 100. Otherwise return false. Examples lessThan100(22, 15) // true // 22 15 37lessTha…...
C++中的智能指针:更安全、更便利的内存管理
在C++编程中,动态内存管理一直是一个重要且具有挑战性的任务。传统的C++中,程序员需要手动分配和释放内存,这往往会导致内存泄漏和悬挂指针等严重问题。为了解决这些问题,C++11引入了智能指针(Smart Pointers)这一概念,它们是一种高级的内存管理工具,可以自动管理内存的…...

google登录k8s dashboard ui显示“您的连接不是私密连接”问题解决梳理
1.问题描述 OS Version:CentOS Linux release 7.9.2009 (Core) K8S Version:Kubernetes v1.20.4 k8s dashboard ui安装完毕后,通过google浏览器登录返现https网页,发现非官方的https网页无法打开 网址:https://192.168.10.236:31001 2.原…...

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…...

数据可视化素材分享 | 数十图表、无数模板
很多人在后台求分享报表、源代码,其实何必这么麻烦,在奥威BI数据可视化平台上点击即可获得大量的可视化素材,如数十种可视化图表,适用于不同分析场景;又如大量不同主题的BI数据可视化报表模板,套用后替换数…...

Hadoop3教程(三十二):(生产调优篇)NameNode故障恢复与集群的安全模式
文章目录 (159)NameNode故障处理(160)集群安全模式&磁盘修复集群安全模式磁盘修复等待安全模式 参考文献 (159)NameNode故障处理 如果NameNode进程挂了并且存储的数据也丢失了,如何恢复Nam…...
uniapp下载附件保存到手机(文件、图片)ios兼容
downloadFile(file),其中file为下载的文件地址uni.downloadFile图片使用uni.saveImageToPhotosAlbum【安卓、ios都合适】文件使用uni.openDocument【安卓图片也可以用这个,ios会失败】 // 下载文件 export function downloadFile(file) {let acceptArr …...
【Edabit 算法 ★☆☆☆☆☆】 Basketball Points
【Edabit 算法 ★☆☆☆☆☆】 Basketball Points language_fundamentals math numbers Instructions You are counting points for a basketball game, given the amount of 2-pointers scored and 3-pointers scored, find the final points for the team and return that …...

Web攻防04_MySQL注入_盲注
文章目录 MYSQL-SQL操作-增删改查盲注概念盲注分类盲注语句参考&更多盲注语句/函数 注入条件-数据回显&错误处理PHP开发项目-注入相关条件:基于延时:基于布尔:基于报错: CMS案例-插入报错&删除延时-PHP&MYSQL1、x…...
Flask自定义装饰和g的使用
1. 在commons.py文件中新增一个装饰器类: 注:一定要加入wraps进行装饰否则,装饰器在给多个函数进行装饰时会报错 from functools import wraps from flask import session, current_app, g# 定义登陆装饰器,封装用户的登陆数据 def user_log…...
【汇编】汇编语言基础知识(学习笔记)
一、汇编语言概述 汇编语言是直接在硬件之上工作的编程语言,首先要了解硬件奈统的结构,才能有效的应用汇编语言对其编程。 二、汇编语言的产生 机器语言:机器语言是机器指令的集合 汇编语言的主体是汇编指令 汇编指令和机器指令的差别在…...
前端 | FormData 用法详解
前端 | FormData 用法详解 介绍 FormData 是 Ajax2.0 对象用以将数据编译成键值对,以便于 XMLHttpRequest 来发送数据。XMLHttpRequest Level 2 提供的一个接口对象,可以使用该对象来模拟和处理表单并方便的进行文件上传操作 如果表单属性设为 mu…...

linux常见命令-文件目录类
9.4 文件目录类 (1)pwd 指令:显示当前工作目录的绝对路径 (2)Is指令:查看当前目录的所有内容信息 基本语法: ls [选项,可选多个] [目录或是文件] 常用选项:-a:显示当前目录所有的文件和目录,包括隐藏的…...

2023 10月8日 至 10 月16日学习总结
1.做的题目 [RootersCTF2019]I_<3_Flask_双层小牛堡的博客-CSDN博客 [NCTF2019]SQLi regexp 盲注-CSDN博客 [网鼎杯 2018]Comment git泄露 / 恢复 二次注入 .DS_Store bash_history文件查看-CSDN博客 PHP LFI 利用临时文件Getshell_双层小牛堡的博客-CSDN博客 …...

【Java 进阶篇】深入了解 Bootstrap 表格和菜单
表格和菜单是网页设计中的重要组成部分,它们用于展示数据、导航和用户交互。Bootstrap 是一个强大的前端框架,提供了丰富的表格样式和菜单组件,使开发者能够轻松创建功能丰富的网页。在本文中,我们将深入探讨 Bootstrap 中表格和菜…...
java的for循环中遇到异常抛出后继续循环执行
java的for循环中遇到异常抛出后继续循环执行 Test public void loopTryCatchTest() throws Exception {Map<String, Object> a new HashMap();a.put("a", "1");a.put("b", null);a.put("c", "3");for (Map.Entry<…...

【Javascript】构造函数之new的作用
目录 new的作用 把对象返回了回来 无new 有new 把构造函数的this指向了要返回的对象 无new编辑 有new new的执行流程 new的作用 创建了新空对象将构造函数的作用域赋值给新对象(this指向新对象)执行构造函数代码 (为这个新对象添加属性)返回新对…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...

Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...