Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
张文彪
/
employmentBusinessPc
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
613f3bfd
authored
Nov 26, 2025
by
zwb
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
招聘会演示平台搭建与简历导入
parent
71cbf619
Show whitespace changes
Inline
Side-by-side
Showing
52 changed files
with
5877 additions
and
0 deletions
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/RemoteUserService.java
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/bo/RemoteLogininforBo.java
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/bo/RemoteOperLogBo.java
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/bo/RemoteSocialBo.java
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/bo/RemoteUserBo.java
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/vo/RemoteTenantVo.java
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/vo/RemoteUserVo.java
employmentBusiness-pc-auth/src/main/java/com/bkty/form/RegisterBody.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/annotation/RepeatSubmit.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/aspectj/RepeatSubmitAspect.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/constant/RegionConstants.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/enums/ResumeEnum.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/factory/RegexPatternPoolFactory.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/utils/ip/RegionUtils.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/utils/reflect/ReflectUtils.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexUtils.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexValidator.java
employmentBusiness-pc-common/employmentBusiness-pc-common-dubbo/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
employmentBusiness-pc-common/employmentBusiness-pc-common-dubbo/src/main/java/org/dromara/common/dubbo/enumd/RequestLogEnum.java
employmentBusiness-pc-common/employmentBusiness-pc-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java
employmentBusiness-pc-common/employmentBusiness-pc-common-redis/src/main/java/org/dromara/common/redis/handler/RedisExceptionHandler.java
employmentBusiness-pc-common/employmentBusiness-pc-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java
employmentBusiness-pc-common/employmentBusiness-pc-common-web/src/main/java/org/dromara/common/web/config/ResourcesConfig.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/config/RestTemplateConfig.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/dto/ResumeListItemCache.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/dto/ResumeMakeDto.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/dto/ResumeModelOptimizationCache.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/dto/ResumeMsgCache.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/entity/ResumeTemplate.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/entity/ResumeTranslationRecord.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeBase.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeBaseVo.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeByPdfVo.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeClub.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeEdu.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeExtra.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeInternship.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeModelVo.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeProject.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeSmartCreationVo.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeVo.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeWorkExp.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/dubbo/RemoteUserServiceImpl.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/mapper/ResumeTemplateMapper.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/mapper/ResumeTranslationRecordMapper.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/service/resume/ResumeCacheService.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/service/resume/impl/ResumeCacheServiceImpl.java
employmentBusiness-pc-nacos/src/main/resources/static/console-ui/public/css/fonts/roboto-bold.ttf
employmentBusiness-pc-nacos/src/main/resources/static/console-ui/public/css/fonts/roboto-bold.woff
employmentBusiness-pc-nacos/src/main/resources/static/console-ui/public/fonts/roboto-bold.eot
employmentBusiness-pc-nacos/src/main/resources/static/console-ui/public/fonts/roboto-bold.ttf
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/RemoteUserService.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
api
;
import
com.bkty.system.api.domain.bo.RemoteUserBo
;
import
com.bkty.system.api.domain.vo.RemoteUserVo
;
import
com.bkty.system.api.model.LoginUser
;
import
org.dromara.common.core.exception.ServiceException
;
import
org.dromara.common.core.exception.user.UserException
;
import
java.util.List
;
/**
* 用户服务
*
* @author Lion Li
*/
public
interface
RemoteUserService
{
/**
* 通过用户名查询用户信息
*
* @param username 用户名
* @return 结果
*/
LoginUser
getUserInfo
(
String
username
)
throws
UserException
;
/**
* 通过用户id查询用户信息
*
* @param userId 用户id
* @return 结果
*/
LoginUser
getUserInfo
(
Long
userId
)
throws
UserException
;
/**
* 通过手机号查询用户信息
*
* @param phonenumber 手机号
* @param tenantId 租户id
* @return 结果
*/
LoginUser
getUserInfoByPhonenumber
(
String
phonenumber
,
String
tenantId
)
throws
UserException
;
/**
* 通过邮箱查询用户信息
*
* @param email 邮箱
* @param tenantId 租户id
* @return 结果
*/
LoginUser
getUserInfoByEmail
(
String
email
,
String
tenantId
)
throws
UserException
;
/**
* 注册用户信息
*
* @param remoteUserBo 用户信息
* @return 结果
*/
Boolean
registerUserInfo
(
RemoteUserBo
remoteUserBo
)
throws
UserException
,
ServiceException
;
/**
* 通过userId查询用户账户
*
* @param userId 用户id
* @return 结果
*/
String
selectUserNameById
(
Long
userId
);
/**
* 通过用户ID查询用户昵称
*
* @param userId 用户id
* @return 结果
*/
String
selectNicknameById
(
Long
userId
);
/**
* 通过用户ID查询用户账户
*
* @param userIds 用户ID 多个用逗号隔开
* @return 用户名称
*/
String
selectNicknameByIds
(
String
userIds
);
/**
* 通过用户ID查询用户手机号
*
* @param userId 用户id
* @return 用户手机号
*/
String
selectPhonenumberById
(
Long
userId
);
/**
* 通过用户ID查询用户邮箱
*
* @param userId 用户id
* @return 用户邮箱
*/
String
selectEmailById
(
Long
userId
);
/**
* 更新用户信息
*
* @param userId 用户ID
* @param ip IP地址
*/
void
recordLoginInfo
(
Long
userId
,
String
ip
);
/**
* 通过用户ID查询用户列表
*
* @param userIds 用户ids
* @return 用户列表
*/
List
<
RemoteUserVo
>
selectListByIds
(
List
<
Long
>
userIds
);
/**
* 通过角色ID查询用户ID
*
* @param roleIds 角色ids
* @return 用户ids
*/
List
<
Long
>
selectUserIdsByRoleIds
(
List
<
Long
>
roleIds
);
}
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/bo/RemoteLogininforBo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
api
.
domain
.
bo
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* 系统访问记录表 sys_logininfor
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public
class
RemoteLogininforBo
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/**
* 访问ID
*/
private
Long
infoId
;
/**
* 租户编号
*/
private
String
tenantId
;
/**
* 用户账号
*/
private
String
userName
;
/**
* 客户端
*/
private
String
clientKey
;
/**
* 设备类型
*/
private
String
deviceType
;
/**
* 登录IP地址
*/
private
String
ipaddr
;
/**
* 登录地点
*/
private
String
loginLocation
;
/**
* 浏览器类型
*/
private
String
browser
;
/**
* 操作系统
*/
private
String
os
;
/**
* 登录状态(0成功 1失败)
*/
private
String
status
;
/**
* 提示消息
*/
private
String
msg
;
/**
* 访问时间
*/
private
Date
loginTime
;
/**
* 请求参数
*/
private
Map
<
String
,
Object
>
params
=
new
HashMap
<>();
}
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/bo/RemoteOperLogBo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
api
.
domain
.
bo
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* 操作日志记录表 oper_log
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public
class
RemoteOperLogBo
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/**
* 日志主键
*/
private
Long
operId
;
/**
* 租户编号
*/
private
String
tenantId
;
/**
* 模块标题
*/
private
String
title
;
/**
* 业务类型(0其它 1新增 2修改 3删除)
*/
private
Integer
businessType
;
/**
* 方法名称
*/
private
String
method
;
/**
* 请求方式
*/
private
String
requestMethod
;
/**
* 操作类别(0其它 1后台用户 2手机端用户)
*/
private
Integer
operatorType
;
/**
* 操作人员
*/
private
String
operName
;
/**
* 部门名称
*/
private
String
deptName
;
/**
* 请求URL
*/
private
String
operUrl
;
/**
* 主机地址
*/
private
String
operIp
;
/**
* 操作地点
*/
private
String
operLocation
;
/**
* 请求参数
*/
private
String
operParam
;
/**
* 返回参数
*/
private
String
jsonResult
;
/**
* 操作状态(0正常 1异常)
*/
private
Integer
status
;
/**
* 错误消息
*/
private
String
errorMsg
;
/**
* 操作时间
*/
private
Date
operTime
;
/**
* 消耗时间
*/
private
Long
costTime
;
/**
* 请求参数
*/
private
Map
<
String
,
Object
>
params
=
new
HashMap
<>();
}
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/bo/RemoteSocialBo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
api
.
domain
.
bo
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serial
;
import
java.io.Serializable
;
/**
* 社会化关系业务对象 sys_social
*
* @author Michelle.Chung
*/
@Data
@NoArgsConstructor
public
class
RemoteSocialBo
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
private
Long
id
;
/**
* 的唯一ID
*/
private
String
authId
;
/**
* 用户来源
*/
private
String
source
;
/**
* 用户的授权令牌
*/
private
String
accessToken
;
/**
* 用户的授权令牌的有效期,部分平台可能没有
*/
private
int
expireIn
;
/**
* 刷新令牌,部分平台可能没有
*/
private
String
refreshToken
;
/**
* 平台唯一id
*/
private
String
openId
;
/**
* 用户的 ID
*/
private
Long
userId
;
/**
* 平台的授权信息,部分平台可能没有
*/
private
String
accessCode
;
/**
* 用户的 unionid
*/
private
String
unionId
;
/**
* 授予的权限,部分平台可能没有
*/
private
String
scope
;
/**
* 授权的第三方账号
*/
private
String
userName
;
/**
* 授权的第三方昵称
*/
private
String
nickName
;
/**
* 授权的第三方邮箱
*/
private
String
email
;
/**
* 授权的第三方头像地址
*/
private
String
avatar
;
/**
* 个别平台的授权信息,部分平台可能没有
*/
private
String
tokenType
;
/**
* id token,部分平台可能没有
*/
private
String
idToken
;
/**
* 小米平台用户的附带属性,部分平台可能没有
*/
private
String
macAlgorithm
;
/**
* 小米平台用户的附带属性,部分平台可能没有
*/
private
String
macKey
;
/**
* 用户的授权code,部分平台可能没有
*/
private
String
code
;
/**
* Twitter平台用户的附带属性,部分平台可能没有
*/
private
String
oauthToken
;
/**
* Twitter平台用户的附带属性,部分平台可能没有
*/
private
String
oauthTokenSecret
;
}
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/bo/RemoteUserBo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
api
.
domain
.
bo
;
import
jakarta.validation.constraints.Email
;
import
jakarta.validation.constraints.NotBlank
;
import
jakarta.validation.constraints.Size
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
org.dromara.common.core.constant.UserConstants
;
import
org.dromara.common.core.xss.Xss
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.util.Date
;
/**
* 用户信息业务对象 sys_user
*
* @author Michelle.Chung
*/
@Data
@NoArgsConstructor
public
class
RemoteUserBo
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/**
* 用户ID
*/
private
Long
userId
;
/**
* 租户ID
*/
private
String
tenantId
;
/**
* 部门ID
*/
private
Long
deptId
;
/**
* 用户账号
*/
@Xss
(
message
=
"用户账号不能包含脚本字符"
)
@NotBlank
(
message
=
"用户账号不能为空"
)
@Size
(
min
=
0
,
max
=
30
,
message
=
"用户账号长度不能超过{max}个字符"
)
private
String
userName
;
/**
* 用户昵称
*/
@Xss
(
message
=
"用户昵称不能包含脚本字符"
)
@Size
(
min
=
0
,
max
=
30
,
message
=
"用户昵称长度不能超过{max}个字符"
)
private
String
nickName
;
/**
* 用户类型(sys_user系统用户)
*/
private
String
userType
;
/**
* 用户邮箱
*/
@Email
(
message
=
"邮箱格式不正确"
)
@Size
(
min
=
0
,
max
=
50
,
message
=
"邮箱长度不能超过{max}个字符"
)
private
String
email
;
/**
* 手机号码
*/
private
String
phonenumber
;
/**
* 用户性别(0男 1女 2未知)
*/
private
String
sex
;
/**
* 头像地址
*/
private
Long
avatar
;
/**
* 密码
*/
private
String
password
;
/**
* 帐号状态(0正常 1停用)
*/
private
String
status
;
/**
* 最后登录IP
*/
private
String
loginIp
;
/**
* 最后登录时间
*/
private
Date
loginDate
;
/**
* 备注
*/
private
String
remark
;
/**
* 数据权限 当前角色ID
*/
private
Long
roleId
;
public
RemoteUserBo
(
Long
userId
)
{
this
.
userId
=
userId
;
}
public
boolean
isSuperAdmin
()
{
return
UserConstants
.
SUPER_ADMIN_ID
.
equals
(
this
.
userId
);
}
}
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/vo/RemoteTenantVo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
api
.
domain
.
vo
;
import
lombok.Data
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.util.Date
;
/**
* 租户视图对象
*
* @author zhujie
*/
@Data
public
class
RemoteTenantVo
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/**
* id
*/
private
Long
id
;
/**
* 租户编号
*/
private
String
tenantId
;
/**
* 联系人
*/
private
String
contactUserName
;
/**
* 联系电话
*/
private
String
contactPhone
;
/**
* 企业名称
*/
private
String
companyName
;
/**
* 统一社会信用代码
*/
private
String
licenseNumber
;
/**
* 地址
*/
private
String
address
;
/**
* 域名
*/
private
String
domain
;
/**
* 企业简介
*/
private
String
intro
;
/**
* 备注
*/
private
String
remark
;
/**
* 租户套餐编号
*/
private
Long
packageId
;
/**
* 过期时间
*/
private
Date
expireTime
;
/**
* 用户数量(-1不限制)
*/
private
Long
accountCount
;
/**
* 租户状态(0正常 1停用)
*/
private
String
status
;
}
employmentBusiness-pc-api/src/main/java/com/bkty/system/api/domain/vo/RemoteUserVo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
api
.
domain
.
vo
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.util.Date
;
/**
* 用户
*
* @author Michelle.Chung
*/
@Data
@NoArgsConstructor
public
class
RemoteUserVo
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/**
* 用户ID
*/
private
Long
userId
;
/**
* 部门ID
*/
private
Long
deptId
;
/**
* 用户账号
*/
private
String
userName
;
/**
* 用户昵称
*/
private
String
nickName
;
/**
* 用户类型(sys_user系统用户)
*/
private
String
userType
;
/**
* 用户邮箱
*/
private
String
email
;
/**
* 手机号码
*/
private
String
phonenumber
;
/**
* 用户性别(0男 1女 2未知)
*/
private
String
sex
;
/**
* 帐号状态(0正常 1停用)
*/
private
String
status
;
/**
* 创建时间
*/
private
Date
createTime
;
}
employmentBusiness-pc-auth/src/main/java/com/bkty/form/RegisterBody.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
form
;
import
jakarta.validation.constraints.NotBlank
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
org.dromara.common.core.domain.model.LoginBody
;
import
org.hibernate.validator.constraints.Length
;
import
static
org
.
dromara
.
common
.
core
.
constant
.
UserConstants
.*;
/**
* 用户注册对象
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode
(
callSuper
=
true
)
public
class
RegisterBody
extends
LoginBody
{
/**
* 用户名
*/
@NotBlank
(
message
=
"{user.username.not.blank}"
)
@Length
(
min
=
USERNAME_MIN_LENGTH
,
max
=
USERNAME_MAX_LENGTH
,
message
=
"{user.username.length.valid}"
)
private
String
username
;
/**
* 用户密码
*/
@NotBlank
(
message
=
"{user.password.not.blank}"
)
@Length
(
min
=
PASSWORD_MIN_LENGTH
,
max
=
PASSWORD_MAX_LENGTH
,
message
=
"{user.password.length.valid}"
)
private
String
password
;
/**
* 用户类型
*/
private
String
userType
;
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/annotation/RepeatSubmit.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
annotation
;
import
java.lang.annotation.*
;
import
java.util.concurrent.TimeUnit
;
/**
* 自定义注解防止表单重复提交
*
* @author jiangxiaoge
*/
@Inherited
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
RepeatSubmit
{
/**
* 间隔时间(ms),小于此时间视为重复提交
*/
int
interval
()
default
5000
;
TimeUnit
timeUnit
()
default
TimeUnit
.
MILLISECONDS
;
/**
* 提示消息 支持国际化 格式为 {code}
*/
String
message
()
default
"请误重复提交"
;
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/aspectj/RepeatSubmitAspect.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
aspectj
;
import
cn.hutool.core.util.ArrayUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.crypto.SecureUtil
;
import
jakarta.servlet.http.HttpServletRequest
;
import
jakarta.servlet.http.HttpServletResponse
;
import
com.alibaba.fastjson2.JSON
;
import
org.aspectj.lang.JoinPoint
;
import
org.aspectj.lang.annotation.AfterReturning
;
import
org.aspectj.lang.annotation.AfterThrowing
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Before
;
import
org.dromara.common.core.annotation.RepeatSubmit
;
import
org.dromara.common.core.domain.R
;
import
org.dromara.common.core.exception.WarnException
;
import
org.dromara.common.core.utils.ServletUtils
;
import
org.dromara.common.core.utils.SpringContextHolder
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.ValueOperations
;
import
org.springframework.validation.BindingResult
;
import
org.springframework.web.multipart.MultipartFile
;
import
org.dromara.common.core.constant.CacheConstants
;
import
java.time.Duration
;
import
java.util.Collection
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.StringJoiner
;
/**
* 防止重复提交(参考美团GTIS防重系统)
*
* @author Lion Li
*/
@Aspect
public
class
RepeatSubmitAspect
{
private
static
final
ThreadLocal
<
String
>
KEY_CACHE
=
new
ThreadLocal
<>();
private
static
final
RedisTemplate
<
String
,
String
>
CLIENT
=
SpringContextHolder
.
getBean
(
RedisTemplate
.
class
);
@Before
(
"@annotation(repeatSubmit)"
)
public
void
doBefore
(
JoinPoint
point
,
RepeatSubmit
repeatSubmit
)
throws
Throwable
{
// 如果注解不为0 则使用注解数值
long
interval
=
repeatSubmit
.
timeUnit
().
toMillis
(
repeatSubmit
.
interval
());
if
(
interval
<
1000
)
{
throw
new
WarnException
(
"重复提交间隔时间不能小于'1'秒"
);
}
HttpServletRequest
request
=
ServletUtils
.
getRequest
();
String
nowParams
=
argsArrayToString
(
point
.
getArgs
());
// 请求地址(作为存放cache的key值)
String
url
=
request
.
getRequestURI
();
// 唯一值(没有消息头则使用请求地址)
String
submitKey
=
Objects
.
toString
(
request
.
getHeader
(
"Authorization"
),
""
);
submitKey
=
SecureUtil
.
md5
(
submitKey
+
":"
+
nowParams
);
// 唯一标识(指定key + url + 消息头)
String
cacheRepeatKey
=
CacheConstants
.
REPEAT_SUBMIT_KEY
+
url
+
submitKey
;
if
(
setObjectIfAbsent
(
cacheRepeatKey
,
""
,
Duration
.
ofMillis
(
interval
)))
{
KEY_CACHE
.
set
(
cacheRepeatKey
);
}
else
{
throw
new
WarnException
(
repeatSubmit
.
message
());
}
}
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning
(
pointcut
=
"@annotation(repeatSubmit)"
,
returning
=
"jsonResult"
)
public
void
doAfterReturning
(
JoinPoint
joinPoint
,
RepeatSubmit
repeatSubmit
,
Object
jsonResult
)
{
if
(
jsonResult
instanceof
R
<?>
r
)
{
try
{
// 成功则不删除redis数据 保证在有效时间内无法重复提交
if
(
r
.
getCode
()
==
R
.
ok
().
getCode
())
{
return
;
}
CLIENT
.
delete
(
KEY_CACHE
.
get
());
}
finally
{
KEY_CACHE
.
remove
();
}
}
}
/**
* 拦截异常操作
*
* @param joinPoint 切点
* @param e 异常
*/
@AfterThrowing
(
value
=
"@annotation(repeatSubmit)"
,
throwing
=
"e"
)
public
void
doAfterThrowing
(
JoinPoint
joinPoint
,
RepeatSubmit
repeatSubmit
,
Exception
e
)
{
CLIENT
.
delete
(
KEY_CACHE
.
get
());
KEY_CACHE
.
remove
();
}
/**
* 参数拼装
*/
private
String
argsArrayToString
(
Object
[]
paramsArray
)
{
StringJoiner
params
=
new
StringJoiner
(
" "
);
if
(
ArrayUtil
.
isEmpty
(
paramsArray
))
{
return
params
.
toString
();
}
for
(
Object
o
:
paramsArray
)
{
if
(
ObjectUtil
.
isNotNull
(
o
)
&&
!
isFilterObject
(
o
))
{
params
.
add
(
JSON
.
toJSONString
(
o
));
}
}
return
params
.
toString
();
}
/**
* 判断是否需要过滤的对象。
*
* @param o 对象信息。
* @return 如果是需要过滤的对象,则返回true;否则返回false。
*/
@SuppressWarnings
(
"rawtypes"
)
public
boolean
isFilterObject
(
final
Object
o
)
{
Class
<?>
clazz
=
o
.
getClass
();
if
(
clazz
.
isArray
())
{
return
MultipartFile
.
class
.
isAssignableFrom
(
clazz
.
getComponentType
());
}
else
if
(
Collection
.
class
.
isAssignableFrom
(
clazz
))
{
Collection
collection
=
(
Collection
)
o
;
for
(
Object
value
:
collection
)
{
return
value
instanceof
MultipartFile
;
}
}
else
if
(
Map
.
class
.
isAssignableFrom
(
clazz
))
{
Map
map
=
(
Map
)
o
;
for
(
Object
value
:
map
.
values
())
{
return
value
instanceof
MultipartFile
;
}
}
return
o
instanceof
MultipartFile
||
o
instanceof
HttpServletRequest
||
o
instanceof
HttpServletResponse
||
o
instanceof
BindingResult
;
}
/**
* 如果不存在则设置 并返回 true 如果存在则返回 false
*
* @param key 缓存的键值
* @param value 缓存的值
* @param duration 缓存的过期时间
* @return set成功或失败
*/
public
boolean
setObjectIfAbsent
(
final
String
key
,
final
String
value
,
final
Duration
duration
)
{
// 获取 ValueOperations
ValueOperations
<
String
,
String
>
valueOperations
=
CLIENT
.
opsForValue
();
// 使用 setIfAbsent 来设置值,如果键不存在
Boolean
isSet
=
CLIENT
.
opsForValue
().
setIfAbsent
(
key
,
value
);
// 如果 setIfAbsent 返回 true,表示设置成功
if
(
Boolean
.
TRUE
.
equals
(
isSet
))
{
// 设置过期时间
CLIENT
.
expire
(
key
,
duration
);
return
true
;
}
return
false
;
// 如果键已存在,则返回 false
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
constant
;
import
cn.hutool.core.lang.RegexPool
;
/**
* 常用正则表达式字符串
* <p>
* 常用正则表达式集合,更多正则见: https://any86.github.io/any-rule/
*
* @author Feng
*/
public
interface
RegexConstants
extends
RegexPool
{
/**
* 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
*/
String
DICTIONARY_TYPE
=
"^[a-z][a-z0-9_]*$"
;
/**
* 权限标识必须符合 tool:build:list 格式,或者空字符串
*/
String
PERMISSION_STRING
=
"^(|^[a-zA-Z0-9_]+:[a-zA-Z0-9_]+:[a-zA-Z0-9_]+)$"
;
/**
* 身份证号码(后6位)
*/
String
ID_CARD_LAST_6
=
"^(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$"
;
/**
* QQ号码
*/
String
QQ_NUMBER
=
"^[1-9][0-9]\\d{4,9}$"
;
/**
* 邮政编码
*/
String
POSTAL_CODE
=
"^[1-9]\\d{5}$"
;
/**
* 注册账号
*/
String
ACCOUNT
=
"^[a-zA-Z][a-zA-Z0-9_]{4,15}$"
;
/**
* 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
*/
String
PASSWORD
=
"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$"
;
/**
* 通用状态(0表示正常,1表示停用)
*/
String
STATUS
=
"^[01]$"
;
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/constant/RegionConstants.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
constant
;
/**
* @author jiangxiaoge
* @description
* @data 2025/2/12
**/
public
class
RegionConstants
{
public
static
final
String
REGION_JSON_ARRAY
=
"""
[
{
"
label
": "
北京
",
"
value
": "
11
",
},
{
"
label
": "
天津
",
"
value
": "
12
",
},
{
"
label
": "
河北
",
"
value
": "
13
",
},
{
"
label
": "
山西
",
"
value
": "
14
",
},
{
"
label
": "
内蒙古
",
"
value
": "
15
",
},
{
"
label
": "
辽宁
",
"
value
": "
21
",
},
{
"
label
": "
吉林
",
"
value
": "
22
",
},
{
"
label
": "
黑龙江
",
"
value
": "
23
",
},
{
"
label
": "
上海
",
"
value
": "
31
",
},
{
"
label
": "
江苏
",
"
value
": "
32
",
},
{
"
label
": "
浙江
",
"
value
": "
33
",
},
{
"
label
": "
安徽
",
"
value
": "
34
",
},
{
"
label
": "
福建
",
"
value
": "
35
",
},
{
"
label
": "
江西
",
"
value
": "
36
",
},
{
"
label
": "
山东
",
"
value
": "
37
",
},
{
"
label
": "
河南
",
"
value
": "
41
",
},
{
"
label
": "
湖北
",
"
value
": "
42
",
},
{
"
label
": "
湖南
",
"
value
": "
43
",
},
{
"
label
": "
广东
",
"
value
": "
44
",
},
{
"
label
": "
广西
",
"
value
": "
45
",
},
{
"
label
": "
海南
",
"
value
": "
46
",
},
{
"
label
": "
重庆
",
"
value
": "
50
",
},
{
"
label
": "
四川
",
"
value
": "
51
",
},
{
"
label
": "
贵州
",
"
value
": "
52
",
},
{
"
label
": "
云南
",
"
value
": "
53
",
},
{
"
label
": "
西藏
",
"
value
": "
54
",
},
{
"
label
": "
陕西
",
"
value
": "
61
",
},
{
"
label
": "
甘肃
",
"
value
": "
62
",
},
{
"
label
": "
青海
",
"
value
": "
63
",
},
{
"
label
": "
宁夏
",
"
value
": "
64
",
},
{
"
label
": "
新疆
",
"
value
": "
65
",
},
{
"
label
": "
台湾
",
"
value
": "
66
",
},
{
"
label
": "
香港
",
"
value
": "
67
",
},
{
"
label
": "
澳门
",
"
value
": "
68
",
},
{
"
label
": "
北京
",
"
value
": "
1101
",
},
{
"
label
": "
天津
",
"
value
": "
1201
",
},
{
"
label
": "
石家庄
",
"
value
": "
1301
",
},
{
"
label
": "
唐山
",
"
value
": "
1302
",
},
{
"
label
": "
秦皇岛
",
"
value
": "
1303
",
},
{
"
label
": "
邯郸
",
"
value
": "
1304
",
},
{
"
label
": "
邢台
",
"
value
": "
1305
",
},
{
"
label
": "
保定
",
"
value
": "
1306
",
},
{
"
label
": "
张家口
",
"
value
": "
1307
",
},
{
"
label
": "
承德
",
"
value
": "
1308
",
},
{
"
label
": "
沧州
",
"
value
": "
1309
",
},
{
"
label
": "
廊坊
",
"
value
": "
1310
",
},
{
"
label
": "
衡水
",
"
value
": "
1311
",
},
{
"
label
": "
太原
",
"
value
": "
1401
",
},
{
"
label
": "
大同
",
"
value
": "
1402
",
},
{
"
label
": "
阳泉
",
"
value
": "
1403
",
},
{
"
label
": "
长治
",
"
value
": "
1404
",
},
{
"
label
": "
晋城
",
"
value
": "
1405
",
},
{
"
label
": "
朔州
",
"
value
": "
1406
",
},
{
"
label
": "
晋中
",
"
value
": "
1407
",
},
{
"
label
": "
运城
",
"
value
": "
1408
",
},
{
"
label
": "
忻州
",
"
value
": "
1409
",
},
{
"
label
": "
临汾
",
"
value
": "
1410
",
},
{
"
label
": "
吕梁
",
"
value
": "
1411
",
},
{
"
label
": "
呼和浩特
",
"
value
": "
1501
",
},
{
"
label
": "
包头
",
"
value
": "
1502
",
},
{
"
label
": "
乌海
",
"
value
": "
1503
",
},
{
"
label
": "
赤峰
",
"
value
": "
1504
",
},
{
"
label
": "
通辽
",
"
value
": "
1505
",
},
{
"
label
": "
鄂尔多斯
",
"
value
": "
1506
",
},
{
"
label
": "
呼伦贝尔
",
"
value
": "
1507
",
},
{
"
label
": "
巴彦淖尔
",
"
value
": "
1508
",
},
{
"
label
": "
乌兰察布
",
"
value
": "
1509
",
},
{
"
label
": "
兴安盟
",
"
value
": "
1522
",
},
{
"
label
": "
锡林郭勒盟
",
"
value
": "
1525
",
},
{
"
label
": "
阿拉善盟
",
"
value
": "
1529
",
},
{
"
label
": "
沈阳
",
"
value
": "
2101
",
},
{
"
label
": "
大连
",
"
value
": "
2102
",
},
{
"
label
": "
鞍山
",
"
value
": "
2103
",
},
{
"
label
": "
抚顺
",
"
value
": "
2104
",
},
{
"
label
": "
本溪
",
"
value
": "
2105
",
},
{
"
label
": "
丹东
",
"
value
": "
2106
",
},
{
"
label
": "
锦州
",
"
value
": "
2107
",
},
{
"
label
": "
营口
",
"
value
": "
2108
",
},
{
"
label
": "
阜新
",
"
value
": "
2109
",
},
{
"
label
": "
辽阳
",
"
value
": "
2110
",
},
{
"
label
": "
盘锦
",
"
value
": "
2111
",
},
{
"
label
": "
铁岭
",
"
value
": "
2112
",
},
{
"
label
": "
朝阳
",
"
value
": "
2113
",
},
{
"
label
": "
葫芦岛
",
"
value
": "
2114
",
},
{
"
label
": "
长春
",
"
value
": "
2201
",
},
{
"
label
": "
吉林
",
"
value
": "
2202
",
},
{
"
label
": "
四平
",
"
value
": "
2203
",
},
{
"
label
": "
辽源
",
"
value
": "
2204
",
},
{
"
label
": "
通化
",
"
value
": "
2205
",
},
{
"
label
": "
白山
",
"
value
": "
2206
",
},
{
"
label
": "
松原
",
"
value
": "
2207
",
},
{
"
label
": "
白城
",
"
value
": "
2208
",
},
{
"
label
": "
延边朝鲜族自治州
",
"
value
": "
2224
",
},
{
"
label
": "
哈尔滨
",
"
value
": "
2301
",
},
{
"
label
": "
齐齐哈尔
",
"
value
": "
2302
",
},
{
"
label
": "
鸡西
",
"
value
": "
2303
",
},
{
"
label
": "
鹤岗
",
"
value
": "
2304
",
},
{
"
label
": "
双鸭山
",
"
value
": "
2305
",
},
{
"
label
": "
大庆
",
"
value
": "
2306
",
},
{
"
label
": "
伊春
",
"
value
": "
2307
",
},
{
"
label
": "
佳木斯
",
"
value
": "
2308
",
},
{
"
label
": "
七台河
",
"
value
": "
2309
",
},
{
"
label
": "
牡丹江
",
"
value
": "
2310
",
},
{
"
label
": "
黑河
",
"
value
": "
2311
",
},
{
"
label
": "
绥化
",
"
value
": "
2312
",
},
{
"
label
": "
大兴安岭地区
",
"
value
": "
2327
",
},
{
"
label
": "
上海
",
"
value
": "
3101
",
},
{
"
label
": "
南京
",
"
value
": "
3201
",
},
{
"
label
": "
无锡
",
"
value
": "
3202
",
},
{
"
label
": "
徐州
",
"
value
": "
3203
",
},
{
"
label
": "
常州
",
"
value
": "
3204
",
},
{
"
label
": "
苏州
",
"
value
": "
3205
",
},
{
"
label
": "
南通
",
"
value
": "
3206
",
},
{
"
label
": "
连云港
",
"
value
": "
3207
",
},
{
"
label
": "
淮安
",
"
value
": "
3208
",
},
{
"
label
": "
盐城
",
"
value
": "
3209
",
},
{
"
label
": "
扬州
",
"
value
": "
3210
",
},
{
"
label
": "
镇江
",
"
value
": "
3211
",
},
{
"
label
": "
泰州
",
"
value
": "
3212
",
},
{
"
label
": "
宿迁
",
"
value
": "
3213
",
},
{
"
label
": "
杭州
",
"
value
": "
3301
",
},
{
"
label
": "
宁波
",
"
value
": "
3302
",
},
{
"
label
": "
温州
",
"
value
": "
3303
",
},
{
"
label
": "
嘉兴
",
"
value
": "
3304
",
},
{
"
label
": "
湖州
",
"
value
": "
3305
",
},
{
"
label
": "
绍兴
",
"
value
": "
3306
",
},
{
"
label
": "
金华
",
"
value
": "
3307
",
},
{
"
label
": "
衢州
",
"
value
": "
3308
",
},
{
"
label
": "
舟山
",
"
value
": "
3309
",
},
{
"
label
": "
台州
",
"
value
": "
3310
",
},
{
"
label
": "
丽水
",
"
value
": "
3311
",
},
{
"
label
": "
合肥
",
"
value
": "
3401
",
},
{
"
label
": "
芜湖
",
"
value
": "
3402
",
},
{
"
label
": "
蚌埠
",
"
value
": "
3403
",
},
{
"
label
": "
淮南
",
"
value
": "
3404
",
},
{
"
label
": "
马鞍山
",
"
value
": "
3405
",
},
{
"
label
": "
淮北
",
"
value
": "
3406
",
},
{
"
label
": "
铜陵
",
"
value
": "
3407
",
},
{
"
label
": "
安庆
",
"
value
": "
3408
",
},
{
"
label
": "
黄山
",
"
value
": "
3410
",
},
{
"
label
": "
滁州
",
"
value
": "
3411
",
},
{
"
label
": "
阜阳
",
"
value
": "
3412
",
},
{
"
label
": "
宿州
",
"
value
": "
3413
",
},
{
"
label
": "
六安
",
"
value
": "
3415
",
},
{
"
label
": "
亳州
",
"
value
": "
3416
",
},
{
"
label
": "
池州
",
"
value
": "
3417
",
},
{
"
label
": "
宣城
",
"
value
": "
3418
",
},
{
"
label
": "
福州
",
"
value
": "
3501
",
},
{
"
label
": "
厦门
",
"
value
": "
3502
",
},
{
"
label
": "
莆田
",
"
value
": "
3503
",
},
{
"
label
": "
三明
",
"
value
": "
3504
",
},
{
"
label
": "
泉州
",
"
value
": "
3505
",
},
{
"
label
": "
漳州
",
"
value
": "
3506
",
},
{
"
label
": "
南平
",
"
value
": "
3507
",
},
{
"
label
": "
龙岩
",
"
value
": "
3508
",
},
{
"
label
": "
宁德
",
"
value
": "
3509
",
},
{
"
label
": "
南昌
",
"
value
": "
3601
",
},
{
"
label
": "
景德镇
",
"
value
": "
3602
",
},
{
"
label
": "
萍乡
",
"
value
": "
3603
",
},
{
"
label
": "
九江
",
"
value
": "
3604
",
},
{
"
label
": "
新余
",
"
value
": "
3605
",
},
{
"
label
": "
鹰潭
",
"
value
": "
3606
",
},
{
"
label
": "
赣州
",
"
value
": "
3607
",
},
{
"
label
": "
吉安
",
"
value
": "
3608
",
},
{
"
label
": "
宜春
",
"
value
": "
3609
",
},
{
"
label
": "
抚州
",
"
value
": "
3610
",
},
{
"
label
": "
上饶
",
"
value
": "
3611
",
},
{
"
label
": "
济南
",
"
value
": "
3701
",
},
{
"
label
": "
青岛
",
"
value
": "
3702
",
},
{
"
label
": "
淄博
",
"
value
": "
3703
",
},
{
"
label
": "
枣庄
",
"
value
": "
3704
",
},
{
"
label
": "
东营
",
"
value
": "
3705
",
},
{
"
label
": "
烟台
",
"
value
": "
3706
",
},
{
"
label
": "
潍坊
",
"
value
": "
3707
",
},
{
"
label
": "
济宁
",
"
value
": "
3708
",
},
{
"
label
": "
泰安
",
"
value
": "
3709
",
},
{
"
label
": "
威海
",
"
value
": "
3710
",
},
{
"
label
": "
日照
",
"
value
": "
3711
",
},
{
"
label
": "
莱芜
",
"
value
": "
3712
",
},
{
"
label
": "
临沂
",
"
value
": "
3713
",
},
{
"
label
": "
德州
",
"
value
": "
3714
",
},
{
"
label
": "
聊城
",
"
value
": "
3715
",
},
{
"
label
": "
滨州
",
"
value
": "
3716
",
},
{
"
label
": "
菏泽
",
"
value
": "
3717
",
},
{
"
label
": "
郑州
",
"
value
": "
4101
",
},
{
"
label
": "
开封
",
"
value
": "
4102
",
},
{
"
label
": "
洛阳
",
"
value
": "
4103
",
},
{
"
label
": "
平顶山
",
"
value
": "
4104
",
},
{
"
label
": "
安阳
",
"
value
": "
4105
",
},
{
"
label
": "
鹤壁
",
"
value
": "
4106
",
},
{
"
label
": "
新乡
",
"
value
": "
4107
",
},
{
"
label
": "
焦作
",
"
value
": "
4108
",
},
{
"
label
": "
濮阳
",
"
value
": "
4109
",
},
{
"
label
": "
许昌
",
"
value
": "
4110
",
},
{
"
label
": "
漯河
",
"
value
": "
4111
",
},
{
"
label
": "
三门峡
",
"
value
": "
4112
",
},
{
"
label
": "
南阳
",
"
value
": "
4113
",
},
{
"
label
": "
商丘
",
"
value
": "
4114
",
},
{
"
label
": "
信阳
",
"
value
": "
4115
",
},
{
"
label
": "
周口
",
"
value
": "
4116
",
},
{
"
label
": "
驻马店
",
"
value
": "
4117
",
},
{
"
label
": "
武汉
",
"
value
": "
4201
",
},
{
"
label
": "
黄石
",
"
value
": "
4202
",
},
{
"
label
": "
十堰
",
"
value
": "
4203
",
},
{
"
label
": "
宜昌
",
"
value
": "
4205
",
},
{
"
label
": "
襄阳
",
"
value
": "
4206
",
},
{
"
label
": "
鄂州
",
"
value
": "
4207
",
},
{
"
label
": "
荆门
",
"
value
": "
4208
",
},
{
"
label
": "
孝感
",
"
value
": "
4209
",
},
{
"
label
": "
荆州
",
"
value
": "
4210
",
},
{
"
label
": "
黄冈
",
"
value
": "
4211
",
},
{
"
label
": "
咸宁
",
"
value
": "
4212
",
},
{
"
label
": "
随州
",
"
value
": "
4213
",
},
{
"
label
": "
恩施土家族苗族自治州
",
"
value
": "
4228
",
},
{
"
label
": "
长沙
",
"
value
": "
4301
",
},
{
"
label
": "
株洲
",
"
value
": "
4302
",
},
{
"
label
": "
湘潭
",
"
value
": "
4303
",
},
{
"
label
": "
衡阳
",
"
value
": "
4304
",
},
{
"
label
": "
邵阳
",
"
value
": "
4305
",
},
{
"
label
": "
岳阳
",
"
value
": "
4306
",
},
{
"
label
": "
常德
",
"
value
": "
4307
",
},
{
"
label
": "
张家界
",
"
value
": "
4308
",
},
{
"
label
": "
益阳
",
"
value
": "
4309
",
},
{
"
label
": "
郴州
",
"
value
": "
4310
",
},
{
"
label
": "
永州
",
"
value
": "
4311
",
},
{
"
label
": "
怀化
",
"
value
": "
4312
",
},
{
"
label
": "
娄底
",
"
value
": "
4313
",
},
{
"
label
": "
湘西土家族苗族自治州
",
"
value
": "
4331
",
},
{
"
label
": "
广州
",
"
value
": "
4401
",
},
{
"
label
": "
韶关
",
"
value
": "
4402
",
},
{
"
label
": "
深圳
",
"
value
": "
4403
",
},
{
"
label
": "
珠海
",
"
value
": "
4404
",
},
{
"
label
": "
汕头
",
"
value
": "
4405
",
},
{
"
label
": "
佛山
",
"
value
": "
4406
",
},
{
"
label
": "
江门
",
"
value
": "
4407
",
},
{
"
label
": "
湛江
",
"
value
": "
4408
",
},
{
"
label
": "
茂名
",
"
value
": "
4409
",
},
{
"
label
": "
肇庆
",
"
value
": "
4412
",
},
{
"
label
": "
惠州
",
"
value
": "
4413
",
},
{
"
label
": "
梅州
",
"
value
": "
4414
",
},
{
"
label
": "
汕尾
",
"
value
": "
4415
",
},
{
"
label
": "
河源
",
"
value
": "
4416
",
},
{
"
label
": "
阳江
",
"
value
": "
4417
",
},
{
"
label
": "
清远
",
"
value
": "
4418
",
},
{
"
label
": "
东莞
",
"
value
": "
4419
",
},
{
"
label
": "
中山
",
"
value
": "
4420
",
},
{
"
label
": "
潮州
",
"
value
": "
4451
",
},
{
"
label
": "
揭阳
",
"
value
": "
4452
",
},
{
"
label
": "
云浮
",
"
value
": "
4453
",
},
{
"
label
": "
南宁
",
"
value
": "
4501
",
},
{
"
label
": "
柳州
",
"
value
": "
4502
",
},
{
"
label
": "
桂林
",
"
value
": "
4503
",
},
{
"
label
": "
梧州
",
"
value
": "
4504
",
},
{
"
label
": "
北海
",
"
value
": "
4505
",
},
{
"
label
": "
防城港
",
"
value
": "
4506
",
},
{
"
label
": "
钦州
",
"
value
": "
4507
",
},
{
"
label
": "
贵港
",
"
value
": "
4508
",
},
{
"
label
": "
玉林
",
"
value
": "
4509
",
},
{
"
label
": "
百色
",
"
value
": "
4510
",
},
{
"
label
": "
贺州
",
"
value
": "
4511
",
},
{
"
label
": "
河池
",
"
value
": "
4512
",
},
{
"
label
": "
来宾
",
"
value
": "
4513
",
},
{
"
label
": "
崇左
",
"
value
": "
4514
",
},
{
"
label
": "
海口
",
"
value
": "
4601
",
},
{
"
label
": "
三亚
",
"
value
": "
4602
",
},
{
"
label
": "
三沙
",
"
value
": "
4603
",
},
{
"
label
": "
儋州
",
"
value
": "
4604
",
},
{
"
label
": "
重庆
",
"
value
": "
5001
",
},
{
"
label
": "
成都
",
"
value
": "
5101
",
},
{
"
label
": "
自贡
",
"
value
": "
5103
",
},
{
"
label
": "
攀枝花
",
"
value
": "
5104
",
},
{
"
label
": "
泸州
",
"
value
": "
5105
",
},
{
"
label
": "
德阳
",
"
value
": "
5106
",
},
{
"
label
": "
绵阳
",
"
value
": "
5107
",
},
{
"
label
": "
广元
",
"
value
": "
5108
",
},
{
"
label
": "
遂宁
",
"
value
": "
5109
",
},
{
"
label
": "
内江
",
"
value
": "
5110
",
},
{
"
label
": "
乐山
",
"
value
": "
5111
",
},
{
"
label
": "
南充
",
"
value
": "
5113
",
},
{
"
label
": "
眉山
",
"
value
": "
5114
",
},
{
"
label
": "
宜宾
",
"
value
": "
5115
",
},
{
"
label
": "
广安
",
"
value
": "
5116
",
},
{
"
label
": "
达州
",
"
value
": "
5117
",
},
{
"
label
": "
雅安
",
"
value
": "
5118
",
},
{
"
label
": "
巴中
",
"
value
": "
5119
",
},
{
"
label
": "
资阳
",
"
value
": "
5120
",
},
{
"
label
": "
阿坝藏族羌族自治州
",
"
value
": "
5132
",
},
{
"
label
": "
甘孜藏族自治州
",
"
value
": "
5133
",
},
{
"
label
": "
凉山彝族自治州
",
"
value
": "
5134
",
},
{
"
label
": "
贵阳
",
"
value
": "
5201
",
},
{
"
label
": "
六盘水
",
"
value
": "
5202
",
},
{
"
label
": "
遵义
",
"
value
": "
5203
",
},
{
"
label
": "
安顺
",
"
value
": "
5204
",
},
{
"
label
": "
毕节
",
"
value
": "
5205
",
},
{
"
label
": "
铜仁
",
"
value
": "
5206
",
},
{
"
label
": "
黔西南布依族苗族自治州
",
"
value
": "
5223
",
},
{
"
label
": "
黔东南苗族侗族自治州
",
"
value
": "
5226
",
},
{
"
label
": "
黔南布依族苗族自治州
",
"
value
": "
5227
",
},
{
"
label
": "
昆明
",
"
value
": "
5301
",
},
{
"
label
": "
曲靖
",
"
value
": "
5303
",
},
{
"
label
": "
玉溪
",
"
value
": "
5304
",
},
{
"
label
": "
保山
",
"
value
": "
5305
",
},
{
"
label
": "
昭通
",
"
value
": "
5306
",
},
{
"
label
": "
丽江
",
"
value
": "
5307
",
},
{
"
label
": "
普洱
",
"
value
": "
5308
",
},
{
"
label
": "
临沧
",
"
value
": "
5309
",
},
{
"
label
": "
楚雄彝族自治州
",
"
value
": "
5323
",
},
{
"
label
": "
红河哈尼族彝族自治州
",
"
value
": "
5325
",
},
{
"
label
": "
文山壮族苗族自治州
",
"
value
": "
5326
",
},
{
"
label
": "
西双版纳傣族自治州
",
"
value
": "
5328
",
},
{
"
label
": "
大理白族自治州
",
"
value
": "
5329
",
},
{
"
label
": "
德宏傣族景颇族自治州
",
"
value
": "
5331
",
},
{
"
label
": "
怒江傈僳族自治州
",
"
value
": "
5333
",
},
{
"
label
": "
迪庆藏族自治州
",
"
value
": "
5334
",
},
{
"
label
": "
拉萨
",
"
value
": "
5401
",
},
{
"
label
": "
日喀则
",
"
value
": "
5402
",
},
{
"
label
": "
昌都
",
"
value
": "
5403
",
},
{
"
label
": "
林芝
",
"
value
": "
5404
",
},
{
"
label
": "
山南
",
"
value
": "
5405
",
},
{
"
label
": "
那曲地区
",
"
value
": "
5424
",
},
{
"
label
": "
阿里地区
",
"
value
": "
5425
",
},
{
"
label
": "
西安
",
"
value
": "
6101
",
},
{
"
label
": "
铜川
",
"
value
": "
6102
",
},
{
"
label
": "
宝鸡
",
"
value
": "
6103
",
},
{
"
label
": "
咸阳
",
"
value
": "
6104
",
},
{
"
label
": "
渭南
",
"
value
": "
6105
",
},
{
"
label
": "
延安
",
"
value
": "
6106
",
},
{
"
label
": "
汉中
",
"
value
": "
6107
",
},
{
"
label
": "
榆林
",
"
value
": "
6108
",
},
{
"
label
": "
安康
",
"
value
": "
6109
",
},
{
"
label
": "
商洛
",
"
value
": "
6110
",
},
{
"
label
": "
兰州
",
"
value
": "
6201
",
},
{
"
label
": "
嘉峪关
",
"
value
": "
6202
",
},
{
"
label
": "
金昌
",
"
value
": "
6203
",
},
{
"
label
": "
白银
",
"
value
": "
6204
",
},
{
"
label
": "
天水
",
"
value
": "
6205
",
},
{
"
label
": "
武威
",
"
value
": "
6206
",
},
{
"
label
": "
张掖
",
"
value
": "
6207
",
},
{
"
label
": "
平凉
",
"
value
": "
6208
",
},
{
"
label
": "
酒泉
",
"
value
": "
6209
",
},
{
"
label
": "
庆阳
",
"
value
": "
6210
",
},
{
"
label
": "
定西
",
"
value
": "
6211
",
},
{
"
label
": "
陇南
",
"
value
": "
6212
",
},
{
"
label
": "
临夏回族自治州
",
"
value
": "
6229
",
},
{
"
label
": "
甘南藏族自治州
",
"
value
": "
6230
",
},
{
"
label
": "
西宁
",
"
value
": "
6301
",
},
{
"
label
": "
海东
",
"
value
": "
6302
",
},
{
"
label
": "
海北藏族自治州
",
"
value
": "
6322
",
},
{
"
label
": "
黄南藏族自治州
",
"
value
": "
6323
",
},
{
"
label
": "
海南藏族自治州
",
"
value
": "
6325
",
},
{
"
label
": "
果洛藏族自治州
",
"
value
": "
6326
",
},
{
"
label
": "
玉树藏族自治州
",
"
value
": "
6327
",
},
{
"
label
": "
海西蒙古族藏族自治州
",
"
value
": "
6328
",
},
{
"
label
": "
银川
",
"
value
": "
6401
",
},
{
"
label
": "
石嘴山
",
"
value
": "
6402
",
},
{
"
label
": "
吴忠
",
"
value
": "
6403
",
},
{
"
label
": "
固原
",
"
value
": "
6404
",
},
{
"
label
": "
中卫
",
"
value
": "
6405
",
},
{
"
label
": "
乌鲁木齐
",
"
value
": "
6501
",
},
{
"
label
": "
克拉玛依
",
"
value
": "
6502
",
},
{
"
label
": "
吐鲁番
",
"
value
": "
6504
",
},
{
"
label
": "
哈密
",
"
value
": "
6505
",
},
{
"
label
": "
昌吉回族自治州
",
"
value
": "
6523
",
},
{
"
label
": "
博尔塔拉蒙古自治州
",
"
value
": "
6527
",
},
{
"
label
": "
巴音郭楞蒙古自治州
",
"
value
": "
6528
",
},
{
"
label
": "
阿克苏地区
",
"
value
": "
6529
",
},
{
"
label
": "
克孜勒苏柯尔克孜自治州
",
"
value
": "
6530
",
},
{
"
label
": "
喀什地区
",
"
value
": "
6531
",
},
{
"
label
": "
和田地区
",
"
value
": "
6532
",
},
{
"
label
": "
伊犁哈萨克自治州
",
"
value
": "
6540
",
},
{
"
label
": "
塔城地区
",
"
value
": "
6542
",
},
{
"
label
": "
阿勒泰地区
",
"
value
": "
6543
",
},
{
"
label
": "
台北
",
"
value
": "
6601
",
},
{
"
label
": "
高雄
",
"
value
": "
6602
",
},
{
"
label
": "
基隆
",
"
value
": "
6603
",
},
{
"
label
": "
台中
",
"
value
": "
6604
",
},
{
"
label
": "
台南
",
"
value
": "
6605
",
},
{
"
label
": "
新竹
",
"
value
": "
6606
",
},
{
"
label
": "
嘉义
",
"
value
": "
6607
",
},
{
"
label
": "
宜兰
",
"
value
": "
6608
",
},
{
"
label
": "
桃园
",
"
value
": "
6609
",
},
{
"
label
": "
苗栗
",
"
value
": "
6610
",
},
{
"
label
": "
彰化
",
"
value
": "
6611
",
},
{
"
label
": "
南投
",
"
value
": "
6612
",
},
{
"
label
": "
云林
",
"
value
": "
6613
",
},
{
"
label
": "
屏东
",
"
value
": "
6614
",
},
{
"
label
": "
台东
",
"
value
": "
6615
",
},
{
"
label
": "
花莲
",
"
value
": "
6616
",
},
{
"
label
": "
澎湖
",
"
value
": "
6617
",
},
{
"
label
": "
香港
",
"
value
": "
6701
",
},
{
"
label
": "
澳门
",
"
value
": "
6801
",
},
]
"""
;
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/enums/ResumeEnum.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
enums
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
lombok.NoArgsConstructor
;
import
java.util.ArrayList
;
import
java.util.EnumSet
;
import
java.util.List
;
/**
* @author jiangxiaoge
* @description 简历相关
* @data 2024/12/16
**/
public
class
ResumeEnum
{
@AllArgsConstructor
@NoArgsConstructor
@Getter
public
enum
ResumeExtra
{
ZYJN
(
0
,
"专业技能"
),
YD
(
1
,
"个人优势"
),
HJXX
(
2
,
"获奖信息"
),
XQAH
(
3
,
"兴趣爱好"
);
private
int
code
;
private
String
name
;
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
public
enum
ResumeOptimizationStatus
{
NOT_OPTIMIZED
(
0
,
"未优化"
),
OPTIMIZATION_FAILED
(
1
,
"优化失败"
),
OPTIMIZATION_SUCCESSFUL
(
2
,
"优化成功"
),
OPTIMIZING
(
3
,
"优化中"
);
private
int
code
;
private
String
description
;
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
public
enum
ResumeModel
{
CUSTOM
(
0
,
"自定义模块"
,
"custom"
,
9
),
CLUB
(
1
,
"校园经历"
,
"clubs"
,
7
),
//社团经历-校园经历
EDU
(
2
,
"教育经历"
,
"edus"
,
0
),
HOBBLES
(
3
,
"兴趣爱好"
,
"hobbles"
,
6
),
INTERNSHIP
(
4
,
"实习经历"
,
"internships"
,
8
),
WORK_EXP
(
5
,
"工作经历"
,
"workExps"
,
1
),
PROJECT
(
6
,
"项目经历"
,
"projects"
,
2
),
SKILL
(
7
,
"专业技能"
,
"skill"
,
3
),
ADVANTAGE
(
8
,
"个人优势"
,
"advantage"
,
4
),
AWARDS
(
9
,
"荣誉奖项"
,
"awards"
,
5
),
//获奖信息-荣誉奖项
BASE
(
10
,
"基本信息"
,
"base"
,
99
),
;
private
int
code
;
private
String
name
;
private
String
webCode
;
private
int
sort
;
public
static
String
getWebCodeByCode
(
Integer
code
){
for
(
ResumeModel
thisEnum
:
EnumSet
.
allOf
(
ResumeModel
.
class
))
{
if
(
thisEnum
.
code
==
code
){
return
thisEnum
.
webCode
;
}
}
return
null
;
}
public
static
List
<
Integer
>
getResumeModel
(){
List
<
Integer
>
codeList
=
new
ArrayList
<>();
for
(
ResumeModel
model
:
EnumSet
.
allOf
(
ResumeModel
.
class
))
{
if
(
model
!=
ResumeModel
.
CUSTOM
&&
model
!=
ResumeModel
.
BASE
){
codeList
.
add
(
model
.
getCode
());
}
}
return
codeList
;
}
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/factory/RegexPatternPoolFactory.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
factory
;
import
cn.hutool.core.lang.PatternPool
;
import
org.dromara.common.core.constant.RegexConstants
;
import
java.util.regex.Pattern
;
/**
* 正则表达式模式池工厂
* <p>初始化的时候将正则表达式加入缓存池当中</p>
* <p>提高正则表达式的性能,避免重复编译相同的正则表达式</p>
*
* @author 21001
*/
public
class
RegexPatternPoolFactory
extends
PatternPool
{
/**
* 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
*/
public
static
final
Pattern
DICTIONARY_TYPE
=
get
(
RegexConstants
.
DICTIONARY_TYPE
);
/**
* 身份证号码(后6位)
*/
public
static
final
Pattern
ID_CARD_LAST_6
=
get
(
RegexConstants
.
ID_CARD_LAST_6
);
/**
* QQ号码
*/
public
static
final
Pattern
QQ_NUMBER
=
get
(
RegexConstants
.
QQ_NUMBER
);
/**
* 邮政编码
*/
public
static
final
Pattern
POSTAL_CODE
=
get
(
RegexConstants
.
POSTAL_CODE
);
/**
* 注册账号
*/
public
static
final
Pattern
ACCOUNT
=
get
(
RegexConstants
.
ACCOUNT
);
/**
* 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
*/
public
static
final
Pattern
PASSWORD
=
get
(
RegexConstants
.
PASSWORD
);
/**
* 通用状态(0表示正常,1表示停用)
*/
public
static
final
Pattern
STATUS
=
get
(
RegexConstants
.
STATUS
);
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/utils/ip/RegionUtils.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
utils
.
ip
;
import
cn.hutool.core.io.FileUtil
;
import
cn.hutool.core.io.resource.ClassPathResource
;
import
cn.hutool.core.util.ObjectUtil
;
import
org.dromara.common.core.exception.ServiceException
;
import
org.dromara.common.core.utils.file.FileUtils
;
import
lombok.extern.slf4j.Slf4j
;
import
org.lionsoul.ip2region.xdb.Searcher
;
import
java.io.File
;
/**
* 根据ip地址定位工具类,离线方式
* 参考地址:<a href="https://gitee.com/lionsoul/ip2region/tree/master/binding/java">集成 ip2region 实现离线IP地址定位库</a>
*
* @author lishuyan
*/
@Slf4j
public
class
RegionUtils
{
private
static
final
Searcher
SEARCHER
;
static
{
String
fileName
=
"/ip2region.xdb"
;
File
existFile
=
FileUtils
.
file
(
FileUtil
.
getTmpDir
()
+
FileUtil
.
FILE_SEPARATOR
+
fileName
);
if
(!
FileUtils
.
exist
(
existFile
))
{
ClassPathResource
fileStream
=
new
ClassPathResource
(
fileName
);
if
(
ObjectUtil
.
isEmpty
(
fileStream
.
getStream
()))
{
throw
new
ServiceException
(
"RegionUtils初始化失败,原因:IP地址库数据不存在!"
);
}
FileUtils
.
writeFromStream
(
fileStream
.
getStream
(),
existFile
);
}
String
dbPath
=
existFile
.
getPath
();
// 1、从 dbPath 加载整个 xdb 到内存。
byte
[]
cBuff
;
try
{
cBuff
=
Searcher
.
loadContentFromFile
(
dbPath
);
}
catch
(
Exception
e
)
{
throw
new
ServiceException
(
"RegionUtils初始化失败,原因:从ip2region.xdb文件加载内容失败!"
+
e
.
getMessage
());
}
// 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
try
{
SEARCHER
=
Searcher
.
newWithBuffer
(
cBuff
);
}
catch
(
Exception
e
)
{
throw
new
ServiceException
(
"RegionUtils初始化失败,原因:"
+
e
.
getMessage
());
}
}
/**
* 根据IP地址离线获取城市
*/
public
static
String
getCityInfo
(
String
ip
)
{
try
{
ip
=
ip
.
trim
();
// 3、执行查询
String
region
=
SEARCHER
.
search
(
ip
);
return
region
.
replace
(
"0|"
,
""
).
replace
(
"|0"
,
""
);
}
catch
(
Exception
e
)
{
log
.
error
(
"IP地址离线获取城市异常 {}"
,
ip
);
return
"未知"
;
}
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/utils/reflect/ReflectUtils.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
utils
.
reflect
;
import
cn.hutool.core.util.ReflectUtil
;
import
org.dromara.common.core.utils.StringUtils
;
import
lombok.AccessLevel
;
import
lombok.NoArgsConstructor
;
import
java.lang.reflect.Method
;
/**
* 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
*
* @author Lion Li
*/
@SuppressWarnings
(
"rawtypes"
)
@NoArgsConstructor
(
access
=
AccessLevel
.
PRIVATE
)
public
class
ReflectUtils
extends
ReflectUtil
{
private
static
final
String
SETTER_PREFIX
=
"set"
;
private
static
final
String
GETTER_PREFIX
=
"get"
;
/**
* 调用Getter方法.
* 支持多级,如:对象名.对象名.方法
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
E
>
E
invokeGetter
(
Object
obj
,
String
propertyName
)
{
Object
object
=
obj
;
for
(
String
name
:
StringUtils
.
split
(
propertyName
,
"."
))
{
String
getterMethodName
=
GETTER_PREFIX
+
StringUtils
.
capitalize
(
name
);
object
=
invoke
(
object
,
getterMethodName
);
}
return
(
E
)
object
;
}
/**
* 调用Setter方法, 仅匹配方法名。
* 支持多级,如:对象名.对象名.方法
*/
public
static
<
E
>
void
invokeSetter
(
Object
obj
,
String
propertyName
,
E
value
)
{
Object
object
=
obj
;
String
[]
names
=
StringUtils
.
split
(
propertyName
,
"."
);
for
(
int
i
=
0
;
i
<
names
.
length
;
i
++)
{
if
(
i
<
names
.
length
-
1
)
{
String
getterMethodName
=
GETTER_PREFIX
+
StringUtils
.
capitalize
(
names
[
i
]);
object
=
invoke
(
object
,
getterMethodName
);
}
else
{
String
setterMethodName
=
SETTER_PREFIX
+
StringUtils
.
capitalize
(
names
[
i
]);
Method
method
=
getMethodByName
(
object
.
getClass
(),
setterMethodName
);
invoke
(
object
,
method
,
value
);
}
}
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexUtils.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
utils
.
regex
;
import
cn.hutool.core.util.ReUtil
;
import
org.dromara.common.core.constant.RegexConstants
;
/**
* 正则相关工具类
*
* @author Feng
*/
public
final
class
RegexUtils
extends
ReUtil
{
/**
* 从输入字符串中提取匹配的部分,如果没有匹配则返回默认值
*
* @param input 要提取的输入字符串
* @param regex 用于匹配的正则表达式,可以使用 {@link RegexConstants} 中定义的常量
* @param defaultInput 如果没有匹配时返回的默认值
* @return 如果找到匹配的部分,则返回匹配的部分,否则返回默认值
*/
public
static
String
extractFromString
(
String
input
,
String
regex
,
String
defaultInput
)
{
try
{
String
str
=
ReUtil
.
get
(
regex
,
input
,
1
);
return
str
==
null
?
defaultInput
:
str
;
}
catch
(
Exception
e
)
{
return
defaultInput
;
}
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexValidator.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
core
.
utils
.
regex
;
import
cn.hutool.core.exceptions.ValidateException
;
import
cn.hutool.core.lang.Validator
;
import
org.dromara.common.core.factory.RegexPatternPoolFactory
;
import
java.util.regex.Pattern
;
/**
* 正则字段校验器
* 主要验证字段非空、是否为满足指定格式等
*
* @author Feng
*/
public
class
RegexValidator
extends
Validator
{
/**
* 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
*/
public
static
final
Pattern
DICTIONARY_TYPE
=
RegexPatternPoolFactory
.
DICTIONARY_TYPE
;
/**
* 身份证号码(后6位)
*/
public
static
final
Pattern
ID_CARD_LAST_6
=
RegexPatternPoolFactory
.
ID_CARD_LAST_6
;
/**
* QQ号码
*/
public
static
final
Pattern
QQ_NUMBER
=
RegexPatternPoolFactory
.
QQ_NUMBER
;
/**
* 邮政编码
*/
public
static
final
Pattern
POSTAL_CODE
=
RegexPatternPoolFactory
.
POSTAL_CODE
;
/**
* 注册账号
*/
public
static
final
Pattern
ACCOUNT
=
RegexPatternPoolFactory
.
ACCOUNT
;
/**
* 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
*/
public
static
final
Pattern
PASSWORD
=
RegexPatternPoolFactory
.
PASSWORD
;
/**
* 通用状态(0表示正常,1表示停用)
*/
public
static
final
Pattern
STATUS
=
RegexPatternPoolFactory
.
STATUS
;
/**
* 检查输入的账号是否匹配预定义的规则
*
* @param value 要验证的账号
* @return 如果账号符合规则,返回 true;否则,返回 false。
*/
public
static
boolean
isAccount
(
CharSequence
value
)
{
return
isMatchRegex
(
ACCOUNT
,
value
);
}
/**
* 验证输入的账号是否符合规则,如果不符合,则抛出 ValidateException 异常
*
* @param value 要验证的账号
* @param errorMsg 验证失败时抛出的异常消息
* @param <T> CharSequence 的子类型
* @return 如果验证通过,返回输入的账号
* @throws ValidateException 如果验证失败
*/
public
static
<
T
extends
CharSequence
>
T
validateAccount
(
T
value
,
String
errorMsg
)
throws
ValidateException
{
if
(!
isAccount
(
value
))
{
throw
new
ValidateException
(
errorMsg
);
}
return
value
;
}
/**
* 检查输入的状态是否匹配预定义的规则
*
* @param value 要验证的状态
* @return 如果状态符合规则,返回 true;否则,返回 false。
*/
public
static
boolean
isStatus
(
CharSequence
value
)
{
return
isMatchRegex
(
STATUS
,
value
);
}
/**
* 验证输入的状态是否符合规则,如果不符合,则抛出 ValidateException 异常
*
* @param value 要验证的状态
* @param errorMsg 验证失败时抛出的异常消息
* @param <T> CharSequence 的子类型
* @return 如果验证通过,返回输入的状态
* @throws ValidateException 如果验证失败
*/
public
static
<
T
extends
CharSequence
>
T
validateStatus
(
T
value
,
String
errorMsg
)
throws
ValidateException
{
if
(!
isStatus
(
value
))
{
throw
new
ValidateException
(
errorMsg
);
}
return
value
;
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-dubbo/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
0 → 100644
View file @
613f3bfd
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
apache
.
dubbo
.
metadata
.
store
.
redis
;
import
org.apache.commons.pool2.impl.GenericObjectPoolConfig
;
import
org.apache.dubbo.common.URL
;
import
org.apache.dubbo.common.config.configcenter.ConfigItem
;
import
org.apache.dubbo.common.logger.ErrorTypeAwareLogger
;
import
org.apache.dubbo.common.logger.LoggerFactory
;
import
org.apache.dubbo.common.utils.*
;
import
org.apache.dubbo.metadata.MappingChangedEvent
;
import
org.apache.dubbo.metadata.MappingListener
;
import
org.apache.dubbo.metadata.MetadataInfo
;
import
org.apache.dubbo.metadata.ServiceNameMapping
;
import
org.apache.dubbo.metadata.report.identifier.*
;
import
org.apache.dubbo.metadata.report.support.AbstractMetadataReport
;
import
org.apache.dubbo.rpc.RpcException
;
import
redis.clients.jedis.*
;
import
redis.clients.jedis.params.SetParams
;
import
redis.clients.jedis.util.JedisClusterCRC16
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
import
static
org
.
apache
.
dubbo
.
common
.
constants
.
CommonConstants
.*;
import
static
org
.
apache
.
dubbo
.
common
.
constants
.
LoggerCodeConstants
.
TRANSPORT_FAILED_RESPONSE
;
import
static
org
.
apache
.
dubbo
.
metadata
.
MetadataConstants
.
META_DATA_STORE_TAG
;
import
static
org
.
apache
.
dubbo
.
metadata
.
ServiceNameMapping
.
DEFAULT_MAPPING_GROUP
;
import
static
org
.
apache
.
dubbo
.
metadata
.
ServiceNameMapping
.
getAppNames
;
import
static
org
.
apache
.
dubbo
.
metadata
.
report
.
support
.
Constants
.
DEFAULT_METADATA_REPORT_CYCLE_REPORT
;
/**
* RedisMetadataReport
*/
public
class
RedisMetadataReport
extends
AbstractMetadataReport
{
private
static
final
String
REDIS_DATABASE_KEY
=
"database"
;
private
static
final
ErrorTypeAwareLogger
logger
=
LoggerFactory
.
getErrorTypeAwareLogger
(
RedisMetadataReport
.
class
);
// protected , for test
protected
JedisPool
pool
;
private
Set
<
HostAndPort
>
jedisClusterNodes
;
private
int
timeout
;
private
String
password
;
private
final
String
root
;
private
final
ConcurrentHashMap
<
String
,
MappingDataListener
>
mappingDataListenerMap
=
new
ConcurrentHashMap
<>();
private
SetParams
jedisParams
=
SetParams
.
setParams
();
public
RedisMetadataReport
(
URL
url
)
{
super
(
url
);
timeout
=
url
.
getParameter
(
TIMEOUT_KEY
,
DEFAULT_TIMEOUT
);
password
=
url
.
getPassword
();
this
.
root
=
url
.
getGroup
(
DEFAULT_ROOT
);
if
(
url
.
getParameter
(
CYCLE_REPORT_KEY
,
DEFAULT_METADATA_REPORT_CYCLE_REPORT
))
{
// ttl default is twice the cycle-report time
jedisParams
.
ex
(
ONE_DAY_IN_MILLISECONDS
*
2
);
}
if
(
url
.
getParameter
(
CLUSTER_KEY
,
false
))
{
jedisClusterNodes
=
new
HashSet
<>();
List
<
URL
>
urls
=
url
.
getBackupUrls
();
for
(
URL
tmpUrl
:
urls
)
{
jedisClusterNodes
.
add
(
new
HostAndPort
(
tmpUrl
.
getHost
(),
tmpUrl
.
getPort
()));
}
}
else
{
int
database
=
url
.
getParameter
(
REDIS_DATABASE_KEY
,
0
);
pool
=
new
JedisPool
(
new
JedisPoolConfig
(),
url
.
getHost
(),
url
.
getPort
(),
timeout
,
password
,
database
);
}
}
@Override
protected
void
doStoreProviderMetadata
(
MetadataIdentifier
providerMetadataIdentifier
,
String
serviceDefinitions
)
{
this
.
storeMetadata
(
providerMetadataIdentifier
,
serviceDefinitions
);
}
@Override
protected
void
doStoreConsumerMetadata
(
MetadataIdentifier
consumerMetadataIdentifier
,
String
value
)
{
this
.
storeMetadata
(
consumerMetadataIdentifier
,
value
);
}
@Override
protected
void
doSaveMetadata
(
ServiceMetadataIdentifier
serviceMetadataIdentifier
,
URL
url
)
{
this
.
storeMetadata
(
serviceMetadataIdentifier
,
URL
.
encode
(
url
.
toFullString
()));
}
@Override
protected
void
doRemoveMetadata
(
ServiceMetadataIdentifier
serviceMetadataIdentifier
)
{
this
.
deleteMetadata
(
serviceMetadataIdentifier
);
}
@Override
protected
List
<
String
>
doGetExportedURLs
(
ServiceMetadataIdentifier
metadataIdentifier
)
{
String
content
=
getMetadata
(
metadataIdentifier
);
if
(
StringUtils
.
isEmpty
(
content
))
{
return
Collections
.
emptyList
();
}
return
new
ArrayList
<>(
Arrays
.
asList
(
URL
.
decode
(
content
)));
}
@Override
protected
void
doSaveSubscriberData
(
SubscriberMetadataIdentifier
subscriberMetadataIdentifier
,
String
urlListStr
)
{
this
.
storeMetadata
(
subscriberMetadataIdentifier
,
urlListStr
);
}
@Override
protected
String
doGetSubscribedURLs
(
SubscriberMetadataIdentifier
subscriberMetadataIdentifier
)
{
return
this
.
getMetadata
(
subscriberMetadataIdentifier
);
}
@Override
public
String
getServiceDefinition
(
MetadataIdentifier
metadataIdentifier
)
{
return
this
.
getMetadata
(
metadataIdentifier
);
}
private
void
storeMetadata
(
BaseMetadataIdentifier
metadataIdentifier
,
String
v
)
{
if
(
pool
!=
null
)
{
storeMetadataStandalone
(
metadataIdentifier
,
v
);
}
else
{
storeMetadataInCluster
(
metadataIdentifier
,
v
);
}
}
private
void
storeMetadataInCluster
(
BaseMetadataIdentifier
metadataIdentifier
,
String
v
)
{
try
(
JedisCluster
jedisCluster
=
new
JedisCluster
(
jedisClusterNodes
,
timeout
,
timeout
,
2
,
password
,
new
GenericObjectPoolConfig
<>()))
{
jedisCluster
.
set
(
metadataIdentifier
.
getIdentifierKey
()
+
META_DATA_STORE_TAG
,
v
,
jedisParams
);
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to put "
+
metadataIdentifier
+
" to redis cluster "
+
v
+
", cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
private
void
storeMetadataStandalone
(
BaseMetadataIdentifier
metadataIdentifier
,
String
v
)
{
try
(
Jedis
jedis
=
pool
.
getResource
())
{
jedis
.
set
(
metadataIdentifier
.
getUniqueKey
(
KeyTypeEnum
.
UNIQUE_KEY
),
v
,
jedisParams
);
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to put "
+
metadataIdentifier
+
" to redis "
+
v
+
", cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
private
void
deleteMetadata
(
BaseMetadataIdentifier
metadataIdentifier
)
{
if
(
pool
!=
null
)
{
deleteMetadataStandalone
(
metadataIdentifier
);
}
else
{
deleteMetadataInCluster
(
metadataIdentifier
);
}
}
private
void
deleteMetadataInCluster
(
BaseMetadataIdentifier
metadataIdentifier
)
{
try
(
JedisCluster
jedisCluster
=
new
JedisCluster
(
jedisClusterNodes
,
timeout
,
timeout
,
2
,
password
,
new
GenericObjectPoolConfig
<>()))
{
jedisCluster
.
del
(
metadataIdentifier
.
getIdentifierKey
()
+
META_DATA_STORE_TAG
);
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to delete "
+
metadataIdentifier
+
" from redis cluster , cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
private
void
deleteMetadataStandalone
(
BaseMetadataIdentifier
metadataIdentifier
)
{
try
(
Jedis
jedis
=
pool
.
getResource
())
{
jedis
.
del
(
metadataIdentifier
.
getUniqueKey
(
KeyTypeEnum
.
UNIQUE_KEY
));
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to delete "
+
metadataIdentifier
+
" from redis , cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
private
String
getMetadata
(
BaseMetadataIdentifier
metadataIdentifier
)
{
if
(
pool
!=
null
)
{
return
getMetadataStandalone
(
metadataIdentifier
);
}
else
{
return
getMetadataInCluster
(
metadataIdentifier
);
}
}
private
String
getMetadataInCluster
(
BaseMetadataIdentifier
metadataIdentifier
)
{
try
(
JedisCluster
jedisCluster
=
new
JedisCluster
(
jedisClusterNodes
,
timeout
,
timeout
,
2
,
password
,
new
GenericObjectPoolConfig
<>()))
{
return
jedisCluster
.
get
(
metadataIdentifier
.
getIdentifierKey
()
+
META_DATA_STORE_TAG
);
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to get "
+
metadataIdentifier
+
" from redis cluster , cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
private
String
getMetadataStandalone
(
BaseMetadataIdentifier
metadataIdentifier
)
{
try
(
Jedis
jedis
=
pool
.
getResource
())
{
return
jedis
.
get
(
metadataIdentifier
.
getUniqueKey
(
KeyTypeEnum
.
UNIQUE_KEY
));
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to get "
+
metadataIdentifier
+
" from redis , cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
/**
* Store class and application names using Redis hashes
* key: default 'dubbo:mapping'
* field: class (serviceInterface)
* value: application_names
* @param serviceInterface field(class)
* @param defaultMappingGroup {@link ServiceNameMapping#DEFAULT_MAPPING_GROUP}
* @param newConfigContent new application_names
* @param ticket previous application_names
* @return
*/
@Override
public
boolean
registerServiceAppMapping
(
String
serviceInterface
,
String
defaultMappingGroup
,
String
newConfigContent
,
Object
ticket
)
{
try
{
if
(
null
!=
ticket
&&
!(
ticket
instanceof
String
))
{
throw
new
IllegalArgumentException
(
"redis publishConfigCas requires stat type ticket"
);
}
String
pathKey
=
buildMappingKey
(
defaultMappingGroup
);
return
storeMapping
(
pathKey
,
serviceInterface
,
newConfigContent
,
(
String
)
ticket
);
}
catch
(
Exception
e
)
{
logger
.
warn
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
"redis publishConfigCas failed."
,
e
);
return
false
;
}
}
private
boolean
storeMapping
(
String
key
,
String
field
,
String
value
,
String
ticket
)
{
if
(
pool
!=
null
)
{
return
storeMappingStandalone
(
key
,
field
,
value
,
ticket
);
}
else
{
return
storeMappingInCluster
(
key
,
field
,
value
,
ticket
);
}
}
/**
* use 'watch' to implement cas.
* Find information about slot distribution by key.
*/
private
boolean
storeMappingInCluster
(
String
key
,
String
field
,
String
value
,
String
ticket
)
{
try
(
JedisCluster
jedisCluster
=
new
JedisCluster
(
jedisClusterNodes
,
timeout
,
timeout
,
2
,
password
,
new
GenericObjectPoolConfig
<>()))
{
Jedis
jedis
=
new
Jedis
(
jedisCluster
.
getConnectionFromSlot
(
JedisClusterCRC16
.
getSlot
(
key
)));
jedis
.
watch
(
key
);
String
oldValue
=
jedis
.
hget
(
key
,
field
);
if
(
null
==
oldValue
||
null
==
ticket
||
oldValue
.
equals
(
ticket
))
{
Transaction
transaction
=
jedis
.
multi
();
transaction
.
hset
(
key
,
field
,
value
);
List
<
Object
>
result
=
transaction
.
exec
();
if
(
null
!=
result
)
{
jedisCluster
.
publish
(
buildPubSubKey
(),
field
);
return
true
;
}
}
else
{
jedis
.
unwatch
();
}
jedis
.
close
();
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to put "
+
key
+
":"
+
field
+
" to redis "
+
value
+
", cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
return
false
;
}
/**
* use 'watch' to implement cas.
* Find information about slot distribution by key.
*/
private
boolean
storeMappingStandalone
(
String
key
,
String
field
,
String
value
,
String
ticket
)
{
try
(
Jedis
jedis
=
pool
.
getResource
())
{
jedis
.
watch
(
key
);
String
oldValue
=
jedis
.
hget
(
key
,
field
);
if
(
null
==
oldValue
||
null
==
ticket
||
oldValue
.
equals
(
ticket
))
{
Transaction
transaction
=
jedis
.
multi
();
transaction
.
hset
(
key
,
field
,
value
);
List
<
Object
>
result
=
transaction
.
exec
();
if
(
null
!=
result
)
{
jedis
.
publish
(
buildPubSubKey
(),
field
);
return
true
;
}
}
jedis
.
unwatch
();
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to put "
+
key
+
":"
+
field
+
" to redis "
+
value
+
", cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
return
false
;
}
/**
* build mapping key
* @param defaultMappingGroup {@link ServiceNameMapping#DEFAULT_MAPPING_GROUP}
* @return
*/
private
String
buildMappingKey
(
String
defaultMappingGroup
)
{
return
this
.
root
+
GROUP_CHAR_SEPARATOR
+
defaultMappingGroup
;
}
/**
* build pub/sub key
*/
private
String
buildPubSubKey
()
{
return
buildMappingKey
(
DEFAULT_MAPPING_GROUP
)
+
GROUP_CHAR_SEPARATOR
+
QUEUES_KEY
;
}
/**
* get content and use content to complete cas
* @param serviceKey class
* @param group {@link ServiceNameMapping#DEFAULT_MAPPING_GROUP}
*/
@Override
public
ConfigItem
getConfigItem
(
String
serviceKey
,
String
group
)
{
String
key
=
buildMappingKey
(
group
);
String
content
=
getMappingData
(
key
,
serviceKey
);
return
new
ConfigItem
(
content
,
content
);
}
/**
* get current application_names
*/
private
String
getMappingData
(
String
key
,
String
field
)
{
if
(
pool
!=
null
)
{
return
getMappingDataStandalone
(
key
,
field
);
}
else
{
return
getMappingDataInCluster
(
key
,
field
);
}
}
private
String
getMappingDataInCluster
(
String
key
,
String
field
)
{
try
(
JedisCluster
jedisCluster
=
new
JedisCluster
(
jedisClusterNodes
,
timeout
,
timeout
,
2
,
password
,
new
GenericObjectPoolConfig
<>()))
{
return
jedisCluster
.
hget
(
key
,
field
);
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to get "
+
key
+
":"
+
field
+
" from redis cluster , cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
private
String
getMappingDataStandalone
(
String
key
,
String
field
)
{
try
(
Jedis
jedis
=
pool
.
getResource
())
{
return
jedis
.
hget
(
key
,
field
);
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to get "
+
key
+
":"
+
field
+
" from redis , cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
/**
* remove listener. If have no listener,thread will dead
*/
@Override
public
void
removeServiceAppMappingListener
(
String
serviceKey
,
MappingListener
listener
)
{
MappingDataListener
mappingDataListener
=
mappingDataListenerMap
.
get
(
buildPubSubKey
());
if
(
null
!=
mappingDataListener
)
{
NotifySub
notifySub
=
mappingDataListener
.
getNotifySub
();
notifySub
.
removeListener
(
serviceKey
,
listener
);
if
(
notifySub
.
isEmpty
())
{
mappingDataListener
.
shutdown
();
}
}
}
/**
* Start a thread and subscribe to {@link this#buildPubSubKey()}.
* Notify {@link MappingListener} if there is a change in the 'application_names' message.
*/
@Override
public
Set
<
String
>
getServiceAppMapping
(
String
serviceKey
,
MappingListener
listener
,
URL
url
)
{
MappingDataListener
mappingDataListener
=
ConcurrentHashMapUtils
.
computeIfAbsent
(
mappingDataListenerMap
,
buildPubSubKey
(),
k
->
{
MappingDataListener
dataListener
=
new
MappingDataListener
(
buildPubSubKey
());
dataListener
.
start
();
return
dataListener
;
});
mappingDataListener
.
getNotifySub
().
addListener
(
serviceKey
,
listener
);
return
this
.
getServiceAppMapping
(
serviceKey
,
url
);
}
@Override
public
Set
<
String
>
getServiceAppMapping
(
String
serviceKey
,
URL
url
)
{
String
key
=
buildMappingKey
(
DEFAULT_MAPPING_GROUP
);
return
getAppNames
(
getMappingData
(
key
,
serviceKey
));
}
@Override
public
MetadataInfo
getAppMetadata
(
SubscriberMetadataIdentifier
identifier
,
Map
<
String
,
String
>
instanceMetadata
)
{
String
content
=
this
.
getMetadata
(
identifier
);
return
JsonUtils
.
toJavaObject
(
content
,
MetadataInfo
.
class
);
}
@Override
public
void
publishAppMetadata
(
SubscriberMetadataIdentifier
identifier
,
MetadataInfo
metadataInfo
)
{
this
.
storeMetadata
(
identifier
,
metadataInfo
.
getContent
());
}
@Override
public
void
unPublishAppMetadata
(
SubscriberMetadataIdentifier
identifier
,
MetadataInfo
metadataInfo
)
{
this
.
deleteMetadata
(
identifier
);
}
// for test
public
MappingDataListener
getMappingDataListener
()
{
return
mappingDataListenerMap
.
get
(
buildPubSubKey
());
}
/**
* Listen for changes in the 'application_names' message and notify the listener.
*/
class
NotifySub
extends
JedisPubSub
{
private
final
Map
<
String
,
Set
<
MappingListener
>>
listeners
=
new
ConcurrentHashMap
<>();
public
void
addListener
(
String
key
,
MappingListener
listener
)
{
Set
<
MappingListener
>
listenerSet
=
listeners
.
computeIfAbsent
(
key
,
k
->
new
ConcurrentHashSet
<>());
listenerSet
.
add
(
listener
);
}
public
void
removeListener
(
String
serviceKey
,
MappingListener
listener
)
{
Set
<
MappingListener
>
listenerSet
=
this
.
listeners
.
get
(
serviceKey
);
if
(
listenerSet
!=
null
)
{
listenerSet
.
remove
(
listener
);
if
(
listenerSet
.
isEmpty
())
{
this
.
listeners
.
remove
(
serviceKey
);
}
}
}
public
Boolean
isEmpty
()
{
return
this
.
listeners
.
isEmpty
();
}
@Override
public
void
onMessage
(
String
key
,
String
msg
)
{
logger
.
info
(
"sub from redis:"
+
key
+
" message:"
+
msg
);
String
applicationNames
=
getMappingData
(
buildMappingKey
(
DEFAULT_MAPPING_GROUP
),
msg
);
MappingChangedEvent
mappingChangedEvent
=
new
MappingChangedEvent
(
msg
,
getAppNames
(
applicationNames
));
if
(!
CollectionUtils
.
isEmpty
(
listeners
.
get
(
msg
)))
{
for
(
MappingListener
mappingListener
:
listeners
.
get
(
msg
))
{
mappingListener
.
onEvent
(
mappingChangedEvent
);
}
}
}
@Override
public
void
onPMessage
(
String
pattern
,
String
key
,
String
msg
)
{
onMessage
(
key
,
msg
);
}
@Override
public
void
onPSubscribe
(
String
pattern
,
int
subscribedChannels
)
{
super
.
onPSubscribe
(
pattern
,
subscribedChannels
);
}
}
/**
* Subscribe application names change message.
*/
class
MappingDataListener
extends
Thread
{
private
String
path
;
private
final
NotifySub
notifySub
=
new
NotifySub
();
// for test
protected
volatile
boolean
running
=
true
;
public
MappingDataListener
(
String
path
)
{
this
.
path
=
path
;
}
public
NotifySub
getNotifySub
()
{
return
notifySub
;
}
@Override
public
void
run
()
{
while
(
running
)
{
if
(
pool
!=
null
)
{
try
(
Jedis
jedis
=
pool
.
getResource
())
{
jedis
.
subscribe
(
notifySub
,
path
);
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to subscribe "
+
path
+
", cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
else
{
try
(
JedisCluster
jedisCluster
=
new
JedisCluster
(
jedisClusterNodes
,
timeout
,
timeout
,
2
,
password
,
new
GenericObjectPoolConfig
<>()))
{
jedisCluster
.
subscribe
(
notifySub
,
path
);
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to subscribe "
+
path
+
", cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
throw
new
RpcException
(
msg
,
e
);
}
}
}
}
public
void
shutdown
()
{
try
{
running
=
false
;
notifySub
.
unsubscribe
(
path
);
}
catch
(
Throwable
e
)
{
String
msg
=
"Failed to unsubscribe "
+
path
+
", cause: "
+
e
.
getMessage
();
logger
.
error
(
TRANSPORT_FAILED_RESPONSE
,
""
,
""
,
msg
,
e
);
}
}
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-dubbo/src/main/java/org/dromara/common/dubbo/enumd/RequestLogEnum.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
dubbo
.
enumd
;
import
lombok.AllArgsConstructor
;
/**
* 请求日志泛型
*
* @author Lion Li
*/
@AllArgsConstructor
public
enum
RequestLogEnum
{
/**
* info 基础信息
*/
INFO
,
/**
* param 参数信息
*/
PARAM
,
/**
* full 全部
*/
FULL
;
}
employmentBusiness-pc-common/employmentBusiness-pc-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
redis
.
config
.
properties
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
org.redisson.config.ReadMode
;
import
org.redisson.config.SubscriptionMode
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
/**
* Redisson 配置属性
*
* @author Lion Li
*/
@Data
@ConfigurationProperties
(
prefix
=
"redisson"
)
public
class
RedissonProperties
{
/**
* redis缓存key前缀
*/
private
String
keyPrefix
;
/**
* 线程池数量,默认值 = 当前处理核数量 * 2
*/
private
int
threads
;
/**
* Netty线程池数量,默认值 = 当前处理核数量 * 2
*/
private
int
nettyThreads
;
/**
* 单机服务配置
*/
private
SingleServerConfig
singleServerConfig
;
/**
* 集群服务配置
*/
private
ClusterServersConfig
clusterServersConfig
;
@Data
@NoArgsConstructor
public
static
class
SingleServerConfig
{
/**
* 客户端名称
*/
private
String
clientName
;
/**
* 最小空闲连接数
*/
private
int
connectionMinimumIdleSize
;
/**
* 连接池大小
*/
private
int
connectionPoolSize
;
/**
* 连接空闲超时,单位:毫秒
*/
private
int
idleConnectionTimeout
;
/**
* 命令等待超时,单位:毫秒
*/
private
int
timeout
;
/**
* 发布和订阅连接池大小
*/
private
int
subscriptionConnectionPoolSize
;
}
@Data
@NoArgsConstructor
public
static
class
ClusterServersConfig
{
/**
* 客户端名称
*/
private
String
clientName
;
/**
* master最小空闲连接数
*/
private
int
masterConnectionMinimumIdleSize
;
/**
* master连接池大小
*/
private
int
masterConnectionPoolSize
;
/**
* slave最小空闲连接数
*/
private
int
slaveConnectionMinimumIdleSize
;
/**
* slave连接池大小
*/
private
int
slaveConnectionPoolSize
;
/**
* 连接空闲超时,单位:毫秒
*/
private
int
idleConnectionTimeout
;
/**
* 命令等待超时,单位:毫秒
*/
private
int
timeout
;
/**
* 发布和订阅连接池大小
*/
private
int
subscriptionConnectionPoolSize
;
/**
* 读取模式
*/
private
ReadMode
readMode
;
/**
* 订阅模式
*/
private
SubscriptionMode
subscriptionMode
;
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-redis/src/main/java/org/dromara/common/redis/handler/RedisExceptionHandler.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
redis
.
handler
;
import
cn.hutool.http.HttpStatus
;
import
com.baomidou.lock.exception.LockFailureException
;
import
jakarta.servlet.http.HttpServletRequest
;
import
lombok.extern.slf4j.Slf4j
;
import
org.dromara.common.core.domain.R
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.RestControllerAdvice
;
/**
* Redis异常处理器
*
* @author AprilWind
*/
@Slf4j
@RestControllerAdvice
public
class
RedisExceptionHandler
{
/**
* 分布式锁Lock4j异常
*/
@ExceptionHandler
(
LockFailureException
.
class
)
public
R
<
Void
>
handleLockFailureException
(
LockFailureException
e
,
HttpServletRequest
request
)
{
String
requestURI
=
request
.
getRequestURI
();
log
.
error
(
"获取锁失败了'{}',发生Lock4j异常."
,
requestURI
,
e
);
return
R
.
fail
(
HttpStatus
.
HTTP_UNAVAILABLE
,
"业务处理中,请稍后再试..."
);
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
redis
.
utils
;
import
lombok.AccessLevel
;
import
lombok.NoArgsConstructor
;
import
org.dromara.common.core.utils.SpringUtils
;
import
org.redisson.api.*
;
import
java.time.Duration
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.function.Consumer
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
/**
* redis 工具类
*
* @author Lion Li
* @version 3.1.0 新增
*/
@NoArgsConstructor
(
access
=
AccessLevel
.
PRIVATE
)
@SuppressWarnings
(
value
=
{
"unchecked"
,
"rawtypes"
})
public
class
RedisUtils
{
private
static
final
RedissonClient
CLIENT
=
SpringUtils
.
getBean
(
RedissonClient
.
class
);
/**
* 限流
*
* @param key 限流key
* @param rateType 限流类型
* @param rate 速率
* @param rateInterval 速率间隔
* @return -1 表示失败
*/
public
static
long
rateLimiter
(
String
key
,
RateType
rateType
,
int
rate
,
int
rateInterval
)
{
RRateLimiter
rateLimiter
=
CLIENT
.
getRateLimiter
(
key
);
rateLimiter
.
trySetRate
(
rateType
,
rate
,
rateInterval
,
RateIntervalUnit
.
SECONDS
);
if
(
rateLimiter
.
tryAcquire
())
{
return
rateLimiter
.
availablePermits
();
}
else
{
return
-
1L
;
}
}
/**
* 获取客户端实例
*/
public
static
RedissonClient
getClient
()
{
return
CLIENT
;
}
/**
* 发布通道消息
*
* @param channelKey 通道key
* @param msg 发送数据
* @param consumer 自定义处理
*/
public
static
<
T
>
void
publish
(
String
channelKey
,
T
msg
,
Consumer
<
T
>
consumer
)
{
RTopic
topic
=
CLIENT
.
getTopic
(
channelKey
);
topic
.
publish
(
msg
);
consumer
.
accept
(
msg
);
}
/**
* 发布消息到指定的频道
*
* @param channelKey 通道key
* @param msg 发送数据
*/
public
static
<
T
>
void
publish
(
String
channelKey
,
T
msg
)
{
RTopic
topic
=
CLIENT
.
getTopic
(
channelKey
);
topic
.
publish
(
msg
);
}
/**
* 订阅通道接收消息
*
* @param channelKey 通道key
* @param clazz 消息类型
* @param consumer 自定义处理
*/
public
static
<
T
>
void
subscribe
(
String
channelKey
,
Class
<
T
>
clazz
,
Consumer
<
T
>
consumer
)
{
RTopic
topic
=
CLIENT
.
getTopic
(
channelKey
);
topic
.
addListener
(
clazz
,
(
channel
,
msg
)
->
consumer
.
accept
(
msg
));
}
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public
static
<
T
>
void
setCacheObject
(
final
String
key
,
final
T
value
)
{
setCacheObject
(
key
,
value
,
false
);
}
/**
* 缓存基本的对象,保留当前对象 TTL 有效期
*
* @param key 缓存的键值
* @param value 缓存的值
* @param isSaveTtl 是否保留TTL有效期(例如: set之前ttl剩余90 set之后还是为90)
* @since Redis 6.X 以上使用 setAndKeepTTL 兼容 5.X 方案
*/
public
static
<
T
>
void
setCacheObject
(
final
String
key
,
final
T
value
,
final
boolean
isSaveTtl
)
{
RBucket
<
T
>
bucket
=
CLIENT
.
getBucket
(
key
);
if
(
isSaveTtl
)
{
try
{
bucket
.
setAndKeepTTL
(
value
);
}
catch
(
Exception
e
)
{
long
timeToLive
=
bucket
.
remainTimeToLive
();
if
(
timeToLive
==
-
1
)
{
setCacheObject
(
key
,
value
);
}
else
{
setCacheObject
(
key
,
value
,
Duration
.
ofMillis
(
timeToLive
));
}
}
}
else
{
bucket
.
set
(
value
);
}
}
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param duration 时间
*/
public
static
<
T
>
void
setCacheObject
(
final
String
key
,
final
T
value
,
final
Duration
duration
)
{
RBatch
batch
=
CLIENT
.
createBatch
();
RBucketAsync
<
T
>
bucket
=
batch
.
getBucket
(
key
);
bucket
.
setAsync
(
value
);
bucket
.
expireAsync
(
duration
);
batch
.
execute
();
}
/**
* 如果不存在则设置 并返回 true 如果存在则返回 false
*
* @param key 缓存的键值
* @param value 缓存的值
* @return set成功或失败
*/
public
static
<
T
>
boolean
setObjectIfAbsent
(
final
String
key
,
final
T
value
,
final
Duration
duration
)
{
RBucket
<
T
>
bucket
=
CLIENT
.
getBucket
(
key
);
return
bucket
.
setIfAbsent
(
value
,
duration
);
}
/**
* 如果存在则设置 并返回 true 如果存在则返回 false
*
* @param key 缓存的键值
* @param value 缓存的值
* @return set成功或失败
*/
public
static
<
T
>
boolean
setObjectIfExists
(
final
String
key
,
final
T
value
,
final
Duration
duration
)
{
RBucket
<
T
>
bucket
=
CLIENT
.
getBucket
(
key
);
return
bucket
.
setIfExists
(
value
,
duration
);
}
/**
* 注册对象监听器
* <p>
* key 监听器需开启 `notify-keyspace-events` 等 redis 相关配置
*
* @param key 缓存的键值
* @param listener 监听器配置
*/
public
static
<
T
>
void
addObjectListener
(
final
String
key
,
final
ObjectListener
listener
)
{
RBucket
<
T
>
result
=
CLIENT
.
getBucket
(
key
);
result
.
addListener
(
listener
);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功;false=设置失败
*/
public
static
boolean
expire
(
final
String
key
,
final
long
timeout
)
{
return
expire
(
key
,
Duration
.
ofSeconds
(
timeout
));
}
/**
* 设置有效时间
*
* @param key Redis键
* @param duration 超时时间
* @return true=设置成功;false=设置失败
*/
public
static
boolean
expire
(
final
String
key
,
final
Duration
duration
)
{
RBucket
rBucket
=
CLIENT
.
getBucket
(
key
);
return
rBucket
.
expire
(
duration
);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public
static
<
T
>
T
getCacheObject
(
final
String
key
)
{
RBucket
<
T
>
rBucket
=
CLIENT
.
getBucket
(
key
);
return
rBucket
.
get
();
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public
static
<
T
>
T
getCacheObject
(
final
String
key
,
Class
<
T
>
clazz
)
{
RBucket
<
T
>
rBucket
=
CLIENT
.
getBucket
(
key
);
return
rBucket
.
get
();
}
/**
* 获得key剩余存活时间
*
* @param key 缓存键值
* @return 剩余存活时间
*/
public
static
<
T
>
long
getTimeToLive
(
final
String
key
)
{
RBucket
<
T
>
rBucket
=
CLIENT
.
getBucket
(
key
);
return
rBucket
.
remainTimeToLive
();
}
/**
* 删除单个对象
*
* @param key 缓存的键值
*/
public
static
boolean
deleteObject
(
final
String
key
)
{
return
CLIENT
.
getBucket
(
key
).
delete
();
}
/**
* 删除集合对象
*
* @param collection 多个对象
*/
public
static
void
deleteObject
(
final
Collection
collection
)
{
RBatch
batch
=
CLIENT
.
createBatch
();
collection
.
forEach
(
t
->
{
batch
.
getBucket
(
t
.
toString
()).
deleteAsync
();
});
batch
.
execute
();
}
/**
* 检查缓存对象是否存在
*
* @param key 缓存的键值
*/
public
static
boolean
isExistsObject
(
final
String
key
)
{
return
CLIENT
.
getBucket
(
key
).
isExists
();
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public
static
<
T
>
boolean
setCacheList
(
final
String
key
,
final
List
<
T
>
dataList
)
{
RList
<
T
>
rList
=
CLIENT
.
getList
(
key
);
return
rList
.
addAll
(
dataList
);
}
/**
* 追加缓存List数据
*
* @param key 缓存的键值
* @param data 待缓存的数据
* @return 缓存的对象
*/
public
static
<
T
>
boolean
addCacheList
(
final
String
key
,
final
T
data
)
{
RList
<
T
>
rList
=
CLIENT
.
getList
(
key
);
return
rList
.
add
(
data
);
}
/**
* 注册List监听器
* <p>
* key 监听器需开启 `notify-keyspace-events` 等 redis 相关配置
*
* @param key 缓存的键值
* @param listener 监听器配置
*/
public
static
<
T
>
void
addListListener
(
final
String
key
,
final
ObjectListener
listener
)
{
RList
<
T
>
rList
=
CLIENT
.
getList
(
key
);
rList
.
addListener
(
listener
);
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public
static
<
T
>
List
<
T
>
getCacheList
(
final
String
key
)
{
RList
<
T
>
rList
=
CLIENT
.
getList
(
key
);
return
rList
.
readAll
();
}
/**
* 获得缓存的list对象(范围)
*
* @param key 缓存的键值
* @param form 起始下标
* @param to 截止下标
* @return 缓存键值对应的数据
*/
public
static
<
T
>
List
<
T
>
getCacheListRange
(
final
String
key
,
int
form
,
int
to
)
{
RList
<
T
>
rList
=
CLIENT
.
getList
(
key
);
return
rList
.
range
(
form
,
to
);
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public
static
<
T
>
boolean
setCacheSet
(
final
String
key
,
final
Set
<
T
>
dataSet
)
{
RSet
<
T
>
rSet
=
CLIENT
.
getSet
(
key
);
return
rSet
.
addAll
(
dataSet
);
}
/**
* 追加缓存Set数据
*
* @param key 缓存的键值
* @param data 待缓存的数据
* @return 缓存的对象
*/
public
static
<
T
>
boolean
addCacheSet
(
final
String
key
,
final
T
data
)
{
RSet
<
T
>
rSet
=
CLIENT
.
getSet
(
key
);
return
rSet
.
add
(
data
);
}
/**
* 注册Set监听器
* <p>
* key 监听器需开启 `notify-keyspace-events` 等 redis 相关配置
*
* @param key 缓存的键值
* @param listener 监听器配置
*/
public
static
<
T
>
void
addSetListener
(
final
String
key
,
final
ObjectListener
listener
)
{
RSet
<
T
>
rSet
=
CLIENT
.
getSet
(
key
);
rSet
.
addListener
(
listener
);
}
/**
* 获得缓存的set
*
* @param key 缓存的key
* @return set对象
*/
public
static
<
T
>
Set
<
T
>
getCacheSet
(
final
String
key
)
{
RSet
<
T
>
rSet
=
CLIENT
.
getSet
(
key
);
return
rSet
.
readAll
();
}
/**
* 缓存Map
*
* @param key 缓存的键值
* @param dataMap 缓存的数据
*/
public
static
<
T
>
void
setCacheMap
(
final
String
key
,
final
Map
<
String
,
T
>
dataMap
)
{
if
(
dataMap
!=
null
)
{
RMap
<
String
,
T
>
rMap
=
CLIENT
.
getMap
(
key
);
rMap
.
putAll
(
dataMap
);
}
}
/**
* 注册Map监听器
* <p>
* key 监听器需开启 `notify-keyspace-events` 等 redis 相关配置
*
* @param key 缓存的键值
* @param listener 监听器配置
*/
public
static
<
T
>
void
addMapListener
(
final
String
key
,
final
ObjectListener
listener
)
{
RMap
<
String
,
T
>
rMap
=
CLIENT
.
getMap
(
key
);
rMap
.
addListener
(
listener
);
}
/**
* 获得缓存的Map
*
* @param key 缓存的键值
* @return map对象
*/
public
static
<
T
>
Map
<
String
,
T
>
getCacheMap
(
final
String
key
)
{
RMap
<
String
,
T
>
rMap
=
CLIENT
.
getMap
(
key
);
return
rMap
.
getAll
(
rMap
.
keySet
());
}
/**
* 获得缓存Map的key列表
*
* @param key 缓存的键值
* @return key列表
*/
public
static
<
T
>
Set
<
String
>
getCacheMapKeySet
(
final
String
key
)
{
RMap
<
String
,
T
>
rMap
=
CLIENT
.
getMap
(
key
);
return
rMap
.
keySet
();
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public
static
<
T
>
void
setCacheMapValue
(
final
String
key
,
final
String
hKey
,
final
T
value
)
{
RMap
<
String
,
T
>
rMap
=
CLIENT
.
getMap
(
key
);
rMap
.
put
(
hKey
,
value
);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public
static
<
T
>
T
getCacheMapValue
(
final
String
key
,
final
String
hKey
)
{
RMap
<
String
,
T
>
rMap
=
CLIENT
.
getMap
(
key
);
return
rMap
.
get
(
hKey
);
}
/**
* 删除Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public
static
<
T
>
T
delCacheMapValue
(
final
String
key
,
final
String
hKey
)
{
RMap
<
String
,
T
>
rMap
=
CLIENT
.
getMap
(
key
);
return
rMap
.
remove
(
hKey
);
}
/**
* 删除Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键
*/
public
static
<
T
>
void
delMultiCacheMapValue
(
final
String
key
,
final
Set
<
String
>
hKeys
)
{
RBatch
batch
=
CLIENT
.
createBatch
();
RMapAsync
<
String
,
T
>
rMap
=
batch
.
getMap
(
key
);
for
(
String
hKey
:
hKeys
)
{
rMap
.
removeAsync
(
hKey
);
}
batch
.
execute
();
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public
static
<
K
,
V
>
Map
<
K
,
V
>
getMultiCacheMapValue
(
final
String
key
,
final
Set
<
K
>
hKeys
)
{
RMap
<
K
,
V
>
rMap
=
CLIENT
.
getMap
(
key
);
return
rMap
.
getAll
(
hKeys
);
}
/**
* 设置原子值
*
* @param key Redis键
* @param value 值
*/
public
static
void
setAtomicValue
(
String
key
,
long
value
)
{
RAtomicLong
atomic
=
CLIENT
.
getAtomicLong
(
key
);
atomic
.
set
(
value
);
}
/**
* 获取原子值
*
* @param key Redis键
* @return 当前值
*/
public
static
long
getAtomicValue
(
String
key
)
{
RAtomicLong
atomic
=
CLIENT
.
getAtomicLong
(
key
);
return
atomic
.
get
();
}
/**
* 递增原子值
*
* @param key Redis键
* @return 当前值
*/
public
static
long
incrAtomicValue
(
String
key
)
{
RAtomicLong
atomic
=
CLIENT
.
getAtomicLong
(
key
);
return
atomic
.
incrementAndGet
();
}
/**
* 递减原子值
*
* @param key Redis键
* @return 当前值
*/
public
static
long
decrAtomicValue
(
String
key
)
{
RAtomicLong
atomic
=
CLIENT
.
getAtomicLong
(
key
);
return
atomic
.
decrementAndGet
();
}
/**
* 获得缓存的基本对象列表(全局匹配忽略租户 自行拼接租户id)
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public
static
Collection
<
String
>
keys
(
final
String
pattern
)
{
Stream
<
String
>
stream
=
CLIENT
.
getKeys
().
getKeysStreamByPattern
(
pattern
);
return
stream
.
collect
(
Collectors
.
toList
());
}
/**
* 删除缓存的基本对象列表(全局匹配忽略租户 自行拼接租户id)
*
* @param pattern 字符串前缀
*/
public
static
void
deleteKeys
(
final
String
pattern
)
{
CLIENT
.
getKeys
().
deleteByPattern
(
pattern
);
}
/**
* 检查redis中是否存在key
*
* @param key 键
*/
public
synchronized
static
Boolean
hasKey
(
String
key
)
{
RKeys
rKeys
=
CLIENT
.
getKeys
();
return
rKeys
.
countExists
(
key
)
>
0
;
}
}
employmentBusiness-pc-common/employmentBusiness-pc-common-web/src/main/java/org/dromara/common/web/config/ResourcesConfig.java
0 → 100644
View file @
613f3bfd
package
org
.
dromara
.
common
.
web
.
config
;
import
org.dromara.common.web.handler.GlobalExceptionHandler
;
import
org.springframework.boot.autoconfigure.AutoConfiguration
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.web.servlet.config.annotation.InterceptorRegistry
;
import
org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
/**
* 通用配置
*
* @author Lion Li
*/
@AutoConfiguration
public
class
ResourcesConfig
implements
WebMvcConfigurer
{
@Override
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
}
@Override
public
void
addResourceHandlers
(
ResourceHandlerRegistry
registry
)
{
}
/**
* 全局异常处理器
*/
@Bean
public
GlobalExceptionHandler
globalExceptionHandler
()
{
return
new
GlobalExceptionHandler
();
}
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/config/RestTemplateConfig.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
config
;
import
org.apache.hc.client5.http.config.RequestConfig
;
import
org.apache.hc.client5.http.impl.classic.CloseableHttpClient
;
import
org.apache.hc.client5.http.impl.classic.HttpClients
;
import
org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager
;
import
org.apache.hc.core5.ssl.SSLContextBuilder
;
import
org.apache.hc.core5.util.Timeout
;
import
org.springframework.cloud.client.loadbalancer.LoadBalanced
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.http.client.HttpComponentsClientHttpRequestFactory
;
import
org.springframework.web.client.RestTemplate
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.TrustManager
;
import
javax.net.ssl.X509TrustManager
;
import
java.security.KeyStoreException
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.cert.X509Certificate
;
/**
* RestTemplate
* @author jiangxiaoge
*/
@Configuration
public
class
RestTemplateConfig
{
@Bean
@LoadBalanced
public
RestTemplate
restTemplate
()
{
return
new
RestTemplate
(
httpRequestFactory
());
}
// 创建一个不带服务发现的 RestTemplate
@Bean
public
RestTemplate
nonLoadBalancedRestTemplate
()
{
return
new
RestTemplate
(
httpRequestFactory
());
}
@Bean
public
HttpComponentsClientHttpRequestFactory
httpRequestFactory
()
{
// 使用自定义 HttpClient
CloseableHttpClient
httpClient
=
httpClient
();
// 创建工厂并绑定 HttpClient
return
new
HttpComponentsClientHttpRequestFactory
(
httpClient
);
}
@Bean
public
CloseableHttpClient
httpClient
()
{
// 配置连接池
PoolingHttpClientConnectionManager
connectionManager
=
new
PoolingHttpClientConnectionManager
();
connectionManager
.
setMaxTotal
(
2000
);
// 最大连接数
connectionManager
.
setDefaultMaxPerRoute
(
200
);
// 每个路由的最大连接数
// 配置超时
RequestConfig
requestConfig
=
RequestConfig
.
custom
()
.
setConnectTimeout
(
Timeout
.
ofSeconds
(
12
))
// 连接超时
.
setResponseTimeout
(
Timeout
.
ofSeconds
(
48
))
// 响应超时
.
build
();
// 创建 HttpClient,并绑定连接池和超时配置
return
HttpClients
.
custom
()
.
setConnectionManager
(
connectionManager
)
.
setDefaultRequestConfig
(
requestConfig
)
.
build
();
}
// 创建一个跳过 SSL 验证的 SSLContext
private
SSLContext
getSSLContext
()
{
try
{
// 创建一个信任管理器,接受所有证书
TrustManager
[]
trustAllCertificates
=
new
TrustManager
[]{
new
X509TrustManager
()
{
public
X509Certificate
[]
getAcceptedIssuers
()
{
return
null
;
}
public
void
checkClientTrusted
(
X509Certificate
[]
certs
,
String
authType
)
{
}
public
void
checkServerTrusted
(
X509Certificate
[]
certs
,
String
authType
)
{
}
}
};
// 使用自定义的信任管理器创建 SSLContext
SSLContext
sslContext
=
SSLContextBuilder
.
create
()
.
loadTrustMaterial
((
chain
,
authType
)
->
true
)
// 忽略 SSL 证书验证
.
build
();
// 使用该 SSLContext
return
sslContext
;
}
catch
(
NoSuchAlgorithmException
|
java
.
security
.
KeyManagementException
e
)
{
throw
new
RuntimeException
(
"Error creating SSLContext"
,
e
);
}
catch
(
KeyStoreException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/dto/ResumeListItemCache.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
dto
;
import
lombok.Data
;
/**
* @author jiangxiaoge
* @description 简历列表item
* @data 2025/5/19
**/
@Data
public
class
ResumeListItemCache
{
private
Integer
publicStatus
;
private
Long
resumeId
;
private
String
resumeName
;
private
Integer
runType
;
private
String
updateTime
;
private
Integer
resumeScore
;
// 使用状态 0=可用 1=作废
private
Integer
useStatus
;
private
String
appraise
;
//默认状态 0=默认 1=不默认
private
Integer
defaultStatus
;
private
String
sex
;
private
String
avatar
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/dto/ResumeMakeDto.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
dto
;
import
lombok.Data
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author jiangxiaoge
* @description 创建简历dto
* @data 2024/12/16
**/
@Data
public
class
ResumeMakeDto
{
/**简历名称*/
private
String
resumeName
;
/**模版id*/
private
String
template
;
/**平台*/
private
int
platform
;
/**未来简历id*/
private
Long
platformResumeId
;
/**未来简历自定义id*/
private
Long
platformCustomId
;
/**简历id*/
private
String
resumeId
;
/**模块id*/
private
Long
modelId
;
/**个人简历基本信息*/
private
Map
<
String
,
Object
>
bodyData
;
private
List
<
String
>
platformIdList
;
/**简历模块排序列表*/
private
Map
<
Long
,
Integer
>
modelSort
;
private
Integer
runType
;
/**简历发布状态 0.未发布 1.已发布*/
private
Integer
publicStatus
;
private
Long
userId
;
/**权益id*/
private
String
vipId
;
/**模版ID*/
private
String
templateId
;
/**模版名称*/
private
String
templateName
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/dto/ResumeModelOptimizationCache.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
dto
;
import
lombok.Data
;
/**
* @author jiangxiaoge
* @description 简历模块优化建议缓存
* @data 2025/5/19
**/
@Data
public
class
ResumeModelOptimizationCache
{
private
Integer
runStatus
;
private
String
optimizationDesc
;
private
String
updateTime
;
public
ResumeModelOptimizationCache
()
{
}
public
ResumeModelOptimizationCache
(
Integer
runStatus
,
String
optimizationDesc
,
String
updateTime
)
{
this
.
runStatus
=
runStatus
;
this
.
optimizationDesc
=
optimizationDesc
;
this
.
updateTime
=
updateTime
;
}
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/dto/ResumeMsgCache.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
dto
;
import
lombok.Data
;
/**
* @author jiangxiaoge
* @description 简历缓存-简历列表
* @data 2025/1/8
**/
@Data
public
class
ResumeMsgCache
{
/**简历id*/
private
String
id
;
/**简历名称*/
private
String
resumeName
;
/**更新时间*/
private
String
updateTime
;
/**运行状态*/
private
Integer
runType
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/entity/ResumeTemplate.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
entity
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
org.dromara.common.mybatis.core.domain.BaseEntity
;
import
lombok.Data
;
/**
* @author Herbert
* @description 简历模版表
* @data 2025/05/07
**/
@Data
@TableName
(
"resume_template"
)
public
class
ResumeTemplate
extends
BaseEntity
{
/**
* 主键id
*/
@TableId
(
type
=
IdType
.
ASSIGN_ID
)
private
String
id
;
/**
* 模版名称
*/
private
String
templateName
;
/**
* 模版路径
*/
private
String
templatePath
;
/**
* 模版别名
*/
private
String
templateAlias
;
/**
* 模版预览地址
*/
private
String
templatePreview
;
/**
* 平台ID
*/
private
String
platformId
;
private
static
final
long
serialVersionUID
=
1L
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/entity/ResumeTranslationRecord.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
entity
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableLogic
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
org.dromara.common.core.utils.Entity
;
import
org.dromara.common.mybatis.core.domain.BaseEntity
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
/**
* @author Herbert
* @description 简历翻译记录表
* @data 2025/04/08
**/
@Data
@TableName
(
"resume_translation_record"
)
public
class
ResumeTranslationRecord
extends
Entity
{
/**主键ID*/
@TableId
(
value
=
"id"
,
type
=
IdType
.
ASSIGN_ID
)
private
Long
id
;
/**简历ID*/
private
Long
resumeId
;
/**简历名称或文件名称*/
private
String
resumeName
;
/**简历类型:选择已有简历-1;简历上传-2;*/
private
String
type
;
/**智能体简历上传文件ID*/
private
String
agentFileId
;
/**简历上传文件ID*/
private
String
fileId
;
/**此参数仅在对话产生的消息中返回*/
private
String
chatId
;
/**此消息所在的会话ID*/
private
String
conversationId
;
/**编写此消息的智能体ID。此参数仅在对话产生的消息中返回*/
private
String
botId
;
/**生成的html路径*/
private
String
pathHtml
;
/**生成的pdf路径*/
private
String
pathPdf
;
/**生成的png路径*/
private
String
pathPng
;
/**智能体翻译后的内容*/
private
String
content
;
/**对话的运行状态。取值为:created-对话已创建;in_progress-智能体正在处理中;completed-智能体已完成处理,本次对话结束;failed-对话失败;requires_action-对话中断,需要进一步处理;canceled-对话已取消*/
private
String
status
;
/**删除标志(0代表存在 2代表删除)*/
@TableLogic
private
String
delFlag
;
@Schema
(
description
=
"模版名称"
)
private
String
templateName
;
@Schema
(
description
=
"源语言"
)
private
String
sourceLanguage
;
@Schema
(
description
=
"目标语言"
)
private
String
targetLanguage
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeBase.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
lombok.Data
;
import
org.dromara.common.core.annotation.JxgInitField
;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/17
**/
@Data
public
class
ResumeBase
{
/**生日*/
@JxgInitField
(
"Age"
)
private
String
birthday
;
/**头像url*/
@JxgInitField
(
"Avatar"
)
private
String
avatar
;
/**城市*/
@JxgInitField
(
"City"
)
private
String
city
;
/**名族*/
@JxgInitField
(
"Ethnic"
)
private
String
ethnic
;
/**岗位*/
@JxgInitField
(
"JobInt"
)
private
String
jobInt
;
/**邮箱*/
@JxgInitField
(
"Mail"
)
private
String
email
;
/**名字*/
@JxgInitField
(
"Name"
)
private
String
username
;
/**薪资*/
@JxgInitField
(
"Pay"
)
private
String
pay
;
/**手机号*/
@JxgInitField
(
"Phone"
)
private
String
phone
;
/**政治面貌*/
@JxgInitField
(
"PolStatus"
)
private
String
polStatus
;
/**性别*/
@JxgInitField
(
"Sex"
)
private
String
sex
;
/**工作状态*/
@JxgInitField
(
"Status"
)
private
String
workStatus
;
/**微信号*/
@JxgInitField
(
"Wechat"
)
private
String
wechat
;
/**参加工作时间*/
@JxgInitField
(
value
=
"WorkTime"
)
private
String
workTime
;
/**简历名称*/
@JxgInitField
(
value
=
"ResumeName"
)
private
String
resumeName
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeBaseVo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
lombok.Data
;
/**
* @author jiangxiaoge
* @description 简历基本信息vo
* @data 2024/12/17
**/
@Data
public
class
ResumeBaseVo
{
private
Long
resumeId
;
private
String
platformId
;
private
String
resumeName
;
private
String
updateTime
;
private
Integer
runType
;
private
Integer
publicStatus
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeByPdfVo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
@Data
@Schema
(
description
=
"根据模版生成pdf,html,png文件请求类"
)
public
class
ResumeByPdfVo
{
@Schema
(
description
=
"html名称"
)
private
String
htmlName
;
@Schema
(
description
=
"pdf名称"
)
private
String
pdfName
;
@Schema
(
description
=
"png名称"
)
private
String
pngName
;
@Schema
(
description
=
"png名称小图"
)
private
String
pngNameMin
;
@Schema
(
description
=
"简历名称"
)
private
String
resumeName
;
@Schema
(
description
=
"简历翻译记录ID"
)
private
Long
resumeTranslationRecordId
;
@Schema
(
description
=
"用户名称"
)
private
String
userName
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeClub.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
lombok.Data
;
import
org.dromara.common.core.annotation.JxgInitField
;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/17
**/
@Data
public
class
ResumeClub
{
/**社团名称*/
@JxgInitField
(
"Name"
)
private
String
clubName
;
/**担任角色*/
@JxgInitField
(
"RoleName"
)
private
String
roleName
;
/**开始时间*/
@JxgInitField
(
"StartTime"
)
private
String
startTime
;
/**结束时间*/
@JxgInitField
(
"EndTime"
)
private
String
endTime
;
/**详情*/
@JxgInitField
(
"Description"
)
private
String
description
;
@JxgInitField
(
"Performance"
)
private
String
performance
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeEdu.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
lombok.Data
;
import
org.dromara.common.core.annotation.JxgInitField
;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/17
**/
@Data
public
class
ResumeEdu
{
/**学历*/
@JxgInitField
(
"Degree"
)
private
String
degree
;
/**开始时间*/
@JxgInitField
(
"StartYear"
)
private
String
startTime
;
/**结束时间*/
@JxgInitField
(
"EndYear"
)
private
String
endTime
;
/**专业*/
@JxgInitField
(
"Major"
)
private
String
major
;
/**学校*/
@JxgInitField
(
"School"
)
private
String
school
;
/**详情*/
@JxgInitField
(
"Description"
)
private
String
description
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeExtra.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
lombok.Data
;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/17
**/
@Data
public
class
ResumeExtra
{
/**数据类型 0.专业技能1.个人优势.获奖信息3.兴趣爱好*/
private
Integer
dataType
;
/**详情*/
private
String
description
;
private
String
infoName
;
private
String
startTime
;
private
String
endTime
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeInternship.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
org.dromara.common.core.annotation.JxgInitField
;
import
lombok.Data
;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/17
**/
@Data
public
class
ResumeInternship
{
@JxgInitField
(
"Corp"
)
private
String
internshipCorp
;
/**实习岗位*/
@JxgInitField
(
"Post"
)
private
String
internshipPost
;
/**成果*/
@JxgInitField
(
"Performance"
)
private
String
performance
;
/**开始时间*/
@JxgInitField
(
"StartTime"
)
private
String
startTime
;
/**结束时间*/
@JxgInitField
(
"EndTime"
)
private
String
endTime
;
/**详情*/
@JxgInitField
(
"Content"
)
private
String
description
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeModelVo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
lombok.Data
;
/**
* @author jiangxiaoge
* @description 模块列表vo
* @data 2024/12/20
**/
@Data
public
class
ResumeModelVo
{
private
Long
modelId
;
private
Integer
modelType
;
private
Integer
dataSort
;
private
int
isShow
;
private
String
modelName
;
private
String
webCode
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeProject.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
org.dromara.common.core.annotation.JxgInitField
;
import
lombok.Data
;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/17
**/
@Data
public
class
ResumeProject
{
/**项目名称*/
@JxgInitField
(
"Name"
)
private
String
projectName
;
/**职位名称*/
@JxgInitField
(
"RoleName"
)
private
String
roleName
;
/**开始时间*/
@JxgInitField
(
"StartTime"
)
private
String
startTime
;
/**结束时间*/
@JxgInitField
(
"EndTime"
)
private
String
endTime
;
/**职位描述*/
@JxgInitField
(
"Description"
)
private
String
description
;
/**项目描述*/
@JxgInitField
(
"Performance"
)
private
String
performance
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeSmartCreationVo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
java.util.Date
;
/**
* @Desc:
* @author: Herbert
* @date: 2025/3/17 13:56
* @since: 17
*/
@Data
@Schema
(
description
=
"简历智作统计数据预处理返回类"
)
public
class
ResumeSmartCreationVo
{
@Schema
(
description
=
"用户ID"
)
private
String
userId
;
@Schema
(
description
=
"用户名称"
)
private
String
username
;
@Schema
(
description
=
"手机号"
)
private
String
phone
;
@Schema
(
description
=
"学号"
)
private
String
studentNumber
;
@Schema
(
description
=
"学校ID"
)
private
String
schoolId
;
@Schema
(
description
=
"简历id"
)
private
String
resumeId
;
@Schema
(
description
=
"简历名称"
)
private
String
resumeName
;
@Schema
(
description
=
"简历创建时间"
)
private
Date
resumeCreateTime
;
@Schema
(
description
=
"简历更新时间"
)
private
Date
resumeUpdateTime
;
@Schema
(
description
=
"简历评分"
)
private
Integer
resumeScore
;
@Schema
(
description
=
"简历优化次数"
)
private
Integer
optimizeCounts
;
@Schema
(
description
=
"下载次数"
)
private
Integer
downloadCounts
;
@Schema
(
description
=
"简历是否删除(true:已删除,false:未删除)"
)
private
Boolean
resumeIsDeleted
;
@Schema
(
description
=
"简历评价"
)
private
String
appraise
;
@Schema
(
description
=
"模版名称"
)
private
String
templateName
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeVo.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
lombok.Data
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author jiangxiaoge
* @description 个人简历
* @data 2024/12/17
**/
@Data
public
class
ResumeVo
{
//基本信息
private
ResumeBase
base
;
//社团信息
private
Map
<
String
,
Object
>
clubs
;
//教育经历
private
Map
<
String
,
Object
>
edus
;
//兴趣爱好
private
Map
<
String
,
Object
>
hobbles
;
//实习经历
private
Map
<
String
,
Object
>
internships
;
//项目经历
private
Map
<
String
,
Object
>
projects
;
//工作经验
private
Map
<
String
,
Object
>
workExps
;
private
Map
<
String
,
Object
>
skill
;
private
Map
<
String
,
Object
>
advantage
;
private
Map
<
String
,
Object
>
awards
;
private
List
<
Map
<
String
,
Object
>>
custom
=
new
ArrayList
<>();
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/domain/vo/ResumeWorkExp.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
domain
.
vo
;
import
org.dromara.common.core.annotation.JxgInitField
;
import
lombok.Data
;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/17
**/
@Data
public
class
ResumeWorkExp
{
@JxgInitField
(
"Content"
)
private
String
workContent
;
/**公司名称*/
@JxgInitField
(
"Corp"
)
private
String
corpName
;
/**开始时间*/
@JxgInitField
(
"StartTime"
)
private
String
startTime
;
/**结束时间*/
@JxgInitField
(
"EndTime"
)
private
String
endTime
;
/**结束时间*/
@JxgInitField
(
"Post"
)
private
String
postName
;
/**工作成绩*/
@JxgInitField
(
"Performance"
)
private
String
performance
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/dubbo/RemoteUserServiceImpl.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
dubbo
;
import
cn.hutool.core.util.ObjectUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.bkty.system.api.RemoteUserService
;
import
com.bkty.system.api.domain.bo.RemoteUserBo
;
import
com.bkty.system.api.domain.vo.RemoteUserVo
;
import
com.bkty.system.api.model.LoginUser
;
import
com.bkty.system.domain.dto.SysUserDto
;
import
com.bkty.system.domain.entity.SysUser
;
import
com.bkty.system.domain.vo.SysUserVo
;
import
com.bkty.system.mapper.SysUserMapper
;
import
com.bkty.system.service.ISysPermissionService
;
import
com.bkty.system.service.ISysUserService
;
import
lombok.RequiredArgsConstructor
;
import
org.apache.dubbo.config.annotation.DubboService
;
import
org.dromara.common.core.enums.UserStatus
;
import
org.dromara.common.core.exception.ServiceException
;
import
org.dromara.common.core.exception.user.UserException
;
import
org.dromara.common.core.utils.DateUtils
;
import
org.dromara.common.core.utils.MapstructUtils
;
import
org.dromara.common.mybatis.helper.DataPermissionHelper
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
/**
* 用户服务
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Service
@DubboService
public
class
RemoteUserServiceImpl
implements
RemoteUserService
{
private
final
ISysUserService
userService
;
private
final
SysUserMapper
userMapper
;
private
final
ISysPermissionService
permissionService
;
/**
* 通过用户名查询用户信息
*
* @param username 用户名
* @return 结果
*/
@Override
public
LoginUser
getUserInfo
(
String
username
)
throws
UserException
{
System
.
out
.
println
(
"进入查询用户方法"
);
SysUserVo
sysUser
=
userMapper
.
selectVoOne
(
new
LambdaQueryWrapper
<
SysUser
>().
eq
(
SysUser:
:
getUserName
,
username
));
if
(
ObjectUtil
.
isNull
(
sysUser
))
{
throw
new
UserException
(
"user.not.exists"
,
username
);
}
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
sysUser
.
getStatus
()))
{
throw
new
UserException
(
"user.blocked"
,
username
);
}
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
return
buildLoginUser
(
sysUser
);
}
/**
* 通过用户id查询用户信息
*
* @param userId 用户id
* @return 结果
*/
@Override
public
LoginUser
getUserInfo
(
Long
userId
)
throws
UserException
{
SysUserVo
sysUser
=
userMapper
.
selectVoById
(
userId
);
if
(
ObjectUtil
.
isNull
(
sysUser
))
{
throw
new
UserException
(
"user.not.exists"
,
""
);
}
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
sysUser
.
getStatus
()))
{
throw
new
UserException
(
"user.blocked"
,
sysUser
.
getUserName
());
}
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
return
buildLoginUser
(
sysUser
);
}
/**
* 通过手机号查询用户信息
*
* @param phonenumber 手机号
* @param tenantId 租户id
* @return 结果
*/
@Override
public
LoginUser
getUserInfoByPhonenumber
(
String
phonenumber
,
String
tenantId
)
throws
UserException
{
SysUserVo
sysUser
=
userMapper
.
selectVoOne
(
new
LambdaQueryWrapper
<
SysUser
>().
eq
(
SysUser:
:
getPhonenumber
,
phonenumber
));
if
(
ObjectUtil
.
isNull
(
sysUser
))
{
throw
new
UserException
(
"user.not.exists"
,
phonenumber
);
}
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
sysUser
.
getStatus
()))
{
throw
new
UserException
(
"user.blocked"
,
phonenumber
);
}
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
return
buildLoginUser
(
sysUser
);
}
/**
* 通过邮箱查询用户信息
*
* @param email 邮箱
* @param tenantId 租户id
* @return 结果
*/
@Override
public
LoginUser
getUserInfoByEmail
(
String
email
,
String
tenantId
)
throws
UserException
{
SysUserVo
user
=
userMapper
.
selectVoOne
(
new
LambdaQueryWrapper
<
SysUser
>().
eq
(
SysUser:
:
getEmail
,
email
));
if
(
ObjectUtil
.
isNull
(
user
))
{
throw
new
UserException
(
"user.not.exists"
,
email
);
}
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
throw
new
UserException
(
"user.blocked"
,
email
);
}
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
return
buildLoginUser
(
user
);
}
/**
* 注册用户信息
*
* @param remoteUserBo 用户信息
* @return 结果
*/
@Override
public
Boolean
registerUserInfo
(
RemoteUserBo
remoteUserBo
)
throws
UserException
,
ServiceException
{
SysUserDto
sysUserDto
=
MapstructUtils
.
convert
(
remoteUserBo
,
SysUserDto
.
class
);
String
username
=
sysUserDto
.
getUserName
();
boolean
exist
=
userMapper
.
exists
(
new
LambdaQueryWrapper
<
SysUser
>()
.
eq
(
SysUser:
:
getUserName
,
sysUserDto
.
getUserName
()));
if
(
exist
)
{
throw
new
UserException
(
"user.register.save.error"
,
username
);
}
return
userService
.
registerUser
(
sysUserDto
,
remoteUserBo
.
getTenantId
());
}
/**
* 通过用户ID查询用户账户
*
* @param userId 用户ID
* @return 用户账户
*/
@Override
public
String
selectUserNameById
(
Long
userId
)
{
return
userService
.
selectUserNameById
(
userId
);
}
/**
* 通过用户ID查询用户昵称
*
* @param userId 用户ID
* @return 用户昵称
*/
@Override
public
String
selectNicknameById
(
Long
userId
)
{
return
userService
.
selectNicknameById
(
userId
);
}
/**
* 通过用户ID查询用户账户
*
* @param userIds 用户ID 多个用逗号隔开
* @return 用户账户
*/
@Override
public
String
selectNicknameByIds
(
String
userIds
)
{
return
userService
.
selectNicknameByIds
(
userIds
);
}
/**
* 通过用户ID查询用户手机号
*
* @param userId 用户id
* @return 用户手机号
*/
@Override
public
String
selectPhonenumberById
(
Long
userId
)
{
return
userService
.
selectPhonenumberById
(
userId
);
}
/**
* 通过用户ID查询用户邮箱
*
* @param userId 用户id
* @return 用户邮箱
*/
@Override
public
String
selectEmailById
(
Long
userId
)
{
return
userService
.
selectEmailById
(
userId
);
}
/**
* 构建登录用户
*/
private
LoginUser
buildLoginUser
(
SysUserVo
userVo
)
{
LoginUser
loginUser
=
new
LoginUser
();
loginUser
.
setTenantId
(
userVo
.
getTenantId
());
loginUser
.
setTenantName
(
userVo
.
getTenantName
());
loginUser
.
setUserId
(
userVo
.
getUserId
());
loginUser
.
setDeptId
(
userVo
.
getDeptId
());
loginUser
.
setUsername
(
userVo
.
getUserName
());
loginUser
.
setNickname
(
userVo
.
getNickName
());
loginUser
.
setPassword
(
userVo
.
getPassword
());
loginUser
.
setUserType
(
userVo
.
getUserType
());
loginUser
.
setMenuPermission
(
permissionService
.
getMenuPermission
(
userVo
.
getUserId
()));
loginUser
.
setRolePermission
(
permissionService
.
getRolePermission
(
userVo
.
getUserId
()));
return
loginUser
;
}
/**
* 更新用户信息
*
* @param userId 用户ID
* @param ip IP地址
*/
@Override
public
void
recordLoginInfo
(
Long
userId
,
String
ip
)
{
SysUser
sysUser
=
new
SysUser
();
sysUser
.
setUserId
(
userId
);
sysUser
.
setLoginIp
(
ip
);
sysUser
.
setLoginDate
(
DateUtils
.
getNowDate
());
sysUser
.
setUpdateBy
(
String
.
valueOf
(
userId
));
DataPermissionHelper
.
ignore
(()
->
userMapper
.
updateById
(
sysUser
));
}
/**
* 通过用户ID查询用户列表
*
* @param userIds 用户ids
* @return 用户列表
*/
@Override
public
List
<
RemoteUserVo
>
selectListByIds
(
List
<
Long
>
userIds
)
{
List
<
SysUserVo
>
sysUserVos
=
userService
.
selectUserByIds
(
userIds
,
null
);
return
MapstructUtils
.
convert
(
sysUserVos
,
RemoteUserVo
.
class
);
}
/**
* 通过角色ID查询用户ID
*
* @param roleIds 角色ids
* @return 用户ids
*/
@Override
public
List
<
Long
>
selectUserIdsByRoleIds
(
List
<
Long
>
roleIds
)
{
return
userService
.
selectUserIdsByRoleIds
(
roleIds
);
}
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/mapper/ResumeTemplateMapper.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.bkty.system.domain.entity.ResumeTemplate
;
import
org.apache.ibatis.annotations.Mapper
;
/**
* @author Herbert
* @description 简历模版表
* @data 2025/05/07
**/
@Mapper
public
interface
ResumeTemplateMapper
extends
BaseMapper
<
ResumeTemplate
>
{
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/mapper/ResumeTranslationRecordMapper.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.bkty.system.domain.entity.ResumeTranslationRecord
;
import
org.apache.ibatis.annotations.Mapper
;
/**
* @author Herbert
* @description 简历翻译记录表
* @data 2025/04/08
**/
@Mapper
public
interface
ResumeTranslationRecordMapper
extends
BaseMapper
<
ResumeTranslationRecord
>
{
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/service/resume/ResumeCacheService.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
service
.
resume
;
import
com.bkty.system.domain.dto.ResumeListItemCache
;
import
com.bkty.system.domain.dto.ResumeMakeDto
;
import
com.bkty.system.domain.dto.ResumeModelOptimizationCache
;
import
com.bkty.system.domain.entity.FunctionResumeBase
;
import
com.bkty.system.domain.entity.FunctionResumeModel
;
import
com.bkty.system.domain.entity.FunctionResumeModelOptimization
;
import
com.bkty.system.domain.vo.ResumeBaseVo
;
import
com.bkty.system.domain.vo.ResumeModelVo
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author jiangxiaoge
* @description 简历缓存Service
* @data 2025/1/8
**/
public
interface
ResumeCacheService
{
/**
* 根据用户的简历列表缓存
*/
void
saveUserResumeListCache
(
FunctionResumeBase
base
,
Long
userId
);
/**
* 查询用户简历信息缓存
* @param userId
* @return
*/
List
<
ResumeBaseVo
>
queryUserResumeCache
(
Long
userId
);
/**
* 删除简历基础信息缓存
* @param resumeId
* @param userId
*/
void
delResumeCache
(
Long
resumeId
,
Long
userId
);
/**
* 根据简历id保存简历模块列表缓存
* @param model
* @param resumeId
*/
void
saveResumeModelListCache
(
FunctionResumeModel
model
,
Long
resumeId
);
/**
* 查询简历模块信息缓存
* @param resumeId
* @return
*/
List
<
ResumeModelVo
>
queryResumeModelCache
(
Long
resumeId
);
/**
* 删除简历模块基础信息缓存
* @param modelId
* @param resumeId
*/
void
delResumeModelCache
(
Long
modelId
,
Long
resumeId
);
/**
* 保存简历模块具体数据
* @param modelId
* @param resumeId
* @param jsonData
*/
void
saveResumeModelDataCache
(
Long
modelId
,
Long
resumeId
,
String
jsonData
);
/**
* 查询简历模块具体数据
* @param modelId
* @param resumeId
* @return
*/
String
queryResumeModelDataCache
(
Long
modelId
,
Long
resumeId
);
/**
* 删除简历模块具体数据
* @param modelId
* @param resumeId
*/
void
delResumeModelDataCache
(
Long
modelId
,
Long
resumeId
);
/**
* 修改模块排序缓存
* @param dto
*/
void
updateModelSort
(
ResumeMakeDto
dto
);
/**
* 刷新模块优化缓存
* @param optimization
*/
void
refreshModelOptimization
(
FunctionResumeModelOptimization
optimization
);
/**
* 查询缓存模块优化信息
* @param id
* @param resumeId
* @return
*/
Map
<
String
,
ResumeModelOptimizationCache
>
queryResumeModelOptimization
(
Long
id
,
Long
resumeId
);
/**
* 查询简历列表缓存
* @param aLong
* @return
*/
List
<
ResumeListItemCache
>
queryResumeList
(
Long
aLong
);
/**
* 刷新简历列表缓存
* @param caches
* @param aLong
*/
void
refreshResumeListCache
(
List
<
ResumeListItemCache
>
caches
,
Long
aLong
);
/**
* 简历缓存模版信息
*/
void
saveResumeTemplateCache
(
Map
<
String
,
Object
>
templateMap
,
String
resumeId
);
void
delResumeListCache
(
Long
userId
);
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/service/resume/impl/ResumeCacheServiceImpl.java
0 → 100644
View file @
613f3bfd
package
com
.
bkty
.
system
.
service
.
resume
.
impl
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.map.MapUtil
;
import
com.alibaba.fastjson2.JSON
;
import
com.bkty.system.domain.dto.ResumeListItemCache
;
import
com.bkty.system.domain.dto.ResumeMakeDto
;
import
com.bkty.system.domain.dto.ResumeModelOptimizationCache
;
import
com.bkty.system.domain.entity.FunctionResumeBase
;
import
com.bkty.system.domain.entity.FunctionResumeModel
;
import
com.bkty.system.domain.entity.FunctionResumeModelOptimization
;
import
com.bkty.system.domain.vo.ResumeBaseVo
;
import
com.bkty.system.domain.vo.ResumeModelVo
;
import
com.bkty.system.service.resume.ResumeCacheService
;
import
lombok.AllArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.dromara.common.core.enums.ResumeEnum
;
import
org.dromara.common.core.utils.DateTimeWrapper
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Service
;
import
java.time.ZoneId
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
/**
* @author jiangxiaoge
* @description 简历缓存ServiceImpl
* @data 2025/1/8
**/
@Slf4j
@AllArgsConstructor
@Service
public
class
ResumeCacheServiceImpl
implements
ResumeCacheService
{
private
final
RedisTemplate
<
String
,
String
>
redisTemplate
;
/**简历基础信息列表key*/
private
final
static
String
REDIS_RESUME_LIST_KEY
=
"resume:msg:%s"
;
/**简历模块基础信息列表key*/
private
final
static
String
REDIS_RESUME_MODEL_LIST_KEY
=
"resume:model:msg:%s"
;
/**简历模块数据key*/
private
final
static
String
REDIS_RESUME_MODEL_DATA_KEY
=
"resume:model:data:%s:%s"
;
@Override
public
void
saveUserResumeListCache
(
FunctionResumeBase
base
,
Long
userId
)
{
ResumeBaseVo
cache
=
new
ResumeBaseVo
();
DateTimeWrapper
dateTimeWrapper
=
DateTimeWrapper
.
parseFromLocalDateTime
(
base
.
getUpdateTime
().
toInstant
()
.
atZone
(
ZoneId
.
of
(
"Asia/Shanghai"
))
.
toLocalDateTime
(),
null
);
cache
.
setResumeName
(
base
.
getResumeName
());
cache
.
setResumeId
(
base
.
getId
());
cache
.
setPlatformId
(
base
.
getPlatformId
());
cache
.
setRunType
(
base
.
getRunType
());
cache
.
setUpdateTime
(
dateTimeWrapper
.
toString
());
String
key
=
REDIS_RESUME_LIST_KEY
.
formatted
(
userId
);
Set
<
String
>
resumeData
=
redisTemplate
.
opsForZSet
().
range
(
key
,
0
,
-
1
);
if
(
CollectionUtil
.
isNotEmpty
(
resumeData
)){
for
(
String
resumeDatum
:
resumeData
)
{
ResumeBaseVo
baseVo
=
JSON
.
parseObject
(
resumeDatum
,
ResumeBaseVo
.
class
);
if
(
baseVo
.
getResumeId
().
equals
(
base
.
getId
())){
redisTemplate
.
opsForZSet
().
remove
(
key
,
resumeDatum
);
break
;
}
}
redisTemplate
.
opsForZSet
().
add
(
key
,
JSON
.
toJSONString
(
cache
),
dateTimeWrapper
.
getDate
().
getTime
());
}
else
{
redisTemplate
.
opsForZSet
().
add
(
key
,
JSON
.
toJSONString
(
cache
),
dateTimeWrapper
.
getDate
().
getTime
());
}
}
@Override
public
List
<
ResumeBaseVo
>
queryUserResumeCache
(
Long
userId
)
{
String
key
=
REDIS_RESUME_LIST_KEY
.
formatted
(
userId
);
Set
<
String
>
resumeData
=
redisTemplate
.
opsForZSet
().
range
(
key
,
0
,
-
1
);
if
(
CollectionUtil
.
isEmpty
(
resumeData
)
&&
resumeData
!=
null
){
List
<
ResumeBaseVo
>
voList
=
new
ArrayList
<>();
for
(
String
resumeDatum
:
resumeData
)
{
ResumeBaseVo
baseVo
=
JSON
.
parseObject
(
resumeDatum
,
ResumeBaseVo
.
class
);
voList
.
add
(
baseVo
);
}
return
voList
;
}
return
List
.
of
();
}
@Override
public
void
delResumeCache
(
Long
resumeId
,
Long
userId
)
{
String
key
=
REDIS_RESUME_LIST_KEY
.
formatted
(
userId
);
Set
<
String
>
resumeData
=
redisTemplate
.
opsForZSet
().
range
(
key
,
0
,
-
1
);
if
(
CollectionUtil
.
isEmpty
(
resumeData
)
&&
resumeData
!=
null
){
for
(
String
resumeDatum
:
resumeData
)
{
ResumeBaseVo
baseVo
=
JSON
.
parseObject
(
resumeDatum
,
ResumeBaseVo
.
class
);
if
(
baseVo
.
getResumeId
().
equals
(
resumeId
)){
redisTemplate
.
opsForZSet
().
remove
(
key
,
resumeDatum
);
break
;
}
}
}
}
@Override
public
void
saveResumeModelListCache
(
FunctionResumeModel
model
,
Long
resumeId
)
{
String
key
=
REDIS_RESUME_MODEL_LIST_KEY
.
formatted
(
resumeId
);
redisTemplate
.
opsForHash
().
put
(
key
,
String
.
valueOf
(
model
.
getId
()),
JSON
.
toJSONString
(
model
));
}
private
ResumeModelVo
initModelVo
(
FunctionResumeModel
m
)
{
ResumeModelVo
modelVo
=
new
ResumeModelVo
();
modelVo
.
setModelId
(
m
.
getId
());
modelVo
.
setModelType
(
m
.
getModelType
());
if
(
m
.
getIsShow
()
!=
null
){
modelVo
.
setIsShow
(
m
.
getIsShow
());
}
modelVo
.
setDataSort
(
m
.
getDataSort
());
modelVo
.
setModelName
(
m
.
getModelName
());
modelVo
.
setWebCode
(
ResumeEnum
.
ResumeModel
.
getWebCodeByCode
(
m
.
getModelType
()));
return
modelVo
;
}
@Override
public
List
<
ResumeModelVo
>
queryResumeModelCache
(
Long
resumeId
)
{
String
key
=
REDIS_RESUME_MODEL_LIST_KEY
.
formatted
(
resumeId
);
List
<
Object
>
values
=
redisTemplate
.
opsForHash
().
values
(
key
);
if
(
CollectionUtil
.
isNotEmpty
(
values
)){
// 使用 fastjson 将 JSON 字符串转换成 ResumeModelVo 对象
List
<
FunctionResumeModel
>
collect
=
values
.
stream
()
.
map
(
value
->
JSON
.
parseObject
(
value
.
toString
(),
FunctionResumeModel
.
class
))
.
toList
();
List
<
ResumeModelVo
>
dataVoList
=
new
ArrayList
<>();
for
(
FunctionResumeModel
model
:
collect
)
{
dataVoList
.
add
(
initModelVo
(
model
));
}
return
dataVoList
;
}
return
List
.
of
();
}
@Override
public
void
delResumeModelCache
(
Long
modelId
,
Long
resumeId
)
{
String
key
=
REDIS_RESUME_MODEL_LIST_KEY
.
formatted
(
resumeId
);
redisTemplate
.
opsForHash
().
delete
(
key
,
String
.
valueOf
(
modelId
));
}
@Override
public
void
saveResumeModelDataCache
(
Long
modelId
,
Long
resumeId
,
String
jsonData
)
{
String
key
=
REDIS_RESUME_MODEL_DATA_KEY
.
formatted
(
resumeId
,
modelId
);
redisTemplate
.
opsForValue
().
set
(
key
,
jsonData
);
}
@Override
public
String
queryResumeModelDataCache
(
Long
modelId
,
Long
resumeId
)
{
String
key
=
REDIS_RESUME_MODEL_DATA_KEY
.
formatted
(
resumeId
,
modelId
);
return
redisTemplate
.
opsForValue
().
get
(
key
);
}
@Override
public
void
delResumeModelDataCache
(
Long
modelId
,
Long
resumeId
)
{
String
key
=
REDIS_RESUME_MODEL_DATA_KEY
.
formatted
(
resumeId
,
modelId
);
redisTemplate
.
delete
(
key
);
}
@Override
public
void
updateModelSort
(
ResumeMakeDto
dto
)
{
String
key
=
REDIS_RESUME_MODEL_LIST_KEY
.
formatted
(
dto
.
getResumeId
());
Map
<
Object
,
Object
>
entries
=
redisTemplate
.
opsForHash
().
entries
(
key
);
if
(
MapUtil
.
isEmpty
(
entries
)){
return
;
}
if
(
CollectionUtil
.
isEmpty
(
dto
.
getModelSort
())){
entries
.
forEach
((
k
,
v
)->{
FunctionResumeModel
modelVo
=
JSON
.
parseObject
(
v
.
toString
(),
FunctionResumeModel
.
class
);
modelVo
.
setIsShow
(
1
);
redisTemplate
.
opsForHash
().
put
(
key
,
k
.
toString
(),
JSON
.
toJSONString
(
modelVo
));
});
}
else
{
Set
<
Long
>
modelIdSet
=
dto
.
getModelSort
().
keySet
();
entries
.
forEach
((
k
,
v
)->{
FunctionResumeModel
modelVo
=
JSON
.
parseObject
(
v
.
toString
(),
FunctionResumeModel
.
class
);
Long
modelId
=
Long
.
valueOf
(
k
.
toString
());
if
(
modelIdSet
.
contains
(
modelId
)){
modelVo
.
setDataSort
(
dto
.
getModelSort
().
get
(
modelId
));
modelVo
.
setIsShow
(
0
);
}
else
{
modelVo
.
setIsShow
(
1
);
}
redisTemplate
.
opsForHash
().
put
(
key
,
k
.
toString
(),
JSON
.
toJSONString
(
modelVo
));
});
}
}
private
final
static
String
RESUME_MODEL_OPTIMIZATION_KEY
=
"resume:model:optimization:%s"
;
@Override
public
void
refreshModelOptimization
(
FunctionResumeModelOptimization
optimization
)
{
String
key
=
RESUME_MODEL_OPTIMIZATION_KEY
.
formatted
(
optimization
.
getResumeId
());
//判断有没有这个key
if
(
Boolean
.
TRUE
.
equals
(
redisTemplate
.
hasKey
(
key
))){
//hash类型删除这个元素
redisTemplate
.
opsForHash
().
delete
(
key
,
optimization
.
getModelCode
());
}
//添加这个元素
ResumeModelOptimizationCache
optimizationCache
=
new
ResumeModelOptimizationCache
();
optimizationCache
.
setRunStatus
(
optimization
.
getRunStatus
());
optimizationCache
.
setOptimizationDesc
(
optimization
.
getOptimizationDesc
());
optimizationCache
.
setUpdateTime
(
DateTimeWrapper
.
parseFromLocalDateTime
(
optimization
.
getUpdateTime
().
toInstant
()
.
atZone
(
ZoneId
.
of
(
"Asia/Shanghai"
))
.
toLocalDateTime
(),
null
).
toString
());
redisTemplate
.
opsForHash
().
put
(
key
,
optimization
.
getModelCode
(),
JSON
.
toJSONString
(
optimizationCache
));
redisTemplate
.
expire
(
key
,
30
,
TimeUnit
.
MINUTES
);
}
@Override
public
Map
<
String
,
ResumeModelOptimizationCache
>
queryResumeModelOptimization
(
Long
id
,
Long
resumeId
)
{
String
key
=
RESUME_MODEL_OPTIMIZATION_KEY
.
formatted
(
resumeId
);
if
(
Boolean
.
TRUE
.
equals
(
redisTemplate
.
hasKey
(
key
))){
Map
<
Object
,
Object
>
entries
=
redisTemplate
.
opsForHash
().
entries
(
key
);
Map
<
String
,
ResumeModelOptimizationCache
>
result
=
new
HashMap
<>();
for
(
Map
.
Entry
<
Object
,
Object
>
entry
:
entries
.
entrySet
())
{
String
field
=
entry
.
getKey
().
toString
();
ResumeModelOptimizationCache
cache
=
JSON
.
parseObject
(
entry
.
getValue
().
toString
(),
ResumeModelOptimizationCache
.
class
);
result
.
put
(
field
,
cache
);
}
return
result
;
}
else
{
return
null
;
}
}
private
final
static
String
REDIS_RESUME_LIST_KEY_V2
=
"resume:list:v2:%s"
;
@Override
public
List
<
ResumeListItemCache
>
queryResumeList
(
Long
userId
)
{
String
key
=
REDIS_RESUME_LIST_KEY_V2
.
formatted
(
userId
);
if
(
Boolean
.
TRUE
.
equals
(
redisTemplate
.
hasKey
(
key
))){
//过滤出resumeId不为空
return
redisTemplate
.
opsForZSet
().
range
(
key
,
0
,
-
1
).
stream
()
.
filter
(
resumeData
->
{
ResumeListItemCache
resumeListItemCache
=
JSON
.
parseObject
(
resumeData
,
ResumeListItemCache
.
class
);
return
resumeListItemCache
.
getResumeId
()
!=
null
;
}).
map
(
resumeData
->
JSON
.
parseObject
(
resumeData
,
ResumeListItemCache
.
class
))
.
collect
(
Collectors
.
toList
());
}
else
{
//存入一个空数组
return
null
;
}
}
@Override
public
void
refreshResumeListCache
(
List
<
ResumeListItemCache
>
caches
,
Long
userId
)
{
String
key
=
REDIS_RESUME_LIST_KEY_V2
.
formatted
(
userId
);
if
(
Boolean
.
TRUE
.
equals
(
redisTemplate
.
hasKey
(
key
))){
redisTemplate
.
delete
(
key
);
}
if
(
CollectionUtil
.
isNotEmpty
(
caches
)){
for
(
ResumeListItemCache
cache
:
caches
)
{
redisTemplate
.
opsForZSet
().
add
(
key
,
JSON
.
toJSONString
(
cache
),
DateTimeWrapper
.
parse
(
cache
.
getUpdateTime
(),
null
).
getDate
().
getTime
());
redisTemplate
.
expire
(
key
,
1
,
TimeUnit
.
DAYS
);
}
}
else
{
redisTemplate
.
opsForZSet
().
add
(
key
,
JSON
.
toJSONString
(
new
ResumeListItemCache
()),
System
.
currentTimeMillis
());
redisTemplate
.
expire
(
key
,
1
,
TimeUnit
.
DAYS
);
}
}
private
final
static
String
REDIS_RESUME_TEMPLATE_KEY
=
"resumeTemplate:%s"
;
/**
* 简历缓存模版信息
*/
@Override
public
void
saveResumeTemplateCache
(
Map
<
String
,
Object
>
templateMap
,
String
resumeId
)
{
String
key
=
REDIS_RESUME_TEMPLATE_KEY
.
formatted
(
resumeId
);
if
(
Boolean
.
TRUE
.
equals
(
redisTemplate
.
hasKey
(
key
))){
redisTemplate
.
delete
(
key
);
}
if
(
templateMap
!=
null
){
redisTemplate
.
opsForValue
().
set
(
key
,
JSON
.
toJSONString
(
templateMap
));
}
}
@Override
public
void
delResumeListCache
(
Long
userId
)
{
String
key
=
REDIS_RESUME_LIST_KEY_V2
.
formatted
(
userId
);
redisTemplate
.
delete
(
key
);
}
}
employmentBusiness-pc-nacos/src/main/resources/static/console-ui/public/css/fonts/roboto-bold.ttf
0 → 100644
View file @
613f3bfd
No preview for this file type
employmentBusiness-pc-nacos/src/main/resources/static/console-ui/public/css/fonts/roboto-bold.woff
0 → 100644
View file @
613f3bfd
No preview for this file type
employmentBusiness-pc-nacos/src/main/resources/static/console-ui/public/fonts/roboto-bold.eot
0 → 100644
View file @
613f3bfd
No preview for this file type
employmentBusiness-pc-nacos/src/main/resources/static/console-ui/public/fonts/roboto-bold.ttf
0 → 100644
View file @
613f3bfd
No preview for this file type
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment