1. 详细说说你的项目吧
从以下几个方面进行项目介绍:
- 项目的背景,包括: 是自研还是外包、什么业务、服务的客户群是谁、谁去运营等问题。
- 项目的业务流程
- 项目的功能模块
- 项目的技术架构
- 个人工作职责
- 个人负责模块的详细说明,包括模块的设计,所用到的技术,技术的实现方案等
例子:
- 我最近参与的项目是我们公司自研的专门针对成人职业技能教育的网络课堂系统,网站提供了成人职业技能培训的相关课程,如: 软件开发培训、职业资格证书培训、成人学历教育培训等课程。
- 项目基于B2B2C的业务模式,培训机构可以在平台入驻、发布课程,我们公司作为运营方由专门的人员对发布的课程进行审核,审核通过后课程才可以发布成功,课程包括免费和收费两种形式,对于免费课程普通用户可以直接选课学习,对于收费课程在选课后需要支付成功才可以继续学习。
- 本项目包括三个端: 用户端(学生端)、机构端、运营端。核心模块包括:内容管理、媒资管理、课程搜索、订单支付、选课管理、认证授权等。
- 本项目采用前后端分离架构,后端采用SpringBoot、SpringCloud技术栈开发,数据库使用了MySQL,还使用的Redis、消息队列、分布式文件系统、Elasticsearch等中间件系统。
- 划分的微服务包括:内容管理服务、媒资管理服务、搜索服务、订单支付服务、学习中心服务、系统管理服务认证授权服务、网关服务、注册中心服务、配置中心服务等。
- 我在这个项目中负责了内容管理、媒资管理、订单支付模块的设计与开发。
- 内容管理模块,是对平台上的课程进行管理,课程的相关信息比较多, 在数据库设计了课程基本信息表、课程营销表、课程计划、课程师资表进行存储,培训机构要发布一门课程需要填写课程基本信息、课程营销信息、课程计划信息、课程师资信息,填写完毕后需要提交审核,由运营人员进行课程信息的审核,整个审核过程是程序自动审核加人工确认的方式,通常24小时审核完成。课程审核通过即可发布课程,课程的相关信息会聚合到课程发布表中,这里不仅要将课程信息写到课程发布表还要将课程信息写到索引库、分布式文件系统中,所以这里存在分布式事务的问题,项目使用本地消息表加任务调度的方式去解决这里的分布式事务,保存数据的最终一致性。
2.Git冲突怎么处理
出现冲突的原因是因为本地文件的版本与远程文件的版本不一致, 且同一行代码内容不同时, Git工具就无法自动合并文件, 解决代码冲突可以使用图形化工具或者手动处理冲突, , 本质都是一样的, 就是对冲突代码进行人工取舍或修改, 图形化工具比较方便, 处理完成后点击apply进行应用就行了, 手动处理的话, 要自己提交暂存区并push文件
3.你在哪个分支开发
一般都是在独立的开发分支进行开发, 开发完成后合并到主分支
4.maven的常用命令
mwn clean //清除target目录中的生成结果
myn compile //编译源代码
mvn test //执行单元测试
mvn package //打包
myn install //打包并把打好的包保存到本地仓库
mvn deploy //打包并把打好的包上传到远程仓库
5.mavne依赖版本冲突怎么处理
maven依赖版本冲突一般是由于间接依赖导致一个jar包即有多个不同的版本,比如:A依赖了B的1.0版本,C依赖了B的2.0版本,项目依赖A和C从而间接依赖了B的1.0和2.0版本,此时B有两个版本引入到了项目中,当存在版本冲突时可能会出现 ClassNotFoundException、NoSuchMethodError等错误。
处理版本冲突可以使用以下方法:
1、使用exclusions 排除依赖
比如: 我们只依赖B的1.0版本,此时可以在依赖C时排除对B的赖。
2、使用dependencyManagement锁定版本号:
通常在父工程对依赖的版本统一管理。
比如: 我们只依赖B的1.0版本,此时可以在父工程中限定B的版本为1.0.
6.MySql常见的储存引擎及区别
- InnoDB
支持事务
使用的锁颗粒度默认为行级锁, 可以支持更高的并发; 也支持表锁
支持外键约束; 外键约束其实降低了表的查询速度, 增加了表之间的耦合度
- MyISAM
不提供事务支持
只支持表级锁
不支持外键
- memory
数据存储在内存中
总结
MyISAM管理非事务表,提供高速存储和检索以及全文搜索能力,如果在应用中执行大量select操作,应该选择MyISAM
InnDB用于事务处理,具有ACID事务支持等特性,如果在应用中执行大量insert和update操作,应该选择InnoDB
7.mysql建表时要注意什么
MYSQL建表的经验有很多,下边列举一些:
- 注意选择存储引擎,如果要支持事务需要选择InnoDB:
- 注意字段类型的选择,
对于日期类型: 如果要记录时分秒建议使用datetime,只记录年月日使用date类型,
对于字符类型的选择,固定长度字段选择char,不固定长度的字段选择varchar,varchar比char节省空间但速度没有char快;
对于内容介绍类的长广文本字段使用text或longtext类型;
如果存储图片等二进制数据使用blob或longblob类型;
对金额字段建议使用DECIMAL;
对于数值类型的字段在确保取值范围足够的前提下尽量使用占用空间较小的类型,
- 主键字段建议使用自然主键,不要有业务意义,建议使用int unsigned类型,特殊场景使用bigint类型
- 如果要存储text、blob字段建议单独建一张表,使用外键关联。
- 尽量不要定义外键,保证表的独立性,可以存在外键意义的字段。
- 设置字段默认值,比如:状态、创建时间等。
- 每个字段写清楚注释。
- 注意字段的约束,比如:非空、唯一、主键等
8.SpringBoot接口开发注解有哪些
@Controller 标记此类是一个控制器,可以返回视图解析器指定的html页面,通过@ResponseBody可以将结果返回json、xml数据。
@RestController 相当于@ResponseBody加 @Controller,实现rest接口开发,返回json数据,不能返回html页面。
@RequestMapping定义接口地址,可以标记在类上也可以标记在方法上,支持http的post、put、get等方法
@PostMapping定义post接口,只能标记在方法上,用于添加记录,复杂条件的查询接口。@GetMapping定义get接口,只能标记在方法上,用于查询接口的定义。
@PutMapping定义put接口,只能标记在方法上,用于修改接口的定义。
@DeleteMapping定义delete接口,只能标记在方法上,用于除接口的定义。
@RequestBody定义在方法上,用于将ison串转成iava对象。
@PathVarible 接收请求路径中占位符的值.
@ApiOperation swagger注解,对接口方法进行说明。
@Apiwagger注解,对接口类进行说明。
@Autowired 基于类型注入。
@Resour 基于名称注入,如果基于名称注入失败转为基于类型注入。
9.你项目的开发流程是什么
1、产品人员设计产品原型。
2、讨论需求。
3、分模块设计接口。
4、出接口文档。
5、将接口文档给到前端人员,前后端分离开发。
6、开发完毕进行测试。
7、测试完毕发布项目,由运维人员进行部署安装。
10.Mybatis分页插件的原理?
首先分页参数放到ThreadLocal中,拦截执行的sql,根据数据库类型添加对应的分页语句重写sql,例如:(select* from table where a) 转换为 (select count(*) from table where a)和(select * from table where a limit ,)
计算出了total总条数、pageNum当前第几页、pagesize每页大小和当前页的数据,是否为首页,是否为尾页,总页数等。
11.MyBatis的ResultType和ResultMap的区别?
ResultType:指定映射类型,只要查询的字段名和类型的属性名匹配可以自动映射。
ResutMap:自定义映射规则,当查询的字段名和映射类型的属性不匹配时可以通过ResultMap自定义映射规则, 也可以实现一对多、一对一映射。
12.树型表的标记字段是什么? 如何查询MySQL树型表?
- 树型表的标记字段是parentid即父结点的id。
- 查询一个树型表的方法:
1) 当层级固定时可以用表的自链接进行查询。
2) 如果想灵活查询每个层级可以使用mysql递归方法,使用with RECURSIVE 实现。
13.#{} 和 ${} 有什么区别?
#{}是标记一个占位符,可以防止sql注入。
${}用于在动态 sql中拼接字符串,可能导致sql注入。
14.系统如何处理异常?
我们自定义一个统一的异常处理器去捕获并处理异常。
使用控制器增加注解@ControllerAdvice和异常处理注解@ExceptionHandler来实现。
1.处理自定义异常
程序在编写代码时根据校验结果主动抛出自定义异常类对象,抛出异常时指定详细的异常信息,异常处理器捕获异常信息记录异常日志并响应给用户。
2.处理未知异常
接口执行过程中的一些运行时异常也会由异常处理器统一捕获,记录异常日志,统一响应给用户500错误在异常处理器中还可以针对某个异常类型进行单独处理。
15.请求参数的合法性校验如何做?
使用基于ISR303的校验框架实现,SpringBoot提供了JSR-303的支持,它就是spring-boot-starter-validation,它包括了很多校验规则,只需要在模型类中通过注解指定校验规则,在controller方法上开启校验。
16.什么情况下Spring事务会失效?
- 在方法中捕获异常没有抛出去
- 非事务方法调用事务方法
- 事务方法内部调用事务方法
- @Transactional标记的方法不是public
- 抛出的异常与rollbackFor指定的异常不匹配,默认rollbackFor指定的异常为RuntimeException
- 数据库表不支持事务,比如MySQL的MyISAM
- Spring的传播行为导致事务失效,
- 比如: ROPAGATION NEVER、PROPAGATION NOT SUPPORTED
- PROPAGATION REQUIRED- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,
- PROPAGATION SUPPORTS-支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
- PROPAGATION REQUIRES NEW - 新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED-以非事务方式执行操作,如果当前存在事务,就把当前事务挂
起。
- PROPAGATION NEVER -以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION NESTED-如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则与PROPAGATION REOUIRED类似的操作。
17.断点续传怎么实现的?
我们是基于分块上传的模式实现断点续传的需求,当文件上传一部分断网后前边已经上传过的不再上传。
- 前端对文件分块。
- 前端使用多线程一块一块上传,上传前给服务端发一个消息校验该分块是否上传,如果已上传则不再上传。
- 等所有分块上传完毕,服务端合并所有分块,校验文件的完整性。
因为分块全部上传到了服务器,服务器将所有分块按顺序进行合并,就是写每个分块文件内容按顺序依次写入一个文件中。使用字节流去读写文件。
- 前端给服务传了一个md5值,服务端合并文件后计算合并后文件的md5是否和前端传的一样,如果一样则说文件完整,如果不一样说明可能由于网络丢包导致文件不完整,这时上传失败需要重新上传。
18.分块文件清理问题?
上传一个文件进行分块上传,上传一半不传了,之前上传到minio的分块文件要清理吗?怎么做的?
1、在数据库中有一张文件表记录minio中存储的文件信息。
2、文件开始上传时会写入文件表,状态为上传中,上传完成会更新状态为上传完成。
3、当一个文件传了一半不再上传了说明该文件没有上传完成,会有定时任务去查询文件表中的记录,如果文件未上传完成则删除minio中没有上传成功的文件目录。
19.xxl-job的工作原理是什么?xxl-job是什么怎么工作?
XXL-J0B分布式任务调度服务由调用中心和执行器组成,调用中心负责按任务调度策略向执行器下发任务,执行器负责接收任务执行任务。
1)首先部罢并启动xxl-job调度中心。(一个java工程)
2)首先在微服务添加xx1-job依赖,在微服务中配置执行器
3)启动微服务,执行器向调度中心上报自己。
4)在微服务中写一个任务方法并用xxl-job的注解去标记执行任务的方法名称。5)在调度中心配置任务调度策略,调度策略就是每隔多长时间执行还是在每天或每月的固定时间去执行,比如每天0点执行,或每隔1小时执行一次等。
6)在调度中心启动任务。
7)调度中心根据任务调度策略,到达时间就开始下发任务给执行器。
8)执行器收到任务就开始执行任务。
20.如何保证任务不重复执行?
1)调度中心按分片广播的方式去下发任务
2)执行器收到作业分片广播的参数:分片总数和分片序号,计算 任务id 除以 分片总数得到一个余数,如果余数等于分片序号这时就去执行这个任务,这里保证了不同的执行器执行不同的任务。
3)配置调度过期策略为"忽略”,避免同一个执行器多次重复执行同一个任务
4)配置任务阻塞处理策略为“丢弃后续调度”,注意:丢弃也没事下一次调度就又可以执行了
5)另外还要保证任务处理的幂等性,执行过的任务可以打一个状态标记已完成,下次再调度执行该任务判断该任务已完成就不再执行
21.任务幂等性如何保证?
它描述了一次和多次请求某一个资源对于资源本身应该具有同样的结果。幂等性是为了解决重复提交问题,比如:恶意刷单,重复支付等。解决幂等性常用的方案:
1)数据库约束,比如:唯一索引,主键。同一个主键不可能两次都插入成功。
2)乐观锁,常用于数据库,更新数据时根据乐观锁状态去更新。
3)唯一序列号,请求前生成唯一的序列号,携带序列号去请求,执行时在redis记录该序列号表示以该序列号的请求执行过了,如果相同的序列号再次来执行说明是重复执行。这里我们在数据库视频处理表中添加处理状态字段,视频处理完成更新状态为完成,执行视频处理前判断状态是否完成,如果完成则不再处理。