XXX人力资源管理平台
XXX公司推出的专业在线教育平台,聚合大量优质教育机构和名师,下设职业培训、公务员考试、托福雅思、考证考级、英语口语、中小学教育等众多在线学习精品课程,打造老师在线上课教学、学生及时互动学习的课堂。对于培训机构而言,可以入驻平台,发布相应的课程信息,也可以和企业定向合作进行定点培训。该项目分为6大模块:课程中心,岗位中心,用户中心,鉴权中心,机构管理中心,系统管理中心;
该项目整体分为6大模板:
课程中心 :管理发布课程,课程的搜索服务
岗位中心 :管理发布岗位信息,岗位的搜索服务
用户中心 :用户注册,用户信息,用户的课程申请和订单管理
鉴权中心 :用户登录以及权限控制
机构管理中心 :机构入驻与管理
系统管理中心 :数据字典,员工角色权限信息的维护
项目是前后端分离架构,前端使用vue,后端采用springboot+springcloud微服务架构,springboot搭建单个服务,springcloud治理服务。
SpringBoot、SpringCloud、Mybatis-Plus、Redis、FastDFS、Elasticsearch、Vue、ElementUI、 Velocity、RabbitMQ 、Gitlab
项目经理:1、架构师:1、UI:1、前端:2、后端:4、测试:2、运维:1。
需求:hrm人力资源系统是一个出租型服务,需要有需求的公司入驻,购买套餐,获得相应的服务。
搭建:基于SSM框架,配置注册Eureka,使用配置中心,配置网关路由
负责任务:基于代码生成器实现租户表的CRUD,租户入驻:使用FastDFS分布式文件系统实现租户LOGO文件的管理,使用百度地图接口,收集租户的地址。
需求:通过主站首页的链接跳转到课程中心门户,在课程中心门户首页有课程类型列表 - 后台:维护课程类型,选中某个类型后跳转到课程的列表页,列表课程信息 - 后台:维护课程信息,选中某个课程跳转到课程详情页,展示课程的详细信息,在课程的详情页可进行课程的购买,线上购买,线下学习,门户网站是高并发,需要进行页面静态化
搭建:基于SSM框架,配置注册Eureka,使用配置中心,配置网关路由
负责任务:使用循环+map的方式完成无线级别课程类型树数据的查询,使用redis对课程类型树的数据进行缓存,在前台页面展示,课程信息维护:基本信息,课程详情,市场信息,图片信息,课程管理表需要反三范式设计,创建人名称和机构名称冗余到了课程基本信息表,完成课程上下线:课程上线时,将上线课程的数据保存到ElasticSearch中,前台只能检索已经上线的课程。课程下线时:将上线课程的数据从ElasticSearch中删除。增删改时同步操作。使用velocity模板引擎技术,实现课程首页页面静态化,将静态化页面上传到FastDFS中,使用RabbitMQ消息队列接收fileId,下载页面完成静态化。课程中心首页:课程类型选择跳转,面包屑加载,课程的分页高级排序搜索。
需求:用户注册和登陆,各种用户的信息维护
搭建:基于SSM框架,配置注册Eureka,使用配置中心,配置网关路由
负责任务:用户注册:使用redis技术实现图形验证码注册,使用阿里云短信服务接口+redis实现短信验证码注册,同时进行用户注册其余信息的维护。用户登录:使用redis+cookie完成用户单点登录。
首先对于跨域的概念是:请求从一个域发出,访问另一个域的资源 ip:端口号 -> 另一个或者端口的资源, 只要ip或者端口不同,都认定为不同的域,如果之间有资源访问,这种行为叫做跨域访问
但不是所有的跨域都会出现跨域问题,跨域问题出现在:出现在ajax请求中,因为同源策源的限制,浏览器出于安全起见,会对ajax跨域请求做限制,限制ajax请求访问其他域的资源
对于跨域问题的解决方法有很多,但是我比较常用CORS
在springboot+springcloud+前后端分离的微服务程序中,解决跨域问题需要,在网关中配置跨域过滤器,因为所有前端的请求都是通过zuul网关进行服务调用的,也就是说所有的前端请求都先访问网关,我们就把跨域配置到zuul网关中。
/**
* 解决跨域问题
*/
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//1) 允许的域,不要写*,否则cookie就无法使用了
//浏览器认为127.0.0.1和localhost不是同一个域
config.addAllowedOrigin("http://127.0.0.1:6001");
config.addAllowedOrigin("http://localhost:6001");
config.addAllowedOrigin("http://127.0.0.1:6002");
config.addAllowedOrigin("http://localhost:6002");
config.addAllowedOrigin("http://127.0.0.1:6003");
config.addAllowedOrigin("http://localhost:6003");
//2) 是否发送Cookie信息
config.setAllowCredentials(true);
//3) 允许的请求方式
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
// 4)允许的头信息
config.addAllowedHeader("*");
//2.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new
UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}
(2)无限级别课程类型树获取
在课程中心业务模块,课程类型无限级别的树形菜单数据的获取
最开始是通过递归的方式进行获取,这种方式每次都要去查询数据库,导致效率低, 当数据量变大,递归深度增加,容易导致栈内存溢出
后面,我使用了嵌套循环的方式,查询出所有的课程类型,放入到一个list中,遍历查出来的所有类型,先判断是不是一级类型,一级类型就存储在一个专门的list容器中,不是一级类型,继续遍历,找出他的父类型,设置子类型到这个父类型中;但是这种方式,查询次数增加,导致效率低下;
所以,在项目中,我最终使用的是循环+Map的方式。
首先查询所有的类型放入List中,再将List中的所有类型放入Map中,Map的key为类型的ID,Map的value为当前类型对象。对List中所有类型进行遍历,如果是一级类型,则放入结果的List集合中,如果不是一级类型,则到Map中根据类型ID找到对应的父类型,将当前类型添加到父类型的children集合中,最终就能实现无线级别属性菜单数据的获取
/**
* 嵌套循环+map
* @return
*/
private List<CourseType> getTreeData() {
//准备一个list集合 存放所有的一级类型
List<CourseType> firstLevelType = new ArrayList<>();
//查询出所有的课程类型
List<CourseType> allCourseTypes = baseMapper.selectList<