初始化
This commit is contained in:
parent
1b1128e82e
commit
f5c4bbbef3
4
enfi-boot-visitor/.gitattributes
vendored
Normal file
4
enfi-boot-visitor/.gitattributes
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.js linguist-language=Java
|
||||
*.css linguist-language=Java
|
||||
*.html linguist-language=Java
|
||||
*.vue linguist-language=Java
|
4
enfi-boot-visitor/.gitignore
vendored
Normal file
4
enfi-boot-visitor/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/target/
|
||||
/.idea/
|
||||
*.iml
|
||||
rebel.xml
|
13
enfi-boot-visitor/db/Dockerfile
Normal file
13
enfi-boot-visitor/db/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM mysql:8.0.19
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
COPY ./tables_nacos.sql /docker-entrypoint-initdb.d
|
||||
|
||||
COPY ./jeecgboot-mysql-5.7.sql /docker-entrypoint-initdb.d
|
||||
|
||||
COPY ./tables_xxl_job.sql /docker-entrypoint-initdb.d
|
7643
enfi-boot-visitor/db/enfi-visitor.sql
Normal file
7643
enfi-boot-visitor/db/enfi-visitor.sql
Normal file
File diff suppressed because one or more lines are too long
51
enfi-boot-visitor/docker-compose-server.yml
Normal file
51
enfi-boot-visitor/docker-compose-server.yml
Normal file
@ -0,0 +1,51 @@
|
||||
#### 镜像上传
|
||||
# 仓库私服: 81.70.17.111:5000
|
||||
# 第一步:上传镜像到docker仓库
|
||||
#docker tag enfi-boot-mysql 81.70.17.111:5000/enfi-boot-mysql:1.1
|
||||
#docker tag enfi-boot-system 81.70.17.111:5000/enfi-boot-system:1.0
|
||||
#docker tag nginxhtml:jeecgboot 81.70.17.111:5000/nginxhtml:1.2
|
||||
|
||||
#docker push 81.70.17.111:5000/enfi-boot-mysql:1.1
|
||||
#docker push 81.70.17.111:5000/enfi-boot-system:1.0
|
||||
#docker push 81.70.17.111:5000/nginxhtml:1.2
|
||||
|
||||
# 第二步:将此yml文件上传服务器,执行启动命令 docker-compose -f ./docker-compose-server.yml up
|
||||
version: '2'
|
||||
services:
|
||||
enfi-boot-mysql:
|
||||
image: 81.70.17.111:5000/enfi-boot-mysql:1.0
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
restart: always
|
||||
container_name: enfi-boot-mysql
|
||||
command:
|
||||
--character-set-server=utf8mb4
|
||||
--collation-server=utf8mb4_general_ci
|
||||
--explicit_defaults_for_timestamp=true
|
||||
--lower_case_table_names=1
|
||||
--max_allowed_packet=128M
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
enfi-boot-redis:
|
||||
image: redis:5.0
|
||||
ports:
|
||||
- 6379:6379
|
||||
restart: always
|
||||
container_name: enfi-boot-redis
|
||||
|
||||
enfi-boot-system:
|
||||
image: 81.70.17.111:5000/enfi-boot-system:1.0
|
||||
restart: always
|
||||
container_name: enfi-boot-system
|
||||
volumes:
|
||||
- /data/config:/enfi-boot/config
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
||||
enfi-boot-nginx:
|
||||
image: 81.70.17.111:5000/nginxhtml
|
||||
restart: always
|
||||
container_name: enfi-boot-nginx
|
||||
ports:
|
||||
- 80:80
|
42
enfi-boot-visitor/docker-compose.yml
Normal file
42
enfi-boot-visitor/docker-compose.yml
Normal file
@ -0,0 +1,42 @@
|
||||
version: '2'
|
||||
services:
|
||||
enfi-boot-mysql:
|
||||
build:
|
||||
context: ./db
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_ROOT_HOST: '%'
|
||||
TZ: Asia/Shanghai
|
||||
restart: always
|
||||
container_name: enfi-boot-mysql
|
||||
image: enfi-boot-mysql
|
||||
command:
|
||||
--character-set-server=utf8mb4
|
||||
--collation-server=utf8mb4_general_ci
|
||||
--explicit_defaults_for_timestamp=true
|
||||
--lower_case_table_names=1
|
||||
--max_allowed_packet=128M
|
||||
--default-authentication-plugin=caching_sha2_password
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
enfi-boot-redis:
|
||||
image: redis:5.0
|
||||
ports:
|
||||
- 6379:6379
|
||||
restart: always
|
||||
hostname: enfi-boot-redis
|
||||
container_name: enfi-boot-redis
|
||||
|
||||
enfi-boot-system:
|
||||
build:
|
||||
context: ./enfi-boot-module-system
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
- enfi-boot-mysql
|
||||
- enfi-boot-redis
|
||||
container_name: enfi-boot-system
|
||||
image: enfi-boot-system
|
||||
hostname: enfi-boot-system
|
||||
ports:
|
||||
- 8080:8080
|
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>enfi-boot-base-api</artifactId>
|
||||
<groupId>org.enfiframework.boot</groupId>
|
||||
<version>3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>enfi-system-local-api</artifactId>
|
||||
|
||||
</project>
|
@ -0,0 +1,55 @@
|
||||
package org.enfi.common.bpm.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.enfi.common.api.vo.Result;
|
||||
import org.enfi.common.system.vo.DictModel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
/**
|
||||
* 流程接口
|
||||
*
|
||||
* @author scott
|
||||
*/
|
||||
public interface IBpmBaseExtAPI {
|
||||
/**
|
||||
* 23. 流程提交接口(online,自定义开发)
|
||||
* @param flowCode 流程业务关联 例如:joa_leave_01
|
||||
* @param id 表单业务数据data id
|
||||
* @param formUrl 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username 流程发起人账号
|
||||
* @param jsonData Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Result<String> startMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,String username, String jsonData) throws Exception;
|
||||
|
||||
/**
|
||||
* 24. 流程提交接口(自定义表单设计器)
|
||||
* @param flowCode 流程业务关联 例如:joa_leave_01
|
||||
* @param id 表单业务数据data id
|
||||
* @param formUrl 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username 流程发起人账号
|
||||
* @param jsonData Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Result<String> startDesFormMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,String username,String jsonData) throws Exception;
|
||||
/**
|
||||
* 25. 保存流程草稿箱接口(自定义开发表单、online表单)
|
||||
* @param flowCode 流程业务关联 例如:joa_leave_01
|
||||
* @param id 表单业务数据data id
|
||||
* @param formUrl 流程审批时附件页面默认展示的PC端表单组件(地址) 【非必填】
|
||||
* @param formUrlMobile 流程审批时附件页面默认展示的移动端表单组件(地址) 【非必填】
|
||||
* @param username 流程发起人账号
|
||||
* @param jsonData Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Result<String> saveMutilProcessDraft(String flowCode, String id, String formUrl, String formUrlMobile,String username,String jsonData) throws Exception;
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package org.enfi.common.online.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.enfi.common.system.vo.DictModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 表单设计器【Online】翻译API接口
|
||||
*
|
||||
* @author sunjianlei
|
||||
*/
|
||||
public interface IOnlineBaseExtAPI {
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步新增
|
||||
*/
|
||||
String cgformPostCrazyForm(String tableName, JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步编辑
|
||||
*/
|
||||
String cgformPutCrazyForm(String tableName, JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* online表单删除数据
|
||||
*
|
||||
* @param cgformCode Online表单code
|
||||
* @param dataIds 数据ID,可逗号分割
|
||||
* @return
|
||||
*/
|
||||
String cgformDeleteDataByCode(String cgformCode, String dataIds);
|
||||
|
||||
/**
|
||||
* 通过online表名查询数据,同时查询出子表的数据
|
||||
*
|
||||
* @param tableName online表名
|
||||
* @param dataIds online数据ID
|
||||
* @return
|
||||
*/
|
||||
JSONObject cgformQueryAllDataByTableName(String tableName, String dataIds);
|
||||
|
||||
/**
|
||||
* 对 cgreportGetData 的返回值做优化,封装 DictModel 集合
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> cgreportGetDataPackage(String code, String dictText, String dictCode, String dataList);
|
||||
|
||||
/**
|
||||
* 【cgreport】通过 head code 获取 sql语句,并执行该语句返回查询数据
|
||||
*
|
||||
* @param code 报表Code,如果没传ID就通过code查
|
||||
* @param forceKey
|
||||
* @param dataList
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> cgreportGetData(String code, String forceKey, String dataList);
|
||||
|
||||
}
|
@ -0,0 +1,330 @@
|
||||
package org.enfi.common.system.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.enfi.common.api.CommonAPI;
|
||||
import org.enfi.common.api.dto.OnlineAuthDTO;
|
||||
import org.enfi.common.api.dto.message.*;
|
||||
import org.enfi.common.system.vo.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Description 底层共通业务API,提供其他独立模块调用
|
||||
* @Author scott
|
||||
* @Date 2019-4-20
|
||||
* @Version V1.0
|
||||
*/
|
||||
public interface ISysBaseAPI extends CommonAPI {
|
||||
|
||||
|
||||
/**
|
||||
* 1发送系统消息
|
||||
* @param message 使用构造器赋值参数 如果不设置category(消息类型)则默认为2 发送系统消息
|
||||
*/
|
||||
void sendSysAnnouncement(MessageDTO message);
|
||||
|
||||
/**
|
||||
* 2发送消息 附带业务参数
|
||||
* @param message 使用构造器赋值参数
|
||||
*/
|
||||
void sendBusAnnouncement(BusMessageDTO message);
|
||||
|
||||
/**
|
||||
* 3通过模板发送消息
|
||||
* @param message 使用构造器赋值参数
|
||||
*/
|
||||
void sendTemplateAnnouncement(TemplateMessageDTO message);
|
||||
|
||||
/**
|
||||
* 4通过模板发送消息 附带业务参数
|
||||
* @param message 使用构造器赋值参数
|
||||
*/
|
||||
void sendBusTemplateAnnouncement(BusTemplateMessageDTO message);
|
||||
|
||||
/**
|
||||
* 5通过消息中心模板,生成推送内容
|
||||
* @param templateDTO 使用构造器赋值参数
|
||||
* @return
|
||||
*/
|
||||
String parseTemplateByCode(TemplateDTO templateDTO);
|
||||
|
||||
/**
|
||||
* 6根据用户id查询用户信息
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
LoginUser getUserById(String id);
|
||||
|
||||
/**
|
||||
* 7通过用户账号查询角色集合
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
List<String> getRolesByUsername(String username);
|
||||
|
||||
/**
|
||||
* 8通过用户账号查询部门集合
|
||||
* @param username
|
||||
* @return 部门 id
|
||||
*/
|
||||
List<String> getDepartIdsByUsername(String username);
|
||||
|
||||
/**
|
||||
* 9通过用户账号查询部门 name
|
||||
* @param username
|
||||
* @return 部门 name
|
||||
*/
|
||||
List<String> getDepartNamesByUsername(String username);
|
||||
|
||||
|
||||
|
||||
/** 11查询所有的父级字典,按照create_time排序 */
|
||||
public List<DictModel> queryAllDict();
|
||||
|
||||
/**
|
||||
* 12查询所有分类字典
|
||||
* @return
|
||||
*/
|
||||
public List<SysCategoryModel> queryAllDSysCategory();
|
||||
|
||||
|
||||
/**
|
||||
* 14查询所有部门 作为字典信息 id -->value,departName -->text
|
||||
* @return
|
||||
*/
|
||||
public List<DictModel> queryAllDepartBackDictModel();
|
||||
|
||||
/**
|
||||
* 15根据业务类型及业务id修改消息已读
|
||||
* @param busType
|
||||
* @param busId
|
||||
*/
|
||||
public void updateSysAnnounReadFlag(String busType, String busId);
|
||||
|
||||
/**
|
||||
* 16查询表字典 支持过滤数据
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param filterSql
|
||||
* @return
|
||||
*/
|
||||
public List<DictModel> queryFilterTableDictInfo(String table, String text, String code, String filterSql);
|
||||
|
||||
/**
|
||||
* 17查询指定table的 text code 获取字典,包含text和value
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keyArray
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public List<String> queryTableDictByKeys(String table, String text, String code, String[] keyArray);
|
||||
|
||||
/**
|
||||
* 18查询所有用户 返回ComboModel
|
||||
* @return
|
||||
*/
|
||||
public List<ComboModel> queryAllUserBackCombo();
|
||||
|
||||
/**
|
||||
* 19分页查询用户 返回JSONObject
|
||||
* @return
|
||||
*/
|
||||
public JSONObject queryAllUser(String userIds, Integer pageNo, Integer pageSize);
|
||||
|
||||
/**
|
||||
* 20获取所有角色
|
||||
* @return
|
||||
*/
|
||||
public List<ComboModel> queryAllRole();
|
||||
|
||||
/**
|
||||
* 21获取所有角色 带参
|
||||
* roleIds 默认选中角色
|
||||
* @return
|
||||
*/
|
||||
public List<ComboModel> queryAllRole(String[] roleIds );
|
||||
|
||||
/**
|
||||
* 22通过用户账号查询角色Id集合
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
public List<String> getRoleIdsByUsername(String username);
|
||||
|
||||
/**
|
||||
* 23通过部门编号查询部门id
|
||||
* @param orgCode
|
||||
* @return
|
||||
*/
|
||||
public String getDepartIdsByOrgCode(String orgCode);
|
||||
|
||||
/**
|
||||
* 24查询所有部门
|
||||
* @return
|
||||
*/
|
||||
public List<SysDepartModel> getAllSysDepart();
|
||||
|
||||
/**
|
||||
* 25查找父级部门
|
||||
* @param departId
|
||||
* @return
|
||||
*/
|
||||
DictModel getParentDepartId(String departId);
|
||||
|
||||
/**
|
||||
* 26根据部门Id获取部门负责人
|
||||
* @param deptId
|
||||
* @return
|
||||
*/
|
||||
public List<String> getDeptHeadByDepId(String deptId);
|
||||
|
||||
/**
|
||||
* 27给指定用户发消息
|
||||
* @param userIds
|
||||
* @param cmd
|
||||
*/
|
||||
public void sendWebSocketMsg(String[] userIds, String cmd);
|
||||
|
||||
/**
|
||||
* 28根据id获取所有参与用户
|
||||
* userIds
|
||||
* @return
|
||||
*/
|
||||
public List<LoginUser> queryAllUserByIds(String[] userIds);
|
||||
|
||||
/**
|
||||
* 29将会议签到信息推动到预览
|
||||
* userIds
|
||||
* @return
|
||||
* @param userId
|
||||
*/
|
||||
void meetingSignWebsocket(String userId);
|
||||
|
||||
/**
|
||||
* 30根据name获取所有参与用户
|
||||
* userNames
|
||||
* @return
|
||||
*/
|
||||
List<LoginUser> queryUserByNames(String[] userNames);
|
||||
|
||||
|
||||
/**
|
||||
* 31获取用户的角色集合
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
Set<String> getUserRoleSet(String username);
|
||||
|
||||
/**
|
||||
* 32获取用户的权限集合
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
Set<String> getUserPermissionSet(String username);
|
||||
|
||||
/**
|
||||
* 33判断是否有online访问的权限
|
||||
* @param onlineAuthDTO
|
||||
* @return
|
||||
*/
|
||||
boolean hasOnlineAuth(OnlineAuthDTO onlineAuthDTO);
|
||||
|
||||
/**
|
||||
* 34通过部门id获取部门全部信息
|
||||
*/
|
||||
SysDepartModel selectAllById(String id);
|
||||
|
||||
/**
|
||||
* 35根据用户id查询用户所属公司下所有用户ids
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<String> queryDeptUsersByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 36根据多个用户账号(逗号分隔),查询返回多个用户信息
|
||||
* @param usernames
|
||||
* @return
|
||||
*/
|
||||
List<JSONObject> queryUsersByUsernames(String usernames);
|
||||
|
||||
/**
|
||||
* 37根据多个用户ID(逗号分隔),查询返回多个用户信息
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
List<JSONObject> queryUsersByIds(String ids);
|
||||
|
||||
/**
|
||||
* 38根据多个部门编码(逗号分隔),查询返回多个部门信息
|
||||
* @param orgCodes
|
||||
* @return
|
||||
*/
|
||||
List<JSONObject> queryDepartsByOrgcodes(String orgCodes);
|
||||
|
||||
/**
|
||||
* 39根据多个部门id(逗号分隔),查询返回多个部门信息
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
List<JSONObject> queryDepartsByIds(String ids);
|
||||
|
||||
/**
|
||||
* 40发送邮件消息
|
||||
* @param email
|
||||
* @param title
|
||||
* @param content
|
||||
*/
|
||||
void sendEmailMsg(String email,String title,String content);
|
||||
/**
|
||||
* 41 获取公司下级部门和公司下所有用户信息
|
||||
* @param orgCode
|
||||
*/
|
||||
List<Map> getDeptUserByOrgCode(String orgCode);
|
||||
|
||||
/**
|
||||
* 查询分类字典翻译
|
||||
*/
|
||||
List<String> loadCategoryDictItem(String ids);
|
||||
|
||||
/**
|
||||
* 根据字典code加载字典text
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param keys 要查询的key
|
||||
* @return
|
||||
*/
|
||||
List<String> loadDictItem(String dictCode, String keys);
|
||||
|
||||
/**
|
||||
* 根据字典code查询字典项
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param dictCode 要查询的key
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> getDictItems(String dictCode);
|
||||
|
||||
/**
|
||||
* 根据多个字典code查询多个字典项
|
||||
* @param dictCodeList
|
||||
* @return key = dictCode ; value=对应的字典项
|
||||
*/
|
||||
Map<String, List<DictModel>> getManyDictItems(List<String> dictCodeList);
|
||||
|
||||
/**
|
||||
* 【JSearchSelectTag下拉搜索组件专用接口】
|
||||
* 大数据量的字典表 走异步加载 即前端输入内容过滤数据
|
||||
*
|
||||
* @param dictCode 字典code格式:table,text,code
|
||||
* @param keyword 过滤关键字
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize);
|
||||
|
||||
}
|
26
enfi-boot-visitor/enfi-boot-base/enfi-boot-base-api/pom.xml
Normal file
26
enfi-boot-visitor/enfi-boot-base/enfi-boot-base-api/pom.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>enfi-boot-base</artifactId>
|
||||
<groupId>org.enfiframework.boot</groupId>
|
||||
<version>3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>enfi-boot-base-api</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>enfi-system-local-api</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.enfiframework.boot</groupId>
|
||||
<artifactId>enfi-boot-base-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
251
enfi-boot-visitor/enfi-boot-base/enfi-boot-base-core/pom.xml
Normal file
251
enfi-boot-visitor/enfi-boot-base/enfi-boot-base-core/pom.xml
Normal file
@ -0,0 +1,251 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.enfiframework.boot</groupId>
|
||||
<artifactId>enfi-boot-base</artifactId>
|
||||
<version>3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>enfi-boot-base-core</artifactId>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>aliyun</id>
|
||||
<name>aliyun Repository</name>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>enfi</id>
|
||||
<name>enfi Repository</name>
|
||||
<url>https://maven.enfi.org/nexus/content/repositories/enfi</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<!--enfi-tools-->
|
||||
<dependency>
|
||||
<groupId>org.enfiframework.boot</groupId>
|
||||
<artifactId>enfi-boot-base-tools</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!--jfinal weixin-->
|
||||
<dependency>
|
||||
<groupId>net.dreamlu</groupId>
|
||||
<artifactId>mica-weixin</artifactId>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
<!--集成springmvc框架并实现自动配置 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!-- websocket -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<!--springboot2.3+ 需引入validation对应的包-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- commons -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>${commons.version}</version>
|
||||
</dependency>
|
||||
<!-- freemarker -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- mybatis-plus -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- druid -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 动态数据源 -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>${dynamic-datasource-spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>hibernate-re</artifactId>
|
||||
<version>3.0.0-beta</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 数据库驱动 -->
|
||||
<!--mysql-->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql-connector-java.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!-- sqlserver-->
|
||||
<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
<artifactId>sqljdbc4</artifactId>
|
||||
<version>${sqljdbc4.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!-- oracle驱动 -->
|
||||
<dependency>
|
||||
<groupId>com.oracle</groupId>
|
||||
<artifactId>ojdbc6</artifactId>
|
||||
<version>${ojdbc6.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!-- postgresql驱动 -->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${postgresql.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Quartz定时任务 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-quartz</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--JWT-->
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>${java-jwt.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--shiro-->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring-boot-starter</artifactId>
|
||||
<version>${shiro.version}</version>
|
||||
</dependency>
|
||||
<!-- shiro-redis -->
|
||||
<dependency>
|
||||
<groupId>org.crazycake</groupId>
|
||||
<artifactId>shiro-redis</artifactId>
|
||||
<version>${shiro-redis.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- knife4j -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||
<version>${knife4j-spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
<!-- 代码生成器 -->
|
||||
<!-- 如下载失败,请参考此文档 http://doc.enfi.com/2043876 -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>codegenerate</artifactId>
|
||||
<version>${codegenerate.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- AutoPoi Excel工具类-->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework</groupId>
|
||||
<artifactId>autopoi-web</artifactId>
|
||||
<version>${autopoi-web.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- mini文件存储服务 -->
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里云短信 -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||
<version>${aliyun-java-sdk-dysmsapi.version}</version>
|
||||
</dependency>
|
||||
<!-- aliyun oss -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>${aliyun.oss.version}</version>
|
||||
</dependency>
|
||||
<!-- 第三方登录 -->
|
||||
<dependency>
|
||||
<groupId>com.xkcoding.justauth</groupId>
|
||||
<artifactId>justauth-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,123 @@
|
||||
package org.enfi.common.api;
|
||||
|
||||
import org.enfi.common.system.vo.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface CommonAPI {
|
||||
|
||||
/**
|
||||
* 1查询用户角色信息
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
Set<String> queryUserRoles(String username);
|
||||
|
||||
|
||||
/**
|
||||
* 2查询用户权限信息
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
Set<String> queryUserAuths(String username);
|
||||
|
||||
/**
|
||||
* 3根据 id 查询数据库中存储的 DynamicDataSourceModel
|
||||
*
|
||||
* @param dbSourceId
|
||||
* @return
|
||||
*/
|
||||
DynamicDataSourceModel getDynamicDbSourceById(String dbSourceId);
|
||||
|
||||
/**
|
||||
* 4根据 code 查询数据库中存储的 DynamicDataSourceModel
|
||||
*
|
||||
* @param dbSourceCode
|
||||
* @return
|
||||
*/
|
||||
DynamicDataSourceModel getDynamicDbSourceByCode(String dbSourceCode);
|
||||
|
||||
/**
|
||||
* 5根据用户账号查询用户信息
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
public LoginUser getUserByName(String username);
|
||||
|
||||
|
||||
/**
|
||||
* 6字典表的 翻译
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
String translateDictFromTable(String table, String text, String code, String key);
|
||||
|
||||
/**
|
||||
* 7普通字典的翻译
|
||||
* @param code
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
String translateDict(String code, String key);
|
||||
|
||||
/**
|
||||
* 8查询数据权限
|
||||
* @return
|
||||
*/
|
||||
List<SysPermissionDataRuleModel> queryPermissionDataRule(String component, String requestPath, String username);
|
||||
|
||||
|
||||
/**
|
||||
* 9查询用户信息
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
SysUserCacheInfo getCacheUser(String username);
|
||||
|
||||
/**
|
||||
* 10获取数据字典
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public List<DictModel> queryDictItemsByCode(String code);
|
||||
|
||||
/**
|
||||
* 获取有效的数据字典项
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public List<DictModel> queryEnableDictItemsByCode(String code);
|
||||
|
||||
/**
|
||||
* 13获取表数据字典
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> queryTableDictItemsByCode(String table, String text, String code);
|
||||
|
||||
/**
|
||||
* 14 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割
|
||||
* @param dictCodes 例如:user_status,sex
|
||||
* @param keys 例如:1,2,0
|
||||
* @return
|
||||
*/
|
||||
Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys);
|
||||
|
||||
/**
|
||||
* 15 字典表的 翻译,可批量
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys 多个用逗号分割
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys);
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package org.enfi.common.api;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jfinal.weixin.sdk.api.AccessToken;
|
||||
import com.jfinal.weixin.sdk.api.AccessTokenApi;
|
||||
import com.jfinal.weixin.sdk.api.ApiConfigKit;
|
||||
import com.jfinal.weixin.sdk.api.ApiResult;
|
||||
import com.jfinal.weixin.sdk.kit.ParaMap;
|
||||
import com.jfinal.weixin.sdk.utils.HttpUtils;
|
||||
import org.enfi.config.WXConfig;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class TemplateMsgApi {
|
||||
private static String sendApiUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";
|
||||
|
||||
public static ApiResult send(Map params) {
|
||||
// String post = HttpUtil.post(sendApiUrl + getToken(), JSONObject.toJSONString(params));
|
||||
AccessTokenApi.removeAccessToken();
|
||||
String post = HttpUtils.post(sendApiUrl + AccessTokenApi.getAccessToken().getAccessToken(), JSONObject.toJSONString(params));
|
||||
if (((Integer) new ApiResult(post).get("errcode")) != 0) {
|
||||
AccessTokenApi.refreshAccessToken(ApiConfigKit.getApiConfig());
|
||||
post = HttpUtils.post(sendApiUrl + AccessTokenApi.getAccessToken().getAccessToken(), JSONObject.toJSONString(params));
|
||||
}
|
||||
return new ApiResult(post);
|
||||
}
|
||||
|
||||
public static String getToken() {
|
||||
String json = HttpUtils.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential", ParaMap.create("appid", WXConfig.getAppId()).put("secret", WXConfig.getAppSecret()).getData());
|
||||
AccessToken accessToken = new AccessToken(json);
|
||||
System.out.println(accessToken);
|
||||
return accessToken.getAccessToken();
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package org.enfi.common.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 文件下载
|
||||
* cloud api 用到的接口传输对象
|
||||
*/
|
||||
@Data
|
||||
public class FileDownDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6749126258686446019L;
|
||||
|
||||
private String filePath;
|
||||
private String uploadpath;
|
||||
private String uploadType;
|
||||
private HttpServletResponse response;
|
||||
|
||||
public FileDownDTO(){}
|
||||
|
||||
public FileDownDTO(String filePath, String uploadpath, String uploadType,HttpServletResponse response){
|
||||
this.filePath = filePath;
|
||||
this.uploadpath = uploadpath;
|
||||
this.uploadType = uploadType;
|
||||
this.response = response;
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package org.enfi.common.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* cloud api 用到的接口传输对象
|
||||
*/
|
||||
@Data
|
||||
public class FileUploadDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4111953058578954386L;
|
||||
|
||||
private MultipartFile file;
|
||||
|
||||
private String bizPath;
|
||||
|
||||
private String uploadType;
|
||||
|
||||
private String customBucket;
|
||||
|
||||
public FileUploadDTO(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单上传 构造器1
|
||||
* @param file
|
||||
* @param bizPath
|
||||
* @param uploadType
|
||||
*/
|
||||
public FileUploadDTO(MultipartFile file,String bizPath,String uploadType){
|
||||
this.file = file;
|
||||
this.bizPath = bizPath;
|
||||
this.uploadType = uploadType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 申明桶 文件上传 构造器2
|
||||
* @param file
|
||||
* @param bizPath
|
||||
* @param uploadType
|
||||
* @param customBucket
|
||||
*/
|
||||
public FileUploadDTO(MultipartFile file,String bizPath,String uploadType,String customBucket){
|
||||
this.file = file;
|
||||
this.bizPath = bizPath;
|
||||
this.uploadType = uploadType;
|
||||
this.customBucket = customBucket;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package org.enfi.common.api.dto;
|
||||
import lombok.Data;
|
||||
import org.enfi.common.system.vo.LoginUser;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 日志对象
|
||||
* cloud api 用到的接口传输对象
|
||||
*/
|
||||
@Data
|
||||
public class LogDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8482720462943906924L;
|
||||
|
||||
/**内容*/
|
||||
private String logContent;
|
||||
|
||||
/**日志类型(0:操作日志;1:登录日志;2:定时任务) */
|
||||
private Integer logType;
|
||||
|
||||
/**操作类型(1:添加;2:修改;3:删除;) */
|
||||
private Integer operateType;
|
||||
|
||||
/**登录用户 */
|
||||
private LoginUser loginUser;
|
||||
|
||||
private String id;
|
||||
private String createBy;
|
||||
private Date createTime;
|
||||
private Long costTime;
|
||||
private String ip;
|
||||
|
||||
/**请求参数 */
|
||||
private String requestParam;
|
||||
|
||||
/**请求类型*/
|
||||
private String requestType;
|
||||
|
||||
/**请求路径*/
|
||||
private String requestUrl;
|
||||
|
||||
/**请求方法 */
|
||||
private String method;
|
||||
|
||||
/**操作人用户名称*/
|
||||
private String username;
|
||||
|
||||
/**操作人用户账户*/
|
||||
private String userid;
|
||||
|
||||
public LogDTO(){
|
||||
|
||||
}
|
||||
|
||||
public LogDTO(String logContent, Integer logType, Integer operatetype){
|
||||
this.logContent = logContent;
|
||||
this.logType = logType;
|
||||
this.operateType = operatetype;
|
||||
}
|
||||
|
||||
public LogDTO(String logContent, Integer logType, Integer operatetype, LoginUser loginUser){
|
||||
this.logContent = logContent;
|
||||
this.logType = logType;
|
||||
this.operateType = operatetype;
|
||||
this.loginUser = loginUser;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package org.enfi.common.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* online 拦截器权限判断
|
||||
* cloud api 用到的接口传输对象
|
||||
*/
|
||||
@Data
|
||||
public class OnlineAuthDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1771827545416418203L;
|
||||
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 可能的请求地址
|
||||
*/
|
||||
private List<String> possibleUrl;
|
||||
|
||||
/**
|
||||
* online开发的菜单地址
|
||||
*/
|
||||
private String onlineFormUrl;
|
||||
|
||||
public OnlineAuthDTO(){
|
||||
|
||||
}
|
||||
|
||||
public OnlineAuthDTO(String username, List<String> possibleUrl, String onlineFormUrl){
|
||||
this.username = username;
|
||||
this.possibleUrl = possibleUrl;
|
||||
this.onlineFormUrl = onlineFormUrl;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.enfi.common.api.dto.message;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 带业务参数的消息
|
||||
*/
|
||||
@Data
|
||||
public class BusMessageDTO extends MessageDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 9104793287983367669L;
|
||||
/**
|
||||
* 业务类型
|
||||
*/
|
||||
private String busType;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
private String busId;
|
||||
|
||||
public BusMessageDTO(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造 带业务参数的消息
|
||||
* @param fromUser
|
||||
* @param toUser
|
||||
* @param title
|
||||
* @param msgContent
|
||||
* @param msgCategory
|
||||
* @param busType
|
||||
* @param busId
|
||||
*/
|
||||
public BusMessageDTO(String fromUser, String toUser, String title, String msgContent, String msgCategory, String busType, String busId){
|
||||
super(fromUser, toUser, title, msgContent, msgCategory);
|
||||
this.busId = busId;
|
||||
this.busType = busType;
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package org.enfi.common.api.dto.message;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 带业务参数的模板消息
|
||||
*/
|
||||
@Data
|
||||
public class BusTemplateMessageDTO extends TemplateMessageDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4277810906346929459L;
|
||||
|
||||
/**
|
||||
* 业务类型
|
||||
*/
|
||||
private String busType;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
private String busId;
|
||||
|
||||
public BusTemplateMessageDTO(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造 带业务参数的模板消息
|
||||
* @param fromUser
|
||||
* @param toUser
|
||||
* @param title
|
||||
* @param templateParam
|
||||
* @param templateCode
|
||||
* @param busType
|
||||
* @param busId
|
||||
*/
|
||||
public BusTemplateMessageDTO(String fromUser, String toUser, String title, Map<String, String> templateParam, String templateCode, String busType, String busId){
|
||||
super(fromUser, toUser, title, templateParam, templateCode);
|
||||
this.busId = busId;
|
||||
this.busType = busType;
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package org.enfi.common.api.dto.message;
|
||||
|
||||
import lombok.Data;
|
||||
import org.enfi.common.constant.CommonConstant;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 普通消息
|
||||
*/
|
||||
@Data
|
||||
public class MessageDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5690444483968058442L;
|
||||
|
||||
/**
|
||||
* 发送人(用户登录账户)
|
||||
*/
|
||||
protected String fromUser;
|
||||
|
||||
/**
|
||||
* 发送给(用户登录账户)
|
||||
*/
|
||||
protected String toUser;
|
||||
|
||||
/**
|
||||
* 发送给所有人
|
||||
*/
|
||||
protected boolean toAll;
|
||||
|
||||
/**
|
||||
* 消息主题
|
||||
*/
|
||||
protected String title;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
protected String content;
|
||||
|
||||
/**
|
||||
* 消息类型 1:消息 2:系统消息
|
||||
*/
|
||||
protected String category;
|
||||
|
||||
|
||||
public MessageDTO(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造器1 系统消息
|
||||
*/
|
||||
public MessageDTO(String fromUser,String toUser,String title, String content){
|
||||
this.fromUser = fromUser;
|
||||
this.toUser = toUser;
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
//默认 都是2系统消息
|
||||
this.category = CommonConstant.MSG_CATEGORY_2;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造器2 支持设置category 1:消息 2:系统消息
|
||||
*/
|
||||
public MessageDTO(String fromUser,String toUser,String title, String content, String category){
|
||||
this.fromUser = fromUser;
|
||||
this.toUser = toUser;
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package org.enfi.common.api.dto.message;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 消息模板dto
|
||||
*/
|
||||
@Data
|
||||
public class TemplateDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 5848247133907528650L;
|
||||
|
||||
/**
|
||||
* 模板编码
|
||||
*/
|
||||
protected String templateCode;
|
||||
|
||||
/**
|
||||
* 模板参数
|
||||
*/
|
||||
protected Map<String, String> templateParam;
|
||||
|
||||
/**
|
||||
* 构造器 通过设置模板参数和模板编码 作为参数获取消息内容
|
||||
*/
|
||||
public TemplateDTO(String templateCode, Map<String, String> templateParam){
|
||||
this.templateCode = templateCode;
|
||||
this.templateParam = templateParam;
|
||||
}
|
||||
|
||||
public TemplateDTO(){
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package org.enfi.common.api.dto.message;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 模板消息
|
||||
*/
|
||||
@Data
|
||||
public class TemplateMessageDTO extends TemplateDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 411137565170647585L;
|
||||
|
||||
|
||||
/**
|
||||
* 发送人(用户登录账户)
|
||||
*/
|
||||
protected String fromUser;
|
||||
|
||||
/**
|
||||
* 发送给(用户登录账户)
|
||||
*/
|
||||
protected String toUser;
|
||||
|
||||
/**
|
||||
* 消息主题
|
||||
*/
|
||||
protected String title;
|
||||
|
||||
|
||||
public TemplateMessageDTO(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造器1 发模板消息用
|
||||
*/
|
||||
public TemplateMessageDTO(String fromUser, String toUser,String title, Map<String, String> templateParam, String templateCode){
|
||||
super(templateCode, templateParam);
|
||||
this.fromUser = fromUser;
|
||||
this.toUser = toUser;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
package org.enfi.common.api.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.enfi.common.constant.CommonConstant;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 接口返回数据格式
|
||||
*
|
||||
* @author scott
|
||||
* @email jeecgos@163.com
|
||||
* @date 2019年1月19日
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "接口返回对象", description = "接口返回对象")
|
||||
public class Result<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 成功标志
|
||||
*/
|
||||
@ApiModelProperty(value = "成功标志")
|
||||
private boolean success = true;
|
||||
|
||||
/**
|
||||
* 返回处理消息
|
||||
*/
|
||||
@ApiModelProperty(value = "返回处理消息")
|
||||
private String message = "";
|
||||
|
||||
/**
|
||||
* 返回代码
|
||||
*/
|
||||
@ApiModelProperty(value = "返回代码")
|
||||
private Integer code = 0;
|
||||
|
||||
/**
|
||||
* 返回数据对象 data
|
||||
*/
|
||||
@ApiModelProperty(value = "返回数据对象")
|
||||
private T result;
|
||||
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
@ApiModelProperty(value = "时间戳")
|
||||
private long timestamp = System.currentTimeMillis();
|
||||
@JsonIgnore
|
||||
private String onlTable;
|
||||
|
||||
public Result() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容VUE3版token失效不跳转登录页面
|
||||
*
|
||||
* @param code
|
||||
* @param message
|
||||
*/
|
||||
public Result(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Result<Object> ok() {
|
||||
Result<Object> r = new Result<Object>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(CommonConstant.SC_OK_200);
|
||||
return r;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Result<Object> ok(String msg) {
|
||||
Result<Object> r = new Result<Object>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(CommonConstant.SC_OK_200);
|
||||
r.setMessage(msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Result<Object> ok(Object data) {
|
||||
Result<Object> r = new Result<Object>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(CommonConstant.SC_OK_200);
|
||||
r.setResult(data);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> OK() {
|
||||
Result<T> r = new Result<T>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(CommonConstant.SC_OK_200);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> OK(String msg) {
|
||||
Result<T> r = new Result<T>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(CommonConstant.SC_OK_200);
|
||||
r.setMessage(msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> OK(T data) {
|
||||
Result<T> r = new Result<T>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(CommonConstant.SC_OK_200);
|
||||
r.setResult(data);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> OK(String msg, T data) {
|
||||
Result<T> r = new Result<T>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(CommonConstant.SC_OK_200);
|
||||
r.setMessage(msg);
|
||||
r.setResult(data);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(String msg, T data) {
|
||||
Result<T> r = new Result<T>();
|
||||
r.setSuccess(false);
|
||||
r.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
|
||||
r.setMessage(msg);
|
||||
r.setResult(data);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Result isResult(Boolean aBoolean) {
|
||||
if (aBoolean) {
|
||||
return OK("成功", null);
|
||||
} else {
|
||||
return error("失败", null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Result<Object> error(String msg) {
|
||||
return error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg);
|
||||
}
|
||||
|
||||
public static Result<Object> error(int code, String msg) {
|
||||
Result<Object> r = new Result<Object>();
|
||||
r.setCode(code);
|
||||
r.setMessage(msg);
|
||||
r.setSuccess(false);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无权限访问返回结果
|
||||
*/
|
||||
public static Result<Object> noauth(String msg) {
|
||||
return error(CommonConstant.SC_JEECG_NO_AUTHZ, msg);
|
||||
}
|
||||
|
||||
public Result<T> success(String message) {
|
||||
this.message = message;
|
||||
this.code = CommonConstant.SC_OK_200;
|
||||
this.success = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result<T> error500(String message) {
|
||||
this.message = message;
|
||||
this.code = CommonConstant.SC_INTERNAL_SERVER_ERROR_500;
|
||||
this.success = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
package org.enfi.common.aspect;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.serializer.PropertyFilter;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.enfi.common.api.dto.LogDTO;
|
||||
import org.enfi.common.api.vo.Result;
|
||||
import org.enfi.common.aspect.annotation.AutoLog;
|
||||
import org.enfi.common.constant.CommonConstant;
|
||||
import org.enfi.common.constant.enums.ModuleType;
|
||||
import org.enfi.modules.base.service.BaseCommonService;
|
||||
import org.enfi.common.system.vo.LoginUser;
|
||||
import org.enfi.common.util.IPUtils;
|
||||
import org.enfi.common.util.SpringContextUtils;
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 系统日志,切面处理类
|
||||
*
|
||||
* @Author scott
|
||||
* @email jeecgos@163.com
|
||||
* @Date 2018年1月14日
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class AutoLogAspect {
|
||||
|
||||
@Resource
|
||||
private BaseCommonService baseCommonService;
|
||||
|
||||
@Pointcut("@annotation(org.enfi.common.aspect.annotation.AutoLog)")
|
||||
public void logPointCut() {
|
||||
|
||||
}
|
||||
|
||||
@Around("logPointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
long beginTime = System.currentTimeMillis();
|
||||
//执行方法
|
||||
Object result = point.proceed();
|
||||
//执行时长(毫秒)
|
||||
long time = System.currentTimeMillis() - beginTime;
|
||||
|
||||
//保存日志
|
||||
saveSysLog(point, time, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) {
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
|
||||
LogDTO dto = new LogDTO();
|
||||
AutoLog syslog = method.getAnnotation(AutoLog.class);
|
||||
if(syslog != null){
|
||||
//update-begin-author:taoyan date:
|
||||
String content = syslog.value();
|
||||
if(syslog.module()== ModuleType.ONLINE){
|
||||
content = getOnlineLogContent(obj, content);
|
||||
}
|
||||
//注解上的描述,操作日志内容
|
||||
dto.setLogType(syslog.logType());
|
||||
dto.setLogContent(content);
|
||||
}
|
||||
|
||||
//请求的方法名
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = signature.getName();
|
||||
dto.setMethod(className + "." + methodName + "()");
|
||||
|
||||
|
||||
//设置操作类型
|
||||
if (dto.getLogType() == CommonConstant.LOG_TYPE_2) {
|
||||
dto.setOperateType(getOperateType(methodName, syslog.operateType()));
|
||||
}
|
||||
|
||||
//获取request
|
||||
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
|
||||
//请求的参数
|
||||
dto.setRequestParam(getReqestParams(request,joinPoint));
|
||||
//设置IP地址
|
||||
dto.setIp(IPUtils.getIpAddr(request));
|
||||
//获取登录用户信息
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
if(sysUser!=null){
|
||||
dto.setUserid(sysUser.getUsername());
|
||||
dto.setUsername(sysUser.getRealname());
|
||||
|
||||
}
|
||||
//耗时
|
||||
dto.setCostTime(time);
|
||||
dto.setCreateTime(new Date());
|
||||
//保存系统日志
|
||||
baseCommonService.addLog(dto);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取操作类型
|
||||
*/
|
||||
private int getOperateType(String methodName,int operateType) {
|
||||
if (operateType > 0) {
|
||||
return operateType;
|
||||
}
|
||||
if (methodName.startsWith("list")) {
|
||||
return CommonConstant.OPERATE_TYPE_1;
|
||||
}
|
||||
if (methodName.startsWith("add")) {
|
||||
return CommonConstant.OPERATE_TYPE_2;
|
||||
}
|
||||
if (methodName.startsWith("edit")) {
|
||||
return CommonConstant.OPERATE_TYPE_3;
|
||||
}
|
||||
if (methodName.startsWith("delete")) {
|
||||
return CommonConstant.OPERATE_TYPE_4;
|
||||
}
|
||||
if (methodName.startsWith("import")) {
|
||||
return CommonConstant.OPERATE_TYPE_5;
|
||||
}
|
||||
if (methodName.startsWith("export")) {
|
||||
return CommonConstant.OPERATE_TYPE_6;
|
||||
}
|
||||
return CommonConstant.OPERATE_TYPE_1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 获取请求参数
|
||||
* @author: scott
|
||||
* @date: 2020/4/16 0:10
|
||||
* @param request: request
|
||||
* @param joinPoint: joinPoint
|
||||
* @Return: java.lang.String
|
||||
*/
|
||||
private String getReqestParams(HttpServletRequest request, JoinPoint joinPoint) {
|
||||
String httpMethod = request.getMethod();
|
||||
String params = "";
|
||||
if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) || "PATCH".equals(httpMethod)) {
|
||||
Object[] paramsArray = joinPoint.getArgs();
|
||||
// java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
|
||||
// https://my.oschina.net/mengzhang6/blog/2395893
|
||||
Object[] arguments = new Object[paramsArray.length];
|
||||
for (int i = 0; i < paramsArray.length; i++) {
|
||||
if (paramsArray[i] instanceof BindingResult || paramsArray[i] instanceof ServletRequest || paramsArray[i] instanceof ServletResponse || paramsArray[i] instanceof MultipartFile) {
|
||||
//ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
|
||||
//ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
|
||||
continue;
|
||||
}
|
||||
arguments[i] = paramsArray[i];
|
||||
}
|
||||
//update-begin-author:taoyan date:20200724 for:日志数据太长的直接过滤掉
|
||||
PropertyFilter profilter = new PropertyFilter() {
|
||||
@Override
|
||||
public boolean apply(Object o, String name, Object value) {
|
||||
if(value!=null && value.toString().length()>500){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
params = JSONObject.toJSONString(arguments, profilter);
|
||||
//update-end-author:taoyan date:20200724 for:日志数据太长的直接过滤掉
|
||||
} else {
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
// 请求的方法参数值
|
||||
Object[] args = joinPoint.getArgs();
|
||||
// 请求的方法参数名称
|
||||
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
|
||||
String[] paramNames = u.getParameterNames(method);
|
||||
if (args != null && paramNames != null) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
params += " " + paramNames[i] + ": " + args[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* online日志内容拼接
|
||||
* @param obj
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
private String getOnlineLogContent(Object obj, String content){
|
||||
if (Result.class.isInstance(obj)){
|
||||
Result res = (Result)obj;
|
||||
String msg = res.getMessage();
|
||||
String tableName = res.getOnlTable();
|
||||
if(oConvertUtils.isNotEmpty(tableName)){
|
||||
content+=",表名:"+tableName;
|
||||
}
|
||||
if(res.isSuccess()){
|
||||
content+= ","+(oConvertUtils.isEmpty(msg)?"操作成功":msg);
|
||||
}else{
|
||||
content+= ","+(oConvertUtils.isEmpty(msg)?"操作失败":msg);
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
/* private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) {
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
|
||||
SysLog sysLog = new SysLog();
|
||||
AutoLog syslog = method.getAnnotation(AutoLog.class);
|
||||
if(syslog != null){
|
||||
//update-begin-author:taoyan date:
|
||||
String content = syslog.value();
|
||||
if(syslog.module()== ModuleType.ONLINE){
|
||||
content = getOnlineLogContent(obj, content);
|
||||
}
|
||||
//注解上的描述,操作日志内容
|
||||
sysLog.setLogContent(content);
|
||||
sysLog.setLogType(syslog.logType());
|
||||
}
|
||||
|
||||
//请求的方法名
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = signature.getName();
|
||||
sysLog.setMethod(className + "." + methodName + "()");
|
||||
|
||||
|
||||
//设置操作类型
|
||||
if (sysLog.getLogType() == CommonConstant.LOG_TYPE_2) {
|
||||
sysLog.setOperateType(getOperateType(methodName, syslog.operateType()));
|
||||
}
|
||||
|
||||
//获取request
|
||||
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
|
||||
//请求的参数
|
||||
sysLog.setRequestParam(getReqestParams(request,joinPoint));
|
||||
|
||||
//设置IP地址
|
||||
sysLog.setIp(IPUtils.getIpAddr(request));
|
||||
|
||||
//获取登录用户信息
|
||||
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
|
||||
if(sysUser!=null){
|
||||
sysLog.setUserid(sysUser.getUsername());
|
||||
sysLog.setUsername(sysUser.getRealname());
|
||||
|
||||
}
|
||||
//耗时
|
||||
sysLog.setCostTime(time);
|
||||
sysLog.setCreateTime(new Date());
|
||||
//保存系统日志
|
||||
sysLogService.save(sysLog);
|
||||
}*/
|
||||
}
|
@ -0,0 +1,390 @@
|
||||
package org.enfi.common.aspect;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.enfi.common.api.CommonAPI;
|
||||
import org.enfi.common.api.vo.Result;
|
||||
import org.enfi.common.aspect.annotation.Dict;
|
||||
import org.enfi.common.constant.CommonConstant;
|
||||
import org.enfi.common.system.vo.DictModel;
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Description: 字典aop类
|
||||
* @Author: dangzhenghui
|
||||
* @Date: 2019-3-17 21:50
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DictAspect {
|
||||
|
||||
@Autowired
|
||||
private CommonAPI commonAPI;
|
||||
@Autowired
|
||||
public RedisTemplate redisTemplate;
|
||||
|
||||
// 定义切点Pointcut
|
||||
@Pointcut("execution(public * org.enfi.modules..*.*Controller.*(..))")
|
||||
public void excudeService() {
|
||||
}
|
||||
|
||||
@Around("excudeService()")
|
||||
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
|
||||
long time1=System.currentTimeMillis();
|
||||
Object result = pjp.proceed();
|
||||
long time2=System.currentTimeMillis();
|
||||
log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms");
|
||||
long start=System.currentTimeMillis();
|
||||
this.parseDictText(result);
|
||||
long end=System.currentTimeMillis();
|
||||
log.debug("注入字典到JSON数据 耗时"+(end-start)+"ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入
|
||||
* 字典注入实现 通过对实体类添加注解@dict 来标识需要的字典内容,字典分为单字典code即可 ,table字典 code table text配合使用与原来jeecg的用法相同
|
||||
* 示例为SysUser 字段为sex 添加了注解@Dict(dicCode = "sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text,已字段名称加_dictText形式返回到前端
|
||||
* 例输入当前返回值的就会多出一个sex_dictText字段
|
||||
* {
|
||||
* sex:1,
|
||||
* sex_dictText:"男"
|
||||
* }
|
||||
* 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了
|
||||
* customRender:function (text) {
|
||||
* if(text==1){
|
||||
* return "男";
|
||||
* }else if(text==2){
|
||||
* return "女";
|
||||
* }else{
|
||||
* return text;
|
||||
* }
|
||||
* }
|
||||
* 目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用
|
||||
* @param result
|
||||
*/
|
||||
private void parseDictText(Object result) {
|
||||
if (result instanceof Result) {
|
||||
if (((Result) result).getResult() instanceof IPage) {
|
||||
List<JSONObject> items = new ArrayList<>();
|
||||
|
||||
//step.1 筛选出加了 Dict 注解的字段列表
|
||||
List<Field> dictFieldList = new ArrayList<>();
|
||||
// 字典数据列表, key = 字典code,value=数据列表
|
||||
Map<String, List<String>> dataListMap = new HashMap<>();
|
||||
|
||||
for (Object record : ((IPage) ((Result) result).getResult()).getRecords()) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String json="{}";
|
||||
try {
|
||||
//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
|
||||
json = mapper.writeValueAsString(record);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error("json解析失败"+e.getMessage(),e);
|
||||
}
|
||||
JSONObject item = JSONObject.parseObject(json);
|
||||
//update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
|
||||
//for (Field field : record.getClass().getDeclaredFields()) {
|
||||
// 遍历所有字段,把字典Code取出来,放到 map 里
|
||||
for (Field field : oConvertUtils.getAllFields(record)) {
|
||||
String value = item.getString(field.getName());
|
||||
if (oConvertUtils.isEmpty(value)) {
|
||||
continue;
|
||||
}
|
||||
//update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
|
||||
if (field.getAnnotation(Dict.class) != null) {
|
||||
if (!dictFieldList.contains(field)) {
|
||||
dictFieldList.add(field);
|
||||
}
|
||||
String code = field.getAnnotation(Dict.class).dicCode();
|
||||
String text = field.getAnnotation(Dict.class).dicText();
|
||||
String table = field.getAnnotation(Dict.class).dictTable();
|
||||
|
||||
List<String> dataList;
|
||||
String dictCode = code;
|
||||
if (!StringUtils.isEmpty(table)) {
|
||||
dictCode = String.format("%s,%s,%s", table, text, code);
|
||||
}
|
||||
dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));
|
||||
}
|
||||
//date类型默认转换string格式化日期
|
||||
if (field.getType().getName().equals("java.util.Date")&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
|
||||
SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
|
||||
}
|
||||
}
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
//step.2 调用翻译方法,一次性翻译
|
||||
Map<String, List<DictModel>> translText = this.translateAllDict(dataListMap);
|
||||
|
||||
//step.3 将翻译结果填充到返回结果里
|
||||
for (JSONObject record : items) {
|
||||
for (Field field : dictFieldList) {
|
||||
String code = field.getAnnotation(Dict.class).dicCode();
|
||||
String text = field.getAnnotation(Dict.class).dicText();
|
||||
String table = field.getAnnotation(Dict.class).dictTable();
|
||||
|
||||
String fieldDictCode = code;
|
||||
if (!StringUtils.isEmpty(table)) {
|
||||
fieldDictCode = String.format("%s,%s,%s", table, text, code);
|
||||
}
|
||||
|
||||
String value = record.getString(field.getName());
|
||||
if (oConvertUtils.isNotEmpty(value)) {
|
||||
List<DictModel> dictModels = translText.get(fieldDictCode);
|
||||
if(dictModels==null || dictModels.size()==0){
|
||||
continue;
|
||||
}
|
||||
|
||||
String textValue = this.translDictText(dictModels, value);
|
||||
log.debug(" 字典Val : " + textValue);
|
||||
log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue);
|
||||
|
||||
// TODO-sun 测试输出,待删
|
||||
log.debug(" ---- dictCode: " + fieldDictCode);
|
||||
log.debug(" ---- value: " + value);
|
||||
log.debug(" ----- text: " + textValue);
|
||||
log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels));
|
||||
|
||||
record.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
((IPage) ((Result) result).getResult()).setRecords(items);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list 去重添加
|
||||
*/
|
||||
private void listAddAllDeduplicate(List<String> dataList, List<String> addList) {
|
||||
// 筛选出dataList中没有的数据
|
||||
List<String> filterList = addList.stream().filter(i -> !dataList.contains(i)).collect(Collectors.toList());
|
||||
dataList.addAll(filterList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一次性把所有的字典都翻译了
|
||||
* 1. 所有的普通数据字典的所有数据只执行一次SQL
|
||||
* 2. 表字典相同的所有数据只执行一次SQL
|
||||
* @param dataListMap
|
||||
* @return
|
||||
*/
|
||||
private Map<String, List<DictModel>> translateAllDict(Map<String, List<String>> dataListMap) {
|
||||
// 翻译后的字典文本,key=dictCode
|
||||
Map<String, List<DictModel>> translText = new HashMap<>();
|
||||
// 需要翻译的数据(有些可以从redis缓存中获取,就不走数据库查询)
|
||||
List<String> needTranslData = new ArrayList<>();
|
||||
//step.1 先通过redis中获取缓存字典数据
|
||||
for (String dictCode : dataListMap.keySet()) {
|
||||
List<String> dataList = dataListMap.get(dictCode);
|
||||
if (dataList.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
// 表字典需要翻译的数据
|
||||
List<String> needTranslDataTable = new ArrayList<>();
|
||||
for (String s : dataList) {
|
||||
String data = s.trim();
|
||||
if (data.length() == 0) {
|
||||
continue; //跳过循环
|
||||
}
|
||||
if (dictCode.contains(",")) {
|
||||
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, data);
|
||||
if (redisTemplate.hasKey(keyString)) {
|
||||
try {
|
||||
String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
list.add(new DictModel(data, text));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
} else if (!needTranslDataTable.contains(data)) {
|
||||
// 去重添加
|
||||
needTranslDataTable.add(data);
|
||||
}
|
||||
} else {
|
||||
String keyString = String.format("sys:cache:dict::%s:%s", dictCode, data);
|
||||
if (redisTemplate.hasKey(keyString)) {
|
||||
try {
|
||||
String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
list.add(new DictModel(data, text));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
} else if (!needTranslData.contains(data)) {
|
||||
// 去重添加
|
||||
needTranslData.add(data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//step.2 调用数据库翻译表字典
|
||||
if (needTranslDataTable.size() > 0) {
|
||||
String[] arr = dictCode.split(",");
|
||||
String table = arr[0], text = arr[1], code = arr[2];
|
||||
String values = String.join(",", needTranslDataTable);
|
||||
log.info("translateDictFromTableByKeys.dictCode:" + dictCode);
|
||||
log.info("translateDictFromTableByKeys.values:" + values);
|
||||
List<DictModel> texts = commonAPI.translateDictFromTableByKeys(table, text, code, values);
|
||||
log.info("translateDictFromTableByKeys.result:" + texts);
|
||||
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
list.addAll(texts);
|
||||
|
||||
// 做 redis 缓存
|
||||
for (DictModel dict : texts) {
|
||||
String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue());
|
||||
try {
|
||||
// update-begin-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
|
||||
// 保留5分钟
|
||||
redisTemplate.opsForValue().set(redisKey, dict.getText(), 300, TimeUnit.SECONDS);
|
||||
// update-end-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//step.3 调用数据库进行翻译普通字典
|
||||
if (needTranslData.size() > 0) {
|
||||
List<String> dictCodeList = Arrays.asList(dataListMap.keySet().toArray(new String[]{}));
|
||||
// 将不包含逗号的字典code筛选出来,因为带逗号的是表字典,而不是普通的数据字典
|
||||
List<String> filterDictCodes = dictCodeList.stream().filter(key -> !key.contains(",")).collect(Collectors.toList());
|
||||
String dictCodes = String.join(",", filterDictCodes);
|
||||
String values = String.join(",", needTranslData);
|
||||
log.info("translateManyDict.dictCodes:" + dictCodes);
|
||||
log.info("translateManyDict.values:" + values);
|
||||
Map<String, List<DictModel>> manyDict = commonAPI.translateManyDict(dictCodes, values);
|
||||
log.info("translateManyDict.result:" + manyDict);
|
||||
for (String dictCode : manyDict.keySet()) {
|
||||
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
List<DictModel> newList = manyDict.get(dictCode);
|
||||
list.addAll(newList);
|
||||
|
||||
// 做 redis 缓存
|
||||
for (DictModel dict : newList) {
|
||||
String redisKey = String.format("sys:cache:dict::%s:%s", dictCode, dict.getValue());
|
||||
try {
|
||||
redisTemplate.opsForValue().set(redisKey, dict.getText());
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return translText;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典值替换文本
|
||||
*
|
||||
* @param dictModels
|
||||
* @param values
|
||||
* @return
|
||||
*/
|
||||
private String translDictText(List<DictModel> dictModels, String values) {
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
// 允许多个逗号分隔,允许传数组对象
|
||||
String[] splitVal = values.split(",");
|
||||
for (String val : splitVal) {
|
||||
String dictText = val;
|
||||
for (DictModel dict : dictModels) {
|
||||
if (val.equals(dict.getValue())) {
|
||||
dictText = dict.getText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.add(dictText);
|
||||
}
|
||||
return String.join(",", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻译字典文本
|
||||
* @param code
|
||||
* @param text
|
||||
* @param table
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
private String translateDictValue(String code, String text, String table, String key) {
|
||||
if(oConvertUtils.isEmpty(key)) {
|
||||
return null;
|
||||
}
|
||||
StringBuffer textValue=new StringBuffer();
|
||||
String[] keys = key.split(",");
|
||||
for (String k : keys) {
|
||||
String tmpValue = null;
|
||||
log.debug(" 字典 key : "+ k);
|
||||
if (k.trim().length() == 0) {
|
||||
continue; //跳过循环
|
||||
}
|
||||
//update-begin--Author:scott -- Date:20210531 ----for: !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
|
||||
if (!StringUtils.isEmpty(table)){
|
||||
log.info("--DictAspect------dicTable="+ table+" ,dicText= "+text+" ,dicCode="+code);
|
||||
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s,%s,%s]",table,text,code,k.trim());
|
||||
if (redisTemplate.hasKey(keyString)){
|
||||
try {
|
||||
tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
}else {
|
||||
tmpValue= commonAPI.translateDictFromTable(table,text,code,k.trim());
|
||||
}
|
||||
}else {
|
||||
String keyString = String.format("sys:cache:dict::%s:%s",code,k.trim());
|
||||
if (redisTemplate.hasKey(keyString)){
|
||||
try {
|
||||
tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
}
|
||||
}else {
|
||||
tmpValue = commonAPI.translateDict(code, k.trim());
|
||||
}
|
||||
}
|
||||
//update-end--Author:scott -- Date:20210531 ----for: !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
|
||||
|
||||
if (tmpValue != null) {
|
||||
if (!"".equals(textValue.toString())) {
|
||||
textValue.append(",");
|
||||
}
|
||||
textValue.append(tmpValue);
|
||||
}
|
||||
|
||||
}
|
||||
return textValue.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package org.enfi.common.aspect;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.Signature;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.enfi.common.aspect.annotation.PrintLnTime;
|
||||
import org.enfi.common.system.util.JwtUtil;
|
||||
import org.enfi.common.util.IPUtils;
|
||||
import org.enfi.common.util.PrintUtil;
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @ClassName: MyAspect
|
||||
* @Author: wanghao
|
||||
* @date: 2021.07.22 10:07
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class MyAspect {
|
||||
|
||||
@Around("@annotation(printLnTime)")
|
||||
public Object printLnTimeAround(ProceedingJoinPoint joinPoint, PrintLnTime printLnTime) throws Throwable {
|
||||
// 接收到请求,记录请求内容
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
String userName = IPUtils.getIpAddr(request);
|
||||
String token = request.getHeader("X-Access-Token");
|
||||
if (oConvertUtils.isNotEmpty(token)) {
|
||||
userName = JwtUtil.getUsername(token);
|
||||
}
|
||||
|
||||
Signature signature = joinPoint.getSignature();
|
||||
String className = joinPoint.getTarget().getClass().getSimpleName();
|
||||
Method method = ((MethodSignature) signature).getMethod();
|
||||
String methodName = method.getName();
|
||||
|
||||
ApiOperation annotation = method.getAnnotation(ApiOperation.class);
|
||||
String value = "";
|
||||
if (oConvertUtils.isNotEmpty(annotation)) {
|
||||
value = ":" + annotation.value() + ": ";
|
||||
}
|
||||
System.out.println();
|
||||
String printImprotMethod = "================== 进入 " + className + ":方法:" + methodName + value + "=====================================";
|
||||
PrintUtil.BLUE.Println(printImprotMethod);
|
||||
StringBuffer stringBufferOne = new StringBuffer();
|
||||
StringBuffer stringBufferTwo = new StringBuffer();
|
||||
for (int i = 0; i < Math.ceil(printImprotMethod.length() / 3); i++) {
|
||||
stringBufferOne.append("=");
|
||||
}
|
||||
String userword = " 用户 ";
|
||||
String user = " " + userName + " ";
|
||||
String zhangwei = stringBufferOne.toString();
|
||||
Integer threeLength = zhangwei.length();
|
||||
int i1 = threeLength - (userword.length() + user.length());
|
||||
for (int i = 0; i < i1; i++) {
|
||||
stringBufferTwo.append("=");
|
||||
}
|
||||
PrintUtil.CYAN.Println(zhangwei + userword + stringBufferTwo + user + zhangwei);
|
||||
//执行方法
|
||||
long startTime = System.currentTimeMillis(); //获取开始时间
|
||||
//注意,如果调用joinPoint.proceed()方法,则修改的参数值不会生效,必须调用joinPoint.proceed(Object[] args)
|
||||
Object proceed = joinPoint.proceed();
|
||||
//方法执行完成后台操作
|
||||
long endTime = System.currentTimeMillis(); //获取结束时间
|
||||
long interval = endTime - startTime;//运行的时间 毫秒
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("HH");//初始化Formatter的转换格式。
|
||||
formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
|
||||
String hour = formatter.format(interval);
|
||||
formatter.applyPattern("mm");
|
||||
String minute = formatter.format(interval);
|
||||
formatter.applyPattern("ss");
|
||||
String second = formatter.format(interval);
|
||||
PrintUtil.RED.Println(className + "类的方法:" + methodName + value + "执行时间: " + hour + "小时,"
|
||||
+ minute + "分钟,"
|
||||
+ second + "秒,共" + interval + "毫秒"
|
||||
);
|
||||
PrintUtil.BLUE.Println("=================================================== 方法执行完毕 ===================================================");
|
||||
System.out.println();
|
||||
//如果这里不返回result,则目标对象实际返回值会被置为null
|
||||
return proceed;
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
package org.enfi.common.aspect;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.enfi.common.api.CommonAPI;
|
||||
import org.enfi.common.aspect.annotation.PermissionData;
|
||||
import org.enfi.common.system.util.EnFiDataAutorUtils;
|
||||
import org.enfi.common.system.util.JwtUtil;
|
||||
import org.enfi.common.system.vo.SysPermissionDataRuleModel;
|
||||
import org.enfi.common.system.vo.SysUserCacheInfo;
|
||||
import org.enfi.common.util.SpringContextUtils;
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据权限切面处理类
|
||||
* 当被请求的方法有注解PermissionData时,会在往当前request中写入数据权限信息
|
||||
* @Date 2019年4月10日
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class PermissionDataAspect {
|
||||
|
||||
@Autowired
|
||||
private CommonAPI commonAPI;
|
||||
|
||||
@Pointcut("@annotation(org.enfi.common.aspect.annotation.PermissionData)")
|
||||
public void pointCut() {
|
||||
|
||||
}
|
||||
|
||||
@Around("pointCut()")
|
||||
public Object arround(ProceedingJoinPoint point) throws Throwable{
|
||||
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
PermissionData pd = method.getAnnotation(PermissionData.class);
|
||||
String component = pd.pageComponent();
|
||||
|
||||
String requestMethod = request.getMethod();
|
||||
String requestPath = request.getRequestURI().substring(request.getContextPath().length());
|
||||
requestPath = filterUrl(requestPath);
|
||||
log.debug("拦截请求 >> "+requestPath+";请求类型 >> "+requestMethod);
|
||||
String username = JwtUtil.getUserNameByToken(request);
|
||||
//查询数据权限信息
|
||||
//TODO 微服务情况下也得支持缓存机制
|
||||
List<SysPermissionDataRuleModel> dataRules = commonAPI.queryPermissionDataRule(component, requestPath, username);
|
||||
if(dataRules!=null && dataRules.size()>0) {
|
||||
//临时存储
|
||||
EnFiDataAutorUtils.installDataSearchConditon(request, dataRules);
|
||||
//TODO 微服务情况下也得支持缓存机制
|
||||
SysUserCacheInfo userinfo = commonAPI.getCacheUser(username);
|
||||
EnFiDataAutorUtils.installUserInfo(request, userinfo);
|
||||
}
|
||||
return point.proceed();
|
||||
}
|
||||
|
||||
private String filterUrl(String requestPath){
|
||||
String url = "";
|
||||
if(oConvertUtils.isNotEmpty(requestPath)){
|
||||
url = requestPath.replace("\\", "/");
|
||||
url = url.replace("//", "/");
|
||||
if(url.indexOf("//")>=0){
|
||||
url = filterUrl(url);
|
||||
}
|
||||
/*if(url.startsWith("/")){
|
||||
url=url.substring(1);
|
||||
}*/
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求地址
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private String getJgAuthRequsetPath(HttpServletRequest request) {
|
||||
String queryString = request.getQueryString();
|
||||
String requestPath = request.getRequestURI();
|
||||
if(oConvertUtils.isNotEmpty(queryString)){
|
||||
requestPath += "?" + queryString;
|
||||
}
|
||||
if (requestPath.indexOf("&") > -1) {// 去掉其他参数(保留一个参数) 例如:loginController.do?login
|
||||
requestPath = requestPath.substring(0, requestPath.indexOf("&"));
|
||||
}
|
||||
if(requestPath.indexOf("=")!=-1){
|
||||
if(requestPath.indexOf(".do")!=-1){
|
||||
requestPath = requestPath.substring(0,requestPath.indexOf(".do")+3);
|
||||
}else{
|
||||
requestPath = requestPath.substring(0,requestPath.indexOf("?"));
|
||||
}
|
||||
}
|
||||
requestPath = requestPath.substring(request.getContextPath().length() + 1);// 去掉项目路径
|
||||
return filterUrl(requestPath);
|
||||
}
|
||||
|
||||
private boolean moHuContain(List<String> list,String key){
|
||||
for(String str : list){
|
||||
if(key.contains(str)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package org.enfi.common.aspect;
|
||||
|
||||
/**
|
||||
* @Author scott
|
||||
* @Date 2020/1/14 13:36
|
||||
* @Description: 请求URL与菜单路由URL转换规则(方便于采用菜单路由URL来配置数据权限规则)
|
||||
*/
|
||||
public enum UrlMatchEnum {
|
||||
CGFORM_DATA("/online/cgform/api/getData/", "/online/cgformList/"),
|
||||
CGFORM_EXCEL_DATA("/online/cgform/api/exportXls/", "/online/cgformList/"),
|
||||
CGFORM_TREE_DATA("/online/cgform/api/getTreeData/", "/online/cgformList/"),
|
||||
CGREPORT_DATA("/online/cgreport/api/getColumnsAndData/", "/online/cgreport/"),
|
||||
CGREPORT_EXCEL_DATA("/online/cgreport/api/exportXls/", "/online/cgreport/");
|
||||
|
||||
|
||||
UrlMatchEnum(String url, String match_url) {
|
||||
this.url = url;
|
||||
this.match_url = match_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request 请求 URL前缀
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 菜单路由 URL前缀 (对应菜单路径)
|
||||
*/
|
||||
private String match_url;
|
||||
|
||||
/**
|
||||
* 根据req url 获取到菜单配置路径(前端页面路由URL)
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static String getMatchResultByUrl(String url) {
|
||||
//获取到枚举
|
||||
UrlMatchEnum[] values = UrlMatchEnum.values();
|
||||
//加强for循环进行遍历操作
|
||||
for (UrlMatchEnum lr : values) {
|
||||
//如果遍历获取的type和参数type一致
|
||||
if (url.indexOf(lr.url) != -1) {
|
||||
//返回type对象的desc
|
||||
return url.replace(lr.url, lr.match_url);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// /**
|
||||
// * 比如request真实请求URL: /online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a
|
||||
// * 转换匹配路由URL后(对应配置的菜单路径):/online/cgformList/81fcf7d8922d45069b0d5ba983612d3a
|
||||
// */
|
||||
// System.out.println(UrlMatchEnum.getMatchResultByUrl("/online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a"));
|
||||
// }
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package org.enfi.common.aspect.annotation;
|
||||
|
||||
import org.enfi.common.constant.CommonConstant;
|
||||
import org.enfi.common.constant.enums.ModuleType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 系统日志注解
|
||||
*
|
||||
* @Author scott
|
||||
* @email jeecgos@163.com
|
||||
* @Date 2019年1月14日
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface AutoLog {
|
||||
|
||||
/**
|
||||
* 日志内容
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* 日志类型
|
||||
*
|
||||
* @return 0:操作日志;1:登录日志;2:定时任务;
|
||||
*/
|
||||
int logType() default CommonConstant.LOG_TYPE_2;
|
||||
|
||||
/**
|
||||
* 操作日志类型
|
||||
*
|
||||
* @return (1查询,2添加,3修改,4删除)
|
||||
*/
|
||||
int operateType() default 0;
|
||||
|
||||
/**
|
||||
* 模块类型 默认为common
|
||||
* @return
|
||||
*/
|
||||
ModuleType module() default ModuleType.COMMON;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package org.enfi.common.aspect.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 类描述: 字典注解
|
||||
* 作 者: dangzhenghui
|
||||
* 日 期: 2019年03月17日-下午9:37:16
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Dict {
|
||||
/**
|
||||
* 方法描述: 数据code
|
||||
* 作 者: dangzhenghui
|
||||
* 日 期: 2019年03月17日-下午9:37:16
|
||||
*
|
||||
* @return 返回类型: String
|
||||
*/
|
||||
String dicCode();
|
||||
|
||||
/**
|
||||
* 方法描述: 数据Text
|
||||
* 作 者: dangzhenghui
|
||||
* 日 期: 2019年03月17日-下午9:37:16
|
||||
*
|
||||
* @return 返回类型: String
|
||||
*/
|
||||
String dicText() default "";
|
||||
|
||||
/**
|
||||
* 方法描述: 数据字典表
|
||||
* 作 者: dangzhenghui
|
||||
* 日 期: 2019年03月17日-下午9:37:16
|
||||
*
|
||||
* @return 返回类型: String
|
||||
*/
|
||||
String dictTable() default "";
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package org.enfi.common.aspect.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* online请求拦截专用注解
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE,ElementType.METHOD})
|
||||
@Documented
|
||||
public @interface OnlineAuth {
|
||||
|
||||
/**
|
||||
* 请求关键字,在xxx/code之前的字符串
|
||||
* @return
|
||||
*/
|
||||
String value();
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package org.enfi.common.aspect.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 数据权限注解
|
||||
* @Author taoyan
|
||||
* @Date 2019年4月11日
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE,ElementType.METHOD})
|
||||
@Documented
|
||||
public @interface PermissionData {
|
||||
/**
|
||||
* 暂时没用
|
||||
* @return
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
|
||||
/**
|
||||
* 配置菜单的组件路径,用于数据权限
|
||||
*/
|
||||
String pageComponent() default "";
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.enfi.common.aspect.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PrintLnTime {
|
||||
}
|
@ -0,0 +1,328 @@
|
||||
package org.enfi.common.constant;
|
||||
|
||||
public interface CommonConstant {
|
||||
|
||||
/**
|
||||
* 正常状态
|
||||
*/
|
||||
public static final Integer STATUS_NORMAL = 0;
|
||||
|
||||
/**
|
||||
* 禁用状态
|
||||
*/
|
||||
public static final Integer STATUS_DISABLE = -1;
|
||||
|
||||
/**
|
||||
* 删除标志
|
||||
*/
|
||||
public static final Integer DEL_FLAG_1 = 1;
|
||||
|
||||
/**
|
||||
* 未删除
|
||||
*/
|
||||
public static final Integer DEL_FLAG_0 = 0;
|
||||
|
||||
/**
|
||||
* 系统日志类型: 登录
|
||||
*/
|
||||
public static final int LOG_TYPE_1 = 1;
|
||||
|
||||
/**
|
||||
* 系统日志类型: 操作
|
||||
*/
|
||||
public static final int LOG_TYPE_2 = 2;
|
||||
|
||||
/**
|
||||
* 操作日志类型: 查询
|
||||
*/
|
||||
public static final int OPERATE_TYPE_1 = 1;
|
||||
|
||||
/**
|
||||
* 操作日志类型: 添加
|
||||
*/
|
||||
public static final int OPERATE_TYPE_2 = 2;
|
||||
|
||||
/**
|
||||
* 操作日志类型: 更新
|
||||
*/
|
||||
public static final int OPERATE_TYPE_3 = 3;
|
||||
|
||||
/**
|
||||
* 操作日志类型: 删除
|
||||
*/
|
||||
public static final int OPERATE_TYPE_4 = 4;
|
||||
|
||||
/**
|
||||
* 操作日志类型: 倒入
|
||||
*/
|
||||
public static final int OPERATE_TYPE_5 = 5;
|
||||
|
||||
/**
|
||||
* 操作日志类型: 导出
|
||||
*/
|
||||
public static final int OPERATE_TYPE_6 = 6;
|
||||
|
||||
|
||||
/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
|
||||
public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
|
||||
/** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
|
||||
public static final Integer SC_OK_200 = 200;
|
||||
|
||||
/**访问权限认证未通过 510*/
|
||||
public static final Integer SC_JEECG_NO_AUTHZ=510;
|
||||
|
||||
/** 登录用户Shiro权限缓存KEY前缀 */
|
||||
public static String PREFIX_USER_SHIRO_CACHE = "shiro:cache:org.enfi.config.shiro.ShiroRealm.authorizationCache:";
|
||||
/** 登录用户Token令牌缓存KEY前缀 */
|
||||
public static final String PREFIX_USER_TOKEN = "prefix_user_token_";
|
||||
/** Token缓存时间:3600秒即一小时 */
|
||||
public static final int TOKEN_EXPIRE_TIME = 3600;
|
||||
|
||||
|
||||
/**
|
||||
* 0:一级菜单
|
||||
*/
|
||||
public static final Integer MENU_TYPE_0 = 0;
|
||||
/**
|
||||
* 1:子菜单
|
||||
*/
|
||||
public static final Integer MENU_TYPE_1 = 1;
|
||||
/**
|
||||
* 2:按钮权限
|
||||
*/
|
||||
public static final Integer MENU_TYPE_2 = 2;
|
||||
|
||||
/**通告对象类型(USER:指定用户,ALL:全体用户)*/
|
||||
public static final String MSG_TYPE_UESR = "USER";
|
||||
public static final String MSG_TYPE_ALL = "ALL";
|
||||
|
||||
/**发布状态(0未发布,1已发布,2已撤销)*/
|
||||
public static final String NO_SEND = "0";
|
||||
public static final String HAS_SEND = "1";
|
||||
public static final String HAS_CANCLE = "2";
|
||||
|
||||
/**阅读状态(0未读,1已读)*/
|
||||
public static final String HAS_READ_FLAG = "1";
|
||||
public static final String NO_READ_FLAG = "0";
|
||||
|
||||
/**优先级(L低,M中,H高)*/
|
||||
public static final String PRIORITY_L = "L";
|
||||
public static final String PRIORITY_M = "M";
|
||||
public static final String PRIORITY_H = "H";
|
||||
|
||||
/**
|
||||
* 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板
|
||||
*/
|
||||
public static final String SMS_TPL_TYPE_0 = "0";
|
||||
public static final String SMS_TPL_TYPE_1 = "1";
|
||||
public static final String SMS_TPL_TYPE_2 = "2";
|
||||
|
||||
/**
|
||||
* 状态(0无效1有效)
|
||||
*/
|
||||
public static final String STATUS_0 = "0";
|
||||
public static final String STATUS_1 = "1";
|
||||
|
||||
/**
|
||||
* 同步工作流引擎1同步0不同步
|
||||
*/
|
||||
public static final Integer ACT_SYNC_1 = 1;
|
||||
public static final Integer ACT_SYNC_0 = 0;
|
||||
|
||||
/**
|
||||
* 消息类型1:通知公告2:系统消息
|
||||
*/
|
||||
public static final String MSG_CATEGORY_1 = "1";
|
||||
public static final String MSG_CATEGORY_2 = "2";
|
||||
|
||||
/**
|
||||
* 是否配置菜单的数据权限 1是0否
|
||||
*/
|
||||
public static final Integer RULE_FLAG_0 = 0;
|
||||
public static final Integer RULE_FLAG_1 = 1;
|
||||
|
||||
/**
|
||||
* 是否用户已被冻结 1正常(解冻) 2冻结
|
||||
*/
|
||||
public static final Integer USER_UNFREEZE = 1;
|
||||
public static final Integer USER_FREEZE = 2;
|
||||
|
||||
/**字典翻译文本后缀*/
|
||||
public static final String DICT_TEXT_SUFFIX = "_dictText";
|
||||
|
||||
/**
|
||||
* 表单设计器主表类型
|
||||
*/
|
||||
public static final Integer DESIGN_FORM_TYPE_MAIN = 1;
|
||||
|
||||
/**
|
||||
* 表单设计器子表表类型
|
||||
*/
|
||||
public static final Integer DESIGN_FORM_TYPE_SUB = 2;
|
||||
|
||||
/**
|
||||
* 表单设计器URL授权通过
|
||||
*/
|
||||
public static final Integer DESIGN_FORM_URL_STATUS_PASSED = 1;
|
||||
|
||||
/**
|
||||
* 表单设计器URL授权未通过
|
||||
*/
|
||||
public static final Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2;
|
||||
|
||||
/**
|
||||
* 表单设计器新增 Flag
|
||||
*/
|
||||
public static final String DESIGN_FORM_URL_TYPE_ADD = "add";
|
||||
/**
|
||||
* 表单设计器修改 Flag
|
||||
*/
|
||||
public static final String DESIGN_FORM_URL_TYPE_EDIT = "edit";
|
||||
/**
|
||||
* 表单设计器详情 Flag
|
||||
*/
|
||||
public static final String DESIGN_FORM_URL_TYPE_DETAIL = "detail";
|
||||
/**
|
||||
* 表单设计器复用数据 Flag
|
||||
*/
|
||||
public static final String DESIGN_FORM_URL_TYPE_REUSE = "reuse";
|
||||
/**
|
||||
* 表单设计器编辑 Flag (已弃用)
|
||||
*/
|
||||
public static final String DESIGN_FORM_URL_TYPE_VIEW = "view";
|
||||
|
||||
/**
|
||||
* online参数值设置(是:Y, 否:N)
|
||||
*/
|
||||
public static final String ONLINE_PARAM_VAL_IS_TURE = "Y";
|
||||
public static final String ONLINE_PARAM_VAL_IS_FALSE = "N";
|
||||
|
||||
/**
|
||||
* 文件上传类型(本地:local,Minio:minio,阿里云:alioss)
|
||||
*/
|
||||
public static final String UPLOAD_TYPE_LOCAL = "local";
|
||||
public static final String UPLOAD_TYPE_MINIO = "minio";
|
||||
public static final String UPLOAD_TYPE_OSS = "alioss";
|
||||
|
||||
/**
|
||||
* 文档上传自定义桶名称
|
||||
*/
|
||||
public static final String UPLOAD_CUSTOM_BUCKET = "eoafile";
|
||||
/**
|
||||
* 文档上传自定义路径
|
||||
*/
|
||||
public static final String UPLOAD_CUSTOM_PATH = "eoafile";
|
||||
/**
|
||||
* 文件外链接有效天数
|
||||
*/
|
||||
public static final Integer UPLOAD_EFFECTIVE_DAYS = 1;
|
||||
|
||||
/**
|
||||
* 员工身份 (1:普通员工 2:上级)
|
||||
*/
|
||||
public static final Integer USER_IDENTITY_1 = 1;
|
||||
public static final Integer USER_IDENTITY_2 = 2;
|
||||
|
||||
/** sys_user 表 username 唯一键索引 */
|
||||
public static final String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username";
|
||||
/** sys_user 表 work_no 唯一键索引 */
|
||||
public static final String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no";
|
||||
/** sys_user 表 phone 唯一键索引 */
|
||||
public static final String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone";
|
||||
/** sys_user 表 email 唯一键索引 */
|
||||
public static final String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email";
|
||||
/** sys_quartz_job 表 job_class_name 唯一键索引 */
|
||||
public static final String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name";
|
||||
/** sys_position 表 code 唯一键索引 */
|
||||
public static final String SQL_INDEX_UNIQ_CODE = "uniq_code";
|
||||
/** sys_role 表 code 唯一键索引 */
|
||||
public static final String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code";
|
||||
/** sys_depart 表 code 唯一键索引 */
|
||||
public static final String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code";
|
||||
/**
|
||||
* 在线聊天 是否为默认分组
|
||||
*/
|
||||
public static final String IM_DEFAULT_GROUP = "1";
|
||||
/**
|
||||
* 在线聊天 图片文件保存路径
|
||||
*/
|
||||
public static final String IM_UPLOAD_CUSTOM_PATH = "imfile";
|
||||
/**
|
||||
* 在线聊天 用户状态
|
||||
*/
|
||||
public static final String IM_STATUS_ONLINE = "online";
|
||||
|
||||
/**
|
||||
* 在线聊天 SOCKET消息类型
|
||||
*/
|
||||
public static final String IM_SOCKET_TYPE = "chatMessage";
|
||||
|
||||
/**
|
||||
* 在线聊天 是否开启默认添加好友 1是 0否
|
||||
*/
|
||||
public static final String IM_DEFAULT_ADD_FRIEND = "1";
|
||||
|
||||
/**
|
||||
* 在线聊天 用户好友缓存前缀
|
||||
*/
|
||||
public static final String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_";
|
||||
|
||||
/**
|
||||
* 考勤补卡业务状态 (1:同意 2:不同意)
|
||||
*/
|
||||
public static final String SIGN_PATCH_BIZ_STATUS_1 = "1";
|
||||
public static final String SIGN_PATCH_BIZ_STATUS_2 = "2";
|
||||
|
||||
/**
|
||||
* 公文文档上传自定义路径
|
||||
*/
|
||||
public static final String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc";
|
||||
/**
|
||||
* 公文文档下载自定义路径
|
||||
*/
|
||||
public static final String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown";
|
||||
|
||||
/**
|
||||
* WPS存储值类别(1 code文号 2 text(WPS模板还是公文发文模板))
|
||||
*/
|
||||
public static final String WPS_TYPE_1="1";
|
||||
public static final String WPS_TYPE_2="2";
|
||||
|
||||
|
||||
public final static String X_ACCESS_TOKEN = "X-Access-Token";
|
||||
public final static String X_SIGN = "X-Sign";
|
||||
public final static String X_TIMESTAMP = "X-TIMESTAMP";
|
||||
public final static String TOKEN_IS_INVALID_MSG = "Token失效,请重新登录!";
|
||||
|
||||
/**
|
||||
* 多租户 请求头
|
||||
*/
|
||||
public final static String TENANT_ID = "tenant-id";
|
||||
|
||||
/**
|
||||
* 微服务读取配置文件属性 服务地址
|
||||
*/
|
||||
public final static String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr";
|
||||
|
||||
/**
|
||||
* 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用
|
||||
*/
|
||||
public final static String THIRD_LOGIN_CODE = "third_login_code";
|
||||
|
||||
/**
|
||||
* 第三方APP同步方向:本地 --> 第三方APP
|
||||
*/
|
||||
String THIRD_SYNC_TO_APP = "SYNC_TO_APP";
|
||||
/**
|
||||
* 第三方APP同步方向:第三方APP --> 本地
|
||||
*/
|
||||
String THIRD_SYNC_TO_LOCAL = "SYNC_TO_LOCAL";
|
||||
|
||||
/** 系统通告消息状态:0=未发布 */
|
||||
String ANNOUNCEMENT_SEND_STATUS_0 = "0";
|
||||
/** 系统通告消息状态:1=已发布 */
|
||||
String ANNOUNCEMENT_SEND_STATUS_1 = "1";
|
||||
/** 系统通告消息状态:2=已撤销 */
|
||||
String ANNOUNCEMENT_SEND_STATUS_2 = "2";
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package org.enfi.common.constant;
|
||||
|
||||
/**
|
||||
* 系统通告 - 发布状态
|
||||
* @Author LeeShaoQing
|
||||
*
|
||||
*/
|
||||
public interface CommonSendStatus {
|
||||
|
||||
public static final String UNPUBLISHED_STATUS_0 = "0"; //未发布
|
||||
|
||||
public static final String PUBLISHED_STATUS_1 = "1"; //已发布
|
||||
|
||||
public static final String REVOKE_STATUS_2 = "2"; //撤销
|
||||
//app端推送会话标识后缀
|
||||
public static final String APP_SESSION_SUFFIX = "_app"; //app端推送会话标识后缀
|
||||
|
||||
|
||||
|
||||
/**流程催办——系统通知消息模板*/
|
||||
public static final String TZMB_BPM_CUIBAN = "bpm_cuiban";
|
||||
/**标准模板—系统消息通知*/
|
||||
public static final String TZMB_SYS_TS_NOTE = "sys_ts_note";
|
||||
/**流程超时提醒——系统通知消息模板*/
|
||||
public static final String TZMB_BPM_CHAOSHI_TIP = "bpm_chaoshi_tip";
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
package org.enfi.common.constant;
|
||||
/**
|
||||
* 数据库上下文常量
|
||||
*/
|
||||
public interface DataBaseConstant {
|
||||
//*********数据库类型****************************************
|
||||
public static final String DB_TYPE_MYSQL = "MYSQL";
|
||||
public static final String DB_TYPE_ORACLE = "ORACLE";
|
||||
public static final String DB_TYPE_DM = "DM";//达梦数据库
|
||||
public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";
|
||||
public static final String DB_TYPE_SQLSERVER = "SQLSERVER";
|
||||
public static final String DB_TYPE_MARIADB = "MARIADB";
|
||||
public static final String DB_TYPE_DB2 = "DB2";
|
||||
public static final String DB_TYPE_HSQL = "HSQL";
|
||||
|
||||
// // 数据库类型,对应 database_type 字典
|
||||
// public static final String DB_TYPE_MYSQL_NUM = "1";
|
||||
// public static final String DB_TYPE_MYSQL7_NUM = "6";
|
||||
// public static final String DB_TYPE_ORACLE_NUM = "2";
|
||||
// public static final String DB_TYPE_SQLSERVER_NUM = "3";
|
||||
// public static final String DB_TYPE_POSTGRESQL_NUM = "4";
|
||||
// public static final String DB_TYPE_MARIADB_NUM = "5";
|
||||
|
||||
//*********系统上下文变量****************************************
|
||||
/**
|
||||
* 数据-所属机构编码
|
||||
*/
|
||||
public static final String SYS_ORG_CODE = "sysOrgCode";
|
||||
/**
|
||||
* 数据-所属机构编码
|
||||
*/
|
||||
public static final String SYS_ORG_CODE_TABLE = "sys_org_code";
|
||||
/**
|
||||
* 数据-所属机构编码
|
||||
*/
|
||||
public static final String SYS_MULTI_ORG_CODE = "sysMultiOrgCode";
|
||||
/**
|
||||
* 数据-所属机构编码
|
||||
*/
|
||||
public static final String SYS_MULTI_ORG_CODE_TABLE = "sys_multi_org_code";
|
||||
/**
|
||||
* 数据-系统用户编码(对应登录用户账号)
|
||||
*/
|
||||
public static final String SYS_USER_CODE = "sysUserCode";
|
||||
/**
|
||||
* 数据-系统用户编码(对应登录用户账号)
|
||||
*/
|
||||
public static final String SYS_USER_CODE_TABLE = "sys_user_code";
|
||||
|
||||
/**
|
||||
* 登录用户真实姓名
|
||||
*/
|
||||
public static final String SYS_USER_NAME = "sysUserName";
|
||||
/**
|
||||
* 登录用户真实姓名
|
||||
*/
|
||||
public static final String SYS_USER_NAME_TABLE = "sys_user_name";
|
||||
/**
|
||||
* 系统日期"yyyy-MM-dd"
|
||||
*/
|
||||
public static final String SYS_DATE = "sysDate";
|
||||
/**
|
||||
* 系统日期"yyyy-MM-dd"
|
||||
*/
|
||||
public static final String SYS_DATE_TABLE = "sys_date";
|
||||
/**
|
||||
* 系统时间"yyyy-MM-dd HH:mm"
|
||||
*/
|
||||
public static final String SYS_TIME = "sysTime";
|
||||
/**
|
||||
* 系统时间"yyyy-MM-dd HH:mm"
|
||||
*/
|
||||
public static final String SYS_TIME_TABLE = "sys_time";
|
||||
/**
|
||||
* 数据-所属机构编码
|
||||
*/
|
||||
public static final String SYS_BASE_PATH = "sys_base_path";
|
||||
//*********系统上下文变量****************************************
|
||||
|
||||
|
||||
//*********系统建表标准字段****************************************
|
||||
/**
|
||||
* 创建者登录名称
|
||||
*/
|
||||
public static final String CREATE_BY_TABLE = "create_by";
|
||||
/**
|
||||
* 创建者登录名称
|
||||
*/
|
||||
public static final String CREATE_BY = "createBy";
|
||||
/**
|
||||
* 创建日期时间
|
||||
*/
|
||||
public static final String CREATE_TIME_TABLE = "create_time";
|
||||
/**
|
||||
* 创建日期时间
|
||||
*/
|
||||
public static final String CREATE_TIME = "createTime";
|
||||
/**
|
||||
* 更新用户登录名称
|
||||
*/
|
||||
public static final String UPDATE_BY_TABLE = "update_by";
|
||||
/**
|
||||
* 更新用户登录名称
|
||||
*/
|
||||
public static final String UPDATE_BY = "updateBy";
|
||||
/**
|
||||
* 更新日期时间
|
||||
*/
|
||||
public static final String UPDATE_TIME = "updateTime";
|
||||
/**
|
||||
* 更新日期时间
|
||||
*/
|
||||
public static final String UPDATE_TIME_TABLE = "update_time";
|
||||
|
||||
/**
|
||||
* 业务流程状态
|
||||
*/
|
||||
public static final String BPM_STATUS = "bpmStatus";
|
||||
/**
|
||||
* 业务流程状态
|
||||
*/
|
||||
public static final String BPM_STATUS_TABLE = "bpm_status";
|
||||
//*********系统建表标准字段****************************************
|
||||
|
||||
|
||||
/**
|
||||
* 租户ID 实体字段名
|
||||
*/
|
||||
String TENANT_ID = "tenantId";
|
||||
/**
|
||||
* 租户ID 数据库字段名
|
||||
*/
|
||||
String TENANT_ID_TABLE = "tenant_id";
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.enfi.common.constant;
|
||||
|
||||
/**
|
||||
* 规则值生成 编码常量类
|
||||
* @author: taoyan
|
||||
* @date: 2020年04月02日
|
||||
*/
|
||||
public class FillRuleConstant {
|
||||
|
||||
/**
|
||||
* 公文发文编码
|
||||
*/
|
||||
public static final String DOC_SEND = "doc_send_code";
|
||||
|
||||
/**
|
||||
* 部门编码
|
||||
*/
|
||||
public static final String DEPART = "org_num_role";
|
||||
|
||||
/**
|
||||
* 分类字典编码
|
||||
*/
|
||||
public static final String CATEGORY = "category_code_rule";
|
||||
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
package org.enfi.common.constant;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
@Component("pca")
|
||||
public class ProvinceCityArea {
|
||||
List<Area> areaList;
|
||||
|
||||
public String getText(String code){
|
||||
this.initAreaList();
|
||||
if(this.areaList!=null || this.areaList.size()>0){
|
||||
List<String> ls = new ArrayList<String>();
|
||||
getAreaByCode(code,ls);
|
||||
return String.join("/",ls);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getCode(String text){
|
||||
this.initAreaList();
|
||||
if(areaList!=null || areaList.size()>0){
|
||||
for(int i=areaList.size()-1;i>=0;i--){
|
||||
if(text.indexOf(areaList.get(i).getText())>=0){
|
||||
return areaList.get(i).getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void getAreaByCode(String code,List<String> ls){
|
||||
for(Area area: areaList){
|
||||
if(area.getId().equals(code)){
|
||||
String pid = area.getPid();
|
||||
ls.add(0,area.getText());
|
||||
getAreaByCode(pid,ls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initAreaList(){
|
||||
//System.out.println("=====================");
|
||||
if(this.areaList==null || this.areaList.size()==0){
|
||||
this.areaList = new ArrayList<Area>();
|
||||
try {
|
||||
String jsonData = oConvertUtils.readStatic("classpath:static/pca.json");
|
||||
JSONObject baseJson = JSONObject.parseObject(jsonData);
|
||||
//第一层 省
|
||||
JSONObject provinceJson = baseJson.getJSONObject("86");
|
||||
for(String provinceKey: provinceJson.keySet()){
|
||||
//System.out.println("===="+provinceKey);
|
||||
Area province = new Area(provinceKey,provinceJson.getString(provinceKey),"86");
|
||||
this.areaList.add(province);
|
||||
//第二层 市
|
||||
JSONObject cityJson = baseJson.getJSONObject(provinceKey);
|
||||
for(String cityKey:cityJson.keySet()){
|
||||
//System.out.println("-----"+cityKey);
|
||||
Area city = new Area(cityKey,cityJson.getString(cityKey),provinceKey);
|
||||
this.areaList.add(city);
|
||||
//第三层 区
|
||||
JSONObject areaJson = baseJson.getJSONObject(cityKey);
|
||||
if(areaJson!=null){
|
||||
for(String areaKey:areaJson.keySet()){
|
||||
//System.out.println("········"+areaKey);
|
||||
Area area = new Area(areaKey,areaJson.getString(areaKey),cityKey);
|
||||
this.areaList.add(area);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private String jsonRead(File file){
|
||||
Scanner scanner = null;
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
try {
|
||||
scanner = new Scanner(file, "utf-8");
|
||||
while (scanner.hasNextLine()) {
|
||||
buffer.append(scanner.nextLine());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
} finally {
|
||||
if (scanner != null) {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
class Area{
|
||||
String id;
|
||||
String text;
|
||||
String pid;
|
||||
|
||||
public Area(String id,String text,String pid){
|
||||
this.id = id;
|
||||
this.text = text;
|
||||
this.pid = pid;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public String getPid() {
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright (c) 2019-2020, 冷冷 (wangiegie@gmail.com).
|
||||
* * <p>
|
||||
* * Licensed under the GNU Lesser General Public License 3.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* * <p>
|
||||
* * https://www.gnu.org/licenses/lgpl.html
|
||||
* * <p>
|
||||
* * 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.enfi.common.constant;
|
||||
|
||||
/**
|
||||
* @author scott
|
||||
* @date 2019年05月18日
|
||||
* 服务名称
|
||||
*/
|
||||
public interface ServiceNameConstants {
|
||||
|
||||
/**
|
||||
* 系统管理 admin
|
||||
*/
|
||||
String SYSTEM_SERVICE = "enfi-system";
|
||||
String SYSTEM_ONLINE = "enfi-online";
|
||||
|
||||
/**
|
||||
* gateway通过header传递根路径 basePath
|
||||
*/
|
||||
String X_GATEWAY_BASE_PATH = "X_GATEWAY_BASE_PATH";
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package org.enfi.common.constant;
|
||||
|
||||
/**
|
||||
* VXESocket 常量
|
||||
*/
|
||||
public class VXESocketConst {
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
public static final String TYPE = "type";
|
||||
/**
|
||||
* 消息数据
|
||||
*/
|
||||
public static final String DATA = "data";
|
||||
|
||||
/**
|
||||
* 消息类型:心跳检测
|
||||
*/
|
||||
public static final String TYPE_HB = "heart_beat";
|
||||
/**
|
||||
* 消息类型:通用数据传递
|
||||
*/
|
||||
public static final String TYPE_CSD = "common_send_date";
|
||||
/**
|
||||
* 消息类型:更新vxe table数据
|
||||
*/
|
||||
public static final String TYPE_UVT = "update_vxe_table";
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package org.enfi.common.constant;
|
||||
|
||||
/**
|
||||
* @Description: Websocket常量类
|
||||
* @author: taoyan
|
||||
* @date: 2020年03月23日
|
||||
*/
|
||||
public class WebsocketConst {
|
||||
|
||||
|
||||
/**
|
||||
* 消息json key:cmd
|
||||
*/
|
||||
public static final String MSG_CMD = "cmd";
|
||||
|
||||
/**
|
||||
* 消息json key:msgId
|
||||
*/
|
||||
public static final String MSG_ID = "msgId";
|
||||
|
||||
/**
|
||||
* 消息json key:msgTxt
|
||||
*/
|
||||
public static final String MSG_TXT = "msgTxt";
|
||||
|
||||
/**
|
||||
* 消息json key:userId
|
||||
*/
|
||||
public static final String MSG_USER_ID = "userId";
|
||||
|
||||
/**
|
||||
* 消息类型 heartcheck
|
||||
*/
|
||||
public static final String CMD_CHECK = "heartcheck";
|
||||
|
||||
/**
|
||||
* 消息类型 user 用户消息
|
||||
*/
|
||||
public static final String CMD_USER = "user";
|
||||
|
||||
/**
|
||||
* 消息类型 topic 系统通知
|
||||
*/
|
||||
public static final String CMD_TOPIC = "topic";
|
||||
|
||||
/**
|
||||
* 消息类型 email
|
||||
*/
|
||||
public static final String CMD_EMAIL = "email";
|
||||
|
||||
/**
|
||||
* 消息类型 meetingsign 会议签到
|
||||
*/
|
||||
public static final String CMD_SIGN = "sign";
|
||||
|
||||
/**
|
||||
* 消息类型 新闻发布/取消
|
||||
*/
|
||||
public static final String NEWS_PUBLISH = "publish";
|
||||
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package org.enfi.common.constant.enums;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* online表单枚举 代码生成器用到
|
||||
*/
|
||||
public enum CgformEnum {
|
||||
|
||||
/**
|
||||
* 单表
|
||||
*/
|
||||
ONE(1, "one", "/enfi/code-template-online", "default.one", "经典风格"),
|
||||
/**
|
||||
* 多表
|
||||
*/
|
||||
MANY(2, "many", "/enfi/code-template-online", "default.onetomany", "经典风格"),
|
||||
/**
|
||||
* 多表
|
||||
*/
|
||||
ERP(2, "erp", "/enfi/code-template-online", "erp.onetomany", "ERP风格"),
|
||||
/**
|
||||
* 多表(jvxe风格)
|
||||
* */
|
||||
JVXE_TABLE(2, "jvxe", "/enfi/code-template-online", "jvxe.onetomany", "JVXE风格"),
|
||||
/**
|
||||
* 多表(内嵌子表风格)
|
||||
*/
|
||||
INNER_TABLE(2, "innerTable", "/enfi/code-template-online", "inner-table.onetomany", "内嵌子表风格"),
|
||||
/**
|
||||
* 多表(tab风格)
|
||||
* */
|
||||
TAB(2, "tab", "/enfi/code-template-online", "tab.onetomany", "Tab风格"),
|
||||
/**
|
||||
* 树形列表
|
||||
*/
|
||||
TREE(3, "tree", "/enfi/code-template-online", "default.tree", "树形列表");
|
||||
|
||||
/**
|
||||
* 类型 1/单表 2/一对多 3/树
|
||||
*/
|
||||
int type;
|
||||
/**
|
||||
* 编码标识
|
||||
*/
|
||||
String code;
|
||||
/**
|
||||
* 代码生成器模板路径
|
||||
*/
|
||||
String templatePath;
|
||||
/**
|
||||
* 代码生成器模板路径
|
||||
*/
|
||||
String stylePath;
|
||||
/**
|
||||
* 模板风格名称
|
||||
*/
|
||||
String note;
|
||||
|
||||
/**
|
||||
* 构造器
|
||||
*
|
||||
* @param type 类型 1/单表 2/一对多 3/树
|
||||
* @param code 模板编码
|
||||
* @param templatePath 模板路径
|
||||
* @param stylePath 模板子路径
|
||||
* @param note
|
||||
*/
|
||||
CgformEnum(int type, String code, String templatePath, String stylePath, String note) {
|
||||
this.type = type;
|
||||
this.code = code;
|
||||
this.templatePath = templatePath;
|
||||
this.stylePath = stylePath;
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取模板路径
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public static String getTemplatePathByConfig(String code) {
|
||||
return getCgformEnumByConfig(code).templatePath;
|
||||
}
|
||||
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getTemplatePath() {
|
||||
return templatePath;
|
||||
}
|
||||
|
||||
public void setTemplatePath(String templatePath) {
|
||||
this.templatePath = templatePath;
|
||||
}
|
||||
|
||||
public String getStylePath() {
|
||||
return stylePath;
|
||||
}
|
||||
|
||||
public void setStylePath(String stylePath) {
|
||||
this.stylePath = stylePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code找枚举
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public static CgformEnum getCgformEnumByConfig(String code) {
|
||||
for (CgformEnum e : CgformEnum.values()) {
|
||||
if (e.code.equals(code)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型找所有
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
public static List<Map<String, Object>> getJspModelList(int type) {
|
||||
List<Map<String, Object>> ls = new ArrayList<Map<String, Object>>();
|
||||
for (CgformEnum e : CgformEnum.values()) {
|
||||
if (e.type == type) {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("code", e.code);
|
||||
map.put("note", e.note);
|
||||
ls.add(map);
|
||||
}
|
||||
}
|
||||
return ls;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.enfi.common.constant.enums;
|
||||
|
||||
/**
|
||||
* 日志按模块分类
|
||||
*/
|
||||
public enum ModuleType {
|
||||
|
||||
/**
|
||||
* 普通
|
||||
*/
|
||||
COMMON,
|
||||
|
||||
/**
|
||||
* online
|
||||
*/
|
||||
ONLINE;
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package org.enfi.common.constant.enums;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 首页自定义
|
||||
* 通过角色编码与首页组件路径配置
|
||||
*/
|
||||
public enum RoleIndexConfigEnum {
|
||||
/**
|
||||
* 管理员
|
||||
*/
|
||||
ADMIN("admin1", "dashboard/Analysis2"),
|
||||
/**
|
||||
* 测试
|
||||
*/
|
||||
TEST("test", "dashboard/Analysis"),
|
||||
/**
|
||||
* hr
|
||||
*/
|
||||
HR("hr", "dashboard/Analysis1");
|
||||
|
||||
/**
|
||||
* 角色编码
|
||||
*/
|
||||
String roleCode;
|
||||
/**
|
||||
* 路由index
|
||||
*/
|
||||
String componentUrl;
|
||||
|
||||
/**
|
||||
* 构造器
|
||||
*
|
||||
* @param roleCode 角色编码
|
||||
* @param componentUrl 首页组件路径(规则跟菜单配置一样)
|
||||
*/
|
||||
RoleIndexConfigEnum(String roleCode, String componentUrl) {
|
||||
this.roleCode = roleCode;
|
||||
this.componentUrl = componentUrl;
|
||||
}
|
||||
/**
|
||||
* 根据code找枚举
|
||||
* @param roleCode 角色编码
|
||||
* @return
|
||||
*/
|
||||
public static RoleIndexConfigEnum getEnumByCode(String roleCode) {
|
||||
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
|
||||
if (e.roleCode.equals(roleCode)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 根据code找index
|
||||
* @param roleCode 角色编码
|
||||
* @return
|
||||
*/
|
||||
public static String getIndexByCode(String roleCode) {
|
||||
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
|
||||
if (e.roleCode.equals(roleCode)) {
|
||||
return e.componentUrl;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getIndexByRoles(List<String> roles) {
|
||||
for (String role : roles) {
|
||||
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
|
||||
if (e.roleCode.equals(role)) {
|
||||
return e.componentUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRoleCode() {
|
||||
return roleCode;
|
||||
}
|
||||
|
||||
public void setRoleCode(String roleCode) {
|
||||
this.roleCode = roleCode;
|
||||
}
|
||||
|
||||
public String getComponentUrl() {
|
||||
return componentUrl;
|
||||
}
|
||||
|
||||
public void setComponentUrl(String componentUrl) {
|
||||
this.componentUrl = componentUrl;
|
||||
}
|
||||
}
|
@ -0,0 +1,538 @@
|
||||
package org.enfi.common.es;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.enfi.common.util.RestUtil;
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 关于 ElasticSearch 的一些方法(创建索引、添加数据、查询等)
|
||||
*
|
||||
* @author sunjianlei
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class EnFiElasticsearchTemplate {
|
||||
/** es服务地址 */
|
||||
private String baseUrl;
|
||||
private final String FORMAT_JSON = "format=json";
|
||||
/** Elasticsearch 的版本号 */
|
||||
private String version = null;
|
||||
|
||||
// ElasticSearch 最大可返回条目数
|
||||
public static final int ES_MAX_SIZE = 10000;
|
||||
|
||||
public EnFiElasticsearchTemplate(@Value("${enfi.elasticsearch.cluster-nodes}") String baseUrl, @Value("${enfi.elasticsearch.check-enabled}") boolean checkEnabled) {
|
||||
log.debug("EnFiElasticsearchTemplate BaseURL:" + baseUrl);
|
||||
if (StringUtils.isNotEmpty(baseUrl)) {
|
||||
this.baseUrl = baseUrl;
|
||||
// 验证配置的ES地址是否有效
|
||||
if (checkEnabled) {
|
||||
try {
|
||||
this.getElasticsearchVersion();
|
||||
log.info("ElasticSearch 服务连接成功");
|
||||
log.info("ElasticSearch version: " + this.version);
|
||||
} catch (Exception e) {
|
||||
this.version = "";
|
||||
log.warn("ElasticSearch 服务连接失败,原因:配置未通过。可能是BaseURL未配置或配置有误,也可能是Elasticsearch服务未启动。接下来将会拒绝执行任何方法!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Elasticsearch 的版本号信息,失败返回null
|
||||
*/
|
||||
private void getElasticsearchVersion() {
|
||||
if (this.version == null) {
|
||||
String url = this.getBaseUrl().toString();
|
||||
JSONObject result = RestUtil.get(url);
|
||||
if (result != null) {
|
||||
JSONObject v = result.getJSONObject("version");
|
||||
this.version = v.getString("number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public StringBuilder getBaseUrl(String indexName, String typeName) {
|
||||
typeName = typeName.trim().toLowerCase();
|
||||
return this.getBaseUrl(indexName).append("/").append(typeName);
|
||||
}
|
||||
|
||||
public StringBuilder getBaseUrl(String indexName) {
|
||||
indexName = indexName.trim().toLowerCase();
|
||||
return this.getBaseUrl().append("/").append(indexName);
|
||||
}
|
||||
|
||||
public StringBuilder getBaseUrl() {
|
||||
return new StringBuilder("http://").append(this.baseUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* cat 查询ElasticSearch系统数据,返回json
|
||||
*/
|
||||
public <T> ResponseEntity<T> _cat(String urlAfter, Class<T> responseType) {
|
||||
String url = this.getBaseUrl().append("/_cat").append(urlAfter).append("?").append(FORMAT_JSON).toString();
|
||||
return RestUtil.request(url, HttpMethod.GET, null, null, null, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有索引
|
||||
* <p>
|
||||
* 查询地址:GET http://{baseUrl}/_cat/indices
|
||||
*/
|
||||
public JSONArray getIndices() {
|
||||
return getIndices(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询单个索引
|
||||
* <p>
|
||||
* 查询地址:GET http://{baseUrl}/_cat/indices/{indexName}
|
||||
*/
|
||||
public JSONArray getIndices(String indexName) {
|
||||
StringBuilder urlAfter = new StringBuilder("/indices");
|
||||
if (!StringUtils.isEmpty(indexName)) {
|
||||
urlAfter.append("/").append(indexName.trim().toLowerCase());
|
||||
}
|
||||
return _cat(urlAfter.toString(), JSONArray.class).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 索引是否存在
|
||||
*/
|
||||
public boolean indexExists(String indexName) {
|
||||
try {
|
||||
JSONArray array = getIndices(indexName);
|
||||
return array != null;
|
||||
} catch (org.springframework.web.client.HttpClientErrorException ex) {
|
||||
if (HttpStatus.NOT_FOUND == ex.getStatusCode()) {
|
||||
return false;
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取索引数据,未查询到返回null
|
||||
* <p>
|
||||
* 查询地址:GET http://{baseUrl}/{indexName}/{typeName}/{dataId}
|
||||
*
|
||||
* @param indexName 索引名称
|
||||
* @param typeName type,一个任意字符串,用于分类
|
||||
* @param dataId 数据id
|
||||
* @return
|
||||
*/
|
||||
public JSONObject getDataById(String indexName, String typeName, String dataId) {
|
||||
String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).toString();
|
||||
log.info("url:" + url);
|
||||
JSONObject result = RestUtil.get(url);
|
||||
boolean found = result.getBoolean("found");
|
||||
if (found) {
|
||||
return result.getJSONObject("_source");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建索引
|
||||
* <p>
|
||||
* 查询地址:PUT http://{baseUrl}/{indexName}
|
||||
*/
|
||||
public boolean createIndex(String indexName) {
|
||||
String url = this.getBaseUrl(indexName).toString();
|
||||
|
||||
/* 返回结果 (仅供参考)
|
||||
"createIndex": {
|
||||
"shards_acknowledged": true,
|
||||
"acknowledged": true,
|
||||
"index": "hello_world"
|
||||
}
|
||||
*/
|
||||
try {
|
||||
return RestUtil.put(url).getBoolean("acknowledged");
|
||||
} catch (org.springframework.web.client.HttpClientErrorException ex) {
|
||||
if (HttpStatus.BAD_REQUEST == ex.getStatusCode()) {
|
||||
log.warn("索引创建失败:" + indexName + " 已存在,无需再创建");
|
||||
} else {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除索引
|
||||
* <p>
|
||||
* 查询地址:DELETE http://{baseUrl}/{indexName}
|
||||
*/
|
||||
public boolean removeIndex(String indexName) {
|
||||
String url = this.getBaseUrl(indexName).toString();
|
||||
try {
|
||||
return RestUtil.delete(url).getBoolean("acknowledged");
|
||||
} catch (org.springframework.web.client.HttpClientErrorException ex) {
|
||||
if (HttpStatus.NOT_FOUND == ex.getStatusCode()) {
|
||||
log.warn("索引删除失败:" + indexName + " 不存在,无需删除");
|
||||
} else {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取索引字段映射(可获取字段类型)
|
||||
* <p>
|
||||
*
|
||||
* @param indexName 索引名称
|
||||
* @param typeName 分类名称
|
||||
* @return
|
||||
*/
|
||||
public JSONObject getIndexMapping(String indexName, String typeName) {
|
||||
String url = this.getBaseUrl(indexName, typeName).append("/_mapping?").append(FORMAT_JSON).toString();
|
||||
// 针对 es 7.x 版本做兼容
|
||||
this.getElasticsearchVersion();
|
||||
if (oConvertUtils.isNotEmpty(this.version) && this.version.startsWith("7")) {
|
||||
url += "&include_type_name=true";
|
||||
}
|
||||
log.info("getIndexMapping-url:" + url);
|
||||
/*
|
||||
* 参考返回JSON结构:
|
||||
*
|
||||
*{
|
||||
* // 索引名称
|
||||
* "[indexName]": {
|
||||
* "mappings": {
|
||||
* // 分类名称
|
||||
* "[typeName]": {
|
||||
* "properties": {
|
||||
* // 字段名
|
||||
* "input_number": {
|
||||
* // 字段类型
|
||||
* "type": "long"
|
||||
* },
|
||||
* "input_string": {
|
||||
* "type": "text",
|
||||
* "fields": {
|
||||
* "keyword": {
|
||||
* "type": "keyword",
|
||||
* "ignore_above": 256
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
try {
|
||||
return RestUtil.get(url);
|
||||
} catch (org.springframework.web.client.HttpClientErrorException e) {
|
||||
String message = e.getMessage();
|
||||
if (message != null && message.contains("404 Not Found")) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取索引字段映射,返回Java实体类
|
||||
*
|
||||
* @param indexName
|
||||
* @param typeName
|
||||
* @return
|
||||
*/
|
||||
public <T> Map<String, T> getIndexMappingFormat(String indexName, String typeName, Class<T> clazz) {
|
||||
JSONObject mapping = this.getIndexMapping(indexName, typeName);
|
||||
Map<String, T> map = new HashMap<>();
|
||||
if (mapping == null) {
|
||||
return map;
|
||||
}
|
||||
// 获取字段属性
|
||||
JSONObject properties = mapping.getJSONObject(indexName)
|
||||
.getJSONObject("mappings")
|
||||
.getJSONObject(typeName)
|
||||
.getJSONObject("properties");
|
||||
// 封装成 java类型
|
||||
for (String key : properties.keySet()) {
|
||||
T entity = properties.getJSONObject(key).toJavaObject(clazz);
|
||||
map.put(key, entity);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存数据,详见:saveOrUpdate
|
||||
*/
|
||||
public boolean save(String indexName, String typeName, String dataId, JSONObject data) {
|
||||
return this.saveOrUpdate(indexName, typeName, dataId, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新数据,详见:saveOrUpdate
|
||||
*/
|
||||
public boolean update(String indexName, String typeName, String dataId, JSONObject data) {
|
||||
return this.saveOrUpdate(indexName, typeName, dataId, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存或修改索引数据
|
||||
* <p>
|
||||
* 查询地址:PUT http://{baseUrl}/{indexName}/{typeName}/{dataId}
|
||||
*
|
||||
* @param indexName 索引名称
|
||||
* @param typeName type,一个任意字符串,用于分类
|
||||
* @param dataId 数据id
|
||||
* @param data 要存储的数据
|
||||
* @return
|
||||
*/
|
||||
public boolean saveOrUpdate(String indexName, String typeName, String dataId, JSONObject data) {
|
||||
String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).append("?refresh=wait_for").toString();
|
||||
/* 返回结果(仅供参考)
|
||||
"createIndexA2": {
|
||||
"result": "created",
|
||||
"_shards": {
|
||||
"total": 2,
|
||||
"successful": 1,
|
||||
"failed": 0
|
||||
},
|
||||
"_seq_no": 0,
|
||||
"_index": "test_index_1",
|
||||
"_type": "test_type_1",
|
||||
"_id": "a2",
|
||||
"_version": 1,
|
||||
"_primary_term": 1
|
||||
}
|
||||
*/
|
||||
|
||||
try {
|
||||
// 去掉 data 中为空的值
|
||||
Set<String> keys = data.keySet();
|
||||
List<String> emptyKeys = new ArrayList<>(keys.size());
|
||||
for (String key : keys) {
|
||||
String value = data.getString(key);
|
||||
//1、剔除空值
|
||||
if (oConvertUtils.isEmpty(value) || "[]".equals(value)) {
|
||||
emptyKeys.add(key);
|
||||
}
|
||||
//2、剔除上传控件值(会导致ES同步失败,报异常failed to parse field [ge_pic] of type [text] )
|
||||
if (oConvertUtils.isNotEmpty(value) && value.indexOf("[{")!=-1) {
|
||||
emptyKeys.add(key);
|
||||
log.info("-------剔除上传控件字段------------key: "+ key);
|
||||
}
|
||||
}
|
||||
for (String key : emptyKeys) {
|
||||
data.remove(key);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
String result = RestUtil.put(url, data).getString("result");
|
||||
return "created".equals(result) || "updated".equals(result);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage() + "\n-- url: " + url + "\n-- data: " + data.toJSONString());
|
||||
//TODO 打印接口返回异常json
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量保存数据
|
||||
*
|
||||
* @param indexName 索引名称
|
||||
* @param typeName type,一个任意字符串,用于分类
|
||||
* @param dataList 要存储的数据数组,每行数据必须包含id
|
||||
* @return
|
||||
*/
|
||||
public boolean saveBatch(String indexName, String typeName, JSONArray dataList) {
|
||||
String url = this.getBaseUrl().append("/_bulk").append("?refresh=wait_for").toString();
|
||||
StringBuilder bodySB = new StringBuilder();
|
||||
for (int i = 0; i < dataList.size(); i++) {
|
||||
JSONObject data = dataList.getJSONObject(i);
|
||||
String id = data.getString("id");
|
||||
// 该行的操作
|
||||
// {"create": {"_id":"${id}", "_index": "${indexName}", "_type": "${typeName}"}}
|
||||
JSONObject action = new JSONObject();
|
||||
JSONObject actionInfo = new JSONObject();
|
||||
actionInfo.put("_id", id);
|
||||
actionInfo.put("_index", indexName);
|
||||
actionInfo.put("_type", typeName);
|
||||
action.put("create", actionInfo);
|
||||
bodySB.append(action.toJSONString()).append("\n");
|
||||
// 该行的数据
|
||||
data.remove("id");
|
||||
bodySB.append(data.toJSONString()).append("\n");
|
||||
}
|
||||
System.out.println("+-+-+-: bodySB.toString(): " + bodySB.toString());
|
||||
HttpHeaders headers = RestUtil.getHeaderApplicationJson();
|
||||
RestUtil.request(url, HttpMethod.PUT, headers, null, bodySB, JSONObject.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除索引数据
|
||||
* <p>
|
||||
* 请求地址:DELETE http://{baseUrl}/{indexName}/{typeName}/{dataId}
|
||||
*/
|
||||
public boolean delete(String indexName, String typeName, String dataId) {
|
||||
String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).toString();
|
||||
/* 返回结果(仅供参考)
|
||||
{
|
||||
"_index": "es_demo",
|
||||
"_type": "docs",
|
||||
"_id": "001",
|
||||
"_version": 3,
|
||||
"result": "deleted",
|
||||
"_shards": {
|
||||
"total": 1,
|
||||
"successful": 1,
|
||||
"failed": 0
|
||||
},
|
||||
"_seq_no": 28,
|
||||
"_primary_term": 18
|
||||
}
|
||||
*/
|
||||
try {
|
||||
return "deleted".equals(RestUtil.delete(url).getString("result"));
|
||||
} catch (org.springframework.web.client.HttpClientErrorException ex) {
|
||||
if (HttpStatus.NOT_FOUND == ex.getStatusCode()) {
|
||||
return false;
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* = = = 以下关于查询和查询条件的方法 = = =*/
|
||||
|
||||
/**
|
||||
* 查询数据
|
||||
* <p>
|
||||
* 请求地址:POST http://{baseUrl}/{indexName}/{typeName}/_search
|
||||
*/
|
||||
public JSONObject search(String indexName, String typeName, JSONObject queryObject) {
|
||||
String url = this.getBaseUrl(indexName, typeName).append("/_search").toString();
|
||||
|
||||
log.info("url:" + url + " ,search: " + queryObject.toJSONString());
|
||||
JSONObject res = RestUtil.post(url, queryObject);
|
||||
log.info("url:" + url + " ,return res: \n" + res.toJSONString());
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _source (源滤波器)指定返回的字段,传null返回所有字段
|
||||
* @param query
|
||||
* @param from 从第几条数据开始
|
||||
* @param size 返回条目数
|
||||
* @return { "query": query }
|
||||
*/
|
||||
public JSONObject buildQuery(List<String> _source, JSONObject query, int from, int size) {
|
||||
JSONObject json = new JSONObject();
|
||||
if (_source != null) {
|
||||
json.put("_source", _source);
|
||||
}
|
||||
json.put("query", query);
|
||||
json.put("from", from);
|
||||
json.put("size", size);
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return { "bool" : { "must": must, "must_not": mustNot, "should": should } }
|
||||
*/
|
||||
public JSONObject buildBoolQuery(JSONArray must, JSONArray mustNot, JSONArray should) {
|
||||
JSONObject bool = new JSONObject();
|
||||
if (must != null) {
|
||||
bool.put("must", must);
|
||||
}
|
||||
if (mustNot != null) {
|
||||
bool.put("must_not", mustNot);
|
||||
}
|
||||
if (should != null) {
|
||||
bool.put("should", should);
|
||||
}
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("bool", bool);
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param field 要查询的字段
|
||||
* @param args 查询参数,参考: *哈哈* OR *哒* NOT *呵* OR *啊*
|
||||
* @return
|
||||
*/
|
||||
public JSONObject buildQueryString(String field, String... args) {
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(field).append(":(");
|
||||
if (args != null) {
|
||||
for (String arg : args) {
|
||||
sb.append(arg).append(" ");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
return this.buildQueryString(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return { "query_string": { "query": query } }
|
||||
*/
|
||||
public JSONObject buildQueryString(String query) {
|
||||
JSONObject queryString = new JSONObject();
|
||||
queryString.put("query", query);
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("query_string", queryString);
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param field 查询字段
|
||||
* @param min 最小值
|
||||
* @param max 最大值
|
||||
* @param containMin 范围内是否包含最小值
|
||||
* @param containMax 范围内是否包含最大值
|
||||
* @return { "range" : { field : { 『 "gt『e』?containMin" : min 』?min!=null , 『 "lt『e』?containMax" : max 』}} }
|
||||
*/
|
||||
public JSONObject buildRangeQuery(String field, Object min, Object max, boolean containMin, boolean containMax) {
|
||||
JSONObject inner = new JSONObject();
|
||||
if (min != null) {
|
||||
if (containMin) {
|
||||
inner.put("gte", min);
|
||||
} else {
|
||||
inner.put("gt", min);
|
||||
}
|
||||
}
|
||||
if (max != null) {
|
||||
if (containMax) {
|
||||
inner.put("lte", max);
|
||||
} else {
|
||||
inner.put("lt", max);
|
||||
}
|
||||
}
|
||||
JSONObject range = new JSONObject();
|
||||
range.put(field, inner);
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("range", range);
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,98 @@
|
||||
package org.enfi.common.es;
|
||||
|
||||
/**
|
||||
* 用于创建 ElasticSearch 的 queryString
|
||||
*
|
||||
* @author sunjianlei
|
||||
*/
|
||||
public class QueryStringBuilder {
|
||||
|
||||
StringBuilder builder;
|
||||
|
||||
public QueryStringBuilder(String field, String str, boolean not, boolean addQuot) {
|
||||
builder = this.createBuilder(field, str, not, addQuot);
|
||||
}
|
||||
|
||||
public QueryStringBuilder(String field, String str, boolean not) {
|
||||
builder = this.createBuilder(field, str, not, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 StringBuilder
|
||||
*
|
||||
* @param field
|
||||
* @param str
|
||||
* @param not 是否是不匹配
|
||||
* @param addQuot 是否添加双引号
|
||||
* @return
|
||||
*/
|
||||
public StringBuilder createBuilder(String field, String str, boolean not, boolean addQuot) {
|
||||
StringBuilder sb = new StringBuilder(field).append(":(");
|
||||
if (not) {
|
||||
sb.append(" NOT ");
|
||||
}
|
||||
this.addQuotEffect(sb, str, addQuot);
|
||||
return sb;
|
||||
}
|
||||
|
||||
public QueryStringBuilder and(String str) {
|
||||
return this.and(str, true);
|
||||
}
|
||||
|
||||
public QueryStringBuilder and(String str, boolean addQuot) {
|
||||
builder.append(" AND ");
|
||||
this.addQuot(str, addQuot);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryStringBuilder or(String str) {
|
||||
return this.or(str, true);
|
||||
}
|
||||
|
||||
public QueryStringBuilder or(String str, boolean addQuot) {
|
||||
builder.append(" OR ");
|
||||
this.addQuot(str, addQuot);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryStringBuilder not(String str) {
|
||||
return this.not(str, true);
|
||||
}
|
||||
|
||||
public QueryStringBuilder not(String str, boolean addQuot) {
|
||||
builder.append(" NOT ");
|
||||
this.addQuot(str, addQuot);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加双引号(模糊查询,不能加双引号)
|
||||
*/
|
||||
private QueryStringBuilder addQuot(String str, boolean addQuot) {
|
||||
return this.addQuotEffect(this.builder, str, addQuot);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否在两边加上双引号
|
||||
* @param builder
|
||||
* @param str
|
||||
* @param addQuot
|
||||
* @return
|
||||
*/
|
||||
private QueryStringBuilder addQuotEffect(StringBuilder builder, String str, boolean addQuot) {
|
||||
if (addQuot) {
|
||||
builder.append('"');
|
||||
}
|
||||
builder.append(str);
|
||||
if (addQuot) {
|
||||
builder.append('"');
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return builder.append(")").toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package org.enfi.common.exception;
|
||||
|
||||
public class EnFiBoot401Exception extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public EnFiBoot401Exception(String message){
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EnFiBoot401Exception(Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public EnFiBoot401Exception(String message, Throwable cause)
|
||||
{
|
||||
super(message,cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package org.enfi.common.exception;
|
||||
|
||||
public class EnFiBootException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public EnFiBootException(String message){
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EnFiBootException(Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public EnFiBootException(String message, Throwable cause)
|
||||
{
|
||||
super(message,cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
package org.enfi.common.exception;
|
||||
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
import org.apache.shiro.authz.UnauthorizedException;
|
||||
import org.enfi.common.api.vo.Result;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.data.redis.connection.PoolException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.multipart.MaxUploadSizeExceededException;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 异常处理器
|
||||
*
|
||||
* @Author scott
|
||||
* @Date 2019
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
@Slf4j
|
||||
public class EnFiBootExceptionHandler {
|
||||
|
||||
|
||||
/**
|
||||
* 校验错误拦截处理
|
||||
*
|
||||
* @param exception 错误信息集合
|
||||
* @return 错误信息
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public Result validationBodyException(MethodArgumentNotValidException exception) {
|
||||
BindingResult result = exception.getBindingResult();
|
||||
List<String> messages = null;
|
||||
if (result.hasErrors()) {
|
||||
List<ObjectError> errors = result.getAllErrors();
|
||||
if (errors != null) {
|
||||
if (errors.size() > 0) {
|
||||
messages = new ArrayList<String>() {{
|
||||
errors.forEach(p -> {
|
||||
FieldError fieldError = (FieldError) p;
|
||||
add(fieldError.getDefaultMessage());
|
||||
});
|
||||
}};
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result.error(messages.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自定义异常
|
||||
*/
|
||||
@ExceptionHandler(EnFiBootException.class)
|
||||
public Result<?> handleEnFiBootException(EnFiBootException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自定义异常
|
||||
*/
|
||||
@ExceptionHandler(EnFiBoot401Exception.class)
|
||||
@ResponseStatus(HttpStatus.UNAUTHORIZED)
|
||||
public Result<?> handleEnFiBoot401Exception(EnFiBoot401Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return new Result(401, e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(NoHandlerFoundException.class)
|
||||
public Result<?> handlerNoFoundException(Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.error(404, "路径不存在,请检查路径是否正确");
|
||||
}
|
||||
|
||||
@ExceptionHandler(DuplicateKeyException.class)
|
||||
public Result<?> handleDuplicateKeyException(DuplicateKeyException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.error("数据库中已存在该记录");
|
||||
}
|
||||
|
||||
@ExceptionHandler({UnauthorizedException.class, AuthorizationException.class})
|
||||
public Result<?> handleAuthorizationException(AuthorizationException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.noauth("没有权限,请联系管理员授权");
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public Result<?> handleException(Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.error("操作失败," + e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param e
|
||||
* @return
|
||||
* @Author 政辉
|
||||
*/
|
||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||
public Result<?> HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("不支持");
|
||||
sb.append(e.getMethod());
|
||||
sb.append("请求方法,");
|
||||
sb.append("支持以下");
|
||||
String[] methods = e.getSupportedMethods();
|
||||
if (methods != null) {
|
||||
for (String str : methods) {
|
||||
sb.append(str);
|
||||
sb.append("、");
|
||||
}
|
||||
}
|
||||
log.error(sb.toString(), e);
|
||||
//return Result.error("没有权限,请联系管理员授权");
|
||||
return Result.error(405, sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException
|
||||
*/
|
||||
@ExceptionHandler(MaxUploadSizeExceededException.class)
|
||||
public Result<?> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.error("文件大小超出10MB限制, 请压缩或降低文件质量! ");
|
||||
}
|
||||
|
||||
@ExceptionHandler(DataIntegrityViolationException.class)
|
||||
public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.error("字段太长,超出数据库字段的长度");
|
||||
}
|
||||
|
||||
@ExceptionHandler(PoolException.class)
|
||||
public Result<?> handlePoolException(PoolException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.error("Redis 连接异常!");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package org.enfi.common.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
/**
|
||||
* 填值规则接口
|
||||
*
|
||||
* @author Yan_东
|
||||
* 如需使用填值规则功能,规则实现类必须实现此接口
|
||||
*/
|
||||
public interface IFillRuleHandler {
|
||||
|
||||
/**
|
||||
* @param params 页面配置固定参数
|
||||
* @param formData 动态表单参数
|
||||
* @return
|
||||
*/
|
||||
public Object execute(JSONObject params, JSONObject formData);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,195 @@
|
||||
package org.enfi.common.system.base.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.beanutils.PropertyUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.enfi.common.api.vo.Result;
|
||||
import org.enfi.common.system.query.QueryGenerator;
|
||||
import org.enfi.common.system.vo.LoginUser;
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
import org.jeecgframework.poi.excel.entity.ImportParams;
|
||||
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
|
||||
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Description: Controller基类
|
||||
* @Author: dangzhenghui@163.com
|
||||
* @Date: 2019-4-21 8:13
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class EnFiController<T, S extends IService<T>> {
|
||||
//issues/2933 EnFiController注入service时改用protected修饰,能避免重复引用service
|
||||
@Autowired
|
||||
protected S service;
|
||||
|
||||
@Value("${enfi.path.upload}")
|
||||
private String upLoadPath;
|
||||
/**
|
||||
* 导出excel
|
||||
*
|
||||
* @param request
|
||||
*/
|
||||
protected ModelAndView exportXls(HttpServletRequest request, T object, Class<T> clazz, String title) {
|
||||
// Step.1 组装查询条件
|
||||
QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap());
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
|
||||
// Step.2 获取导出数据
|
||||
List<T> pageList = service.list(queryWrapper);
|
||||
List<T> exportList = null;
|
||||
|
||||
// 过滤选中数据
|
||||
String selections = request.getParameter("selections");
|
||||
if (oConvertUtils.isNotEmpty(selections)) {
|
||||
List<String> selectionList = Arrays.asList(selections.split(","));
|
||||
exportList = pageList.stream().filter(item -> selectionList.contains(getId(item))).collect(Collectors.toList());
|
||||
} else {
|
||||
exportList = pageList;
|
||||
}
|
||||
|
||||
// Step.3 AutoPoi 导出Excel
|
||||
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
|
||||
mv.addObject(NormalExcelConstants.FILE_NAME, title); //此处设置的filename无效 ,前端会重更新设置一下
|
||||
mv.addObject(NormalExcelConstants.CLASS, clazz);
|
||||
//update-begin--Author:liusq Date:20210126 for:图片导出报错,ImageBasePath未设置--------------------
|
||||
ExportParams exportParams=new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title);
|
||||
exportParams.setImageBasePath(upLoadPath);
|
||||
//update-end--Author:liusq Date:20210126 for:图片导出报错,ImageBasePath未设置----------------------
|
||||
mv.addObject(NormalExcelConstants.PARAMS,exportParams);
|
||||
mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
|
||||
return mv;
|
||||
}
|
||||
/**
|
||||
* 根据每页sheet数量导出多sheet
|
||||
*
|
||||
* @param request
|
||||
* @param object 实体类
|
||||
* @param clazz 实体类class
|
||||
* @param title 标题
|
||||
* @param exportFields 导出字段自定义
|
||||
* @param pageNum 每个sheet的数据条数
|
||||
* @param request
|
||||
*/
|
||||
protected ModelAndView exportXlsSheet(HttpServletRequest request, T object, Class<T> clazz, String title,String exportFields,Integer pageNum) {
|
||||
// Step.1 组装查询条件
|
||||
QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap());
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
// Step.2 计算分页sheet数据
|
||||
double total = service.count();
|
||||
int count = (int)Math.ceil(total/pageNum);
|
||||
// Step.3 多sheet处理
|
||||
List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>();
|
||||
for (int i = 1; i <=count ; i++) {
|
||||
Page<T> page = new Page<T>(i, pageNum);
|
||||
IPage<T> pageList = service.page(page, queryWrapper);
|
||||
List<T> records = pageList.getRecords();
|
||||
List<T> exportList = null;
|
||||
// 过滤选中数据
|
||||
String selections = request.getParameter("selections");
|
||||
if (oConvertUtils.isNotEmpty(selections)) {
|
||||
List<String> selectionList = Arrays.asList(selections.split(","));
|
||||
exportList = records.stream().filter(item -> selectionList.contains(getId(item))).collect(Collectors.toList());
|
||||
} else {
|
||||
exportList = records;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
ExportParams exportParams=new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title+i,upLoadPath);
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
//map.put("title",exportParams);//表格Title
|
||||
map.put(NormalExcelConstants.PARAMS,exportParams);//表格Title
|
||||
map.put(NormalExcelConstants.CLASS,clazz);//表格对应实体
|
||||
map.put(NormalExcelConstants.DATA_LIST, exportList);//数据集合
|
||||
listMap.add(map);
|
||||
}
|
||||
// Step.4 AutoPoi 导出Excel
|
||||
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
|
||||
mv.addObject(NormalExcelConstants.FILE_NAME, title); //此处设置的filename无效 ,前端会重更新设置一下
|
||||
mv.addObject(NormalExcelConstants.MAP_LIST, listMap);
|
||||
return mv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据权限导出excel,传入导出字段参数
|
||||
*
|
||||
* @param request
|
||||
*/
|
||||
protected ModelAndView exportXls(HttpServletRequest request, T object, Class<T> clazz, String title,String exportFields) {
|
||||
ModelAndView mv = this.exportXls(request,object,clazz,title);
|
||||
mv.addObject(NormalExcelConstants.EXPORT_FIELDS,exportFields);
|
||||
return mv;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象ID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getId(T item) {
|
||||
try {
|
||||
return PropertyUtils.getProperty(item, "id").toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过excel导入数据
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
protected Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<T> clazz) {
|
||||
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
|
||||
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
|
||||
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
|
||||
MultipartFile file = entity.getValue();// 获取上传文件对象
|
||||
ImportParams params = new ImportParams();
|
||||
params.setTitleRows(2);
|
||||
params.setHeadRows(1);
|
||||
params.setNeedSave(true);
|
||||
try {
|
||||
List<T> list = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);
|
||||
//update-begin-author:taoyan date:20190528 for:批量插入数据
|
||||
long start = System.currentTimeMillis();
|
||||
service.saveBatch(list);
|
||||
//400条 saveBatch消耗时间1592毫秒 循环插入消耗时间1947毫秒
|
||||
//1200条 saveBatch消耗时间3687毫秒 循环插入消耗时间5212毫秒
|
||||
log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
//update-end-author:taoyan date:20190528 for:批量插入数据
|
||||
return Result.ok("文件导入成功!数据行数:" + list.size());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.error("文件导入失败:" + e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
file.getInputStream().close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result.error("文件导入失败!");
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package org.enfi.common.system.base.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @Description: Entity基类
|
||||
* @Author: dangzhenghui@163.com
|
||||
* @Date: 2019-4-28
|
||||
* @Version: 1.1
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class EnFiEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** ID */
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@ApiModelProperty(value = "ID")
|
||||
private String id;
|
||||
/** 创建人 */
|
||||
@ApiModelProperty(value = "创建人")
|
||||
@Excel(name = "创建人", width = 15)
|
||||
private String createBy;
|
||||
/** 创建时间 */
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
@Excel(name = "创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private java.util.Date createTime;
|
||||
/** 更新人 */
|
||||
@ApiModelProperty(value = "更新人")
|
||||
@Excel(name = "更新人", width = 15)
|
||||
private String updateBy;
|
||||
/** 更新时间 */
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
@Excel(name = "更新时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private java.util.Date updateTime;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package org.enfi.common.system.base.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* @Description: Service基类
|
||||
* @Author: dangzhenghui@163.com
|
||||
* @Date: 2019-4-21 8:13
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public interface EnFiService<T> extends IService<T> {
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package org.enfi.common.system.base.service.impl;
|
||||
|
||||
import org.enfi.common.system.base.entity.EnFiEntity;
|
||||
import org.enfi.common.system.base.service.EnFiService;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @Description: ServiceImpl基类
|
||||
* @Author: dangzhenghui@163.com
|
||||
* @Date: 2019-4-21 8:13
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class EnFiServiceImpl<M extends BaseMapper<T>, T extends EnFiEntity> extends ServiceImpl<M, T> implements EnFiService<T> {
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.enfi.common.system.query;
|
||||
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
|
||||
/**
|
||||
* 查询链接规则
|
||||
*
|
||||
* @Author Sunjianlei
|
||||
*/
|
||||
public enum MatchTypeEnum {
|
||||
|
||||
AND("AND"),
|
||||
OR("OR");
|
||||
|
||||
private String value;
|
||||
|
||||
MatchTypeEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static MatchTypeEnum getByValue(Object value) {
|
||||
if (oConvertUtils.isEmpty(value)) {
|
||||
return null;
|
||||
}
|
||||
return getByValue(value.toString());
|
||||
}
|
||||
|
||||
public static MatchTypeEnum getByValue(String value) {
|
||||
if (oConvertUtils.isEmpty(value)) {
|
||||
return null;
|
||||
}
|
||||
for (MatchTypeEnum val : values()) {
|
||||
if (val.getValue().toLowerCase().equals(value.toLowerCase())) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package org.enfi.common.system.query;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class QueryCondition implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4740166316629191651L;
|
||||
|
||||
private String field;
|
||||
/** 组件的类型(例如:input、select、radio) */
|
||||
private String type;
|
||||
/**
|
||||
* 对应的数据库字段的类型
|
||||
* 支持:int、bigDecimal、short、long、float、double、boolean
|
||||
*/
|
||||
private String dbType;
|
||||
private String rule;
|
||||
private String val;
|
||||
|
||||
public String getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public void setField(String field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDbType() {
|
||||
return dbType;
|
||||
}
|
||||
|
||||
public void setDbType(String dbType) {
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public String getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
||||
public void setRule(String rule) {
|
||||
this.rule = rule;
|
||||
}
|
||||
|
||||
public String getVal() {
|
||||
return val;
|
||||
}
|
||||
|
||||
public void setVal(String val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuffer sb =new StringBuffer();
|
||||
if(field == null || "".equals(field)){
|
||||
return "";
|
||||
}
|
||||
sb.append(this.field).append(" ").append(this.rule).append(" ").append(this.type).append(" ").append(this.dbType).append(" ").append(this.val);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,73 @@
|
||||
package org.enfi.common.system.query;
|
||||
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
|
||||
/**
|
||||
* Query 规则 常量
|
||||
* @Author Scott
|
||||
* @Date 2019年02月14日
|
||||
*/
|
||||
public enum QueryRuleEnum {
|
||||
|
||||
GT(">","gt","大于"),
|
||||
GE(">=","ge","大于等于"),
|
||||
LT("<","lt","小于"),
|
||||
LE("<=","le","小于等于"),
|
||||
EQ("=","eq","等于"),
|
||||
NE("!=","ne","不等于"),
|
||||
IN("IN","in","包含"),
|
||||
LIKE("LIKE","like","全模糊"),
|
||||
LEFT_LIKE("LEFT_LIKE","left_like","左模糊"),
|
||||
RIGHT_LIKE("RIGHT_LIKE","right_like","右模糊"),
|
||||
EQ_WITH_ADD("EQWITHADD","eq_with_add","带加号等于"),
|
||||
LIKE_WITH_AND("LIKEWITHAND","like_with_and","多词模糊匹配————暂时未用上"),
|
||||
SQL_RULES("USE_SQL_RULES","ext","自定义SQL片段");
|
||||
|
||||
private String value;
|
||||
|
||||
private String condition;
|
||||
|
||||
private String msg;
|
||||
|
||||
QueryRuleEnum(String value, String condition, String msg){
|
||||
this.value = value;
|
||||
this.condition = condition;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public void setCondition(String condition) {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
public static QueryRuleEnum getByValue(String value){
|
||||
if(oConvertUtils.isEmpty(value)) {
|
||||
return null;
|
||||
}
|
||||
for(QueryRuleEnum val :values()){
|
||||
if (val.getValue().equals(value) || val.getCondition().equals(value)){
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
package org.enfi.common.system.util;
|
||||
|
||||
import org.enfi.common.system.vo.SysPermissionDataRuleModel;
|
||||
import org.enfi.common.system.vo.SysUserCacheInfo;
|
||||
import org.enfi.common.util.SpringContextUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName: EnFiDataAutorUtils
|
||||
* @Description: 数据权限查询规则容器工具类
|
||||
* @Author: 张代浩
|
||||
* @Date: 2012-12-15 下午11:27:39
|
||||
*
|
||||
*/
|
||||
public class EnFiDataAutorUtils {
|
||||
|
||||
public static final String MENU_DATA_AUTHOR_RULES = "MENU_DATA_AUTHOR_RULES";
|
||||
|
||||
public static final String MENU_DATA_AUTHOR_RULE_SQL = "MENU_DATA_AUTHOR_RULE_SQL";
|
||||
|
||||
public static final String SYS_USER_INFO = "SYS_USER_INFO";
|
||||
|
||||
/**
|
||||
* 往链接请求里面,传入数据查询条件
|
||||
*
|
||||
* @param request
|
||||
* @param dataRules
|
||||
*/
|
||||
public static synchronized void installDataSearchConditon(HttpServletRequest request, List<SysPermissionDataRuleModel> dataRules) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<SysPermissionDataRuleModel> list = (List<SysPermissionDataRuleModel>)loadDataSearchConditon();// 1.先从request获取MENU_DATA_AUTHOR_RULES,如果存则获取到LIST
|
||||
if (list==null) {
|
||||
// 2.如果不存在,则new一个list
|
||||
list = new ArrayList<SysPermissionDataRuleModel>();
|
||||
}
|
||||
for (SysPermissionDataRuleModel tsDataRule : dataRules) {
|
||||
list.add(tsDataRule);
|
||||
}
|
||||
request.setAttribute(MENU_DATA_AUTHOR_RULES, list); // 3.往list里面增量存指
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求对应的数据权限规则
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static synchronized List<SysPermissionDataRuleModel> loadDataSearchConditon() {
|
||||
return (List<SysPermissionDataRuleModel>) SpringContextUtils.getHttpServletRequest().getAttribute(MENU_DATA_AUTHOR_RULES);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求对应的数据权限SQL
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static synchronized String loadDataSearchConditonSQLString() {
|
||||
return (String) SpringContextUtils.getHttpServletRequest().getAttribute(MENU_DATA_AUTHOR_RULE_SQL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 往链接请求里面,传入数据查询条件
|
||||
*
|
||||
* @param request
|
||||
* @param sql
|
||||
*/
|
||||
public static synchronized void installDataSearchConditon(HttpServletRequest request, String sql) {
|
||||
String ruleSql = (String)loadDataSearchConditonSQLString();
|
||||
if (!StringUtils.hasText(ruleSql)) {
|
||||
request.setAttribute(MENU_DATA_AUTHOR_RULE_SQL,sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将用户信息存到request
|
||||
* @param request
|
||||
* @param userinfo
|
||||
*/
|
||||
public static synchronized void installUserInfo(HttpServletRequest request, SysUserCacheInfo userinfo) {
|
||||
request.setAttribute(SYS_USER_INFO, userinfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将用户信息存到request
|
||||
* @param userinfo
|
||||
*/
|
||||
public static synchronized void installUserInfo(SysUserCacheInfo userinfo) {
|
||||
SpringContextUtils.getHttpServletRequest().setAttribute(SYS_USER_INFO, userinfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从request获取用户信息
|
||||
* @return
|
||||
*/
|
||||
public static synchronized SysUserCacheInfo loadUserInfo() {
|
||||
return (SysUserCacheInfo) SpringContextUtils.getHttpServletRequest().getAttribute(SYS_USER_INFO);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,245 @@
|
||||
package org.enfi.common.system.util;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTDecodeException;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.enfi.common.api.vo.Result;
|
||||
import org.enfi.common.constant.CommonConstant;
|
||||
import org.enfi.common.constant.DataBaseConstant;
|
||||
import org.enfi.common.exception.EnFiBootException;
|
||||
import org.enfi.common.system.vo.LoginUser;
|
||||
import org.enfi.common.system.vo.SysUserCacheInfo;
|
||||
import org.enfi.common.util.DateUtils;
|
||||
import org.enfi.common.util.SpringContextUtils;
|
||||
import org.enfi.common.util.oConvertUtils;
|
||||
|
||||
/**
|
||||
* @Author Scott
|
||||
* @Date 2018-07-12 14:23
|
||||
* @Desc JWT工具类
|
||||
**/
|
||||
public class JwtUtil {
|
||||
|
||||
// Token过期时间30分钟(用户登录过期时间是此时间的两倍,以token在reids缓存时间为准)
|
||||
public static final long EXPIRE_TIME = 30 * 60 * 1000;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param response
|
||||
* @param code
|
||||
* @param errorMsg
|
||||
*/
|
||||
public static void responseError(ServletResponse response, Integer code, String errorMsg) {
|
||||
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
|
||||
Result jsonResult = new Result(code, errorMsg);
|
||||
OutputStream os = null;
|
||||
try {
|
||||
os = httpServletResponse.getOutputStream();
|
||||
httpServletResponse.setCharacterEncoding("UTF-8");
|
||||
httpServletResponse.setStatus(401);
|
||||
os.write(new ObjectMapper().writeValueAsString(jsonResult).getBytes("UTF-8"));
|
||||
os.flush();
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验token是否正确
|
||||
*
|
||||
* @param token 密钥
|
||||
* @param secret 用户的密码
|
||||
* @return 是否正确
|
||||
*/
|
||||
public static boolean verify(String token, String username, String secret) {
|
||||
try {
|
||||
// 根据密码生成JWT效验器
|
||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||
JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build();
|
||||
// 效验TOKEN
|
||||
DecodedJWT jwt = verifier.verify(token);
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得token中的信息无需secret解密也能获得
|
||||
*
|
||||
* @return token中包含的用户名
|
||||
*/
|
||||
public static String getUsername(String token) {
|
||||
try {
|
||||
DecodedJWT jwt = JWT.decode(token);
|
||||
return jwt.getClaim("username").asString();
|
||||
} catch (JWTDecodeException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名,5min后过期
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param secret 用户的密码
|
||||
* @return 加密的token
|
||||
*/
|
||||
public static String sign(String username, String secret) {
|
||||
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
|
||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||
// 附带username信息
|
||||
return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据request中的token获取用户账号
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
* @throws EnFiBootException
|
||||
*/
|
||||
public static String getUserNameByToken(HttpServletRequest request) throws EnFiBootException {
|
||||
String accessToken = request.getHeader("X-Access-Token");
|
||||
String username = getUsername(accessToken);
|
||||
if (oConvertUtils.isEmpty(username)) {
|
||||
throw new EnFiBootException("未获取到用户");
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从session中获取变量
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static String getSessionData(String key) {
|
||||
//${myVar}%
|
||||
//得到${} 后面的值
|
||||
String moshi = "";
|
||||
if(key.indexOf("}")!=-1){
|
||||
moshi = key.substring(key.indexOf("}")+1);
|
||||
}
|
||||
String returnValue = null;
|
||||
if (key.contains("#{")) {
|
||||
key = key.substring(2,key.indexOf("}"));
|
||||
}
|
||||
if (oConvertUtils.isNotEmpty(key)) {
|
||||
HttpSession session = SpringContextUtils.getHttpServletRequest().getSession();
|
||||
returnValue = (String) session.getAttribute(key);
|
||||
}
|
||||
//结果加上${} 后面的值
|
||||
if(returnValue!=null){returnValue = returnValue + moshi;}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从当前用户中获取变量
|
||||
* @param key
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
//TODO 急待改造 sckjkdsjsfjdk
|
||||
public static String getUserSystemData(String key,SysUserCacheInfo user) {
|
||||
if(user==null) {
|
||||
user = EnFiDataAutorUtils.loadUserInfo();
|
||||
}
|
||||
//#{sys_user_code}%
|
||||
|
||||
// 获取登录用户信息
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
|
||||
String moshi = "";
|
||||
if(key.indexOf("}")!=-1){
|
||||
moshi = key.substring(key.indexOf("}")+1);
|
||||
}
|
||||
String returnValue = null;
|
||||
//针对特殊标示处理#{sysOrgCode},判断替换
|
||||
if (key.contains("#{")) {
|
||||
key = key.substring(2,key.indexOf("}"));
|
||||
} else {
|
||||
key = key;
|
||||
}
|
||||
//替换为系统登录用户帐号
|
||||
if (key.equals(DataBaseConstant.SYS_USER_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_CODE_TABLE)) {
|
||||
if(user==null) {
|
||||
returnValue = sysUser.getUsername();
|
||||
}else {
|
||||
returnValue = user.getSysUserCode();
|
||||
}
|
||||
}
|
||||
//替换为系统登录用户真实名字
|
||||
else if (key.equals(DataBaseConstant.SYS_USER_NAME)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_NAME_TABLE)) {
|
||||
if(user==null) {
|
||||
returnValue = sysUser.getRealname();
|
||||
}else {
|
||||
returnValue = user.getSysUserName();
|
||||
}
|
||||
}
|
||||
|
||||
//替换为系统用户登录所使用的机构编码
|
||||
else if (key.equals(DataBaseConstant.SYS_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_ORG_CODE_TABLE)) {
|
||||
if(user==null) {
|
||||
returnValue = sysUser.getOrgCode();
|
||||
}else {
|
||||
returnValue = user.getSysOrgCode();
|
||||
}
|
||||
}
|
||||
//替换为系统用户所拥有的所有机构编码
|
||||
else if (key.equals(DataBaseConstant.SYS_MULTI_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_MULTI_ORG_CODE_TABLE)) {
|
||||
if(user==null){
|
||||
//TODO 暂时使用用户登录部门,存在逻辑缺陷,不是用户所拥有的部门
|
||||
returnValue = sysUser.getOrgCode();
|
||||
}else{
|
||||
if(user.isOneDepart()) {
|
||||
returnValue = user.getSysMultiOrgCode().get(0);
|
||||
}else {
|
||||
returnValue = Joiner.on(",").join(user.getSysMultiOrgCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
//替换为当前系统时间(年月日)
|
||||
else if (key.equals(DataBaseConstant.SYS_DATE)|| key.toLowerCase().equals(DataBaseConstant.SYS_DATE_TABLE)) {
|
||||
returnValue = DateUtils.formatDate();
|
||||
}
|
||||
//替换为当前系统时间(年月日时分秒)
|
||||
else if (key.equals(DataBaseConstant.SYS_TIME)|| key.toLowerCase().equals(DataBaseConstant.SYS_TIME_TABLE)) {
|
||||
returnValue = DateUtils.now();
|
||||
}
|
||||
//流程状态默认值(默认未发起)
|
||||
else if (key.equals(DataBaseConstant.BPM_STATUS)|| key.toLowerCase().equals(DataBaseConstant.BPM_STATUS_TABLE)) {
|
||||
returnValue = "1";
|
||||
}
|
||||
//update-begin-author:taoyan date:20210330 for:多租户ID作为系统变量
|
||||
else if (key.equals(DataBaseConstant.TENANT_ID) || key.toLowerCase().equals(DataBaseConstant.TENANT_ID_TABLE)){
|
||||
returnValue = sysUser.getRelTenantIds();
|
||||
if(oConvertUtils.isEmpty(returnValue) || (returnValue!=null && returnValue.indexOf(",")>0)){
|
||||
returnValue = SpringContextUtils.getHttpServletRequest().getHeader(CommonConstant.TENANT_ID);
|
||||
}
|
||||
}
|
||||
//update-end-author:taoyan date:20210330 for:多租户ID作为系统变量
|
||||
if(returnValue!=null){returnValue = returnValue + moshi;}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjUzMzY1MTMsInVzZXJuYW1lIjoiYWRtaW4ifQ.xjhud_tWCNYBOg_aRlMgOdlZoWFFKB_givNElHNw3X0";
|
||||
// System.out.println(JwtUtil.getUsername(token));
|
||||
// }
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ComboModel implements Serializable {
|
||||
private String id;
|
||||
private String title;
|
||||
/**文档管理 表单table默认选中*/
|
||||
private boolean checked;
|
||||
/**文档管理 表单table 用户账号*/
|
||||
private String username;
|
||||
/**文档管理 表单table 用户邮箱*/
|
||||
private String email;
|
||||
/**文档管理 表单table 角色编码*/
|
||||
private String roleCode;
|
||||
|
||||
public ComboModel(){
|
||||
|
||||
};
|
||||
|
||||
public ComboModel(String id,String title,boolean checked,String username){
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.checked = false;
|
||||
this.username = username;
|
||||
};
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DictModel implements Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DictModel() {
|
||||
}
|
||||
|
||||
public DictModel(String value, String text) {
|
||||
this.value = value;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典value
|
||||
*/
|
||||
private String value;
|
||||
/**
|
||||
* 字典文本
|
||||
*/
|
||||
private String text;
|
||||
|
||||
/**
|
||||
* 特殊用途: JgEditableTable
|
||||
* @return
|
||||
*/
|
||||
public String getTitle() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 查询多个字典时用到
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DictModelMany extends DictModel {
|
||||
|
||||
/**
|
||||
* 字典code,根据多个字段code查询时才用到,用于区分不同的字典选项
|
||||
*/
|
||||
private String dictCode;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 字典查询参数实体
|
||||
*/
|
||||
@Data
|
||||
public class DictQuery {
|
||||
/**
|
||||
* 表名
|
||||
*/
|
||||
private String table;
|
||||
/**
|
||||
* 存储列
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 显示列
|
||||
*/
|
||||
private String text;
|
||||
|
||||
/**
|
||||
* 关键字查询
|
||||
*/
|
||||
private String keyword;
|
||||
|
||||
/**
|
||||
* 存储列的值 用于回显查询
|
||||
*/
|
||||
private String codeValue;
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
@Data
|
||||
public class DynamicDataSourceModel {
|
||||
|
||||
public DynamicDataSourceModel() {
|
||||
|
||||
}
|
||||
|
||||
public DynamicDataSourceModel(Object dbSource) {
|
||||
if (dbSource != null) {
|
||||
BeanUtils.copyProperties(dbSource, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* 数据源编码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 数据库类型
|
||||
*/
|
||||
private String dbType;
|
||||
/**
|
||||
* 驱动类
|
||||
*/
|
||||
private String dbDriver;
|
||||
/**
|
||||
* 数据源地址
|
||||
*/
|
||||
private String dbUrl;
|
||||
|
||||
// /**
|
||||
// * 数据库名称
|
||||
// */
|
||||
// private java.lang.String dbName;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String dbUsername;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String dbPassword;
|
||||
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 在线用户信息
|
||||
* </p>
|
||||
*
|
||||
* @Author scott
|
||||
* @since 2018-12-20
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class LoginUser {
|
||||
|
||||
/**
|
||||
* 登录人id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 登录人账号
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 登录人名字
|
||||
*/
|
||||
private String realname;
|
||||
|
||||
/**
|
||||
* 登录人密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 当前登录部门code
|
||||
*/
|
||||
private String orgCode;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 生日
|
||||
*/
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date birthday;
|
||||
|
||||
/**
|
||||
* 性别(1:男 2:女)
|
||||
*/
|
||||
private Integer sex;
|
||||
|
||||
/**
|
||||
* 电子邮件
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 电话
|
||||
*/
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 状态(1:正常 2:冻结 )
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
private Integer delFlag;
|
||||
/**
|
||||
* 同步工作流引擎1同步0不同步
|
||||
*/
|
||||
private Integer activitiSync;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 身份(1 普通员工 2 上级)
|
||||
*/
|
||||
private Integer userIdentity;
|
||||
|
||||
/**
|
||||
* 管理部门ids
|
||||
*/
|
||||
private String departIds;
|
||||
|
||||
/**
|
||||
* 职务,关联职务表
|
||||
*/
|
||||
private String post;
|
||||
|
||||
/**
|
||||
* 座机号
|
||||
*/
|
||||
private String telephone;
|
||||
|
||||
/**多租户id配置,编辑用户的时候设置*/
|
||||
private String relTenantIds;
|
||||
|
||||
/**设备id uniapp推送用*/
|
||||
private String clientId;
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
|
||||
/**
|
||||
* @Author qinfeng
|
||||
* @Date 2020/2/19 12:01
|
||||
* @Description:
|
||||
* @Version 1.0
|
||||
*/
|
||||
public class SysCategoryModel {
|
||||
/**主键*/
|
||||
private String id;
|
||||
/**父级节点*/
|
||||
private String pid;
|
||||
/**类型名称*/
|
||||
private String name;
|
||||
/**类型编码*/
|
||||
private String code;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getPid() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
public void setPid(String pid) {
|
||||
this.pid = pid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
/**
|
||||
* lvdandan 部门机构model
|
||||
*/
|
||||
public class SysDepartModel {
|
||||
/**ID*/
|
||||
private String id;
|
||||
/**父机构ID*/
|
||||
private String parentId;
|
||||
/**机构/部门名称*/
|
||||
private String departName;
|
||||
/**英文名*/
|
||||
private String departNameEn;
|
||||
/**缩写*/
|
||||
private String departNameAbbr;
|
||||
/**排序*/
|
||||
private Integer departOrder;
|
||||
/**描述*/
|
||||
private String description;
|
||||
/**机构类别 1组织机构,2岗位*/
|
||||
private String orgCategory;
|
||||
/**机构类型*/
|
||||
private String orgType;
|
||||
/**机构编码*/
|
||||
private String orgCode;
|
||||
/**手机号*/
|
||||
private String mobile;
|
||||
/**传真*/
|
||||
private String fax;
|
||||
/**地址*/
|
||||
private String address;
|
||||
/**备注*/
|
||||
private String memo;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(String parentId) {
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public String getDepartName() {
|
||||
return departName;
|
||||
}
|
||||
|
||||
public void setDepartName(String departName) {
|
||||
this.departName = departName;
|
||||
}
|
||||
|
||||
public String getDepartNameEn() {
|
||||
return departNameEn;
|
||||
}
|
||||
|
||||
public void setDepartNameEn(String departNameEn) {
|
||||
this.departNameEn = departNameEn;
|
||||
}
|
||||
|
||||
public String getDepartNameAbbr() {
|
||||
return departNameAbbr;
|
||||
}
|
||||
|
||||
public void setDepartNameAbbr(String departNameAbbr) {
|
||||
this.departNameAbbr = departNameAbbr;
|
||||
}
|
||||
|
||||
public Integer getDepartOrder() {
|
||||
return departOrder;
|
||||
}
|
||||
|
||||
public void setDepartOrder(Integer departOrder) {
|
||||
this.departOrder = departOrder;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getOrgCategory() {
|
||||
return orgCategory;
|
||||
}
|
||||
|
||||
public void setOrgCategory(String orgCategory) {
|
||||
this.orgCategory = orgCategory;
|
||||
}
|
||||
|
||||
public String getOrgType() {
|
||||
return orgType;
|
||||
}
|
||||
|
||||
public void setOrgType(String orgType) {
|
||||
this.orgType = orgType;
|
||||
}
|
||||
|
||||
public String getOrgCode() {
|
||||
return orgCode;
|
||||
}
|
||||
|
||||
public void setOrgCode(String orgCode) {
|
||||
this.orgCode = orgCode;
|
||||
}
|
||||
|
||||
public String getMobile() {
|
||||
return mobile;
|
||||
}
|
||||
|
||||
public void setMobile(String mobile) {
|
||||
this.mobile = mobile;
|
||||
}
|
||||
|
||||
public String getFax() {
|
||||
return fax;
|
||||
}
|
||||
|
||||
public void setFax(String fax) {
|
||||
this.fax = fax;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getMemo() {
|
||||
return memo;
|
||||
}
|
||||
|
||||
public void setMemo(String memo) {
|
||||
this.memo = memo;
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 菜单权限规则表
|
||||
* </p>
|
||||
*
|
||||
* @Author huangzhilin
|
||||
* @since 2019-03-29
|
||||
*/
|
||||
public class SysPermissionDataRuleModel {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 对应的菜单id
|
||||
*/
|
||||
private String permissionId;
|
||||
|
||||
/**
|
||||
* 规则名称
|
||||
*/
|
||||
private String ruleName;
|
||||
|
||||
/**
|
||||
* 字段
|
||||
*/
|
||||
private String ruleColumn;
|
||||
|
||||
/**
|
||||
* 条件
|
||||
*/
|
||||
private String ruleConditions;
|
||||
|
||||
/**
|
||||
* 规则值
|
||||
*/
|
||||
private String ruleValue;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 修改人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getPermissionId() {
|
||||
return permissionId;
|
||||
}
|
||||
|
||||
public void setPermissionId(String permissionId) {
|
||||
this.permissionId = permissionId;
|
||||
}
|
||||
|
||||
public String getRuleName() {
|
||||
return ruleName;
|
||||
}
|
||||
|
||||
public void setRuleName(String ruleName) {
|
||||
this.ruleName = ruleName;
|
||||
}
|
||||
|
||||
public String getRuleColumn() {
|
||||
return ruleColumn;
|
||||
}
|
||||
|
||||
public void setRuleColumn(String ruleColumn) {
|
||||
this.ruleColumn = ruleColumn;
|
||||
}
|
||||
|
||||
public String getRuleConditions() {
|
||||
return ruleConditions;
|
||||
}
|
||||
|
||||
public void setRuleConditions(String ruleConditions) {
|
||||
this.ruleConditions = ruleConditions;
|
||||
}
|
||||
|
||||
public String getRuleValue() {
|
||||
return ruleValue;
|
||||
}
|
||||
|
||||
public void setRuleValue(String ruleValue) {
|
||||
this.ruleValue = ruleValue;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getCreateBy() {
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy) {
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public String getUpdateBy() {
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy) {
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package org.enfi.common.system.vo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.enfi.common.util.DateUtils;
|
||||
|
||||
public class SysUserCacheInfo {
|
||||
|
||||
private String sysUserCode;
|
||||
|
||||
private String sysUserName;
|
||||
|
||||
private String sysOrgCode;
|
||||
|
||||
private List<String> sysMultiOrgCode;
|
||||
|
||||
private boolean oneDepart;
|
||||
|
||||
public boolean isOneDepart() {
|
||||
return oneDepart;
|
||||
}
|
||||
|
||||
public void setOneDepart(boolean oneDepart) {
|
||||
this.oneDepart = oneDepart;
|
||||
}
|
||||
|
||||
public String getSysDate() {
|
||||
return DateUtils.formatDate();
|
||||
}
|
||||
|
||||
public String getSysTime() {
|
||||
return DateUtils.now();
|
||||
}
|
||||
|
||||
public String getSysUserCode() {
|
||||
return sysUserCode;
|
||||
}
|
||||
|
||||
public void setSysUserCode(String sysUserCode) {
|
||||
this.sysUserCode = sysUserCode;
|
||||
}
|
||||
|
||||
public String getSysUserName() {
|
||||
return sysUserName;
|
||||
}
|
||||
|
||||
public void setSysUserName(String sysUserName) {
|
||||
this.sysUserName = sysUserName;
|
||||
}
|
||||
|
||||
public String getSysOrgCode() {
|
||||
return sysOrgCode;
|
||||
}
|
||||
|
||||
public void setSysOrgCode(String sysOrgCode) {
|
||||
this.sysOrgCode = sysOrgCode;
|
||||
}
|
||||
|
||||
public List<String> getSysMultiOrgCode() {
|
||||
return sysMultiOrgCode;
|
||||
}
|
||||
|
||||
public void setSysMultiOrgCode(List<String> sysMultiOrgCode) {
|
||||
this.sysMultiOrgCode = sysMultiOrgCode;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import javax.naming.AuthenticationException;
|
||||
import javax.naming.CommunicationException;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class AdTest {
|
||||
public AdTest() {
|
||||
}
|
||||
|
||||
public static int connect(String host, String post, String username, String password) {
|
||||
DirContext ctx = null;
|
||||
int rs = 0;
|
||||
String domain = "@enfi.com.cn";
|
||||
String name = username.indexOf(domain) > 0 ? username : username + domain;
|
||||
Hashtable<String, String> HashEnv = new Hashtable();
|
||||
HashEnv.put("java.naming.security.authentication", "simple");
|
||||
HashEnv.put("java.naming.security.principal", name);
|
||||
HashEnv.put("java.naming.security.credentials", password);
|
||||
HashEnv.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
HashEnv.put("com.sun.jndi.ldap.connect.timeout", "3000");
|
||||
HashEnv.put("java.naming.provider.url", "ldap://" + host + ":" + post);
|
||||
|
||||
try {
|
||||
ctx = new InitialDirContext(HashEnv);
|
||||
System.out.println("身份验证成功!");
|
||||
} catch (AuthenticationException var22) {
|
||||
System.out.println("身份验证失败!");
|
||||
rs = 1;
|
||||
var22.printStackTrace();
|
||||
} catch (CommunicationException var23) {
|
||||
System.out.println("AD域连接失败!");
|
||||
rs = 2;
|
||||
var23.printStackTrace();
|
||||
} catch (Exception var24) {
|
||||
System.out.println("身份验证未知异常!");
|
||||
rs = 3;
|
||||
var24.printStackTrace();
|
||||
} finally {
|
||||
if (null != ctx) {
|
||||
try {
|
||||
ctx.close();
|
||||
ctx = null;
|
||||
} catch (Exception var21) {
|
||||
var21.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return rs;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
/**
|
||||
*
|
||||
* @Author 张代浩
|
||||
*
|
||||
*/
|
||||
public enum BrowserType {
|
||||
IE11,IE10,IE9,IE8,IE7,IE6,Firefox,Safari,Chrome,Opera,Camino,Gecko
|
||||
}
|
@ -0,0 +1,206 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @Author 张代浩
|
||||
*
|
||||
*/
|
||||
public class BrowserUtils {
|
||||
|
||||
// 判断是否是IE
|
||||
public static boolean isIE(HttpServletRequest request) {
|
||||
return (request.getHeader("USER-AGENT").toLowerCase().indexOf("msie") > 0 || request
|
||||
.getHeader("USER-AGENT").toLowerCase().indexOf("rv:11.0") > 0) ? true
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取IE版本
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static Double getIEversion(HttpServletRequest request) {
|
||||
Double version = 0.0;
|
||||
if (getBrowserType(request, IE11)) {
|
||||
version = 11.0;
|
||||
} else if (getBrowserType(request, IE10)) {
|
||||
version = 10.0;
|
||||
} else if (getBrowserType(request, IE9)) {
|
||||
version = 9.0;
|
||||
} else if (getBrowserType(request, IE8)) {
|
||||
version = 8.0;
|
||||
} else if (getBrowserType(request, IE7)) {
|
||||
version = 7.0;
|
||||
} else if (getBrowserType(request, IE6)) {
|
||||
version = 6.0;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览器类型
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static BrowserType getBrowserType(HttpServletRequest request) {
|
||||
BrowserType browserType = null;
|
||||
if (getBrowserType(request, IE11)) {
|
||||
browserType = BrowserType.IE11;
|
||||
}
|
||||
if (getBrowserType(request, IE10)) {
|
||||
browserType = BrowserType.IE10;
|
||||
}
|
||||
if (getBrowserType(request, IE9)) {
|
||||
browserType = BrowserType.IE9;
|
||||
}
|
||||
if (getBrowserType(request, IE8)) {
|
||||
browserType = BrowserType.IE8;
|
||||
}
|
||||
if (getBrowserType(request, IE7)) {
|
||||
browserType = BrowserType.IE7;
|
||||
}
|
||||
if (getBrowserType(request, IE6)) {
|
||||
browserType = BrowserType.IE6;
|
||||
}
|
||||
if (getBrowserType(request, FIREFOX)) {
|
||||
browserType = BrowserType.Firefox;
|
||||
}
|
||||
if (getBrowserType(request, SAFARI)) {
|
||||
browserType = BrowserType.Safari;
|
||||
}
|
||||
if (getBrowserType(request, CHROME)) {
|
||||
browserType = BrowserType.Chrome;
|
||||
}
|
||||
if (getBrowserType(request, OPERA)) {
|
||||
browserType = BrowserType.Opera;
|
||||
}
|
||||
if (getBrowserType(request, "Camino")) {
|
||||
browserType = BrowserType.Camino;
|
||||
}
|
||||
return browserType;
|
||||
}
|
||||
|
||||
private static boolean getBrowserType(HttpServletRequest request,
|
||||
String brosertype) {
|
||||
return request.getHeader("USER-AGENT").toLowerCase()
|
||||
.indexOf(brosertype) > 0 ? true : false;
|
||||
}
|
||||
|
||||
private final static String IE11 = "rv:11.0";
|
||||
private final static String IE10 = "MSIE 10.0";
|
||||
private final static String IE9 = "MSIE 9.0";
|
||||
private final static String IE8 = "MSIE 8.0";
|
||||
private final static String IE7 = "MSIE 7.0";
|
||||
private final static String IE6 = "MSIE 6.0";
|
||||
private final static String MAXTHON = "Maxthon";
|
||||
private final static String QQ = "QQBrowser";
|
||||
private final static String GREEN = "GreenBrowser";
|
||||
private final static String SE360 = "360SE";
|
||||
private final static String FIREFOX = "Firefox";
|
||||
private final static String OPERA = "Opera";
|
||||
private final static String CHROME = "Chrome";
|
||||
private final static String SAFARI = "Safari";
|
||||
private final static String OTHER = "其它";
|
||||
|
||||
public static String checkBrowse(HttpServletRequest request) {
|
||||
String userAgent = request.getHeader("USER-AGENT");
|
||||
if (regex(OPERA, userAgent)) {
|
||||
return OPERA;
|
||||
}
|
||||
if (regex(CHROME, userAgent)) {
|
||||
return CHROME;
|
||||
}
|
||||
if (regex(FIREFOX, userAgent)) {
|
||||
return FIREFOX;
|
||||
}
|
||||
if (regex(SAFARI, userAgent)) {
|
||||
return SAFARI;
|
||||
}
|
||||
if (regex(SE360, userAgent)) {
|
||||
return SE360;
|
||||
}
|
||||
if (regex(GREEN, userAgent)) {
|
||||
return GREEN;
|
||||
}
|
||||
if (regex(QQ, userAgent)) {
|
||||
return QQ;
|
||||
}
|
||||
if (regex(MAXTHON, userAgent)) {
|
||||
return MAXTHON;
|
||||
}
|
||||
if (regex(IE11, userAgent)) {
|
||||
return IE11;
|
||||
}
|
||||
if (regex(IE10, userAgent)) {
|
||||
return IE10;
|
||||
}
|
||||
if (regex(IE9, userAgent)) {
|
||||
return IE9;
|
||||
}
|
||||
if (regex(IE8, userAgent)) {
|
||||
return IE8;
|
||||
}
|
||||
if (regex(IE7, userAgent)) {
|
||||
return IE7;
|
||||
}
|
||||
if (regex(IE6, userAgent)) {
|
||||
return IE6;
|
||||
}
|
||||
return OTHER;
|
||||
}
|
||||
|
||||
public static boolean regex(String regex, String str) {
|
||||
Pattern p = Pattern.compile(regex, Pattern.MULTILINE);
|
||||
Matcher m = p.matcher(str);
|
||||
return m.find();
|
||||
}
|
||||
|
||||
|
||||
private static Map<String, String> langMap = new HashMap<String, String>();
|
||||
private final static String ZH = "zh";
|
||||
private final static String ZH_CN = "zh-cn";
|
||||
|
||||
private final static String EN = "en";
|
||||
private final static String EN_US = "en";
|
||||
|
||||
|
||||
static
|
||||
{
|
||||
langMap.put(ZH, ZH_CN);
|
||||
langMap.put(EN, EN_US);
|
||||
}
|
||||
|
||||
public static String getBrowserLanguage(HttpServletRequest request) {
|
||||
|
||||
String browserLang = request.getLocale().getLanguage();
|
||||
String browserLangCode = (String)langMap.get(browserLang);
|
||||
|
||||
if(browserLangCode == null)
|
||||
{
|
||||
browserLangCode = EN_US;
|
||||
}
|
||||
return browserLangCode;
|
||||
}
|
||||
|
||||
/** 判断请求是否来自电脑端 */
|
||||
public static boolean isDesktop(HttpServletRequest request) {
|
||||
return !isMobile(request);
|
||||
}
|
||||
|
||||
/** 判断请求是否来自移动端 */
|
||||
public static boolean isMobile(HttpServletRequest request) {
|
||||
String ua = request.getHeader("User-Agent").toLowerCase();
|
||||
Pattern pattern = Pattern.compile("(phone|pad|pod|iphone|ipod|ios|ipad|android|mobile|blackberry|iemobile|mqqbrowser|juc|fennec|wosbrowser|browserng|webos|symbian|windows phone)");
|
||||
return pattern.matcher(ua).find();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,285 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.enfi.common.constant.CommonConstant;
|
||||
import org.enfi.common.constant.DataBaseConstant;
|
||||
import org.enfi.common.util.filter.FileTypeFilter;
|
||||
import org.enfi.common.util.oss.OssBootUtil;
|
||||
import org.jeecgframework.poi.util.PoiPublicUtil;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Slf4j
|
||||
public class CommonUtils {
|
||||
|
||||
//中文正则
|
||||
private static Pattern ZHONGWEN_PATTERN = Pattern.compile("[\u4e00-\u9fa5]");
|
||||
|
||||
public static String uploadOnlineImage(byte[] data,String basePath,String bizPath,String uploadType){
|
||||
String dbPath = null;
|
||||
String fileName = "image" + Math.round(Math.random() * 100000000000L);
|
||||
fileName += "." + PoiPublicUtil.getFileExtendName(data);
|
||||
try {
|
||||
if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){
|
||||
File file = new File(basePath + File.separator + bizPath + File.separator );
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();// 创建文件根目录
|
||||
}
|
||||
String savePath = file.getPath() + File.separator + fileName;
|
||||
File savefile = new File(savePath);
|
||||
FileCopyUtils.copy(data, savefile);
|
||||
dbPath = bizPath + File.separator + fileName;
|
||||
}else {
|
||||
InputStream in = new ByteArrayInputStream(data);
|
||||
String relativePath = bizPath+"/"+fileName;
|
||||
if(CommonConstant.UPLOAD_TYPE_MINIO.equals(uploadType)){
|
||||
dbPath = MinioUtil.upload(in,relativePath);
|
||||
}else if(CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)){
|
||||
dbPath = OssBootUtil.upload(in,relativePath);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return dbPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件名是否带盘符,重新处理
|
||||
* @param fileName
|
||||
* @return
|
||||
*/
|
||||
public static String getFileName(String fileName){
|
||||
//判断是否带有盘符信息
|
||||
// Check for Unix-style path
|
||||
int unixSep = fileName.lastIndexOf('/');
|
||||
// Check for Windows-style path
|
||||
int winSep = fileName.lastIndexOf('\\');
|
||||
// Cut off at latest possible point
|
||||
int pos = (winSep > unixSep ? winSep : unixSep);
|
||||
if (pos != -1) {
|
||||
// Any sort of path separator found...
|
||||
fileName = fileName.substring(pos + 1);
|
||||
}
|
||||
//替换上传文件名字的特殊字符
|
||||
fileName = fileName.replace("=","").replace(",","").replace("&","")
|
||||
.replace("#", "").replace("“", "").replace("”", "");
|
||||
//替换上传文件名字中的空格
|
||||
fileName=fileName.replaceAll("\\s","");
|
||||
return fileName;
|
||||
}
|
||||
|
||||
// java 判断字符串里是否包含中文字符
|
||||
public static boolean ifContainChinese(String str) {
|
||||
if(str.getBytes().length == str.length()){
|
||||
return false;
|
||||
}else{
|
||||
Matcher m = ZHONGWEN_PATTERN.matcher(str);
|
||||
if (m.find()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一全局上传
|
||||
* @Return: java.lang.String
|
||||
*/
|
||||
public static String upload(MultipartFile file, String bizPath, String uploadType) {
|
||||
String url = "";
|
||||
if(CommonConstant.UPLOAD_TYPE_MINIO.equals(uploadType)){
|
||||
url = MinioUtil.upload(file,bizPath);
|
||||
}else{
|
||||
url = OssBootUtil.upload(file,bizPath);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
/**
|
||||
* 本地文件上传
|
||||
* @param mf 文件
|
||||
* @param bizPath 自定义路径
|
||||
* @return
|
||||
*/
|
||||
public static String uploadLocal(MultipartFile mf,String bizPath,String uploadpath){
|
||||
try {
|
||||
//update-begin-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
FileTypeFilter.fileTypeFilter(mf);
|
||||
//update-end-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
String fileName = null;
|
||||
File file = new File(uploadpath + File.separator + bizPath + File.separator );
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();// 创建文件根目录
|
||||
}
|
||||
String orgName = mf.getOriginalFilename();// 获取文件名
|
||||
orgName = CommonUtils.getFileName(orgName);
|
||||
if(orgName.indexOf(".")!=-1){
|
||||
fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
|
||||
}else{
|
||||
fileName = orgName+ "_" + System.currentTimeMillis();
|
||||
}
|
||||
String savePath = file.getPath() + File.separator + fileName;
|
||||
File savefile = new File(savePath);
|
||||
FileCopyUtils.copy(mf.getBytes(), savefile);
|
||||
String dbpath = null;
|
||||
if(oConvertUtils.isNotEmpty(bizPath)){
|
||||
dbpath = bizPath + File.separator + fileName;
|
||||
}else{
|
||||
dbpath = fileName;
|
||||
}
|
||||
if (dbpath.contains("\\")) {
|
||||
dbpath = dbpath.replace("\\", "/");
|
||||
}
|
||||
return dbpath;
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一全局上传 带桶
|
||||
* @Return: java.lang.String
|
||||
*/
|
||||
public static String upload(MultipartFile file, String bizPath, String uploadType, String customBucket) {
|
||||
String url = "";
|
||||
if(CommonConstant.UPLOAD_TYPE_MINIO.equals(uploadType)){
|
||||
url = MinioUtil.upload(file,bizPath,customBucket);
|
||||
}else{
|
||||
url = OssBootUtil.upload(file,bizPath,customBucket);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/** 当前系统数据库类型 */
|
||||
private static String DB_TYPE = "";
|
||||
private static DbType dbTypeEnum = null;
|
||||
|
||||
/**
|
||||
* 全局获取平台数据库类型(作废了)
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static String getDatabaseType() {
|
||||
if(oConvertUtils.isNotEmpty(DB_TYPE)){
|
||||
return DB_TYPE;
|
||||
}
|
||||
DataSource dataSource = SpringContextUtils.getApplicationContext().getBean(DataSource.class);
|
||||
try {
|
||||
return getDatabaseTypeByDataSource(dataSource);
|
||||
} catch (SQLException e) {
|
||||
//e.printStackTrace();
|
||||
log.warn(e.getMessage(),e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局获取平台数据库类型(对应mybaisPlus枚举)
|
||||
* @return
|
||||
*/
|
||||
public static DbType getDatabaseTypeEnum() {
|
||||
if (oConvertUtils.isNotEmpty(dbTypeEnum)) {
|
||||
return dbTypeEnum;
|
||||
}
|
||||
try {
|
||||
DataSource dataSource = SpringContextUtils.getApplicationContext().getBean(DataSource.class);
|
||||
dbTypeEnum = JdbcUtils.getDbType(dataSource.getConnection().getMetaData().getURL());
|
||||
return dbTypeEnum;
|
||||
} catch (SQLException e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据数据源key获取DataSourceProperty
|
||||
* @param sourceKey
|
||||
* @return
|
||||
*/
|
||||
public static DataSourceProperty getDataSourceProperty(String sourceKey){
|
||||
DynamicDataSourceProperties prop = SpringContextUtils.getApplicationContext().getBean(DynamicDataSourceProperties.class);
|
||||
Map<String, DataSourceProperty> map = prop.getDatasource();
|
||||
DataSourceProperty db = (DataSourceProperty)map.get(sourceKey);
|
||||
return db;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据sourceKey 获取数据源连接
|
||||
* @param sourceKey
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static Connection getDataSourceConnect(String sourceKey) throws SQLException {
|
||||
if (oConvertUtils.isEmpty(sourceKey)) {
|
||||
sourceKey = "master";
|
||||
}
|
||||
DynamicDataSourceProperties prop = SpringContextUtils.getApplicationContext().getBean(DynamicDataSourceProperties.class);
|
||||
Map<String, DataSourceProperty> map = prop.getDatasource();
|
||||
DataSourceProperty db = (DataSourceProperty)map.get(sourceKey);
|
||||
if(db==null){
|
||||
return null;
|
||||
}
|
||||
DriverManagerDataSource ds = new DriverManagerDataSource ();
|
||||
ds.setDriverClassName(db.getDriverClassName());
|
||||
ds.setUrl(db.getUrl());
|
||||
ds.setUsername(db.getUsername());
|
||||
ds.setPassword(db.getPassword());
|
||||
return ds.getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库类型
|
||||
* @param dataSource
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
private static String getDatabaseTypeByDataSource(DataSource dataSource) throws SQLException{
|
||||
if("".equals(DB_TYPE)) {
|
||||
Connection connection = dataSource.getConnection();
|
||||
try {
|
||||
DatabaseMetaData md = connection.getMetaData();
|
||||
String dbType = md.getDatabaseProductName().toLowerCase();
|
||||
if(dbType.indexOf("mysql")>=0) {
|
||||
DB_TYPE = DataBaseConstant.DB_TYPE_MYSQL;
|
||||
}else if(dbType.indexOf("oracle")>=0 ||dbType.indexOf("dm")>=0) {
|
||||
DB_TYPE = DataBaseConstant.DB_TYPE_ORACLE;
|
||||
}else if(dbType.indexOf("sqlserver")>=0||dbType.indexOf("sql server")>=0) {
|
||||
DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;
|
||||
}else if(dbType.indexOf("postgresql")>=0) {
|
||||
DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;
|
||||
}else if(dbType.indexOf("mariadb")>=0) {
|
||||
DB_TYPE = DataBaseConstant.DB_TYPE_MARIADB;
|
||||
}else {
|
||||
log.error("数据库类型:[" + dbType + "]不识别!");
|
||||
//throw new EnFiBootException("数据库类型:["+dbType+"]不识别!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
return DB_TYPE;
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,654 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 类描述:时间操作定义类
|
||||
*
|
||||
* @Author: 张代浩
|
||||
* @Date:2012-12-8 12:15:03
|
||||
* @Version 1.0
|
||||
*/
|
||||
public class DateUtils extends PropertyEditorSupport {
|
||||
|
||||
public static ThreadLocal<SimpleDateFormat> date_sdf = new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override
|
||||
protected SimpleDateFormat initialValue() {
|
||||
return new SimpleDateFormat("yyyy-MM-dd");
|
||||
}
|
||||
};
|
||||
public static ThreadLocal<SimpleDateFormat> yyyyMMdd = new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override
|
||||
protected SimpleDateFormat initialValue() {
|
||||
return new SimpleDateFormat("yyyyMMdd");
|
||||
}
|
||||
};
|
||||
public static ThreadLocal<SimpleDateFormat> date_sdf_wz = new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override
|
||||
protected SimpleDateFormat initialValue() {
|
||||
return new SimpleDateFormat("yyyy年MM月dd日");
|
||||
}
|
||||
};
|
||||
public static ThreadLocal<SimpleDateFormat> time_sdf = new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override
|
||||
protected SimpleDateFormat initialValue() {
|
||||
return new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
}
|
||||
};
|
||||
public static ThreadLocal<SimpleDateFormat> yyyymmddhhmmss = new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override
|
||||
protected SimpleDateFormat initialValue() {
|
||||
return new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
}
|
||||
};
|
||||
public static ThreadLocal<SimpleDateFormat> short_time_sdf = new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override
|
||||
protected SimpleDateFormat initialValue() {
|
||||
return new SimpleDateFormat("HH:mm");
|
||||
}
|
||||
};
|
||||
public static ThreadLocal<SimpleDateFormat> datetimeFormat = new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override
|
||||
protected SimpleDateFormat initialValue() {
|
||||
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
};
|
||||
|
||||
// 以毫秒表示的时间
|
||||
private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
|
||||
private static final long HOUR_IN_MILLIS = 3600 * 1000;
|
||||
private static final long MINUTE_IN_MILLIS = 60 * 1000;
|
||||
private static final long SECOND_IN_MILLIS = 1000;
|
||||
|
||||
// 指定模式的时间格式
|
||||
private static SimpleDateFormat getSDFormat(String pattern) {
|
||||
return new SimpleDateFormat(pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前日历,这里用中国时间表示
|
||||
*
|
||||
* @return 以当地时区表示的系统当前日历
|
||||
*/
|
||||
public static Calendar getCalendar() {
|
||||
return Calendar.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定毫秒数表示的日历
|
||||
*
|
||||
* @param millis 毫秒数
|
||||
* @return 指定毫秒数表示的日历
|
||||
*/
|
||||
public static Calendar getCalendar(long millis) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
// --------------------cal.setTimeInMillis(millis);
|
||||
cal.setTime(new Date(millis));
|
||||
return cal;
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// getDate
|
||||
// 各种方式获取的Date
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 当前日期
|
||||
*
|
||||
* @return 系统当前时间
|
||||
*/
|
||||
public static Date getDate() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定毫秒数表示的日期
|
||||
*
|
||||
* @param millis 毫秒数
|
||||
* @return 指定毫秒数表示的日期
|
||||
*/
|
||||
public static Date getDate(long millis) {
|
||||
return new Date(millis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间戳转换为字符串
|
||||
*
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
public static String timestamptoStr(Timestamp time) {
|
||||
Date date = null;
|
||||
if (null != time) {
|
||||
date = new Date(time.getTime());
|
||||
}
|
||||
return date2Str(date_sdf.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转换时间戳
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static Timestamp str2Timestamp(String str) {
|
||||
Date date = str2Date(str, date_sdf.get());
|
||||
return new Timestamp(date.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转换成日期
|
||||
*
|
||||
* @param str
|
||||
* @param sdf
|
||||
* @return
|
||||
*/
|
||||
public static Date str2Date(String str, SimpleDateFormat sdf) {
|
||||
if (null == str || "".equals(str)) {
|
||||
return null;
|
||||
}
|
||||
Date date = null;
|
||||
try {
|
||||
date = sdf.parse(str);
|
||||
return date;
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期转换为字符串
|
||||
*
|
||||
* @param date_sdf 日期格式
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String date2Str(SimpleDateFormat date_sdf) {
|
||||
Date date = getDate();
|
||||
if (null == date) {
|
||||
return null;
|
||||
}
|
||||
return date_sdf.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间
|
||||
*
|
||||
* @param date
|
||||
* @param format
|
||||
* @return
|
||||
*/
|
||||
public static String dateformat(String date, String format) {
|
||||
SimpleDateFormat sformat = new SimpleDateFormat(format);
|
||||
Date _date = null;
|
||||
try {
|
||||
_date = sformat.parse(date);
|
||||
} catch (ParseException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return sformat.format(_date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期转换为字符串
|
||||
*
|
||||
* @param date 日期
|
||||
* @param date_sdf 日期格式
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String date2Str(Date date, SimpleDateFormat date_sdf) {
|
||||
if (null == date) {
|
||||
return null;
|
||||
}
|
||||
return date_sdf.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期转换为字符串
|
||||
*
|
||||
* @param format 日期格式
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String getDate(String format) {
|
||||
Date date = new Date();
|
||||
if (null == date) {
|
||||
return null;
|
||||
}
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(format);
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定毫秒数的时间戳
|
||||
*
|
||||
* @param millis 毫秒数
|
||||
* @return 指定毫秒数的时间戳
|
||||
*/
|
||||
public static Timestamp getTimestamp(long millis) {
|
||||
return new Timestamp(millis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 以字符形式表示的时间戳
|
||||
*
|
||||
* @param time 毫秒数
|
||||
* @return 以字符形式表示的时间戳
|
||||
*/
|
||||
public static Timestamp getTimestamp(String time) {
|
||||
return new Timestamp(Long.parseLong(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统当前的时间戳
|
||||
*
|
||||
* @return 系统当前的时间戳
|
||||
*/
|
||||
public static Timestamp getTimestamp() {
|
||||
return new Timestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前时间,格式 yyyy-MM-dd HH:mm:ss
|
||||
*
|
||||
* @return 当前时间的标准形式字符串
|
||||
*/
|
||||
public static String now() {
|
||||
return datetimeFormat.get().format(getCalendar().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期的时间戳
|
||||
*
|
||||
* @param date 指定日期
|
||||
* @return 指定日期的时间戳
|
||||
*/
|
||||
public static Timestamp getTimestamp(Date date) {
|
||||
return new Timestamp(date.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日历的时间戳
|
||||
*
|
||||
* @param cal 指定日历
|
||||
* @return 指定日历的时间戳
|
||||
*/
|
||||
public static Timestamp getCalendarTimestamp(Calendar cal) {
|
||||
// ---------------------return new Timestamp(cal.getTimeInMillis());
|
||||
return new Timestamp(cal.getTime().getTime());
|
||||
}
|
||||
|
||||
public static Timestamp gettimestamp() {
|
||||
Date dt = new Date();
|
||||
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String nowTime = df.format(dt);
|
||||
Timestamp buydate = Timestamp.valueOf(nowTime);
|
||||
return buydate;
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// getMillis
|
||||
// 各种方式获取的Millis
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 系统时间的毫秒数
|
||||
*
|
||||
* @return 系统时间的毫秒数
|
||||
*/
|
||||
public static long getMillis() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日历的毫秒数
|
||||
*
|
||||
* @param cal 指定日历
|
||||
* @return 指定日历的毫秒数
|
||||
*/
|
||||
public static long getMillis(Calendar cal) {
|
||||
// --------------------return cal.getTimeInMillis();
|
||||
return cal.getTime().getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期的毫秒数
|
||||
*
|
||||
* @param date 指定日期
|
||||
* @return 指定日期的毫秒数
|
||||
*/
|
||||
public static long getMillis(Date date) {
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定时间戳的毫秒数
|
||||
*
|
||||
* @param ts 指定时间戳
|
||||
* @return 指定时间戳的毫秒数
|
||||
*/
|
||||
public static long getMillis(Timestamp ts) {
|
||||
return ts.getTime();
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// formatDate
|
||||
// 将日期按照一定的格式转化为字符串
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 默认方式表示的系统当前日期,具体格式:年-月-日
|
||||
*
|
||||
* @return 默认日期按“年-月-日“格式显示
|
||||
*/
|
||||
public static String formatDate() {
|
||||
return date_sdf.get().format(getCalendar().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认方式表示的系统当前日期,具体格式:yyyy-MM-dd HH:mm:ss
|
||||
*
|
||||
* @return 默认日期按“yyyy-MM-dd HH:mm:ss“格式显示
|
||||
*/
|
||||
public static String formatDateTime() {
|
||||
return datetimeFormat.get().format(getCalendar().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时间字符串
|
||||
*/
|
||||
public static String getDataString(SimpleDateFormat formatstr) {
|
||||
return formatstr.format(getCalendar().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期的默认显示,具体格式:年-月-日
|
||||
*
|
||||
* @param cal 指定的日期
|
||||
* @return 指定日期按“年-月-日“格式显示
|
||||
*/
|
||||
public static String formatDate(Calendar cal) {
|
||||
return date_sdf.get().format(cal.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期的默认显示,具体格式:年-月-日
|
||||
*
|
||||
* @param date 指定的日期
|
||||
* @return 指定日期按“年-月-日“格式显示
|
||||
*/
|
||||
public static String formatDate(Date date) {
|
||||
return date_sdf.get().format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定毫秒数表示日期的默认显示,具体格式:年-月-日
|
||||
*
|
||||
* @param millis 指定的毫秒数
|
||||
* @return 指定毫秒数表示日期按“年-月-日“格式显示
|
||||
*/
|
||||
public static String formatDate(long millis) {
|
||||
return date_sdf.get().format(new Date(millis));
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认日期按指定格式显示
|
||||
*
|
||||
* @param pattern 指定的格式
|
||||
* @return 默认日期按指定格式显示
|
||||
*/
|
||||
public static String formatDate(String pattern) {
|
||||
return getSDFormat(pattern).format(getCalendar().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期按指定格式显示
|
||||
*
|
||||
* @param cal 指定的日期
|
||||
* @param pattern 指定的格式
|
||||
* @return 指定日期按指定格式显示
|
||||
*/
|
||||
public static String formatDate(Calendar cal, String pattern) {
|
||||
return getSDFormat(pattern).format(cal.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期按指定格式显示
|
||||
*
|
||||
* @param date 指定的日期
|
||||
* @param pattern 指定的格式
|
||||
* @return 指定日期按指定格式显示
|
||||
*/
|
||||
public static String formatDate(Date date, String pattern) {
|
||||
return getSDFormat(pattern).format(date);
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// formatTime
|
||||
// 将日期按照一定的格式转化为字符串
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 默认方式表示的系统当前日期,具体格式:年-月-日 时:分
|
||||
*
|
||||
* @return 默认日期按“年-月-日 时:分“格式显示
|
||||
*/
|
||||
public static String formatTime() {
|
||||
return time_sdf.get().format(getCalendar().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定毫秒数表示日期的默认显示,具体格式:年-月-日 时:分
|
||||
*
|
||||
* @param millis 指定的毫秒数
|
||||
* @return 指定毫秒数表示日期按“年-月-日 时:分“格式显示
|
||||
*/
|
||||
public static String formatTime(long millis) {
|
||||
return time_sdf.get().format(new Date(millis));
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期的默认显示,具体格式:年-月-日 时:分
|
||||
*
|
||||
* @param cal 指定的日期
|
||||
* @return 指定日期按“年-月-日 时:分“格式显示
|
||||
*/
|
||||
public static String formatTime(Calendar cal) {
|
||||
return time_sdf.get().format(cal.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期的默认显示,具体格式:年-月-日 时:分
|
||||
*
|
||||
* @param date 指定的日期
|
||||
* @return 指定日期按“年-月-日 时:分“格式显示
|
||||
*/
|
||||
public static String formatTime(Date date) {
|
||||
return time_sdf.get().format(date);
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// formatShortTime
|
||||
// 将日期按照一定的格式转化为字符串
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 默认方式表示的系统当前日期,具体格式:时:分
|
||||
*
|
||||
* @return 默认日期按“时:分“格式显示
|
||||
*/
|
||||
public static String formatShortTime() {
|
||||
return short_time_sdf.get().format(getCalendar().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定毫秒数表示日期的默认显示,具体格式:时:分
|
||||
*
|
||||
* @param millis 指定的毫秒数
|
||||
* @return 指定毫秒数表示日期按“时:分“格式显示
|
||||
*/
|
||||
public static String formatShortTime(long millis) {
|
||||
return short_time_sdf.get().format(new Date(millis));
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期的默认显示,具体格式:时:分
|
||||
*
|
||||
* @param cal 指定的日期
|
||||
* @return 指定日期按“时:分“格式显示
|
||||
*/
|
||||
public static String formatShortTime(Calendar cal) {
|
||||
return short_time_sdf.get().format(cal.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定日期的默认显示,具体格式:时:分
|
||||
*
|
||||
* @param date 指定的日期
|
||||
* @return 指定日期按“时:分“格式显示
|
||||
*/
|
||||
public static String formatShortTime(Date date) {
|
||||
return short_time_sdf.get().format(date);
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// parseDate
|
||||
// parseCalendar
|
||||
// parseTimestamp
|
||||
// 将字符串按照一定的格式转化为日期或时间
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间
|
||||
*
|
||||
* @param src 将要转换的原始字符窜
|
||||
* @param pattern 转换的匹配格式
|
||||
* @return 如果转换成功则返回转换后的日期
|
||||
* @throws ParseException
|
||||
*/
|
||||
public static Date parseDate(String src, String pattern) throws ParseException {
|
||||
return getSDFormat(pattern).parse(src);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间
|
||||
*
|
||||
* @param src 将要转换的原始字符窜
|
||||
* @param pattern 转换的匹配格式
|
||||
* @return 如果转换成功则返回转换后的日期
|
||||
* @throws ParseException
|
||||
*/
|
||||
public static Calendar parseCalendar(String src, String pattern) throws ParseException {
|
||||
|
||||
Date date = parseDate(src, pattern);
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static String formatAddDate(String src, String pattern, int amount) throws ParseException {
|
||||
Calendar cal;
|
||||
cal = parseCalendar(src, pattern);
|
||||
cal.add(Calendar.DATE, amount);
|
||||
return formatDate(cal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间
|
||||
*
|
||||
* @param src 将要转换的原始字符窜
|
||||
* @param pattern 转换的匹配格式
|
||||
* @return 如果转换成功则返回转换后的时间戳
|
||||
* @throws ParseException
|
||||
*/
|
||||
public static Timestamp parseTimestamp(String src, String pattern) throws ParseException {
|
||||
Date date = parseDate(src, pattern);
|
||||
return new Timestamp(date.getTime());
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// dateDiff
|
||||
// 计算两个日期之间的差值
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 计算两个时间之间的差值,根据标志的不同而不同
|
||||
*
|
||||
* @param flag 计算标志,表示按照年/月/日/时/分/秒等计算
|
||||
* @param calSrc 减数
|
||||
* @param calDes 被减数
|
||||
* @return 两个日期之间的差值
|
||||
*/
|
||||
public static int dateDiff(char flag, Calendar calSrc, Calendar calDes) {
|
||||
|
||||
long millisDiff = getMillis(calSrc) - getMillis(calDes);
|
||||
|
||||
if (flag == 'y') {
|
||||
return (calSrc.get(Calendar.YEAR) - calDes.get(Calendar.YEAR));
|
||||
}
|
||||
|
||||
if (flag == 'd') {
|
||||
return (int) (millisDiff / DAY_IN_MILLIS);
|
||||
}
|
||||
|
||||
if (flag == 'h') {
|
||||
return (int) (millisDiff / HOUR_IN_MILLIS);
|
||||
}
|
||||
|
||||
if (flag == 'm') {
|
||||
return (int) (millisDiff / MINUTE_IN_MILLIS);
|
||||
}
|
||||
|
||||
if (flag == 's') {
|
||||
return (int) (millisDiff / SECOND_IN_MILLIS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static Long getCurrentTimestamp() {
|
||||
return Long.valueOf(DateUtils.yyyymmddhhmmss.get().format(new Date()));
|
||||
}
|
||||
|
||||
/**
|
||||
* String类型 转换为Date, 如果参数长度为10 转换格式”yyyy-MM-dd“ 如果参数长度为19 转换格式”yyyy-MM-dd
|
||||
* HH:mm:ss“ * @param text String类型的时间值
|
||||
*/
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
if (StringUtils.hasText(text)) {
|
||||
try {
|
||||
if (text.indexOf(":") == -1 && text.length() == 10) {
|
||||
setValue(DateUtils.date_sdf.get().parse(text));
|
||||
} else if (text.indexOf(":") > 0 && text.length() == 19) {
|
||||
setValue(DateUtils.datetimeFormat.get().parse(text));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Could not parse date, date format is error ");
|
||||
}
|
||||
} catch (ParseException ex) {
|
||||
IllegalArgumentException iae = new IllegalArgumentException("Could not parse date: " + ex.getMessage());
|
||||
iae.initCause(ex);
|
||||
throw iae;
|
||||
}
|
||||
} else {
|
||||
setValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getYear() {
|
||||
GregorianCalendar calendar = new GregorianCalendar();
|
||||
calendar.setTime(getDate());
|
||||
return calendar.get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public enum DySmsEnum {
|
||||
|
||||
LOGIN_TEMPLATE_CODE("SMS_175435174","JEECG","code"),
|
||||
FORGET_PASSWORD_TEMPLATE_CODE("SMS_175435174","JEECG","code"),
|
||||
REGISTER_TEMPLATE_CODE("SMS_175430166","JEECG","code"),
|
||||
ENFI_REGISTER_TEMPLATE_CODE("SMS_207950037","中国恩菲","code"),
|
||||
ENFI_GUEST_TEMPLATE_CODE("SMS_227748934","中国恩菲",""),
|
||||
/**会议通知*/
|
||||
MEET_NOTICE_TEMPLATE_CODE("SMS_201480469","H5活动之家","username,title,minute,time"),
|
||||
/**我的计划通知*/
|
||||
PLAN_NOTICE_TEMPLATE_CODE("SMS_201470515","H5活动之家","username,title,time");
|
||||
|
||||
/**
|
||||
* 短信模板编码
|
||||
*/
|
||||
private String templateCode;
|
||||
/**
|
||||
* 签名
|
||||
*/
|
||||
private String signName;
|
||||
/**
|
||||
* 短信模板必需的数据名称,多个key以逗号分隔,此处配置作为校验
|
||||
*/
|
||||
private String keys;
|
||||
|
||||
private DySmsEnum(String templateCode,String signName,String keys) {
|
||||
this.templateCode = templateCode;
|
||||
this.signName = signName;
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
public String getTemplateCode() {
|
||||
return templateCode;
|
||||
}
|
||||
|
||||
public void setTemplateCode(String templateCode) {
|
||||
this.templateCode = templateCode;
|
||||
}
|
||||
|
||||
public String getSignName() {
|
||||
return signName;
|
||||
}
|
||||
|
||||
public void setSignName(String signName) {
|
||||
this.signName = signName;
|
||||
}
|
||||
|
||||
public String getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public void setKeys(String keys) {
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
public static DySmsEnum toEnum(String templateCode) {
|
||||
if(StringUtils.isEmpty(templateCode)){
|
||||
return null;
|
||||
}
|
||||
for(DySmsEnum item : DySmsEnum.values()) {
|
||||
if(item.getTemplateCode().equals(templateCode)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,123 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import org.enfi.config.StaticConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyuncs.DefaultAcsClient;
|
||||
import com.aliyuncs.IAcsClient;
|
||||
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
|
||||
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
|
||||
import com.aliyuncs.exceptions.ClientException;
|
||||
import com.aliyuncs.profile.DefaultProfile;
|
||||
import com.aliyuncs.profile.IClientProfile;
|
||||
|
||||
/**
|
||||
* Created on 17/6/7.
|
||||
* 短信API产品的DEMO程序,工程中包含了一个SmsDemo类,直接通过
|
||||
* 执行main函数即可体验短信产品API功能(只需要将AK替换成开通了云通信-短信产品功能的AK即可)
|
||||
* 工程依赖了2个jar包(存放在工程的libs目录下)
|
||||
* 1:aliyun-java-sdk-core.jar
|
||||
* 2:aliyun-java-sdk-dysmsapi.jar
|
||||
*
|
||||
* 备注:Demo工程编码采用UTF-8
|
||||
* 国际短信发送请勿参照此DEMO
|
||||
*/
|
||||
public class DySmsHelper {
|
||||
|
||||
private final static Logger logger=LoggerFactory.getLogger(DySmsHelper.class);
|
||||
|
||||
//产品名称:云通信短信API产品,开发者无需替换
|
||||
static final String product = "Dysmsapi";
|
||||
//产品域名,开发者无需替换
|
||||
static final String domain = "dysmsapi.aliyuncs.com";
|
||||
|
||||
// TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
|
||||
static String accessKeyId;
|
||||
static String accessKeySecret;
|
||||
|
||||
public static void setAccessKeyId(String accessKeyId) {
|
||||
DySmsHelper.accessKeyId = accessKeyId;
|
||||
}
|
||||
|
||||
public static void setAccessKeySecret(String accessKeySecret) {
|
||||
DySmsHelper.accessKeySecret = accessKeySecret;
|
||||
}
|
||||
|
||||
public static String getAccessKeyId() {
|
||||
return accessKeyId;
|
||||
}
|
||||
|
||||
public static String getAccessKeySecret() {
|
||||
return accessKeySecret;
|
||||
}
|
||||
|
||||
|
||||
public static boolean sendSms(String phone,JSONObject templateParamJson,DySmsEnum dySmsEnum) throws ClientException {
|
||||
//可自助调整超时时间
|
||||
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
|
||||
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
|
||||
|
||||
//update-begin-author:taoyan date:20200811 for:配置类数据获取
|
||||
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
|
||||
setAccessKeyId(staticConfig.getAccessKeyId());
|
||||
setAccessKeySecret(staticConfig.getAccessKeySecret());
|
||||
//update-end-author:taoyan date:20200811 for:配置类数据获取
|
||||
|
||||
//初始化acsClient,暂不支持region化
|
||||
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
|
||||
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
|
||||
IAcsClient acsClient = new DefaultAcsClient(profile);
|
||||
|
||||
//验证json参数
|
||||
//validateParam(templateParamJson,dySmsEnum);
|
||||
|
||||
//组装请求对象-具体描述见控制台-文档部分内容
|
||||
SendSmsRequest request = new SendSmsRequest();
|
||||
//必填:待发送手机号
|
||||
request.setPhoneNumbers(phone);
|
||||
//必填:短信签名-可在短信控制台中找到
|
||||
request.setSignName(dySmsEnum.getSignName());
|
||||
//必填:短信模板-可在短信控制台中找到
|
||||
request.setTemplateCode(dySmsEnum.getTemplateCode());
|
||||
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
|
||||
//request.setTemplateParam(templateParamJson.toJSONString());
|
||||
|
||||
//选填-上行短信扩展码(无特殊需求用户请忽略此字段)
|
||||
//request.setSmsUpExtendCode("90997");
|
||||
|
||||
//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
|
||||
//request.setOutId("yourOutId");
|
||||
|
||||
boolean result = false;
|
||||
|
||||
//hint 此处可能会抛出异常,注意catch
|
||||
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
|
||||
logger.info("短信接口返回的数据----------------");
|
||||
logger.info("{Code:" + sendSmsResponse.getCode()+",Message:" + sendSmsResponse.getMessage()+",RequestId:"+ sendSmsResponse.getRequestId()+",BizId:"+sendSmsResponse.getBizId()+"}");
|
||||
|
||||
if ("OK".equals(sendSmsResponse.getCode())) {
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private static void validateParam(JSONObject templateParamJson,DySmsEnum dySmsEnum) {
|
||||
String keys = dySmsEnum.getKeys();
|
||||
String [] keyArr = keys.split(",");
|
||||
for(String item :keyArr) {
|
||||
if(!templateParamJson.containsKey(item)) {
|
||||
throw new RuntimeException("模板缺少参数:"+item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// public static void main(String[] args) throws ClientException, InterruptedException {
|
||||
// JSONObject obj = new JSONObject();
|
||||
// obj.put("code", "1234");
|
||||
// sendSms("13800138000", obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
|
||||
// }
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.enfi.common.handler.IFillRuleHandler;
|
||||
|
||||
|
||||
/**
|
||||
* 规则值自动生成工具类
|
||||
*
|
||||
* @author qinfeng
|
||||
* @举例: 自动生成订单号;自动生成当前日期
|
||||
*/
|
||||
@Slf4j
|
||||
public class FillRuleUtil {
|
||||
|
||||
/**
|
||||
* @param ruleCode ruleCode
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object executeRule(String ruleCode, JSONObject formData) {
|
||||
if (!StringUtils.isEmpty(ruleCode)) {
|
||||
try {
|
||||
// 获取 Service
|
||||
ServiceImpl impl = (ServiceImpl) SpringContextUtils.getBean("sysFillRuleServiceImpl");
|
||||
// 根据 ruleCode 查询出实体
|
||||
QueryWrapper queryWrapper = new QueryWrapper();
|
||||
queryWrapper.eq("rule_code", ruleCode);
|
||||
JSONObject entity = JSON.parseObject(JSON.toJSONString(impl.getOne(queryWrapper)));
|
||||
if (entity == null) {
|
||||
log.warn("填值规则:" + ruleCode + " 不存在");
|
||||
return null;
|
||||
}
|
||||
// 获取必要的参数
|
||||
String ruleClass = entity.getString("ruleClass");
|
||||
JSONObject params = entity.getJSONObject("ruleParams");
|
||||
if (params == null) {
|
||||
params = new JSONObject();
|
||||
}
|
||||
if (formData == null) {
|
||||
formData = new JSONObject();
|
||||
}
|
||||
// 通过反射执行配置的类里的方法
|
||||
IFillRuleHandler ruleHandler = (IFillRuleHandler) Class.forName(ruleClass).newInstance();
|
||||
return ruleHandler.execute(params, formData);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
/**
|
||||
* HTML 工具类
|
||||
*/
|
||||
public class HTMLUtils {
|
||||
|
||||
/**
|
||||
* 获取HTML内的文本,不包含标签
|
||||
*
|
||||
* @param html HTML 代码
|
||||
*/
|
||||
public static String getInnerText(String html) {
|
||||
if (StringUtils.isNotBlank(html)) {
|
||||
//去掉 html 的标签
|
||||
String content = html.replaceAll("</?[^>]+>", "");
|
||||
// 将多个空格合并成一个空格
|
||||
content = content.replaceAll("( )+", " ");
|
||||
// 反向转义字符
|
||||
content = HtmlUtils.htmlUnescape(content);
|
||||
return content.trim();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* IP地址
|
||||
*
|
||||
* @Author scott
|
||||
* @email jeecgos@163.com
|
||||
* @Date 2019年01月14日
|
||||
*/
|
||||
public class IPUtils {
|
||||
private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
|
||||
|
||||
/**
|
||||
* 获取IP地址
|
||||
*
|
||||
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
|
||||
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
|
||||
*/
|
||||
public static String getIpAddr(HttpServletRequest request) {
|
||||
String ip = null;
|
||||
try {
|
||||
ip = request.getHeader("x-forwarded-for");
|
||||
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
}
|
||||
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
}
|
||||
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("IPUtils ERROR ", e);
|
||||
}
|
||||
|
||||
// //使用代理,则获取第一个IP地址
|
||||
// if(StringUtils.isEmpty(ip) && ip.length() > 15) {
|
||||
// if(ip.indexOf(",") > 0) {
|
||||
// ip = ip.substring(0, ip.indexOf(","));
|
||||
// }
|
||||
// }
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.enfi.common.api.vo.Result;
|
||||
import org.enfi.common.constant.CommonConstant;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 导出返回信息
|
||||
*/
|
||||
@Slf4j
|
||||
public class ImportExcelUtil {
|
||||
|
||||
public static Result<?> imporReturnRes(int errorLines,int successLines,List<String> errorMessage) throws IOException {
|
||||
if (errorLines == 0) {
|
||||
return Result.ok("共" + successLines + "行数据全部导入成功!");
|
||||
} else {
|
||||
JSONObject result = new JSONObject(5);
|
||||
int totalCount = successLines + errorLines;
|
||||
result.put("totalCount", totalCount);
|
||||
result.put("errorCount", errorLines);
|
||||
result.put("successCount", successLines);
|
||||
result.put("msg", "总上传行数:" + totalCount + ",已导入行数:" + successLines + ",错误行数:" + errorLines);
|
||||
String fileUrl = PmsUtil.saveErrorTxtByList(errorMessage, "userImportExcelErrorLog");
|
||||
int lastIndex = fileUrl.lastIndexOf(File.separator);
|
||||
String fileName = fileUrl.substring(lastIndex + 1);
|
||||
result.put("fileUrl", "/sys/common/static/" + fileUrl);
|
||||
result.put("fileName", fileName);
|
||||
Result res = Result.ok(result);
|
||||
res.setCode(201);
|
||||
res.setMessage("文件导入成功,但有错误。");
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> importDateSave(List<?> list, Class serviceClass, List<String> errorMessage, String errorFlag) {
|
||||
IService bean =(IService) SpringContextUtils.getBean(serviceClass);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
try {
|
||||
boolean save = bean.save(list.get(i));
|
||||
if(!save){
|
||||
throw new Exception(errorFlag);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String message = e.getMessage().toLowerCase();
|
||||
int lineNumber = i + 1;
|
||||
// 通过索引名判断出错信息
|
||||
if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_ROLE_CODE)) {
|
||||
errorMessage.add("第 " + lineNumber + " 行:角色编码已经存在,忽略导入。");
|
||||
} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME)) {
|
||||
errorMessage.add("第 " + lineNumber + " 行:任务类名已经存在,忽略导入。");
|
||||
}else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_CODE)) {
|
||||
errorMessage.add("第 " + lineNumber + " 行:职务编码已经存在,忽略导入。");
|
||||
}else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_DEPART_ORG_CODE)) {
|
||||
errorMessage.add("第 " + lineNumber + " 行:部门编码已经存在,忽略导入。");
|
||||
}else {
|
||||
errorMessage.add("第 " + lineNumber + " 行:未知错误,忽略导入");
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public static List<String> importDateSaveOne(Object obj, Class serviceClass,List<String> errorMessage,int i,String errorFlag) {
|
||||
IService bean =(IService) SpringContextUtils.getBean(serviceClass);
|
||||
try {
|
||||
boolean save = bean.save(obj);
|
||||
if(!save){
|
||||
throw new Exception(errorFlag);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String message = e.getMessage().toLowerCase();
|
||||
int lineNumber = i + 1;
|
||||
// 通过索引名判断出错信息
|
||||
if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_ROLE_CODE)) {
|
||||
errorMessage.add("第 " + lineNumber + " 行:角色编码已经存在,忽略导入。");
|
||||
} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME)) {
|
||||
errorMessage.add("第 " + lineNumber + " 行:任务类名已经存在,忽略导入。");
|
||||
}else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_CODE)) {
|
||||
errorMessage.add("第 " + lineNumber + " 行:职务编码已经存在,忽略导入。");
|
||||
}else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_DEPART_ORG_CODE)) {
|
||||
errorMessage.add("第 " + lineNumber + " 行:部门编码已经存在,忽略导入。");
|
||||
}else {
|
||||
errorMessage.add("第 " + lineNumber + " 行:未知错误,忽略导入");
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
public class MD5Util {
|
||||
|
||||
public static String byteArrayToHexString(byte b[]) {
|
||||
StringBuffer resultSb = new StringBuffer();
|
||||
for (int i = 0; i < b.length; i++){
|
||||
resultSb.append(byteToHexString(b[i]));
|
||||
}
|
||||
return resultSb.toString();
|
||||
}
|
||||
|
||||
private static String byteToHexString(byte b) {
|
||||
int n = b;
|
||||
if (n < 0) {
|
||||
n += 256;
|
||||
}
|
||||
int d1 = n / 16;
|
||||
int d2 = n % 16;
|
||||
return hexDigits[d1] + hexDigits[d2];
|
||||
}
|
||||
|
||||
public static String MD5Encode(String origin, String charsetname) {
|
||||
String resultString = null;
|
||||
try {
|
||||
resultString = new String(origin);
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
if (charsetname == null || "".equals(charsetname)) {
|
||||
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
|
||||
} else {
|
||||
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
}
|
||||
return resultString;
|
||||
}
|
||||
|
||||
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
|
||||
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
|
||||
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import io.minio.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.enfi.common.util.filter.FileTypeFilter;
|
||||
import org.enfi.common.util.filter.StrAttackFilter;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
/**
|
||||
* minio文件上传工具类
|
||||
*/
|
||||
@Slf4j
|
||||
public class MinioUtil {
|
||||
private static String minioUrl;
|
||||
private static String minioName;
|
||||
private static String minioPass;
|
||||
private static String bucketName;
|
||||
|
||||
public static void setMinioUrl(String minioUrl) {
|
||||
MinioUtil.minioUrl = minioUrl;
|
||||
}
|
||||
|
||||
public static void setMinioName(String minioName) {
|
||||
MinioUtil.minioName = minioName;
|
||||
}
|
||||
|
||||
public static void setMinioPass(String minioPass) {
|
||||
MinioUtil.minioPass = minioPass;
|
||||
}
|
||||
|
||||
public static void setBucketName(String bucketName) {
|
||||
MinioUtil.bucketName = bucketName;
|
||||
}
|
||||
|
||||
public static String getMinioUrl() {
|
||||
return minioUrl;
|
||||
}
|
||||
|
||||
public static String getBucketName() {
|
||||
return bucketName;
|
||||
}
|
||||
|
||||
private static MinioClient minioClient = null;
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
public static String upload(MultipartFile file, String bizPath, String customBucket) {
|
||||
String file_url = "";
|
||||
//update-begin-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
|
||||
bizPath=StrAttackFilter.filter(bizPath);
|
||||
//update-end-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
|
||||
String newBucket = bucketName;
|
||||
if(oConvertUtils.isNotEmpty(customBucket)){
|
||||
newBucket = customBucket;
|
||||
}
|
||||
try {
|
||||
initMinio(minioUrl, minioName,minioPass);
|
||||
// 检查存储桶是否已经存在
|
||||
if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(newBucket).build())) {
|
||||
log.info("Bucket already exists.");
|
||||
} else {
|
||||
// 创建一个名为ota的存储桶
|
||||
minioClient.makeBucket(MakeBucketArgs.builder().bucket(newBucket).build());
|
||||
log.info("create a new bucket.");
|
||||
}
|
||||
//update-begin-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
FileTypeFilter.fileTypeFilter(file);
|
||||
//update-end-author:liusq date:20210809 for: 过滤上传文件类型
|
||||
InputStream stream = file.getInputStream();
|
||||
// 获取文件名
|
||||
String orgName = file.getOriginalFilename();
|
||||
if("".equals(orgName)){
|
||||
orgName=file.getName();
|
||||
}
|
||||
orgName = CommonUtils.getFileName(orgName);
|
||||
String objectName = bizPath+"/"
|
||||
+( orgName.indexOf(".")==-1
|
||||
?orgName + "_" + System.currentTimeMillis()
|
||||
:orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."))
|
||||
);
|
||||
|
||||
// 使用putObject上传一个本地文件到存储桶中。
|
||||
if(objectName.startsWith("/")){
|
||||
objectName = objectName.substring(1);
|
||||
}
|
||||
PutObjectArgs objectArgs = PutObjectArgs.builder().object(objectName)
|
||||
.bucket(newBucket)
|
||||
.contentType("application/octet-stream")
|
||||
.stream(stream,stream.available(),-1).build();
|
||||
minioClient.putObject(objectArgs);
|
||||
stream.close();
|
||||
file_url = minioUrl+newBucket+"/"+objectName;
|
||||
}catch (Exception e){
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return file_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param file
|
||||
* @param bizPath
|
||||
* @return
|
||||
*/
|
||||
public static String upload(MultipartFile file, String bizPath) {
|
||||
return upload(file,bizPath,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件流
|
||||
* @param bucketName
|
||||
* @param objectName
|
||||
* @return
|
||||
*/
|
||||
public static InputStream getMinioFile(String bucketName,String objectName){
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
initMinio(minioUrl, minioName, minioPass);
|
||||
GetObjectArgs objectArgs = GetObjectArgs.builder().object(objectName)
|
||||
.bucket(bucketName).build();
|
||||
inputStream = minioClient.getObject(objectArgs);
|
||||
} catch (Exception e) {
|
||||
log.info("文件获取失败" + e.getMessage());
|
||||
}
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param bucketName
|
||||
* @param objectName
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void removeObject(String bucketName, String objectName) {
|
||||
try {
|
||||
initMinio(minioUrl, minioName,minioPass);
|
||||
RemoveObjectArgs objectArgs = RemoveObjectArgs.builder().object(objectName)
|
||||
.bucket(bucketName).build();
|
||||
minioClient.removeObject(objectArgs);
|
||||
}catch (Exception e){
|
||||
log.info("文件删除失败" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件外链
|
||||
* @param bucketName
|
||||
* @param objectName
|
||||
* @param expires
|
||||
* @return
|
||||
*/
|
||||
public static String getObjectURL(String bucketName, String objectName, Integer expires) {
|
||||
initMinio(minioUrl, minioName,minioPass);
|
||||
try{
|
||||
GetPresignedObjectUrlArgs objectArgs = GetPresignedObjectUrlArgs.builder().object(objectName)
|
||||
.bucket(bucketName)
|
||||
.expiry(expires).build();
|
||||
String url = minioClient.getPresignedObjectUrl(objectArgs);
|
||||
return URLDecoder.decode(url,"UTF-8");
|
||||
}catch (Exception e){
|
||||
log.info("文件路径获取失败" + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化客户端
|
||||
* @param minioUrl
|
||||
* @param minioName
|
||||
* @param minioPass
|
||||
* @return
|
||||
*/
|
||||
private static MinioClient initMinio(String minioUrl, String minioName,String minioPass) {
|
||||
if (minioClient == null) {
|
||||
try {
|
||||
minioClient = MinioClient.builder()
|
||||
.endpoint(minioUrl)
|
||||
.credentials(minioName, minioPass)
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return minioClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到minio
|
||||
* @param stream
|
||||
* @param relativePath
|
||||
* @return
|
||||
*/
|
||||
public static String upload(InputStream stream,String relativePath) throws Exception {
|
||||
initMinio(minioUrl, minioName,minioPass);
|
||||
if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
|
||||
log.info("Bucket already exists.");
|
||||
} else {
|
||||
// 创建一个名为ota的存储桶
|
||||
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||
log.info("create a new bucket.");
|
||||
}
|
||||
PutObjectArgs objectArgs = PutObjectArgs.builder().object(relativePath)
|
||||
.bucket(bucketName)
|
||||
.contentType("application/octet-stream")
|
||||
.stream(stream,stream.available(),-1).build();
|
||||
minioClient.putObject(objectArgs);
|
||||
stream.close();
|
||||
return minioUrl+bucketName+"/"+relativePath;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
/**
|
||||
* @Author 张代浩
|
||||
*/
|
||||
public class MyClassLoader extends ClassLoader {
|
||||
public static Class getClassByScn(String className) {
|
||||
Class myclass = null;
|
||||
try {
|
||||
myclass = Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(className+" not found!");
|
||||
}
|
||||
return myclass;
|
||||
}
|
||||
|
||||
// 获得类的全名,包括包名
|
||||
public static String getPackPath(Object object) {
|
||||
// 检查用户传入的参数是否为空
|
||||
if (object == null) {
|
||||
throw new IllegalArgumentException("参数不能为空!");
|
||||
}
|
||||
// 获得类的全名,包括包名
|
||||
String clsName = object.getClass().getName();
|
||||
return clsName;
|
||||
}
|
||||
|
||||
public static String getAppPath(Class cls) {
|
||||
// 检查用户传入的参数是否为空
|
||||
if (cls == null) {
|
||||
throw new IllegalArgumentException("参数不能为空!");
|
||||
}
|
||||
ClassLoader loader = cls.getClassLoader();
|
||||
// 获得类的全名,包括包名
|
||||
String clsName = cls.getName() + ".class";
|
||||
// 获得传入参数所在的包
|
||||
Package pack = cls.getPackage();
|
||||
String path = "";
|
||||
// 如果不是匿名包,将包名转化为路径
|
||||
if (pack != null) {
|
||||
String packName = pack.getName();
|
||||
// 此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库
|
||||
if (packName.startsWith("java.") || packName.startsWith("javax.")) {
|
||||
throw new IllegalArgumentException("不要传送系统类!");
|
||||
}
|
||||
// 在类的名称中,去掉包名的部分,获得类的文件名
|
||||
clsName = clsName.substring(packName.length() + 1);
|
||||
// 判定包名是否是简单包名,如果是,则直接将包名转换为路径,
|
||||
if (packName.indexOf(".") < 0) {
|
||||
path = packName + "/";
|
||||
} else {// 否则按照包名的组成部分,将包名转换为路径
|
||||
int start = 0, end = 0;
|
||||
end = packName.indexOf(".");
|
||||
while (end != -1) {
|
||||
path = path + packName.substring(start, end) + "/";
|
||||
start = end + 1;
|
||||
end = packName.indexOf(".", start);
|
||||
}
|
||||
path = path + packName.substring(start) + "/";
|
||||
}
|
||||
}
|
||||
// 调用ClassLoader的getResource方法,传入包含路径信息的类文件名
|
||||
java.net.URL url = loader.getResource(path + clsName);
|
||||
// 从URL对象中获取路径信息
|
||||
String realPath = url.getPath();
|
||||
// 去掉路径信息中的协议名"file:"
|
||||
int pos = realPath.indexOf("file:");
|
||||
if (pos > -1) {
|
||||
realPath = realPath.substring(pos + 5);
|
||||
}
|
||||
// 去掉路径信息最后包含类文件信息的部分,得到类所在的路径
|
||||
pos = realPath.indexOf(path + clsName);
|
||||
realPath = realPath.substring(0, pos - 1);
|
||||
// 如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名
|
||||
if (realPath.endsWith("!")) {
|
||||
realPath = realPath.substring(0, realPath.lastIndexOf("/"));
|
||||
}
|
||||
/*------------------------------------------------------------
|
||||
ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径
|
||||
中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要
|
||||
的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的
|
||||
中文及空格路径
|
||||
-------------------------------------------------------------*/
|
||||
try {
|
||||
realPath = java.net.URLDecoder.decode(realPath, "utf-8");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return realPath;
|
||||
}// getAppPath定义结束
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.SecureRandom;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.PBEParameterSpec;
|
||||
public class PasswordUtil {
|
||||
|
||||
/**
|
||||
* JAVA6支持以下任意一种算法 PBEWITHMD5ANDDES PBEWITHMD5ANDTRIPLEDES
|
||||
* PBEWITHSHAANDDESEDE PBEWITHSHA1ANDRC2_40 PBKDF2WITHHMACSHA1
|
||||
* */
|
||||
|
||||
/**
|
||||
* 定义使用的算法为:PBEWITHMD5andDES算法
|
||||
*/
|
||||
public static final String ALGORITHM = "PBEWithMD5AndDES";//加密算法
|
||||
public static final String Salt = "63293188";//密钥
|
||||
|
||||
/**
|
||||
* 定义迭代次数为1000次
|
||||
*/
|
||||
private static final int ITERATIONCOUNT = 1000;
|
||||
|
||||
/**
|
||||
* 获取加密算法中使用的盐值,解密中使用的盐值必须与加密中使用的相同才能完成操作. 盐长度必须为8字节
|
||||
*
|
||||
* @return byte[] 盐值
|
||||
* */
|
||||
public static byte[] getSalt() throws Exception {
|
||||
// 实例化安全随机数
|
||||
SecureRandom random = new SecureRandom();
|
||||
// 产出盐
|
||||
return random.generateSeed(8);
|
||||
}
|
||||
|
||||
public static byte[] getStaticSalt() {
|
||||
// 产出盐
|
||||
return Salt.getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据PBE密码生成一把密钥
|
||||
*
|
||||
* @param password
|
||||
* 生成密钥时所使用的密码
|
||||
* @return Key PBE算法密钥
|
||||
* */
|
||||
private static Key getPBEKey(String password) {
|
||||
// 实例化使用的算法
|
||||
SecretKeyFactory keyFactory;
|
||||
SecretKey secretKey = null;
|
||||
try {
|
||||
keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
|
||||
// 设置PBE密钥参数
|
||||
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
|
||||
// 生成密钥
|
||||
secretKey = keyFactory.generateSecret(keySpec);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密明文字符串
|
||||
*
|
||||
* @param plaintext
|
||||
* 待加密的明文字符串
|
||||
* @param password
|
||||
* 生成密钥时所使用的密码
|
||||
* @param salt
|
||||
* 盐值
|
||||
* @return 加密后的密文字符串
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String encrypt(String plaintext, String password, String salt) {
|
||||
|
||||
Key key = getPBEKey(password);
|
||||
byte[] encipheredData = null;
|
||||
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt.getBytes(), ITERATIONCOUNT);
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);
|
||||
//update-begin-author:sccott date:20180815 for:中文作为用户名时,加密的密码windows和linux会得到不同的结果 gitee/issues/IZUD7
|
||||
encipheredData = cipher.doFinal(plaintext.getBytes("utf-8"));
|
||||
//update-end-author:sccott date:20180815 for:中文作为用户名时,加密的密码windows和linux会得到不同的结果 gitee/issues/IZUD7
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return bytesToHexString(encipheredData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密密文字符串
|
||||
*
|
||||
* @param ciphertext
|
||||
* 待解密的密文字符串
|
||||
* @param password
|
||||
* 生成密钥时所使用的密码(如需解密,该参数需要与加密时使用的一致)
|
||||
* @param salt
|
||||
* 盐值(如需解密,该参数需要与加密时使用的一致)
|
||||
* @return 解密后的明文字符串
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String decrypt(String ciphertext, String password, String salt) {
|
||||
|
||||
Key key = getPBEKey(password);
|
||||
byte[] passDec = null;
|
||||
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt.getBytes(), ITERATIONCOUNT);
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
|
||||
|
||||
passDec = cipher.doFinal(hexStringToBytes(ciphertext));
|
||||
}
|
||||
|
||||
catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
}
|
||||
return new String(passDec);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字节数组转换为十六进制字符串
|
||||
*
|
||||
* @param src
|
||||
* 字节数组
|
||||
* @return
|
||||
*/
|
||||
public static String bytesToHexString(byte[] src) {
|
||||
StringBuilder stringBuilder = new StringBuilder("");
|
||||
if (src == null || src.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
int v = src[i] & 0xFF;
|
||||
String hv = Integer.toHexString(v);
|
||||
if (hv.length() < 2) {
|
||||
stringBuilder.append(0);
|
||||
}
|
||||
stringBuilder.append(hv);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将十六进制字符串转换为字节数组
|
||||
*
|
||||
* @param hexString
|
||||
* 十六进制字符串
|
||||
* @return
|
||||
*/
|
||||
public static byte[] hexStringToBytes(String hexString) {
|
||||
if (hexString == null || hexString.equals("")) {
|
||||
return null;
|
||||
}
|
||||
hexString = hexString.toUpperCase();
|
||||
int length = hexString.length() / 2;
|
||||
char[] hexChars = hexString.toCharArray();
|
||||
byte[] d = new byte[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
int pos = i * 2;
|
||||
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
private static byte charToByte(char c) {
|
||||
return (byte) "0123456789ABCDEF".indexOf(c);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
/**
|
||||
* 使用Spring自身提供的地址匹配工具匹配URL
|
||||
*/
|
||||
public class PathMatcherUtil {
|
||||
|
||||
public static void main(String[] args) {
|
||||
String url = "/sys/dict/loadDictOrderByValue/tree,s2,2";
|
||||
String p = "/sys/dict/loadDictOrderByValue/*";
|
||||
|
||||
System.out.println(PathMatcherUtil.match(p,url));
|
||||
}
|
||||
|
||||
/**
|
||||
* 实际验证路径匹配权限
|
||||
*
|
||||
* @param matchPath 权限url
|
||||
* @param path 访问路径
|
||||
* @return 是否拥有权限
|
||||
*/
|
||||
public static boolean match(String matchPath, String path) {
|
||||
SpringAntMatcher springAntMatcher = new SpringAntMatcher(matchPath, true);
|
||||
return springAntMatcher.matches(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实际验证路径匹配权限
|
||||
*
|
||||
* @param list 权限url
|
||||
* @param path 访问路径
|
||||
* @return 是否拥有权限
|
||||
*/
|
||||
public static boolean matches(Collection<String> list, String path) {
|
||||
for (String s : list) {
|
||||
SpringAntMatcher springAntMatcher = new SpringAntMatcher(s, true);
|
||||
if (springAntMatcher.matches(path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 地址表达式匹配工具
|
||||
*/
|
||||
private static class SpringAntMatcher implements Matcher {
|
||||
private final AntPathMatcher antMatcher;
|
||||
private final String pattern;
|
||||
|
||||
private SpringAntMatcher(String pattern, boolean caseSensitive) {
|
||||
this.pattern = pattern;
|
||||
this.antMatcher = createMatcher(caseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String path) {
|
||||
return this.antMatcher.match(this.pattern, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> extractUriTemplateVariables(String path) {
|
||||
return this.antMatcher.extractUriTemplateVariables(this.pattern, path);
|
||||
}
|
||||
|
||||
private static AntPathMatcher createMatcher(boolean caseSensitive) {
|
||||
AntPathMatcher matcher = new AntPathMatcher();
|
||||
matcher.setTrimTokens(false);
|
||||
matcher.setCaseSensitive(caseSensitive);
|
||||
return matcher;
|
||||
}
|
||||
}
|
||||
|
||||
private interface Matcher {
|
||||
boolean matches(String var1);
|
||||
|
||||
Map<String, String> extractUriTemplateVariables(String var1);
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class PmsUtil {
|
||||
|
||||
|
||||
private static String uploadPath;
|
||||
|
||||
@Value("${enfi.path.upload}")
|
||||
public void setUploadPath(String uploadPath) {
|
||||
PmsUtil.uploadPath = uploadPath;
|
||||
}
|
||||
|
||||
public static String saveErrorTxtByList(List<String> msg, String name) {
|
||||
Date d = new Date();
|
||||
String saveDir = "logs" + File.separator + DateUtils.yyyyMMdd.get().format(d) + File.separator;
|
||||
String saveFullDir = uploadPath + File.separator + saveDir;
|
||||
|
||||
File saveFile = new File(saveFullDir);
|
||||
if (!saveFile.exists()) {
|
||||
saveFile.mkdirs();
|
||||
}
|
||||
name += DateUtils.yyyymmddhhmmss.get().format(d) + Math.round(Math.random() * 10000);
|
||||
String saveFilePath = saveFullDir + name + ".txt";
|
||||
|
||||
try {
|
||||
//封装目的地
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(saveFilePath));
|
||||
//遍历集合
|
||||
for (String s : msg) {
|
||||
//写数据
|
||||
if (s.indexOf("_") > 0) {
|
||||
String arr[] = s.split("_");
|
||||
bw.write("第" + arr[0] + "行:" + arr[1]);
|
||||
} else {
|
||||
bw.write(s);
|
||||
}
|
||||
//bw.newLine();
|
||||
bw.write("\r\n");
|
||||
}
|
||||
//释放资源
|
||||
bw.flush();
|
||||
bw.close();
|
||||
} catch (Exception e) {
|
||||
log.info("excel导入生成错误日志文件异常:" + e.getMessage());
|
||||
}
|
||||
return saveDir + name + ".txt";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
public enum PrintUtil {
|
||||
RED {
|
||||
public Integer getColor() {return 31;}
|
||||
},
|
||||
GREEN {
|
||||
public Integer getColor() {return 32;}
|
||||
},
|
||||
YELLOW {
|
||||
public Integer getColor() {return 33;}
|
||||
},
|
||||
BLUE {
|
||||
public Integer getColor() {return 34;}
|
||||
},
|
||||
PURPULE {
|
||||
public Integer getColor() {return 35;}
|
||||
},
|
||||
CYAN {
|
||||
public Integer getColor() {return 36;}
|
||||
},
|
||||
WHITE{
|
||||
public Integer getColor() {return 37;}
|
||||
},
|
||||
BLACK{
|
||||
public Integer getColor() {return 30;}
|
||||
};
|
||||
|
||||
public Integer getColor() {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
public void Println(String val) {
|
||||
val=oConvertUtils.isEmpty(val)?"null":val;
|
||||
printSingleColor(getColor(),2,val);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param code 颜色代号:背景颜色代号(41-46);前景色代号(31-36)
|
||||
* @param n 数字+m:1加粗;3斜体;4下划线
|
||||
* @param content 要打印的内容
|
||||
* 格式:System.out.println("\33[前景色代号;背景色代号;数字m")
|
||||
* %s是字符串占位符,%d 是数字占位符
|
||||
*/
|
||||
private void printSingleColor(int code,int n,String content){
|
||||
System.out.format("\33[%d;%dm%s%n", code, n, content);
|
||||
}
|
||||
}
|
@ -0,0 +1,307 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import com.google.zxing.*;
|
||||
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
||||
import com.google.zxing.client.j2se.MatrixToImageWriter;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.swing.filechooser.FileSystemView;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @ClassName: QRCodeUtil
|
||||
* @Author: wanghao
|
||||
* @date: 2021.11.13 15:26
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class QRCodeUtil {
|
||||
/**
|
||||
* CODE_WIDTH:二维码宽度,单位像素
|
||||
* CODE_HEIGHT:二维码高度,单位像素
|
||||
* FRONT_COLOR:二维码前景色,0x000000 表示黑色
|
||||
* BACKGROUND_COLOR:二维码背景色,0xFFFFFF 表示白色
|
||||
* 演示用 16 进制表示,和前端页面 CSS 的取色是一样的,注意前后景颜色应该对比明显,如常见的黑白
|
||||
*/
|
||||
private static final int CODE_WIDTH = 400;
|
||||
private static final int CODE_HEIGHT = 400;
|
||||
private static final int FRONT_COLOR = 0x000000;
|
||||
private static final int BACKGROUND_COLOR = 0xFFFFFF;
|
||||
|
||||
@SneakyThrows
|
||||
public static String crateQRCode(String content, int width, int height) {
|
||||
|
||||
String resultImage = "";
|
||||
if (!StringUtils.isEmpty(content)) {
|
||||
ServletOutputStream stream = null;
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
@SuppressWarnings("rawtypes")
|
||||
HashMap<EncodeHintType, Comparable> hints = new HashMap<>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); // 指定字符编码为“utf-8”
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); // 指定二维码的纠错等级为中级
|
||||
hints.put(EncodeHintType.MARGIN, 2); // 设置图片的边距
|
||||
|
||||
try {
|
||||
QRCodeWriter writer = new QRCodeWriter();
|
||||
BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
|
||||
BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
|
||||
ImageIO.write(bufferedImage, "png", os);
|
||||
/**
|
||||
* 原生转码前面没有 data:image/png;base64 这些字段,返回给前端是无法被解析,可以让前端加,也可以在下面加上
|
||||
*/
|
||||
resultImage = "data:image/png;base64," + Base64.encode(os.toByteArray());
|
||||
|
||||
return resultImage;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
stream.flush();
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String crateQRCode(InputStream inputStream) {
|
||||
return "data:image/png;base64," + Base64.encode(toByteArray(inputStream));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private static byte[] toByteArray(InputStream input) {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[4096];
|
||||
int n = 0;
|
||||
while (-1 != (n = input.read(buffer))) {
|
||||
output.write(buffer, 0, n);
|
||||
}
|
||||
return output.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param codeContent 二维码参数内容,如果是一个网页地址,如 https://www.baidu.com/ 则 微信扫一扫会直接进入此地址, 如果是一些参数,如
|
||||
* 1541656080837,则微信扫一扫会直接回显这些参数值
|
||||
* @param codeImgFileSaveDir 二维码图片保存的目录,如 D:/codes
|
||||
* @param fileName 二维码图片文件名称,带格式,如 123.png
|
||||
*/
|
||||
public static void createCodeToFile(String codeContent, File codeImgFileSaveDir, String fileName) {
|
||||
try {
|
||||
if (codeContent == null || "".equals(codeContent)) {
|
||||
log.info("二维码内容为空,不进行操作...");
|
||||
return;
|
||||
}
|
||||
codeContent = codeContent.trim();
|
||||
if (codeImgFileSaveDir == null || codeImgFileSaveDir.isFile()) {
|
||||
codeImgFileSaveDir = FileSystemView.getFileSystemView().getHomeDirectory();
|
||||
log.info("二维码图片存在目录为空,默认放在桌面...");
|
||||
}
|
||||
if (!codeImgFileSaveDir.exists()) {
|
||||
codeImgFileSaveDir.mkdirs();
|
||||
log.info("二维码图片存在目录不存在,开始创建...");
|
||||
}
|
||||
if (fileName == null || "".equals(fileName)) {
|
||||
fileName = new Date().getTime() + ".png";
|
||||
log.info("二维码图片文件名为空,随机生成 png 格式图片...");
|
||||
}
|
||||
|
||||
BufferedImage bufferedImage = getBufferedImage(codeContent);
|
||||
|
||||
/*
|
||||
* javax.imageio.ImageIO:java扩展的图像IO
|
||||
* write(RenderedImage im, String formatName, File output)
|
||||
* im:待写入的图像, formatName:图像写入的格式,output:写入的图像文件,文件不存在时会自动创建
|
||||
*/
|
||||
File codeImgFile = new File(codeImgFileSaveDir, fileName);
|
||||
ImageIO.write(bufferedImage, "png", codeImgFile);
|
||||
|
||||
log.info("二维码图片生成成功:" + codeImgFile.getPath());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二维码并输出到输出流, 通常用于输出到网页上进行显示
|
||||
* 输出到网页与输出到磁盘上的文件中,区别在于最后一句 ImageIO.write
|
||||
* write(RenderedImage im,String formatName,File output):写到文件中
|
||||
* write(RenderedImage im,String formatName,OutputStream output):输出到输出流中
|
||||
*
|
||||
* @param codeContent :二维码内容
|
||||
* @param outputStream :输出流,比如 HttpServletResponse 的 getOutputStream
|
||||
*/
|
||||
public static void createCodeToOutputStream(String codeContent, OutputStream outputStream) {
|
||||
try {
|
||||
if (codeContent == null || "".equals(codeContent.trim())) {
|
||||
log.info("二维码内容为空,不进行操作...");
|
||||
return;
|
||||
}
|
||||
codeContent = codeContent.trim();
|
||||
|
||||
BufferedImage bufferedImage = getBufferedImage(codeContent);
|
||||
/*
|
||||
* 区别就是以一句,输出到输出流中,如果第三个参数是 File,则输出到文件中
|
||||
*/
|
||||
ImageIO.write(bufferedImage, "png", outputStream);
|
||||
log.info("二维码图片生成到输出流成功...");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("发生错误: {}!", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static BufferedImage getBufferedImage(String codeContent) throws WriterException {
|
||||
/*
|
||||
* com.google.zxing.EncodeHintType:编码提示类型,枚举类型
|
||||
* EncodeHintType.CHARACTER_SET:设置字符编码类型
|
||||
* EncodeHintType.ERROR_CORRECTION:设置误差校正
|
||||
* ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
|
||||
* 不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
|
||||
* EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近
|
||||
*/
|
||||
Map<EncodeHintType, Object> hints = new HashMap();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
|
||||
hints.put(EncodeHintType.MARGIN, 1);
|
||||
|
||||
/*
|
||||
* MultiFormatWriter:多格式写入,这是一个工厂类,里面重载了两个 encode 方法,用于写入条形码或二维码
|
||||
* encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
|
||||
* contents:条形码/二维码内容
|
||||
* format:编码类型,如 条形码,二维码 等
|
||||
* width:码的宽度
|
||||
* height:码的高度
|
||||
* hints:码内容的编码类型
|
||||
* BarcodeFormat:枚举该程序包已知的条形码格式,即创建何种码,如 1 维的条形码,2 维的二维码 等
|
||||
* BitMatrix:位(比特)矩阵或叫2D矩阵,也就是需要的二维码
|
||||
*/
|
||||
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
|
||||
BitMatrix bitMatrix = multiFormatWriter.encode(codeContent, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);
|
||||
|
||||
/*
|
||||
* java.awt.image.BufferedImage:具有图像数据的可访问缓冲图像,实现了 RenderedImage 接口
|
||||
* BitMatrix 的 get(int x, int y) 获取比特矩阵内容,指定位置有值,则返回true,将其设置为前景色,否则设置为背景色
|
||||
* BufferedImage 的 setRGB(int x, int y, int rgb) 方法设置图像像素
|
||||
* x:像素位置的横坐标,即列
|
||||
* y:像素位置的纵坐标,即行
|
||||
* rgb:像素的值,采用 16 进制,如 0xFFFFFF 白色
|
||||
*/
|
||||
BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
|
||||
for (int x = 0; x < CODE_WIDTH; x++) {
|
||||
for (int y = 0; y < CODE_HEIGHT; y++) {
|
||||
bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
|
||||
}
|
||||
}
|
||||
return bufferedImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据本地二维码图片解析二维码内容 注:图片必须是二维码图片,但也可以是微信用户二维码名片,上面有名称、头像也是可以的)
|
||||
*
|
||||
* @param file 本地二维码图片文件,如 E:\\logs\\2.jpg
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String parseQRCodeByFile(File file) {
|
||||
String resultStr = null;
|
||||
if (file == null || file.isDirectory() || !file.exists()) {
|
||||
return resultStr;
|
||||
}
|
||||
try {
|
||||
/*
|
||||
* ImageIO的BufferedImage read(URL input)方法用于读取网络图片文件转为内存缓冲图像
|
||||
* 同理还有:read(File input)、read(InputStream input)、、read(ImageInputStream stream)
|
||||
*/
|
||||
BufferedImage bufferedImage = ImageIO.read(file);
|
||||
/*
|
||||
* com.google.zxing.client.j2se.BufferedImageLuminanceSource:缓冲图像亮度源
|
||||
* 将 java.awt.image.BufferedImage 转为 zxing 的 缓冲图像亮度源
|
||||
* 关键就是下面这几句:HybridBinarizer 用于读取二维码图像数据,BinaryBitmap 二进制位图
|
||||
*/
|
||||
BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
Hashtable hints = new Hashtable();
|
||||
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
|
||||
/*
|
||||
* 如果图片不是二维码图片,则 decode 抛异常:com.google.zxing.NotFoundException
|
||||
* MultiFormatWriter 的 encode 用于对内容进行编码成 2D 矩阵
|
||||
* MultiFormatReader 的 decode 用于读取二进制位图数据
|
||||
*/
|
||||
Result result = new MultiFormatReader().decode(bitmap, hints);
|
||||
resultStr = result.getText();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
log.error("图片非二维码图片, 路径是: {}!", file.getPath());
|
||||
}
|
||||
return resultStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据网络二维码图片解析二维码内容, 区别仅仅在于 ImageIO.read(url); 这一个重载的方法)
|
||||
*
|
||||
* @param url 二维码图片网络地址,如 https://res.wx.qq.com/mpres/htmledition/images/mp_qrcode3a7b38.gif
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String parseQRCodeByUrl(URL url) {
|
||||
String resultStr = null;
|
||||
if (url == null) {
|
||||
return resultStr;
|
||||
}
|
||||
try {
|
||||
/*
|
||||
* ImageIO 的 BufferedImage read(URL input) 方法用于读取网络图片文件转为内存缓冲图像
|
||||
* 同理还有:read(File input)、read(InputStream input)、、read(ImageInputStream stream)
|
||||
* 如果图片网络地址错误,比如不能访问,则 read 抛异常:javax.imageio.IIOException: Can't get input stream from URL!
|
||||
*/
|
||||
BufferedImage bufferedImage = ImageIO.read(url);
|
||||
/*
|
||||
* com.google.zxing.client.j2se.BufferedImageLuminanceSource:缓冲图像亮度源
|
||||
* 将 java.awt.image.BufferedImage 转为 zxing 的 缓冲图像亮度源
|
||||
* 关键就是下面这几句:HybridBinarizer 用于读取二维码图像数据,BinaryBitmap 二进制位图
|
||||
*/
|
||||
BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
Hashtable hints = new Hashtable();
|
||||
/*
|
||||
* 如果内容包含中文,则解码的字符集格式应该和编码时一致
|
||||
*/
|
||||
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
|
||||
/*
|
||||
* 如果图片不是二维码图片,则 decode 抛异常:com.google.zxing.NotFoundException
|
||||
* MultiFormatWriter 的 encode 用于对内容进行编码成 2D 矩阵
|
||||
* MultiFormatReader 的 decode 用于读取二进制位图数据
|
||||
*/
|
||||
Result result = new MultiFormatReader().decode(bitmap, hints);
|
||||
resultStr = result.getText();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("二维码图片地址错误, 地址是: {}!", url);
|
||||
} catch (NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
log.error("图片非二维码图片, 地址是: {}!", url);
|
||||
}
|
||||
return resultStr;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,255 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author 张代浩
|
||||
* @desc 通过反射来动态调用get 和 set 方法
|
||||
*/
|
||||
@Slf4j
|
||||
public class ReflectHelper {
|
||||
|
||||
private Class cls;
|
||||
|
||||
/**
|
||||
* 传过来的对象
|
||||
*/
|
||||
private Object obj;
|
||||
|
||||
/**
|
||||
* 存放get方法
|
||||
*/
|
||||
private Hashtable<String, Method> getMethods = null;
|
||||
/**
|
||||
* 存放set方法
|
||||
*/
|
||||
private Hashtable<String, Method> setMethods = null;
|
||||
|
||||
/**
|
||||
* 定义构造方法 -- 一般来说是个pojo
|
||||
*
|
||||
* @param o 目标对象
|
||||
*/
|
||||
public ReflectHelper(Object o) {
|
||||
obj = o;
|
||||
initMethods();
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 初始化
|
||||
*/
|
||||
public void initMethods() {
|
||||
getMethods = new Hashtable<String, Method>();
|
||||
setMethods = new Hashtable<String, Method>();
|
||||
cls = obj.getClass();
|
||||
Method[] methods = cls.getMethods();
|
||||
// 定义正则表达式,从方法中过滤出getter / setter 函数.
|
||||
String gs = "get(\\w+)";
|
||||
Pattern getM = Pattern.compile(gs);
|
||||
String ss = "set(\\w+)";
|
||||
Pattern setM = Pattern.compile(ss);
|
||||
// 把方法中的"set" 或者 "get" 去掉
|
||||
String rapl = "$1";
|
||||
String param;
|
||||
for (int i = 0; i < methods.length; ++i) {
|
||||
Method m = methods[i];
|
||||
String methodName = m.getName();
|
||||
if (Pattern.matches(gs, methodName)) {
|
||||
param = getM.matcher(methodName).replaceAll(rapl).toLowerCase();
|
||||
getMethods.put(param, m);
|
||||
} else if (Pattern.matches(ss, methodName)) {
|
||||
param = setM.matcher(methodName).replaceAll(rapl).toLowerCase();
|
||||
setMethods.put(param, m);
|
||||
} else {
|
||||
// logger.info(methodName + " 不是getter,setter方法!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 调用set方法
|
||||
*/
|
||||
public boolean setMethodValue(String property, Object object) {
|
||||
Method m = setMethods.get(property.toLowerCase());
|
||||
if (m != null) {
|
||||
try {
|
||||
// 调用目标类的setter函数
|
||||
m.invoke(obj, object);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
log.info("invoke getter on " + property + " error: " + ex.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 调用set方法
|
||||
*/
|
||||
public Object getMethodValue(String property) {
|
||||
Object value = null;
|
||||
Method m = getMethods.get(property.toLowerCase());
|
||||
if (m != null) {
|
||||
try {
|
||||
/*
|
||||
* 调用obj类的setter函数
|
||||
*/
|
||||
value = m.invoke(obj, new Object[]{});
|
||||
|
||||
} catch (Exception ex) {
|
||||
log.info("invoke getter on " + property + " error: " + ex.toString());
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把map中的内容全部注入到obj中
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public Object setAll(Map<String, Object> data) {
|
||||
if (data == null || data.keySet().size() <= 0) {
|
||||
return null;
|
||||
}
|
||||
for (Entry<String, Object> entry : data.entrySet()) {
|
||||
this.setMethodValue(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把map中的内容全部注入到obj中
|
||||
*
|
||||
* @param o
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static Object setAll(Object o, Map<String, Object> data) {
|
||||
ReflectHelper reflectHelper = new ReflectHelper(o);
|
||||
reflectHelper.setAll(data);
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把map中的内容全部注入到新实例中
|
||||
*
|
||||
* @param clazz
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T setAll(Class<T> clazz, Map<String, Object> data) {
|
||||
T o = null;
|
||||
try {
|
||||
o = clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
o = null;
|
||||
return o;
|
||||
}
|
||||
return (T) setAll(o, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入的class将mapList转换为实体类list
|
||||
*
|
||||
* @param mapist
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
public static <T> List<T> transList2Entrys(List<Map<String, Object>> mapist, Class<T> clazz) {
|
||||
List<T> list = new ArrayList<T>();
|
||||
if (mapist != null && mapist.size() > 0) {
|
||||
for (Map<String, Object> data : mapist) {
|
||||
list.add(ReflectHelper.setAll(clazz, data));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据属性名获取属性值
|
||||
*/
|
||||
public static Object getFieldValueByName(String fieldName, Object o) {
|
||||
try {
|
||||
String firstLetter = fieldName.substring(0, 1).toUpperCase();
|
||||
String getter = "get" + firstLetter + fieldName.substring(1);
|
||||
Method method = o.getClass().getMethod(getter, new Class[]{});
|
||||
Object value = method.invoke(o, new Object[]{});
|
||||
return value;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取属性值
|
||||
*/
|
||||
public static Object getFieldVal(String fieldName, Object o) {
|
||||
try {
|
||||
// 暴力反射获取属性
|
||||
Field filed = o.getClass().getDeclaredField(fieldName);
|
||||
// 设置反射时取消Java的访问检查,暴力访问
|
||||
filed.setAccessible(true);
|
||||
Object val = filed.get(o);
|
||||
return val;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取属性名数组
|
||||
*/
|
||||
public static String[] getFiledName(Object o) {
|
||||
Field[] fields = o.getClass().getDeclaredFields();
|
||||
String[] fieldNames = new String[fields.length];
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
//log.info(fields[i].getType());
|
||||
fieldNames[i] = fields[i].getName();
|
||||
}
|
||||
return fieldNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取属性类型(type),属性名(name),属性值(value)的map组成的list
|
||||
*/
|
||||
public static List<Map> getFiledsInfo(Object o) {
|
||||
Field[] fields = o.getClass().getDeclaredFields();
|
||||
String[] fieldNames = new String[fields.length];
|
||||
List<Map> list = new ArrayList<Map>();
|
||||
Map<String, Object> infoMap = null;
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
infoMap = new HashMap<String, Object>();
|
||||
infoMap.put("type", fields[i].getType().toString());
|
||||
infoMap.put("name", fields[i].getName());
|
||||
infoMap.put("value", getFieldValueByName(fields[i].getName(), o));
|
||||
list.add(infoMap);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象的所有属性值,返回一个对象数组
|
||||
*/
|
||||
public static Object[] getFiledValues(Object o) {
|
||||
String[] fieldNames = getFiledName(o);
|
||||
Object[] value = new Object[fieldNames.length];
|
||||
for (int i = 0; i < fieldNames.length; i++) {
|
||||
value[i] = getFieldValueByName(fieldNames[i], o);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.enfi.common.api.vo.Result;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* 通过 RESTful 风格的接口操纵 desform 里的数据
|
||||
*
|
||||
* @author sunjianlei
|
||||
*/
|
||||
public class RestDesformUtil {
|
||||
|
||||
private static String domain = null;
|
||||
private static String path = null;
|
||||
|
||||
static {
|
||||
domain = SpringContextUtils.getDomain();
|
||||
path = oConvertUtils.getString(SpringContextUtils.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据
|
||||
*
|
||||
* @param desformCode
|
||||
* @param dataId
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public static Result queryOne(String desformCode, String dataId, String token) {
|
||||
String url = getBaseUrl(desformCode, dataId).toString();
|
||||
HttpHeaders headers = getHeaders(token);
|
||||
ResponseEntity<JSONObject> result = RestUtil.request(url, HttpMethod.GET, headers, null, null, JSONObject.class);
|
||||
return packageReturn(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param desformCode
|
||||
* @param formData
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public static Result addOne(String desformCode, JSONObject formData, String token) {
|
||||
return addOrEditOne(desformCode, formData, token, HttpMethod.POST);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据
|
||||
*
|
||||
* @param desformCode
|
||||
* @param formData
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public static Result editOne(String desformCode, JSONObject formData, String token) {
|
||||
return addOrEditOne(desformCode, formData, token, HttpMethod.PUT);
|
||||
}
|
||||
|
||||
private static Result addOrEditOne(String desformCode, JSONObject formData, String token, HttpMethod method) {
|
||||
String url = getBaseUrl(desformCode).toString();
|
||||
HttpHeaders headers = getHeaders(token);
|
||||
ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, formData, JSONObject.class);
|
||||
return packageReturn(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param desformCode
|
||||
* @param dataId
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public static Result removeOne(String desformCode, String dataId, String token) {
|
||||
String url = getBaseUrl(desformCode, dataId).toString();
|
||||
HttpHeaders headers = getHeaders(token);
|
||||
ResponseEntity<JSONObject> result = RestUtil.request(url, HttpMethod.DELETE, headers, null, null, JSONObject.class);
|
||||
return packageReturn(result);
|
||||
}
|
||||
|
||||
private static Result packageReturn(ResponseEntity<JSONObject> result) {
|
||||
if (result.getBody() != null) {
|
||||
return result.getBody().toJavaObject(Result.class);
|
||||
}
|
||||
return Result.error("操作失败");
|
||||
}
|
||||
|
||||
private static StringBuilder getBaseUrl() {
|
||||
StringBuilder builder = new StringBuilder(domain).append(path);
|
||||
builder.append("/desform/api");
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static StringBuilder getBaseUrl(String desformCode, String dataId) {
|
||||
StringBuilder builder = getBaseUrl();
|
||||
builder.append("/").append(desformCode);
|
||||
if (dataId != null) {
|
||||
builder.append("/").append(dataId);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static StringBuilder getBaseUrl(String desformCode) {
|
||||
return getBaseUrl(desformCode, null);
|
||||
}
|
||||
|
||||
private static HttpHeaders getHeaders(String token) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
String mediaType = MediaType.APPLICATION_JSON_UTF8_VALUE;
|
||||
headers.setContentType(MediaType.parseMediaType(mediaType));
|
||||
headers.set("Accept", mediaType);
|
||||
headers.set("X-Access-Token", token);
|
||||
return headers;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,263 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 调用 Restful 接口 Util
|
||||
*
|
||||
* @author sunjianlei
|
||||
*/
|
||||
@Slf4j
|
||||
public class RestUtil {
|
||||
|
||||
private static String domain = null;
|
||||
|
||||
public static String getDomain() {
|
||||
if (domain == null) {
|
||||
domain = SpringContextUtils.getDomain();
|
||||
// issues/2959
|
||||
// 微服务版集成企业微信单点登录
|
||||
// 因为微服务版没有端口号,导致 SpringContextUtils.getDomain() 方法获取的域名的端口号变成了:-1所以出问题了,只需要把这个-1给去掉就可以了。
|
||||
if (domain.endsWith(":-1")) {
|
||||
domain = domain.substring(0, domain.length() - 3);
|
||||
}
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
|
||||
public static String path = null;
|
||||
|
||||
public static String getPath() {
|
||||
if (path == null) {
|
||||
path = SpringContextUtils.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path");
|
||||
}
|
||||
return oConvertUtils.getString(path);
|
||||
}
|
||||
|
||||
public static String getBaseUrl() {
|
||||
String basepath = getDomain() + getPath();
|
||||
log.info(" RestUtil.getBaseUrl: " + basepath);
|
||||
return basepath;
|
||||
}
|
||||
|
||||
/**
|
||||
* RestAPI 调用器
|
||||
*/
|
||||
private final static RestTemplate RT;
|
||||
|
||||
static {
|
||||
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
|
||||
requestFactory.setConnectTimeout(3000);
|
||||
requestFactory.setReadTimeout(3000);
|
||||
RT = new RestTemplate(requestFactory);
|
||||
// 解决乱码问题
|
||||
RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static RestTemplate getRestTemplate() {
|
||||
return RT;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 get 请求
|
||||
*/
|
||||
public static JSONObject get(String url) {
|
||||
return getNative(url, null, null).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 get 请求
|
||||
*/
|
||||
public static JSONObject get(String url, JSONObject variables) {
|
||||
return getNative(url, variables, null).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 get 请求
|
||||
*/
|
||||
public static JSONObject get(String url, JSONObject variables, JSONObject params) {
|
||||
return getNative(url, variables, params).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 get 请求,返回原生 ResponseEntity 对象
|
||||
*/
|
||||
public static ResponseEntity<JSONObject> getNative(String url, JSONObject variables, JSONObject params) {
|
||||
return request(url, HttpMethod.GET, variables, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Post 请求
|
||||
*/
|
||||
public static JSONObject post(String url) {
|
||||
return postNative(url, null, null).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Post 请求
|
||||
*/
|
||||
public static JSONObject post(String url, JSONObject params) {
|
||||
return postNative(url, null, params).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 Post 请求
|
||||
*/
|
||||
public static JSONObject post(String url, JSONObject variables, JSONObject params) {
|
||||
return postNative(url, variables, params).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 POST 请求,返回原生 ResponseEntity 对象
|
||||
*/
|
||||
public static ResponseEntity<JSONObject> postNative(String url, JSONObject variables, JSONObject params) {
|
||||
return request(url, HttpMethod.POST, variables, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 put 请求
|
||||
*/
|
||||
public static JSONObject put(String url) {
|
||||
return putNative(url, null, null).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 put 请求
|
||||
*/
|
||||
public static JSONObject put(String url, JSONObject params) {
|
||||
return putNative(url, null, params).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 put 请求
|
||||
*/
|
||||
public static JSONObject put(String url, JSONObject variables, JSONObject params) {
|
||||
return putNative(url, variables, params).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 put 请求,返回原生 ResponseEntity 对象
|
||||
*/
|
||||
public static ResponseEntity<JSONObject> putNative(String url, JSONObject variables, JSONObject params) {
|
||||
return request(url, HttpMethod.PUT, variables, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 delete 请求
|
||||
*/
|
||||
public static JSONObject delete(String url) {
|
||||
return deleteNative(url, null, null).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 delete 请求
|
||||
*/
|
||||
public static JSONObject delete(String url, JSONObject variables, JSONObject params) {
|
||||
return deleteNative(url, variables, params).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 delete 请求,返回原生 ResponseEntity 对象
|
||||
*/
|
||||
public static ResponseEntity<JSONObject> deleteNative(String url, JSONObject variables, JSONObject params) {
|
||||
return request(url, HttpMethod.DELETE, null, variables, params, JSONObject.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
*/
|
||||
public static ResponseEntity<JSONObject> request(String url, HttpMethod method, JSONObject variables, JSONObject params) {
|
||||
return request(url, method, getHeaderApplicationJson(), variables, params, JSONObject.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
*
|
||||
* @param url 请求地址
|
||||
* @param method 请求方式
|
||||
* @param headers 请求头 可空
|
||||
* @param variables 请求url参数 可空
|
||||
* @param params 请求body参数 可空
|
||||
* @param responseType 返回类型
|
||||
* @return ResponseEntity<responseType>
|
||||
*/
|
||||
public static <T> ResponseEntity<T> request(String url, HttpMethod method, HttpHeaders headers, JSONObject variables, Object params, Class<T> responseType) {
|
||||
log.info(" RestUtil --- request --- url = "+ url);
|
||||
if (StringUtils.isEmpty(url)) {
|
||||
throw new RuntimeException("url 不能为空");
|
||||
}
|
||||
if (method == null) {
|
||||
throw new RuntimeException("method 不能为空");
|
||||
}
|
||||
if (headers == null) {
|
||||
headers = new HttpHeaders();
|
||||
}
|
||||
// 请求体
|
||||
String body = "";
|
||||
if (params != null) {
|
||||
if (params instanceof JSONObject) {
|
||||
body = ((JSONObject) params).toJSONString();
|
||||
|
||||
} else {
|
||||
body = params.toString();
|
||||
}
|
||||
}
|
||||
// 拼接 url 参数
|
||||
if (variables != null) {
|
||||
url += ("?" + asUrlVariables(variables));
|
||||
}
|
||||
// 发送请求
|
||||
HttpEntity<String> request = new HttpEntity<>(body, headers);
|
||||
return RT.exchange(url, method, request, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取JSON请求头
|
||||
*/
|
||||
public static HttpHeaders getHeaderApplicationJson() {
|
||||
return getHeader(MediaType.APPLICATION_JSON_UTF8_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求头
|
||||
*/
|
||||
public static HttpHeaders getHeader(String mediaType) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType(mediaType));
|
||||
headers.add("Accept", mediaType);
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 JSONObject 转为 a=1&b=2&c=3...&n=n 的形式
|
||||
*/
|
||||
public static String asUrlVariables(JSONObject variables) {
|
||||
Map<String, Object> source = variables.getInnerMap();
|
||||
Iterator<String> it = source.keySet().iterator();
|
||||
StringBuilder urlVariables = new StringBuilder();
|
||||
while (it.hasNext()) {
|
||||
String key = it.next();
|
||||
String value = "";
|
||||
Object object = source.get(key);
|
||||
if (object != null) {
|
||||
if (!StringUtils.isEmpty(object.toString())) {
|
||||
value = object.toString();
|
||||
}
|
||||
}
|
||||
urlVariables.append("&").append(key).append("=").append(value);
|
||||
}
|
||||
// 去掉第一个&
|
||||
return urlVariables.substring(1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.enfi.common.constant.ServiceNameConstants;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
@Component
|
||||
public class SpringContextUtils implements ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* 上下文对象实例
|
||||
*/
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
SpringContextUtils.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取applicationContext
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取HttpServletRequest
|
||||
*/
|
||||
public static HttpServletRequest getHttpServletRequest() {
|
||||
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
}
|
||||
/**
|
||||
* 获取HttpServletResponse
|
||||
*/
|
||||
public static HttpServletResponse getHttpServletResponse() {
|
||||
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目根路径 basePath
|
||||
*/
|
||||
public static String getDomain(){
|
||||
HttpServletRequest request = getHttpServletRequest();
|
||||
StringBuffer url = request.getRequestURL();
|
||||
//微服务情况下,获取gateway的basePath
|
||||
String basePath = request.getHeader(ServiceNameConstants.X_GATEWAY_BASE_PATH);
|
||||
if(oConvertUtils.isNotEmpty(basePath)){
|
||||
return basePath;
|
||||
}else{
|
||||
return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getOrigin(){
|
||||
HttpServletRequest request = getHttpServletRequest();
|
||||
return request.getHeader("Origin");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过name获取 Bean.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static Object getBean(String name) {
|
||||
return getApplicationContext().getBean(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过class获取Bean.
|
||||
*
|
||||
* @param clazz
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> T getBean(Class<T> clazz) {
|
||||
return getApplicationContext().getBean(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过name,以及Clazz返回指定的Bean
|
||||
*
|
||||
* @param name
|
||||
* @param clazz
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> T getBean(String name, Class<T> clazz) {
|
||||
return getApplicationContext().getBean(name, clazz);
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.enfi.common.exception.EnFiBootException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* sql注入处理工具类
|
||||
*
|
||||
* @author zhoujf
|
||||
*/
|
||||
@Slf4j
|
||||
public class SqlInjectionUtil {
|
||||
/**
|
||||
* sign 用于表字典加签的盐值【SQL漏洞】
|
||||
* (上线修改值 20200501,同步修改前端的盐值)
|
||||
*/
|
||||
private final static String TABLE_DICT_SIGN_SALT = "20200501";
|
||||
private final static String xssStr = "'|and |exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+";
|
||||
|
||||
/*
|
||||
* 针对表字典进行额外的sign签名校验(增加安全机制)
|
||||
* @param dictCode:
|
||||
* @param sign:
|
||||
* @param request:
|
||||
* @Return: void
|
||||
*/
|
||||
public static void checkDictTableSign(String dictCode, String sign, HttpServletRequest request) {
|
||||
//表字典SQL注入漏洞,签名校验
|
||||
String accessToken = request.getHeader("X-Access-Token");
|
||||
String signStr = dictCode + SqlInjectionUtil.TABLE_DICT_SIGN_SALT + accessToken;
|
||||
String javaSign = SecureUtil.md5(signStr);
|
||||
if (!javaSign.equals(sign)) {
|
||||
log.error("表字典,SQL注入漏洞签名校验失败 :" + sign + "!=" + javaSign+ ",dictCode=" + dictCode);
|
||||
throw new EnFiBootException("无权限访问!");
|
||||
}
|
||||
log.info(" 表字典,SQL注入漏洞签名校验成功!sign=" + sign + ",dictCode=" + dictCode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sql注入过滤处理,遇到注入关键字抛异常
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static void filterContent(String value) {
|
||||
if (value == null || "".equals(value)) {
|
||||
return;
|
||||
}
|
||||
// 统一转为小写
|
||||
value = value.toLowerCase();
|
||||
String[] xssArr = xssStr.split("\\|");
|
||||
for (int i = 0; i < xssArr.length; i++) {
|
||||
if (value.indexOf(xssArr[i]) > -1) {
|
||||
log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
|
||||
log.error("请注意,值可能存在SQL注入风险!---> {}", value);
|
||||
throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* sql注入过滤处理,遇到注入关键字抛异常
|
||||
*
|
||||
* @param values
|
||||
* @return
|
||||
*/
|
||||
public static void filterContent(String[] values) {
|
||||
String[] xssArr = xssStr.split("\\|");
|
||||
for (String value : values) {
|
||||
if (value == null || "".equals(value)) {
|
||||
return;
|
||||
}
|
||||
// 统一转为小写
|
||||
value = value.toLowerCase();
|
||||
for (int i = 0; i < xssArr.length; i++) {
|
||||
if (value.indexOf(xssArr[i]) > -1) {
|
||||
log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
|
||||
log.error("请注意,值可能存在SQL注入风险!---> {}", value);
|
||||
throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @特殊方法(不通用) 仅用于字典条件SQL参数,注入过滤
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static void specialFilterContent(String value) {
|
||||
String specialXssStr = " exec | insert | select | delete | update | drop | count | chr | mid | master | truncate | char | declare |;|+|";
|
||||
String[] xssArr = specialXssStr.split("\\|");
|
||||
if (value == null || "".equals(value)) {
|
||||
return;
|
||||
}
|
||||
// 统一转为小写
|
||||
value = value.toLowerCase();
|
||||
for (int i = 0; i < xssArr.length; i++) {
|
||||
if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
|
||||
log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
|
||||
log.error("请注意,值可能存在SQL注入风险!---> {}", value);
|
||||
throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @特殊方法(不通用) 仅用于Online报表SQL解析,注入过滤
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static void specialFilterContentForOnlineReport(String value) {
|
||||
String specialXssStr = " exec | insert | delete | update | drop | chr | mid | master | truncate | char | declare |";
|
||||
String[] xssArr = specialXssStr.split("\\|");
|
||||
if (value == null || "".equals(value)) {
|
||||
return;
|
||||
}
|
||||
// 统一转为小写
|
||||
value = value.toLowerCase();
|
||||
for (int i = 0; i < xssArr.length; i++) {
|
||||
if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
|
||||
log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
|
||||
log.error("请注意,值可能存在SQL注入风险!---> {}", value);
|
||||
throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
/**
|
||||
* 系统公告自定义跳转方式
|
||||
*/
|
||||
public enum SysAnnmentTypeEnum {
|
||||
/**
|
||||
* 邮件跳转组件
|
||||
*/
|
||||
EMAIL("email", "component", "modules/eoa/email/modals/EoaEmailInForm"),
|
||||
/**
|
||||
* 工作流跳转链接我的办公
|
||||
*/
|
||||
BPM("bpm", "url", "/bpm/task/MyTaskList");
|
||||
|
||||
/**
|
||||
* 业务类型(email:邮件 bpm:流程)
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 打开方式 组件:component 路由:url
|
||||
*/
|
||||
private String openType;
|
||||
/**
|
||||
* 组件/路由 地址
|
||||
*/
|
||||
private String openPage;
|
||||
|
||||
SysAnnmentTypeEnum(String type, String openType, String openPage) {
|
||||
this.type = type;
|
||||
this.openType = openType;
|
||||
this.openPage = openPage;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getOpenType() {
|
||||
return openType;
|
||||
}
|
||||
|
||||
public void setOpenType(String openType) {
|
||||
this.openType = openType;
|
||||
}
|
||||
|
||||
public String getOpenPage() {
|
||||
return openPage;
|
||||
}
|
||||
|
||||
public void setOpenPage(String openPage) {
|
||||
this.openPage = openPage;
|
||||
}
|
||||
|
||||
public static SysAnnmentTypeEnum getByType(String type) {
|
||||
if (oConvertUtils.isEmpty(type)) {
|
||||
return null;
|
||||
}
|
||||
for (SysAnnmentTypeEnum val : values()) {
|
||||
if (val.getType().equals(type)) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import org.enfi.common.system.util.JwtUtil;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ThreadUtil {
|
||||
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
public static void setApplicationContext(ApplicationContext applicationContext) {
|
||||
ThreadUtil.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public static ThreadPoolExecutor getTheadPool() {
|
||||
return ThreadUtil.getTheadPool(5);
|
||||
}
|
||||
|
||||
public static HttpServletRequest getRequest() {
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = servletRequestAttributes.getRequest();
|
||||
return request;
|
||||
}
|
||||
|
||||
public static HttpServletResponse getResponse() {
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletResponse response = servletRequestAttributes.getResponse();
|
||||
return response;
|
||||
}
|
||||
|
||||
public static ThreadPoolExecutor getTheadPool(Integer corePoolSize) {
|
||||
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, //核心线程数
|
||||
20, //最大线程数
|
||||
120, TimeUnit.SECONDS, //每个线程最大运行时间 ,和时间单位
|
||||
new LinkedBlockingQueue<Runnable>(20000));//线程存放队列 ,有界队列容量2万
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);//设置子线程共享
|
||||
return threadPoolExecutor;
|
||||
}
|
||||
|
||||
|
||||
public static Boolean waitThreadPoolCompleted(ThreadPoolExecutor threadPoolExecutor) {
|
||||
return ThreadUtil.waitThreadPoolCompleted(threadPoolExecutor, "");
|
||||
}
|
||||
|
||||
public static Boolean waitThreadPoolCompleted(ThreadPoolExecutor threadPoolExecutor, String message) {
|
||||
return ThreadUtil.waitThreadPoolCompleted(threadPoolExecutor, message, () -> {
|
||||
});
|
||||
}
|
||||
|
||||
public static Boolean waitThreadPoolCompleted(ThreadPoolExecutor threadPoolExecutor, String message, ExecuteOperation operation) {
|
||||
threadPoolExecutor.shutdown();
|
||||
try {
|
||||
while (true) {
|
||||
TimeUnit.MILLISECONDS.sleep(1000); //线程睡眠一秒
|
||||
if (threadPoolExecutor.isTerminated()) {
|
||||
System.out.println("===========================================================================");
|
||||
System.out.println(message + " 全部线程执行完毕 ");
|
||||
System.out.println("===========================================================================");
|
||||
operation.execute();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String getUserName() {
|
||||
return JwtUtil.getUserNameByToken(getRequest());
|
||||
}
|
||||
|
||||
public interface ExecuteOperation {
|
||||
void execute();
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.enfi.common.api.CommonAPI;
|
||||
import org.enfi.common.constant.CommonConstant;
|
||||
import org.enfi.common.exception.EnFiBoot401Exception;
|
||||
import org.enfi.common.system.util.JwtUtil;
|
||||
import org.enfi.common.system.vo.LoginUser;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @Author scott
|
||||
* @Date 2019/9/23 14:12
|
||||
* @Description: 编程校验token有效性
|
||||
*/
|
||||
@Slf4j
|
||||
public class TokenUtils {
|
||||
|
||||
/**
|
||||
* 获取 request 里传递的 token
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static String getTokenByRequest(HttpServletRequest request) {
|
||||
String token = request.getParameter("token");
|
||||
if (token == null) {
|
||||
token = request.getHeader("X-Access-Token");
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证Token
|
||||
*/
|
||||
public static boolean verifyToken(HttpServletRequest request, CommonAPI commonAPI, RedisUtil redisUtil) {
|
||||
log.debug(" -- url --" + request.getRequestURL());
|
||||
String token = getTokenByRequest(request);
|
||||
|
||||
if (StringUtils.isBlank(token)) {
|
||||
throw new EnFiBoot401Exception("Token不能为空!");
|
||||
}
|
||||
|
||||
// 解密获得username,用于和数据库进行对比
|
||||
String username = JwtUtil.getUsername(token);
|
||||
if (username == null) {
|
||||
throw new EnFiBoot401Exception("Token非法无效!");
|
||||
}
|
||||
|
||||
// 查询用户信息
|
||||
LoginUser user = commonAPI.getUserByName(username);
|
||||
if (user == null) {
|
||||
throw new EnFiBoot401Exception("用户不存在!");
|
||||
}
|
||||
// 判断用户状态
|
||||
if (user.getStatus() != 1) {
|
||||
throw new EnFiBoot401Exception("账号已锁定,请联系管理员!");
|
||||
}
|
||||
// 校验token是否超时失效 & 或者账号密码是否错误
|
||||
if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
|
||||
throw new EnFiBoot401Exception("Token失效,请重新登录");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证Token
|
||||
*/
|
||||
public static boolean verifyToken(String token, CommonAPI commonAPI, RedisUtil redisUtil) {
|
||||
if (StringUtils.isBlank(token)) {
|
||||
throw new EnFiBoot401Exception("token不能为空!");
|
||||
}
|
||||
|
||||
// 解密获得username,用于和数据库进行对比
|
||||
String username = JwtUtil.getUsername(token);
|
||||
if (username == null) {
|
||||
throw new EnFiBoot401Exception("token非法无效!");
|
||||
}
|
||||
|
||||
// 查询用户信息
|
||||
LoginUser user = commonAPI.getUserByName(username);
|
||||
if (user == null) {
|
||||
throw new EnFiBoot401Exception("用户不存在!");
|
||||
}
|
||||
// 判断用户状态
|
||||
if (user.getStatus() != 1) {
|
||||
throw new EnFiBoot401Exception("账号已被锁定,请联系管理员!");
|
||||
}
|
||||
// 校验token是否超时失效 & 或者账号密码是否错误
|
||||
if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
|
||||
throw new EnFiBoot401Exception(CommonConstant.TOKEN_IS_INVALID_MSG);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token(保证用户在线操作不掉线)
|
||||
* @param token
|
||||
* @param userName
|
||||
* @param passWord
|
||||
* @param redisUtil
|
||||
* @return
|
||||
*/
|
||||
private static boolean jwtTokenRefresh(String token, String userName, String passWord, RedisUtil redisUtil) {
|
||||
String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
|
||||
if (oConvertUtils.isNotEmpty(cacheToken)) {
|
||||
// 校验token有效性
|
||||
if (!JwtUtil.verify(cacheToken, userName, passWord)) {
|
||||
String newAuthorization = JwtUtil.sign(userName, passWord);
|
||||
// 设置Toekn缓存有效时间
|
||||
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization);
|
||||
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);
|
||||
}
|
||||
//update-begin--Author:scott Date:20191005 for:解决每次请求,都重写redis中 token缓存问题
|
||||
// else {
|
||||
// redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, cacheToken);
|
||||
// // 设置超时时间
|
||||
// redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
|
||||
// }
|
||||
//update-end--Author:scott Date:20191005 for:解决每次请求,都重写redis中 token缓存问题
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
*
|
||||
* @Author 张代浩
|
||||
*
|
||||
*/
|
||||
public class UUIDGenerator {
|
||||
|
||||
|
||||
/**
|
||||
* 产生一个32位的UUID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
public static String generate() {
|
||||
return new StringBuilder(32).append(format(getIP())).append(
|
||||
format(getJVM())).append(format(getHiTime())).append(
|
||||
format(getLoTime())).append(format(getCount())).toString();
|
||||
|
||||
}
|
||||
|
||||
private static final int IP;
|
||||
static {
|
||||
int ipadd;
|
||||
try {
|
||||
ipadd = toInt(InetAddress.getLocalHost().getAddress());
|
||||
} catch (Exception e) {
|
||||
ipadd = 0;
|
||||
}
|
||||
IP = ipadd;
|
||||
}
|
||||
|
||||
private static short counter = (short) 0;
|
||||
|
||||
private static final int JVM = (int) (System.currentTimeMillis() >>> 8);
|
||||
|
||||
private final static String format(int intval) {
|
||||
String formatted = Integer.toHexString(intval);
|
||||
StringBuilder buf = new StringBuilder("00000000");
|
||||
buf.replace(8 - formatted.length(), 8, formatted);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private final static String format(short shortval) {
|
||||
String formatted = Integer.toHexString(shortval);
|
||||
StringBuilder buf = new StringBuilder("0000");
|
||||
buf.replace(4 - formatted.length(), 4, formatted);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private final static int getJVM() {
|
||||
return JVM;
|
||||
}
|
||||
|
||||
private final static short getCount() {
|
||||
synchronized (UUIDGenerator.class) {
|
||||
if (counter < 0) {
|
||||
counter = 0;
|
||||
}
|
||||
return counter++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unique in a local network
|
||||
*/
|
||||
private final static int getIP() {
|
||||
return IP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unique down to millisecond
|
||||
*/
|
||||
private final static short getHiTime() {
|
||||
return (short) (System.currentTimeMillis() >>> 32);
|
||||
}
|
||||
|
||||
private final static int getLoTime() {
|
||||
return (int) System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private final static int toInt(byte[] bytes) {
|
||||
int result = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package org.enfi.common.util;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.jfinal.kit.Kv;
|
||||
import com.jfinal.weixin.sdk.api.AccessTokenApi;
|
||||
import com.jfinal.weixin.sdk.utils.HttpUtils;
|
||||
import com.jfinal.weixin.sdk.utils.JsonUtils;
|
||||
import com.jfinal.wxaapp.api.WxaAccessTokenApi;
|
||||
import com.jfinal.wxaapp.api.WxaQrcodeApi;
|
||||
import com.xkcoding.http.support.hutool.HutoolImpl;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @ClassName: WxaQrcodeApiPlus
|
||||
* @Author: wanghao
|
||||
* @date: 2021.11.13 20:59
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class WxaQrcodeApiPlus extends WxaQrcodeApi {
|
||||
private static final String getWxaCodeUnLimitURL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
|
||||
private static final Boolean check_path = false;
|
||||
private static String env_version = "release";
|
||||
|
||||
public static void setEnv(Env env) {
|
||||
env_version = env.getEnv();
|
||||
}
|
||||
|
||||
public static void setCheckPath(Boolean checkPath) {
|
||||
checkPath = checkPath;
|
||||
}
|
||||
|
||||
public static InputStream getUnLimit(String scene, String page) {
|
||||
return getUnLimit(scene, page, 430);
|
||||
}
|
||||
|
||||
public static InputStream getUnLimit(String scene, String page, int width) {
|
||||
return getUnLimit(scene, page, width, true, null);
|
||||
}
|
||||
|
||||
public static InputStream getUnLimit(String scene, String page, int width, String r, String g, String b) {
|
||||
Map<String, String> lineColor = new HashMap();
|
||||
lineColor.put("r", r);
|
||||
lineColor.put("g", g);
|
||||
lineColor.put("b", b);
|
||||
return getUnLimit(scene, page, width, false, lineColor);
|
||||
}
|
||||
|
||||
private static InputStream getUnLimit(String scene, String page, int width, boolean autoColor, Map<String, String> lineColor) {
|
||||
Kv kv = Kv.by("page", page)
|
||||
.set("scene", scene)
|
||||
.set("width", String.valueOf(width))
|
||||
.set("auto_color", autoColor)
|
||||
.set("line_color", lineColor)
|
||||
.set("env_version", env_version)
|
||||
.set("check_path", check_path);
|
||||
AccessTokenApi.removeAccessToken();
|
||||
String url = getWxaCodeUnLimitURL + AccessTokenApi.getAccessToken().getAccessToken();
|
||||
return HttpUtils.download(url, JsonUtils.toJson(kv));
|
||||
}
|
||||
|
||||
public static InputStream getUnLimit(String scene, String page, int width, boolean autoColor, Map<String, String> lineColor, boolean isHyaline) {
|
||||
Kv kv = Kv.by("page", page)
|
||||
.set("scene", scene)
|
||||
.set("width", String.valueOf(width))
|
||||
.set("auto_color", autoColor)
|
||||
.set("line_color", lineColor)
|
||||
.set("is_hyaline", isHyaline)
|
||||
.set("env_version", env_version)
|
||||
.set("check_path", check_path);
|
||||
String url = getWxaCodeUnLimitURL + AccessTokenApi.getAccessToken().getAccessToken();
|
||||
return HttpUtils.download(url, JsonUtils.toJson(kv));
|
||||
}
|
||||
|
||||
public enum Env {
|
||||
develop("develop"),//开发版
|
||||
release("release"),//正式版
|
||||
trial("trial");//体验版
|
||||
// 成员变量
|
||||
private final String env;
|
||||
|
||||
// 构造方法
|
||||
Env(String env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public String getEnv() {
|
||||
return env;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user