01
业务背景
我们的项目是一个招聘网站,但不是传统意义的收简历与投简历。
招聘端为用户提供的是效率与人力资源管理工具,是ToC的服务,主要是数据管理与文件管理。
求职端主要功能是建立自己的简历,以及更新简历。
求职者的简历会由定时任务自动推送到招聘者手中,与招聘者建立联系。
在招聘者更新简历后,可以主动把最新简历发送给所有已经简历联系的招聘者。
案例网址:即将品牌升级为"职位尽量快"
02
技术背景
这个项目开始的时候是一个人开发,但是仍旧使用了git做版本管理。
没有使用框架,主要是十多年不用java了,配框架的学习成本太高了,第一版要的就是节奏快。
数据库使用了pgsql,原因是需要pgsql的一些扩展函数,比如nlp相关的;另外,pgsql新版本的分区功能也不错
整体部署在阿里云上,都是ECS原生部署,没有使用rds等。
文件存储使用了oss。
03
项目结构
逻辑代码
controller:用于存放servlet,响应请求
dao:数据持久操作类
desk:文本处理,使用了工厂模式
filter:主要是过滤器
hanlp:是nlp处理框架,hanlp的相关代码
helper:有数据库helper,有sql的helper,还有log的helper
model:用于存放实体类(这里是个不规范的地方)
dto:数据传递的实体类
service:用于业务逻辑的处理层
util:类型转化,缓存,读取配置文件等
配置文件
基本的用户名,密码等配置文件
ehCache缓存的配置文件
hanlp的配置文件
log4j2的配置文件
多个sql配置文件(待讲解点)
页面
使用了layui,这是ui框架(这是个付费框架,一定要阅读协议)
多html页面,方便seo,也方便做统计报表
04
前后端的伪分离
前端页面是跟后端页面打包在一个war包里的。
数据交互用servlet+js+json的方式。
后端没有使用任何框架,用servlet3.0响应请求(方便大家学习)
05
后端为什么要迁移
原因
管理通用性与开发统一性
很多功能自己写的并不如别人验证过的好
降低开发成本
目标
仍旧用自研+开源连接池的方式做数据操作,因为我们是数据项目,持久化框架灵活性不够
逻辑代码基于spring boot开发
完成前端页面的单独项目,因为pc站需要cdn来提升用户体验。
配置部分
每天带领大家一起进步,从底向上进行项目拆解,所以先从项目中的sql文件开始。
拿一个sql举例,这个是要将招聘者了解到的候选人的基本信息插入到表中。
createCandiPanel=insert into candi_panels (userId,candiName,candiPhone,candiEmail) values (%s);
页面提交的是一个表单,那么,如何把表单数据,自动套入到模板sql呢?
首先,增加一个表单元素的配置,注意,表单元素的名字,要跟字段一致。
这个也写入到配置文件中。
createColCandiPanel=userId|string,candiName|string,candiPhone|string,candiEmail|string
然后是DAO层的通用方法,用来将传入的json数据进行持久化:
public int createPanel(String panelName,JsonObject jsonPanel) { //从配置文件中读取sql String queryCreateFullName = createPrefix + panelName; //从配置文件中读取字段名和数据类型 String strColumes = queryUserAssis.getProperty(createColPrefix + panelName); //创建空的条件语句用于sql条件拼接 StringBuilder strQuery = new StringBuilder(); for (String colNameType : strColumes.split(",")){ String[] arrCol = colNameType.split("\\|"); String colName = arrCol[0]; String colType = arrCol[1]; if(jsonPanel.has(colName)){ String elementVal = jsonPanel.get(colName).getAsString().trim(); strQuery.append(SqlHelper.formatInsertSqlColName(elementVal,colType)); }else { LogHelper.getInstance().noteLog(UserAssisDao.class.getName(),"createPanel() json key '" + colName + "' is null|error|", "error"); } } //格式化sql String sqlFormat = String.format(queryUserAssis.getProperty(queryCreateFullName),strQuery.substring(0, strQuery.length() - 1)); return DatabaseHelper.executeUpdate(DatabaseHelper.getConnection(),sqlFormat); }
下面是我们针对这个场景编写的解析json到sql的转换:
public static String formatInsertSqlColName(String colVal,String colType) { String strSqlAppend = ""; if(StringUtil.isNotEmpty(colVal) && (colType.equals("string") || colType.equals("date"))){ strSqlAppend = String.format("'%s'," , colVal); }else if(StringUtil.isNotEmptyObj(colVal) && colType.equals("int")){ strSqlAppend = String.format("%s," , colVal); }else if(StringUtil.isEmptyObj(colVal) && (colType.equals("string"))){ strSqlAppend = String.format("'%s'," , strNotString); }else if(StringUtil.isEmptyObj(colVal) && (colType.equals("date"))) { strSqlAppend = String.format("'%s',", strNotDate); }else if(StringUtil.isEmptyObj(colVal) && (colType.equals("int"))) { strSqlAppend = String.format("%s,", strNotNum); } return strSqlAppend; }
至此,一个通用的sql解析与拼接功能完成,我在原生项目上,迈出一小步。
在介绍完原生项目的结构后,开始讲解到spring boot的迁移。