提交 deb6d648 authored 作者: wangmenglong's avatar wangmenglong

首次提交

上级 17dfe875
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
def git_url="https://gitlab.365jft.com/root/cm_crm.git"
def credentialsId_val="5a1987eb-5b29-4886-b6d5-fc8d7ba94bbe" //git凭据
def harbor_url="172.30.156.70:8081"
def harbor_pro_name="cm" //harbor上的镜像仓库名
def harbor_auth="29244d80-2457-4753-9912-04bd9233569c" //harbor凭据
def project_version = "${project_version}".split(',') // 替换为要检查的属性名
def checkArray=new String[1]
def versionArray=new String[1]
def proStr = ''
def versionStr = ''
def tag= "latest" //版本
def operate = "${operate}"
def operateType= "service"
//k8s命名空间
def kube_space="odd-cloud"
//nacos命名空间
def nacos_space="cm_crm"
//nacos组
def nacos_group="cm-crm-group"
def part = "${part}"
def gray = "${gray}"
def proArray=["cm-crm"]
echo '------------------------'+operate
if (operate == "release") {
node {
// 删除镜像版本 def response = sh returnStdout: true, script: 'curl -u admin:harbor12345 -X GET "http://192.168.0.247:8081/api/v2.0/projects/cm-crm-web/repositories/cm-crm-web/artifacts?page=1&page_size=1&with_tag=true&with_label=false&with_scan_overview=false&with_signature=false&with_immutable_status=false"'
// echo '-----------'+response
// def response = sh returnStdout: true, script: 'curl -u "admin:harbor12345" -X DELETE "http://192.168.0.247:8081/api/v2.0/projects/cm-crm/repositories/cm-crm-base"'
stage('pull code') {
checkout([$class: 'GitSCM', branches: [[name: '*/master']],
extensions: [], userRemoteConfigs: [[credentialsId: "${credentialsId_val}",
url: "${git_url}"]]])
def n=0
for(int i = 0;i < project_version.size(); i++){
if (i % 2 == 0){
checkArray[n] = project_version[i];
versionArray[n] = project_version[i+1];
n++
}
}
echo 'pull code over--------------------------------------------------------------------------------------------'+"${project_version}"
}
stage('build jar') {
// sh "mvn clean"
// sh "mvn install"
// sh "mvn install" //第一次要执行以下,要不找不到pom文件 这段代码一定不要删
sh "mvn -f cm-crm-lib install"
for(int i = 0; i < checkArray.size(); i++){
if (checkArray[i]=="true"){
def pro = proArray[i]
def ver = versionArray[i]
sh "mvn -f ${pro} package"
proStr = proStr + pro
proStr = proStr + ','
versionStr = versionStr + ver
versionStr = versionStr + ','
}
}
proStr = proStr.substring(0 , proStr.size() -1 )
versionStr = versionStr.substring(0 , versionStr.size() - 1)
echo 'bulid jar over---------------------------------------------------------------------------------------------'
}
stage('build images') {
for(int i = 0; i < checkArray.size(); i++){
if (checkArray[i] == "true") {
def pro = proArray[i]
def version = versionArray[i]
sh "mvn -f ${pro} dockerfile:build"
def image_name="${pro}:${tag}"
sh "docker tag ${image_name} ${harbor_url}/${harbor_pro_name}/${pro}:${version}"
}
}
echo 'bulid images over-------------------------------------------------------------------------------------------------'
}
stage('push images') {
withCredentials([usernamePassword(credentialsId: "${harbor_auth}",
passwordVariable: 'pwd', usernameVariable: 'account')]) {
sh "docker login -u ${account} -p ${pwd} ${harbor_url}"
for(int i = 0;i < checkArray.size(); i++){
if (checkArray[i]=="true"){
def pro = proArray[i]
def version = versionArray[i]
sh "docker push ${harbor_url}/${harbor_pro_name}/${pro}:${version}"
}
}
}
echo 'push images over-------------------------------------------------------------------------------------------------'
}
stage('clean images') {
for(int i = 0;i < checkArray.size(); i++){
if (checkArray[i] == "true"){
def pro = proArray[i]
def version = versionArray[i]
sh "docker rmi ${pro}:${tag}"
sh "docker rmi ${harbor_url}/${harbor_pro_name}/${pro}:${version}"
}
}
echo 'clean images over-----------------------------------------------------------------------------------------------'
}
stage('remote deploy') {
echo 'proStr-----------------------------------------------------------------------------------------------'+"${proStr}"
echo 'versionStr-----------------------------------------------------------------------------------------------'+"${versionStr}"
echo 'operateType-----------------------------------------------------------------------------------------------'+"${operateType}"
sshPublisher(publishers: [sshPublisherDesc(configName: 'jft-m0',
transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/deploy/deploy.sh $proStr $versionStr $operateType $kube_space $harbor_pro_name $gray $part $nacos_space $nacos_group",
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false,
patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')],
usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo 'deploy over--------------------------------------------------------------------------------------------------------'
}
}
}
if (operate == "delete") {
node{
stage('clean harbor'){
def n=0
for(int i = 0;i < project_version.size(); i++){
if (i % 2 == 0){
checkArray[n] = project_version[i];
versionArray[n] = project_version[i+1];
n++
}
}
for(int i = 0; i < checkArray.size(); i++){
if (checkArray[i]=="true"){
def pro = proArray[i]
def ver = versionArray[i]
echo '-------------------------------------------------------------pro===='+pro
def response = sh returnStdout: true, script: 'curl -u "admin:harbor12345" -X DELETE "http://172.30.156.70:8081/api/v2.0/projects/cm-crm/repositories/"'+"${pro}"
proStr = proStr + pro
proStr = proStr + ','
versionStr = versionStr + ver
versionStr = versionStr + ','
}
}
proStr = proStr.substring(0 , proStr.size() -1 )
versionStr = versionStr.substring(0 , versionStr.size() - 1)
echo 'clean kube--------------------------------------------------------------------------------------------------------'
}
stage('clean kube') {
sshPublisher(publishers: [sshPublisherDesc(configName: 'jft-m0',
transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/deploy/delete.sh $proStr $versionStr $operateType $kube_space $harbor_pro_name $gray $part $nacos_space $nacos_group",
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false,
patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')],
usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo 'clean kube--------------------------------------------------------------------------------------------------------'
sleep(40)
}
stage('clean images jft-n0') {
sshPublisher(publishers: [sshPublisherDesc(configName: 'jft-n0',
transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/deploy/images-delete.sh $proStr $versionStr $harbor_pro_name",
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false,
patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')],
usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo 'clean images jft-n0--------------------------------------------------------------------------------------------------------'
}
stage('clean images jft-n1') {
sshPublisher(publishers: [sshPublisherDesc(configName: 'jft-n1',
transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/deploy/images-delete.sh $proStr $versionStr $harbor_pro_name",
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false,
patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')],
usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo 'clean images jft-n1--------------------------------------------------------------------------------------------------------'
}
stage('clean images jft-n2') {
sshPublisher(publishers: [sshPublisherDesc(configName: 'jft-n2',
transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/deploy/images-delete.sh $proStr $versionStr $harbor_pro_name",
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false,
patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')],
usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo 'clean images jft-n2--------------------------------------------------------------------------------------------------------'
}
}
}
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cm.crm</groupId>
<artifactId>cm</artifactId>
<version>1.0</version>
</parent>
<groupId>com.cm.crm</groupId>
<artifactId>cm-crm-lib</artifactId>
<version>1.0</version>
<name>cm-crm-lib</name>
<description>lib</description>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
import java.util.ArrayList;
import java.util.List;
public class TestArrayList {
private static List<Integer> list = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
// for (int i = 0; i < 10; i++) {
testList();
// list.clear();
// }
}
private static void testList() throws InterruptedException {
Runnable runnable = () -> {
for (int i = 0; i < 10000; i++) {
list.add(i);
}
System.out.println(list.size());
};
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
Thread t3 = new Thread(runnable);
t1.start();
t2.start();
t3.start();
t1.join();
System.out.println("==========================1");
t2.join();
System.out.println("==========================2");
t3.join();
}
}
package base.controller;
import javax.servlet.http.HttpServletRequest;
/**
* web层通用数据处理
*
* @author ruoyi
*/
public class BaseController
{
public int pageNum ;
public int pageSize ;
public void PageInit(HttpServletRequest request) {
// 在这里处理请求参数
pageNum = request.getParameter("pageNum") != null ? Integer.parseInt(request.getParameter("pageNum")) : 1;
pageSize = request.getParameter("pageSize") != null ? Integer.parseInt(request.getParameter("pageSize")) : 10;
}
}
package base.result;
import enums.ExceptionCodeEnum;
public class BaseResult {
private Object data;
private boolean isSuccess = false;
private String status = "";
private String message = "";
private String code;
public BaseResult() {
}
public static BaseResult success(String code, Object data) {
BaseResult result = new BaseResult();
result.data = data;
result.code = code;
result.isSuccess = true;
result.status = "success";
return result;
}
public static BaseResult success(String code) {
BaseResult result = new BaseResult();
result.code = code;
result.isSuccess = true;
result.status = "success";
return result;
}
public static BaseResult success(Object data) {
BaseResult result = new BaseResult();
result.data = data;
result.code = "normal_001";
result.isSuccess = true;
result.status = "success";
return result;
}
public static BaseResult success() {
BaseResult result = new BaseResult();
result.code = "normal_001";
result.isSuccess = true;
result.status = "success";
return result;
}
public static BaseResult error(String code) {
BaseResult result = new BaseResult();
result.code = code;
result.isSuccess = false;
result.status = "error";
return result;
}
public static BaseResult error(String code,Object data) {
BaseResult result = new BaseResult();
result.code = code;
result.isSuccess = false;
result.status = "error";
result.data = data;
return result;
}
public static BaseResult error(ExceptionCodeEnum exceptionCodeEnum) {
BaseResult result = new BaseResult();
result.code = exceptionCodeEnum.getCode();
result.message = exceptionCodeEnum.getMessage();
result.isSuccess = false;
result.status = "error";
return result;
}
public Object getData() {
return this.data;
}
public boolean getIsSuccess() {
return this.isSuccess;
}
public String getStatus() {
return this.status;
}
public String getMessage() {
return this.message;
}
public String getCode() {
return this.code;
}
}
\ No newline at end of file
package data.parent;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
@Data
abstract public class IdentityObj {
@TableId("id")
private String id;
@TableField(value = "del")
private Boolean del;
@TableField(value = "base_code")
private String baseCode;
@TableField(value = "create_time")
private String createTime;
@TableField(value = "update_time")
private String updateTime;
@TableField(value = "user_id")
private String userId;
@TableField(value = "user_name")
private String userName;
/**
* @description: 删除时间(如果数据使用过,执行删除操作时更新del=1和删除时间;如果未使用过,直接真删)
* @author: wangmenglong
* @date; 2023/12/8 10:20
**/
@TableField(value = "del_time")
private String delTime;
}
package data.parent;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
@Data
abstract public class NameObj extends IdentityObj {
@TableField("name")
private String name;
}
package data.parent;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
@Data
abstract public class SimpleIdentityObj {
@TableId("id")
private String id;
@TableField(value = "base_code")
private String baseCode;
}
package data.parent;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
/**
* @author wangmenglong
* @description:
* @date 2023/12/28 14:22
*/
@Data
public class SimpleNameObj extends SimpleIdentityObj{
@TableField("name")
private String name;
}
package data.system;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import data.parent.NameObj;
import lombok.Data;
/**
* @author wangmenglong
* @description: 合作伙伴
* @date 2025/5/9 10:50
*/
@Data
@TableName(value = "tb_branch_office")
public class BranchOffice extends NameObj {
/**
* 备注
**/
@TableField("remark")
private String remark;
}
package data.system;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import data.parent.NameObj;
import lombok.Data;
/**
* @author wangmenglong
* @description: 合作伙伴
* @date 2025/5/9 10:50
*/
@Data
@TableName(value = "tb_cooperate")
public class Cooperate extends NameObj {
/**
* 编码
**/
@TableField("code")
private String code;
/**
* 备注
**/
@TableField("remark")
private String remark;
/**
* 区县id
**/
@TableField("county_district_id")
private String countyDistrictId;
/**
* 区县
**/
@TableField("county_district")
private String countyDistrict;
}
package data.system;
import com.baomidou.mybatisplus.annotation.TableName;
import data.parent.SimpleNameObj;
import lombok.Data;
/**
* @author wangmenglong
* @description: 县区
* @date 2025/5/9 10:50
*/
@Data
@TableName(value = "tb_county_district")
public class CountyDistrict extends SimpleNameObj {
}
package data.user;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import data.parent.NameObj;
import lombok.Data;
import mongo.parent.MongoNameObj;
/**
* @author wangmenglong
* @description: 用户
* @date 2023/12/11 10:50
*/
@Data
@TableName(value = "tb_user")
public class User extends NameObj {
/**
* 用户名
**/
@TableField("account")
private String account;
/**
* 密码
**/
@TableField("password")
private String password;
/**
* 状态(normal 正常,disable停用)
**/
@TableField("state")
private String state;
/**
* 用户类型,普通(只能登录前端general),管理(前后端都可以登录admin),
**/
@TableField("type")
private String type;
}
package data.visitRecord;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import data.parent.IdentityObj;
import data.parent.NameObj;
import lombok.Data;
/**
* @author wangmenglong
* @description: 走访记录
* @date 2025/5/9 10:50
*/
@Data
@TableName(value = "tb_visit_record")
public class VisitRecord extends IdentityObj {
/**
* 分公司id
**/
@TableField("branch_office_id")
private String branchOfficeId;
/**
* 分公司
**/
@TableField("branch_office")
private String branchOffice;
/**
* 合作伙伴id
**/
@TableField("cooperate_id")
private String cooperateId;
/**
* 合作伙伴
**/
@TableField("cooperate")
private String cooperate;
/**
* 合作伙伴code
**/
@TableField("cooperate_code")
private String cooperateCode;
/**
* 是否合作过
**/
@TableField("interact")
private Boolean interact;
/**
* 商机名称
**/
@TableField("business_title")
private String businessTitle;
@TableField("money")
private Integer money;
/**
* 建设内容
**/
@TableField("business_content")
private String businessContent;
/**
* 预计签约时间
**/
@TableField("sign_date")
private String signDate;
/**
* 走访照片
**/
@TableField("photo_url")
private String photoUrl;
}
package enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.HashMap;
import java.util.Map;
/**
* 异常码枚举
*/
@AllArgsConstructor
@Getter
public enum ExceptionCodeEnum {
NORMAL_001("normal_001", "保存成功"),
NORMAL_002("normal_002", "提交成功"),
ERROR_001("error_001", "保存失败"),
ERROR_002("error_002", "提交失败")
;
private static final Map<String, ExceptionCodeEnum> CACHE = new HashMap<>(ExceptionCodeEnum.values().length);
static {
for (ExceptionCodeEnum value : ExceptionCodeEnum.values()) {
CACHE.put(value.getCode(), value);
}
}
private final String code;
private final String message;
public static ExceptionCodeEnum getByCode(String code) {
return CACHE.get(code);
}
}
package excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.*;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.poi.ss.usermodel.FillPatternType;
import java.net.URL;
import java.util.Date;
/**
* @author zhangsufang
* @description: 简历导出
* @date 2023/12/22 10:25
*/
@Data
@HeadRowHeight(20)
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 22)
@HeadFontStyle(fontHeightInPoints = 11)
@ContentStyle(wrapped = true)
@ColumnWidth(20)
@TableName(value = "tb_visit_record")
//设置行高,其他导出不需要可以删掉
@ContentRowHeight(100)
public class ExportVisitRecord {
@ExcelProperty("分公司")
@TableField("branch_office")
private String branchOffice;
@ExcelProperty("合作伙伴编号")
@TableField("cooperate_code")
private String cooperateCode;
@ExcelProperty("合作伙伴")
@TableField("cooperate")
private String cooperate;
@ExcelProperty("是否合作过")
private String interact;
@ExcelProperty("商机名称")
private String businessTitle;
@ExcelProperty("金额")
private Integer money;
@ExcelProperty("创建时间")
private String createTime;
@ExcelProperty("建设内容")
private String businessContent;
@ExcelProperty(value = "走访图片")
private URL photoUrl;
@ExcelProperty("预计签约时间")
private String signDate;
}
package mongo.collection;
/**
* 集合名称
*/
public class CollectionName {
/**
* 后台账号
*/
public static final String USER_ACCOUNT = "user";
/**
* 对话框
*/
public static final String DIALOGUE = "dialogue";
/**
* 内容
*/
public static final String CONTENT = "content";
/**
* 系统设置
*/
public static final String SYSTEM_CONFIG = "system_config";
/**
* 热词排行
*/
public static final String PROBLEM_TOP = "problem_top";
/**
* 热词排行
*/
public static final String PROBLEM_YEAR_TOP = "problem_year_top";
/**
* 热词排行
*/
public static final String PROBLEM_MONTH_TOP = "problem_month_top";
}
package mongo.parent;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.context.annotation.Primary;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@Data
@Primary
abstract public class MongoIdentityObj {
private String id;
private Boolean del;
private String baseCode;
//@TableField(value = "createTime")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
private String userId;
private String userName;
/**
* @description: 删除时间(如果数据使用过,执行删除操作时更新del=1和删除时间;如果未使用过,直接真删)
* @author: wangmenglong
* @date; 2023/12/8 10:20
**/
private String delTime;
public MongoIdentityObj(){
this.del = false;
try {
//this.createTime = getMongoDate(new Date());
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 计算得到MongoDB存储的日期,(默认情况下mongo中存储的是标准的时间,中国时间是东八区,存在mongo中少8小时,所以增加8小时)
* http://www.iteye.com/problems/88507
*
* @author: Gao Peng
* @date: 2016年5月4日 上午9:26:23
* @param: @param
* date
* @param: @return
* @return: Date
*/
public static Date getMongoDate(Date date) throws Exception{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Calendar ca = Calendar.getInstance();
ca.setTime(date);
ca.add(Calendar.HOUR_OF_DAY, 8);
return DateUtils.parseDate(sdf.format(ca.getTime()));
}
}
package mongo.parent;
import lombok.Data;
@Data
abstract public class MongoNameObj extends MongoIdentityObj {
private String name;
}
package redis;
public class RedisKey {
/**
* 锁定+userId
*/
public static final String CONTENT_LIMIT = "cm-crm:content:limit:";
/**
* 问题时间+userId
*/
public static final String CONTENT_TIME = "cm-crm:content:time:";
}
package util;
public class AppStartParam {
public static String getMqInstanceId(String[] args) {
String instanceId = "";
if (args.length >= 6) {
String param = args[6];
// String param = "--rocketmq.instance-id=MQ_INST_1776639105090731_BX4zKKfW%";
instanceId = param.substring(param.indexOf("=") + 1, param.length());
}
return instanceId;
}
// public static void main(String[] args) {
// System.setProperty("instanceId",getMqInstanceId());
// System.out.println(System.getProperty("instanceId"));
// }
}
package util;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Author wangmenglong
* @Description 公共工具类
* @Date 2022/3/8 10:04
* @Version 1.0
*/
public class CommonUtils {
/**
* @Author wangmenglong
* @Description 去除字符串中的空格、回车、换行符、制表符
* @Date 2022/3/8 10:22
* @Param [str]
* @return java.lang.String
**/
public static String replaceBlank(String str) {
String dest = "";
if (!StringUtils.isEmpty(str)) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(str);
dest = m.replaceAll("");
}
return dest;
}
/**
* @author: wangmenglong
* @date; 2024/1/9 15:26
* @description: 计算当前时间距离明天凌晨0时0分0秒的秒数
* @param: [currentDate]
* @return: java.lang.Integer
**/
public static Integer getRemainSecondsOneDay(Date currentDate) {
//使用plusDays加传入的时间加1天,将时分秒设置成0
LocalDateTime midnight = LocalDateTime.ofInstant(currentDate.toInstant(),
ZoneId.systemDefault()).plusDays(1).withHour(0).withMinute(0)
.withSecond(0).withNano(0);
LocalDateTime currentDateTime = LocalDateTime.ofInstant(currentDate.toInstant(),
ZoneId.systemDefault());
//使用ChronoUnit.SECONDS.between方法,传入两个LocalDateTime对象即可得到相差的秒数
long seconds = ChronoUnit.SECONDS.between(currentDateTime, midnight);
return (int) seconds;
}
/**
* @author: wangmenglong
* @date; 2024/3/8 14:42
* @description: 获取两个日期之间所有的日期yyyy-MM-dd
* @param: [startDate, endDate]
* @return: java.util.List<java.lang.String>
**/
public static List<String> getDateRange(String startDate, String endDate) {
List<String> dateRange = new ArrayList<>();
LocalDate startLocalDate = LocalDate.parse(startDate);
LocalDate endLocalDate = LocalDate.parse(endDate);
long daysBetween = ChronoUnit.DAYS.between(startLocalDate, endLocalDate);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
for (int i = 0; i <= daysBetween; i++) {
LocalDate currentDate = startLocalDate.plusDays(i);
String localDateNowStr = currentDate.format(formatter);
dateRange.add(localDateNowStr);
}
return dateRange;
}
/**
* @author: wangmenglong
* @date; 2024/3/8 14:42
* @description: 获取两个日期之间所有的月份yyyy-MM
* @param: [startDate, endDate]
* @return: java.util.List<java.lang.String>
**/
public static List<String> getMonthDateRange(String startDate, String endDate) {
List<String> dateRange = new ArrayList<>();
LocalDate startLocalDate = LocalDate.parse(startDate);
LocalDate endLocalDate = LocalDate.parse(endDate);
long monthsBetween = ChronoUnit.MONTHS.between(startLocalDate, endLocalDate);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
for (int i = 0; i <= monthsBetween; i++) {
LocalDate date = startLocalDate.plusMonths(i);
String localDateNowStr = date.format(formatter);
dateRange.add(localDateNowStr);
}
return dateRange;
}
/**
* @author: wangmenglong
* @date; 2024/5/15 18:13
* @description: 比较金额是否在区间范围内
* @param: [value, lower, upper]
* @return: boolean
**/
public static boolean isInRange(BigDecimal value, BigDecimal lower, BigDecimal upper) {
int lowerCompare = value.compareTo(lower);
int upperCompare = value.compareTo(upper);
return lowerCompare >= 0 && upperCompare <= 0;
}
}
package util;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* 常用配置
*/
public class ConfigCache {
/**
* 数值及状态名
*/
private static Map<Integer, String> valStateMap;
/**
* 状态名及数值
*/
private static Map<String, Integer> stateValMap;
private static ConfigCache instance;
private ConfigCache() {
valStateMap = new HashMap<>();
/**
* 招聘状态取值
* 报备report 1,状态:上车:bycar 2,到达:arrived 3,面试:interview 4,面试通过:interviewpass 5,入职:entry 6
*/
valStateMap.put(2, "bycar");
valStateMap.put(3, "arrived");
valStateMap.put(4, "interview");
valStateMap.put(5, "interviewpass");
valStateMap.put(6, "entry");
stateValMap = new HashMap<>();
stateValMap.put("bycar", 2);
stateValMap.put("arrived", 3);
stateValMap.put("interview", 4);
}
public static ConfigCache getInstance() {
if (instance == null) {
instance = new ConfigCache();
}
return instance;
}
public Map<Integer, String> getValStateMap() {
return valStateMap;
}
public Map<String, Integer> getstateValMap() {
return stateValMap;
}
}
package util;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
/**
* @author yuetianwang
* @description 加密工具类
* @date 2021/8/4 18:38
*/
public class CryptoUtil {
public static final String SALT = "K2mQCycm";
/**
* 加盐签名
*
* @param map 签名的数据
* @return
*/
public static String SHA256(String slat, TreeMap<String, Object> map) {
StringBuilder sb = new StringBuilder();
map.forEach((k, v) -> {
sb.append(k).append("=").append("v");
sb.append("&");
});
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
sb.append(slat);
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(sb.toString().getBytes(StandardCharsets.UTF_8));
byte[] digest = messageDigest.digest();
return byte2Hex(digest);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* 校验加盐签名
*
* @param map 签名的数据
* @param sign 比对的签名
* @return
*/
public static boolean SHA256Validate(String slat, TreeMap<String, Object> map, String sign) {
String otherSign = SHA256(slat, map);
return Objects.equals(sign, otherSign);
}
/**
* 将byte转为16进制
*
* @param bytes
* @return
*/
private static String byte2Hex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
String temp = null;
for (int i = 0; i < bytes.length; i++) {
temp = Integer.toHexString(bytes[i] & 0xFF);
if (temp.length() == 1) {
//1得到一位的进行补0操作
sb.append("0");
}
sb.append(temp);
}
return sb.toString();
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
package util;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
/**
* @Author wangmenglong
* @Description MD5加密
* @Date 2021/9/15 14:32
* @Version 1.0
*/
public class MD5Utils {
private static final String SALT = "junying";
/**
* 字符换MD5
* @param password
* @return
*/
public static String strToMd5(String password) {
if(StringUtils.isEmpty(password)){
return password;
}
password = SALT + password + SALT;
String md5Prd = DigestUtils.md5DigestAsHex(password.getBytes());
return md5Prd;
}
}
package util;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
/**
* @Author zhangziyuan
* @Description
* @Date 2021/6/17
**/
public class MultipartFileToFile {
/**
* MultipartFile 转 File
*
* @param file
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile file) throws Exception {
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
file = null;
} else {
// InputStream ins = null;
// ins = file.getInputStream();
String originalFilename = file.getOriginalFilename();
String[] filename = originalFilename.split("\\.");
toFile=File.createTempFile(filename[0] + UUID.randomUUID(), filename[1]);
file.transferTo(toFile);
//inputStreamToFile(ins, toFile);
// ins.close();
}
return toFile;
}
//获取流文件
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除本地临时文件
*
* @param file
*/
public static void delteTempFile(File file) {
if (file != null) {
// File del = new File(file.toURI());
// del.delete();
file.delete();
}
}
}
package util;
import java.util.Collections;
import java.util.List;
/**
* 分页类
*/
public class Paging {
/**
* 当前页码
*/
private int page;
/**
* 页码总数
*/
//private int total;
/**
* 数据行总数
*/
private int total;
/**
* 数据
*/
private List list;
private String code;
private Paging() {
}
public Paging(int count, List data) {
// this.page = page;
this.total = count;
this.list = data;
this.code = "0";
}
public static Paging error(String code) {
Paging paging = new Paging();
paging.setTotal(0);
paging.setList(Collections.emptyList());
paging.setCode(code);
return paging;
}
/**
* 当前页码
*
* @return the page
*/
public int getPage() {
return page;
}
/**
* 当前页码
*
* @param page the page to set
*/
public void setPage(int page) {
this.page = page;
}
/**
* 数据行总数
*
* @return the count
*/
public int getTotal() {
return total;
}
/**
* 数据行总数
*
* @param total the count to set
*/
public void setTotal(int total) {
this.total = total;
}
/**
* 数据
*
* @return the data
*/
public List getList() {
return list;
}
/**
* 数据
*
* @param list the data to set
*/
public void setList(List list) {
this.list = list;
}
/**
* @return the code
*/
public String getCode() {
return code;
}
/**
* @param code the code to set
*/
public void setCode(String code) {
this.code = code;
}
}
package util;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.springframework.core.io.ClassPathResource;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* @author wangmenglong
* @description: RSA加解密
* @date 2024/3/11 17:01
*/
public class RSAUtil {
private static final String ALGORITHM = "RSA";
public static void main(String [] args) throws Exception {
// KeyPair keyPair = generateRsaKey(2048);
// genPublicFile(keyPair);
String encryptData = encrypt("下班",getPublicKey());
System.out.println("加密后结果为:"+ encryptData );
//
String decryptData = decrypt(encryptData,getPrivateKey());
System.out.println("解密后结果为:"+ decryptData);
}
/**
* RSA私钥解密
* @param str 解密字符串
* @param privateKey 私钥
* @return 明文
*/
public static String decrypt(String str, String privateKey) {
//64位解码加密后的字符串
byte[] inputByte;
String outStr = "";
try {
inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
java.security.Security.addProvider(
new org.bouncycastle.jce.provider.BouncyCastleProvider()
);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, priKey);
outStr = new String(cipher.doFinal(inputByte));
} catch (UnsupportedEncodingException | NoSuchPaddingException | InvalidKeyException |
IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException |
NoSuchAlgorithmException e) {
e.printStackTrace();
}
return outStr;
}
/**
* RSA公钥加密
* @param str 需要加密的字符串
* @param publicKey 公钥
* @return 密文
* @throws Exception 加密过程中的异常信息
*/
public static String encrypt(String str, String publicKey) throws Exception {
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(decoded));
//RSA加密
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
return outStr;
}
public static String getPrivateKey() throws IOException {
ClassPathResource classPathResource = new ClassPathResource("private_key.jks");
InputStream inputStream =classPathResource.getInputStream();
byte[] privateKeyByte = new byte[inputStream.available()];
inputStream.read(privateKeyByte);
String privateKeyAll = new String(privateKeyByte);
String privateKey = privateKeyAll.replace("-----BEGIN RSA PRIVATE KEY-----","").replace("-----END RSA PRIVATE KEY-----","");
// System.out.println("私钥为:"+privateKey);
return privateKey;
}
public static String getPublicKey() throws IOException {
ClassPathResource classPathResource = new ClassPathResource("public_key.jks");
InputStream inputStream =classPathResource.getInputStream();
byte[] publicKeyByte = new byte[inputStream.available()];
inputStream.read(publicKeyByte);
String publicKeyAll = new String(publicKeyByte);
String publicKey = publicKeyAll.replace("-----BEGIN PUBLIC KEY-----","").replace("-----END PUBLIC KEY-----","");
// System.out.println("公钥为:"+publicKey);
return publicKey;
}
/**
* 生成RSA 公私钥,可选长度为1025,2048位.
*/
public static KeyPair generateRsaKey(int keySize) {
Map<String,String> result = new HashMap<>(2);
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
// 初始化密钥对生成器,密钥大小为1024 2048位
keyPairGen.initialize(keySize, new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
return keyPair;
// 得到公钥字符串
// result.put("publicKey", new String(Base64.encodeBase64(keyPair.getPublic().getEncoded())));
// // 得到私钥字符串
// result.put("privateKey", new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded())));
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
return null;
}
/**
* 生成公钥文件
* @param keyPair 密钥对
* @return 公钥/私钥文件
*/
public static File genPublicFile(KeyPair keyPair) {
try (StringWriter sw = new StringWriter()) {
// 得到公钥
PublicKey publicKey = keyPair.getPublic();
// 得到私钥
PrivateKey privateKey = keyPair.getPrivate();
// 获取PublicKey并将其转换为PEM格式的字符串
try (JcaPEMWriter pemWriter = new JcaPEMWriter(sw)) {
pemWriter.writeObject(publicKey);
pemWriter.writeObject(privateKey);
} catch (IOException e) {
throw new RuntimeException(e);
}
File file = new File("E:\\rsa.jks");
try (FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
BufferedWriter bw = new BufferedWriter(fw)
) {
bw.write(sw.toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
return file;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package util.excel;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ExcelXlsxReader extends DefaultHandler {
/**
* 单元格中的数据可能的数据类型
*/
enum CellDataType {
BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL
}
/**
* 共享字符串表
*/
private SharedStringsTable sst;
/**
* 上一次的索引值
*/
private String lastIndex;
/**
* 文件的绝对路径
*/
private String filePath = "";
/**
* 工作表索引
*/
private int sheetIndex = 0;
/**
* sheet名
*/
private String sheetName = "";
/**
* 总行数
*/
private int totalRows = 0;
/**
* 一行内cell集合
*/
private List<String> cellList = new ArrayList<String>();
/**
* 判断整行是否为空行的标记
*/
private boolean flag = false;
/**
* 当前行
*/
private int curRow = 1;
/**
* 当前列
*/
private int curCol = 0;
/**
* T元素标识
*/
private boolean isTElement;
/**
* 判断是否有V值
*/
private boolean isSroRow;
private String systag="";
/**
* 判断上一单元格是否为文本空单元格
*/
private boolean startElementFlag = true;
private boolean endElementFlag = false;
private boolean charactersFlag = false;
/**
* 异常信息,如果为空则表示没有异常
*/
private String exceptionMessage;
/**
* 单元格数据类型,默认为字符串类型
*/
private CellDataType nextDataType = CellDataType.SSTINDEX;
private final DataFormatter formatter = new DataFormatter();
/**
* 单元格日期格式的索引
*/
private short formatIndex;
/**
* 日期格式字符串
*/
private String formatString;
//定义前一个元素和当前元素的位置,用来计算其中空的单元格数量,如A6和A8等
private String prePreRef = "A", preRef = null, ref = null;
//定义该文档一行最大的单元格数,用来补全一行最后可能缺失的单元格
private String maxRef = null;
/**
* 单元格
*/
private StylesTable stylesTable;
//解析结果保存
private List<List<String>> container = new ArrayList<>();
public ExcelXlsxReader(){ }
public ExcelXlsxReader(StylesTable stylesTable, SharedStringsTable sst, List<List<String>> container ){
this.stylesTable = stylesTable;
this.sst = sst;
this.container = container;
}
/**
* 遍历工作簿中所有的电子表格
* 并缓存在mySheetList中
*
* @param filename
* @throws Exception
*/
public Map<String, List> process(String filename) throws Exception {
Map<String, List> map = new HashMap<>();
filePath = filename;
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader xssfReader = new XSSFReader(pkg);
stylesTable = xssfReader.getStylesTable();
SharedStringsTable sst = xssfReader.getSharedStringsTable();
XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
this.sst = sst;
parser.setContentHandler(this);
XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
while (sheets.hasNext()) { //遍历sheet
curRow = 1; //标记初始行为第一行
sheetIndex++;
InputStream sheet = sheets.next(); //sheets.next()和sheets.getSheetName()不能换位置,否则sheetName报错
//InputStream sheet = xssfReader.getSheet("rId1");
//sheetName = sheets.getSheetName();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource); //解析excel的每条记录,在这个过程中startElement()、characters()、endElement()这三个函数会依次执行
map.put(String.valueOf(sheetIndex), container);
container = new ArrayList<>();
sheet.close();
}
return map; //返回该excel文件的总行数,不包括首列和空行
}
public Map<String, List<List<String>>> process(File file) throws Exception {
Map<String, List<List<String>>> map = new HashMap<>();
OPCPackage pkg = OPCPackage.open(file);
XSSFReader xssfReader = new XSSFReader(pkg);
stylesTable = xssfReader.getStylesTable();
SharedStringsTable sst = xssfReader.getSharedStringsTable();
XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
this.sst = sst;
parser.setContentHandler(this);
XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
while (sheets.hasNext()) { //遍历sheet
curRow = 1; //标记初始行为第一行
sheetIndex++;
InputStream sheet = sheets.next(); //sheets.next()和sheets.getSheetName()不能换位置,否则sheetName报错
//InputStream sheet = xssfReader.getSheet("rId1");
//sheetName = sheets.getSheetName();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource); //解析excel的每条记录,在这个过程中startElement()、characters()、endElement()这三个函数会依次执行
map.put(String.valueOf(sheetIndex), container);
container = new ArrayList<>();
sheet.close();
}
return map; //返回该excel文件的总行数,不包括首列和空行
}
/**
* 第一个执行
*
* @param uri
* @param localName
* @param name
* @param attributes
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
//c => 单元格
// if(systag.equals("")){
// systag=name;
// }
if ("c".equals(name)) {
//前一个单元格的位置
if (preRef == null) {
preRef = attributes.getValue("r");
} else {
//中部文本空单元格标识 ‘endElementFlag’ 判断前一次是否为文本空字符串,true则表明不是文本空字符串,false表明是文本空字符串跳过把空字符串的位置赋予preRef
if (endElementFlag) {
preRef = ref;
}
}
//当前单元格的位置
ref = attributes.getValue("r");
//首部文本空单元格标识 ‘startElementFlag’ 判断前一次,即首部是否为文本空字符串,true则表明不是文本空字符串,false表明是文本空字符串, 且已知当前格,即第二格带“B”标志,则ref赋予preRef
if (!startElementFlag && !flag) { //上一个单元格为文本空单元格,执行下面的,使ref=preRef;flag为true表明该单元格之前有数据值,即该单元格不是首部空单元格,则跳过
// 这里只有上一个单元格为文本空单元格,且之前的几个单元格都没有值才会执行
preRef = ref;
}
//设定单元格类型
this.setNextDataType(attributes);
endElementFlag = false;
charactersFlag = false;
startElementFlag = false;
// if(name.equals(systag)){ //当前节点和上一个节点相同
// isSroRow=true;
// }
}
//当元素为t时
if ("t".equals(name)) {
isTElement = true;
} else {
isTElement = false;
}
//置空
lastIndex = "";
// systag=name;
}
/**
* 第二个执行
* 得到单元格对应的索引值或是内容值
* 如果单元格类型是字符串、INLINESTR、数字、日期,lastIndex则是索引值
* 如果单元格类型是布尔值、错误、公式,lastIndex则是内容值
*
* @param ch
* @param start
* @param length
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
startElementFlag = true;
charactersFlag = true;
lastIndex += new String(ch, start, length);
}
/**
* 第三个执行
*
* @param uri
* @param localName
* @param name
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
//t元素也包含字符串
// if(isSroRow){
// cellList.add(curCol, "");
// curCol++;
// endElementFlag = true;
// isSroRow=false;
// }
if (isTElement) {//这个程序没经过
//将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
String value = lastIndex.trim();
cellList.add(curCol, value);
endElementFlag = true;
curCol++;
isTElement = false;
//如果里面某个单元格含有值,则标识该行不为空行
if (value != null && !"".equals(value)) {
flag = true;
}
}
if ("v".equals(name)) {
//v => 单元格的值,如果单元格是字符串,则v标签的值为该字符串在SST中的索引
String value = this.getDataValue(lastIndex.trim(), "");//根据索引值获取对应的单元格值
int len = -1;
//补全单元格之间的空单元格
if (!ref.equals(preRef)) {
len = countNullCell(ref, preRef);
for (int i = 0; i < len; i++) {
cellList.add(curCol, "");
curCol++;
}
} else if (ref.equals(preRef) && !ref.startsWith("A")) { //ref等于preRef,且以B或者C...开头,表明首部为空格271 int len = countNullCell(ref, "A");
for (int i = 0; i <= len; i++) {
cellList.add(curCol, "");
curCol++;
}
}
cellList.add(curCol, value);
curCol++;
endElementFlag = true;
//如果里面某个单元格含有值,则标识该行不为空行
if (value != null && !"".equals(value)) {
flag = true;
}
} else {
//如果标签名称为row,这说明已到行尾,调用optRows()方法
if ("row".equals(name)) {
//默认第一行为表头,以该行单元格数目为最大数目
if (curRow == 1) {
maxRef = ref;
}
//补全一行尾部可能缺失的单元格
if (maxRef != null) {
int len = -1;
//前一单元格,true则不是文本空字符串,false则是文本空字符串
if (charactersFlag) {
if(ref!=null){
len = countNullCell(maxRef, ref);
}
} else {
if(preRef!=null) {
len = countNullCell(maxRef, preRef);
}
}
// if (charactersFlag) {
// len = countNullCell(maxRef, ref);
// } else {
// len = countNullCell(maxRef, preRef);
// }
for (int i = 0; i <= len; i++) {
cellList.add(curCol, "");
curCol++;
}
}
if (flag && curRow != 1) { //该行不为空行且该行不是第一行,则发送(第一行为列名,不需要)
// ReadExcel.sendRows(filePath, sheetName, sheetIndex, curRow, cellList);
totalRows++;
}
if(cellList.size()!=0){
if(flag){
container.add(cellList);
curRow++;
}
}
// cellList.clear();
cellList = new ArrayList<String>();
curRow++;
curCol = 0;
preRef = null;
prePreRef = null;
ref = null;
flag = false;
}
}
}
/**
* 处理数据类型
*
* @param attributes
*/
public void setNextDataType(Attributes attributes) {
nextDataType = CellDataType.NUMBER; //cellType为空,则表示该单元格类型为数字
formatIndex = -1;
formatString = null;
String cellType = attributes.getValue("t"); //单元格类型
String cellStyleStr = attributes.getValue("s"); //
String columnData = attributes.getValue("r"); //获取单元格的位置,如A1,B1
if ("b".equals(cellType)) { //处理布尔值
nextDataType = CellDataType.BOOL;
} else if ("e".equals(cellType)) { //处理错误
nextDataType = CellDataType.ERROR;
} else if ("inlineStr".equals(cellType)) {
nextDataType = CellDataType.INLINESTR;
} else if ("s".equals(cellType)) { //处理字符串
nextDataType = CellDataType.SSTINDEX;
} else if ("str".equals(cellType)) {
nextDataType = CellDataType.FORMULA;
}
if (cellStyleStr != null) { //处理日期
int styleIndex = Integer.parseInt(cellStyleStr);
XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
formatIndex = style.getDataFormat();
formatString = style.getDataFormatString();
if (formatString == null) {
nextDataType = CellDataType.NULL;
formatString = BuiltinFormats.getBuiltinFormat(formatIndex);
}else{
if (formatString.contains("m/d/yyyy") || formatString.contains("yyyy/mm/dd") || formatString.contains("yyyy/m/d")) {
nextDataType = CellDataType.DATE;
formatString = "yyyy-MM-dd";
}
}
}
}
/**
* 对解析出来的数据进行类型处理
*
* @param value 单元格的值,
* value代表解析:BOOL的为0或1, ERROR的为内容值,FORMULA的为内容值,INLINESTR的为索引值需转换为内容值,
* SSTINDEX的为索引值需转换为内容值, NUMBER为内容值,DATE为内容值
* @param thisStr 一个空字符串
* @return
*/
@SuppressWarnings("deprecation")
public String getDataValue(String value, String thisStr) {
switch (nextDataType) {
// 这几个的顺序不能随便交换,交换了很可能会导致数据错误
case BOOL: //布尔值
char first = value.charAt(0);
thisStr = first == '0' ? "FALSE" : "TRUE";
break;
case ERROR: //错误
thisStr = "\"ERROR:" + value.toString() + '"';
break;
case FORMULA: //公式
thisStr = '"' + value.toString() + '"';
break;
case INLINESTR:
XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());
thisStr = rtsi.toString();
rtsi = null;
break;
case SSTINDEX: //字符串
String sstIndex = value.toString();
try {
int idx = Integer.parseInt(sstIndex);
XSSFRichTextString rtss = new XSSFRichTextString(sst.getEntryAt(idx));//根据idx索引值获取内容值
thisStr = rtss.toString();
// System.out.println(thisStr);
//有些字符串是文本格式的,但内容却是日期
rtss = null;
} catch (NumberFormatException ex) {
thisStr = value.toString();
}
break;
case NUMBER: //数字
if (formatString != null) {
thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString).trim();
} else {
thisStr = value;
}
thisStr = thisStr.replace("_", "").trim();
break;
case DATE: //日期
thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString);
// 对日期字符串作特殊处理,去掉T
thisStr = thisStr.replace("T", " ");
break;
default:
thisStr = " ";
break;
}
return thisStr;
}
public int countNullCell(String ref, String preRef) {
//excel2007最大行数是1048576,最大列数是16384,最后一列列名是XFD
String xfd = ref.replaceAll("\\d+", "");
String xfd_1 = preRef.replaceAll("\\d+", "");
xfd = fillChar(xfd, 3, '@', true);
xfd_1 = fillChar(xfd_1, 3, '@', true);
char[] letter = xfd.toCharArray();
char[] letter_1 = xfd_1.toCharArray();
int res = (letter[0] - letter_1[0]) * 26 * 26 + (letter[1] - letter_1[1]) * 26 + (letter[2] - letter_1[2]);
return res - 1;
}
public String fillChar(String str, int len, char let, boolean isPre) {
int len_1 = str.length();
if (len_1 < len) {
if (isPre) {
for (int i = 0; i < (len - len_1); i++) {
str = let + str;
}
} else {
for (int i = 0; i < (len - len_1); i++) {
str = str + let;
}
}
}
return str;
}
/**
* @return the exceptionMessage
*/
public String getExceptionMessage() {
return exceptionMessage;
}
}
package util.excel;
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.util.CellReference;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 读取excel
*/
public interface ReadExcel {
/**
* 返回结果成功或失败
*/
public JSONObject execute();
/**
* 获取excel列名
*/
default String getColumnName(int columnIndex) {
return CellReference.convertNumToColString(columnIndex);
}
/**
* 获取excel单元格信息
* CellTypeEnum 类型值
* NUMERIC 数值型0
* STRING  字符串型1
* FORMULA 公式型 2
* BLANK   空值 3
* BOOLEAN  布尔型4
* ERROR   错误5
*/
default String[] getCellForm(Cell cell) {
if (cell == null) {
return null;
}
String[] form = new String[4];
String columnName = "";
String type = "";
String val = "";
String formula = "";
switch (cell.getCellTypeEnum()) {
case NUMERIC:
columnName = getColumnName(cell.getColumnIndex());
type = "NUMERIC";
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date d = cell.getDateCellValue();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
val = format.format(d);
} else {
val = String.valueOf(cell.getNumericCellValue());
}
break;
case STRING:
columnName = getColumnName(cell.getColumnIndex());
type = "STRING";
val = cell.getStringCellValue();
break;
case FORMULA:
columnName = getColumnName(cell.getColumnIndex());
type = "FORMULA";
val = String.valueOf(cell.getNumericCellValue());
formula = cell.getCellFormula();
break;
case BLANK:
columnName = getColumnName(cell.getColumnIndex());
type = "BLANK";
val = "";
break;
case BOOLEAN:
columnName = getColumnName(cell.getColumnIndex());
type = "BOOLEAN";
val = cell.getStringCellValue();
break;
case ERROR:
columnName = getColumnName(cell.getColumnIndex());
type = "ERROR";
val = "";
break;
default:
break;
}
form[0] = columnName;
form[1] = type;
form[2] = val;
form[3] = formula;
return form;
}
/**
* 获取excel单元格的值
* CellTypeEnum 类型值
* NUMERIC 数值型0
* STRING  字符串型1
* FORMULA 公式型 2
* BLANK   空值 3
* BOOLEAN  布尔型4
* ERROR   错误5
*/
default String getCellVal(Cell cell, FormulaEvaluator formulaEvaluator) {
if (cell == null) {
return null;
}
String val = "";
switch (cell.getCellTypeEnum()) {
case NUMERIC:
val = String.valueOf(cell.getNumericCellValue());
break;
case STRING:
val = cell.getStringCellValue();
break;
case FORMULA:
val = String.valueOf(formulaEvaluator.evaluate(cell).getNumberValue());
break;
case BLANK:
val = "";
break;
case BOOLEAN:
val = cell.getStringCellValue();
break;
case ERROR:
val = "";
break;
default:
break;
}
return val;
}
default String getCellVal(Cell cell) {
if (cell == null) {
return null;
}
String val = "";
switch (cell.getCellTypeEnum()) {
case NUMERIC:
val = String.valueOf(cell.getNumericCellValue());
break;
case STRING:
val = cell.getStringCellValue();
break;
case FORMULA:
val = String.valueOf(cell.getNumericCellValue());
break;
case BLANK:
val = "";
break;
case BOOLEAN:
val = cell.getStringCellValue();
break;
case ERROR:
val = "";
break;
default:
break;
}
return val;
}
}
package util.qrCode;
import java.awt.*;
class LogoConfig {
// logo默认边框颜色
public static final Color DEFAULT_BORDERCOLOR = Color.WHITE;
// logo默认边框宽度
public static final int DEFAULT_BORDER = 2;
// logo大小默认为照片的1/5
public static final int DEFAULT_LOGOPART = 5;
private final int border = DEFAULT_BORDER;
private final Color borderColor;
private final int logoPart;
public LogoConfig() {
this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
}
public LogoConfig(Color borderColor, int logoPart) {
this.borderColor = borderColor;
this.logoPart = logoPart;
}
public Color getBorderColor() {
return borderColor;
}
public int getBorder() {
return border;
}
public int getLogoPart() {
return logoPart;
}
}
package util.qrCode;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: (二维码) *
* @author:wangmenglong *
* @date:2015-10-29 下午05:27:13
*/
public class ZXingCode {
private static final int QRCOLOR = 0xFF000000; //默认是黑色
private static final int BGWHITE = 0xFFFFFFFF; //背景颜色
public static void main(String[] args) throws WriterException {
try {
String base64 = "data:image/jpeg;base64,"+getLogoQRCode("{\"pro_id\":\"1\",\"action\":\"interview\",\"base_code\":\"001\"}", null, "测试项目(接站二维码)");
System.out.println(base64);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 生成带logo的二维码图片 * *
*/
public static String getLogoQRCode(String qrUrl, HttpServletRequest request, String productName) {
// String filePath = request.getSession().getServletContext().getRealPath("/") + "resources/images/logoImages/llhlogo.png";
//filePath是二维码logo的路径,但是实际中我们是放在项目的某个路径下面的,所以路径用上面的,把下面的注释就好
//String filePath = "C:/Users/Administrator/Desktop/logo.png";
//去掉data:image/png;base64,因为下面base64ToBufferedImage方法从base64转换成BufferedImage的时候这个会报错不识别
//String base64Url="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAABSCAYAAADHLIObAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyVpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ4IDc5LjE2NDAzNiwgMjAxOS8wOC8xMy0wMTowNjo1NyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEYwQ0U5QjlGN0Q2MTFFQkJCRTNFQTFFRjA5OTI1NzkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEYwQ0U5QkFGN0Q2MTFFQkJCRTNFQTFFRjA5OTI1NzkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4RjBDRTlCN0Y3RDYxMUVCQkJFM0VBMUVGMDk5MjU3OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4RjBDRTlCOEY3RDYxMUVCQkJFM0VBMUVGMDk5MjU3OSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pk1EutgAABU+SURBVHja7F0JeJTltT6zZZLMZN8TAkgQkU24rFJQVNSCYsuqqGipIlSlKs9jea7Kpba9InCfWmuLVuqGClVAlMVWoQiCZRNZRUC2hJCELGSbLLPf856ZP8yamWxgJB/PT5LJzD/f/37nvOc953z/ROV0OinAiODj5+7jej4y3Y9dicPERz4f+/hYw8cnfFh8n6QKAOR4Phbx0Z06RqBxgo+5fHzk+aDa43sNHwvdT+gAMfgANqvdWGmUB7UeT3iBj9904BT2ULCa6+nak/hY2YFNs8ZkPlYBSASRk3x06sCkWeMcH93UbkQ7QGz+yOJjitotcdr9sNqc9NYnJVRSbrscb/9zADm4vYMIml/wRgG9sqKYKqrtl2MKgwBkensHsrbeQVv2mEijUZHd7rgcU8gAkPr2DuSqTRfIwWY5/qYE6tYp8nJMIULb3kH87nQ9vbu+jCaNTqBZU1JJy1Z5OYa6vbv0H5cVkiFSTfffmRwURJvdSVU1dvpybzU9+5d8KiixtPpc2rVF/uNfF+goW+TjU1MpPkYTEMCaOgd9/p9KenttKVmtHJUY64eOnKH5s7Louh5RFKlXk6oVjBiC3NkeQTxyso5+vTCX4mO1tHxBDkXoLqJhdzjpfJmV/r2rit5ZV0YO/jkyQu0V5evMDrp1WCzNeSCdovTqK9MiTbV2Wvh2EZktTnry3jQvEE+fM9Pm3dX0wb/KyMLaEiCptN4mBwuMZjr4fEcVPTIptX0ByUZBTv4PX9U8b426ef4Ea3r9oxI6nW+m7p31NLiPUR4vZSG+ZnM5bdhWQRVVdtJHqBp1W5wHz4GAT0nQ/jCAxKQghDVMUyB+jQ/pn+KLXvLBeSqtsAmAOK6/zkCTbk2k6Ch1k0DdedBEn35ZKe81Y2KqAPX+hjJau7Wcyirsskg6ttA45sxh/Yx0tshC3zINKIHIAZnJ38KKtTzvxFhNqxhKq3BkeZWNHnj2tKRpvxyfLAB5YmNmkn9vfSm9/UkpRTHQar56lZqEu6bclkiT+fkxBk1I0r/A7zN93mmqtzgozqihu0Yl0PZvqulMgUXAwfkA4pDeBprJLguw7n/mlMsLVOBOuLSK7hubRJE8j64ZeurTPeqHAyRW+ek/5tHhE3USJZe/mEOdM7w7EyD3ZWvL6IPPy7yIH+BrmcOem5HJVmqkYMaJCDx/yTna821Ng3XhMVgzFgBXkZqkk0j8KOtJHZ/z968X0H/2m+T8+L2N3+ul33RuNfBaXUfCncaxdaj4ivD9kVN1YgWeA4Q+bVwSjbsh3utxXDAs6b//nE87D5gC0kZBsYXeWFNCe4/UetEAAFWsGJqye7aefvGzZOY+NX3Gkmcb60ZYvp0Bt7BXzL4vrU1AbNVgk5msIxi3TqcWbTfyv2LIEOW9ToiUyD4QLT3dGOBoNU5axhnKgGujG6IoAH55+XmOxBbm2Xpy8j+1j/9jvaAP7+QFwkIlshw6x8C/vLyYQVTRoF4uK0+I09BPh8e1WTBtNSDrrQ7hKQ1jkH/eIq7sCySGPiKwE8DdDx6vpVzmu55XufLlwlIrrd5YLrwK6/MNSnDtSL2Gnro/hUYPjRNvALW8+GahUEZWqo4G9Y7mIGQTXvSUST9YIHMLzIyjSmzEVGcXPgoc4Z1B64ngt+x0F7ceYr597pV8ijX6R1UIbrudqFe3SHrivnTqkhkhIGJAPx76vo707Bk3DY5hrekQa8VitOVoNSB3HappcDVjlEYIvinBClwJUBQrfpejPHhP53Me8B2seupdiTTuxgTxACX4wKLf/7RMHht9fQxlpERQVoqO0pl22kXRAkR+PNfsliAcPRO1bBHhAwkL698zmnp0jZQg9c13NXSGMxStxj/wxLI+hLQZ0NNARez65H4buO+it4rk/Qf2MtDNg2NlEfpeHX1JEo5Wsci8QrNwosrNWznZkcFdyen/I7gPgUDtljFf7TNJxhEodVO5LQ9thZhoDV3DfNqji54DnJnymJu7sOyaMSGFijjXBpiqS1RVaxUgv2RRXA83ZCsE1yFYBCtpVZjs3hfHwMGdFVmC303lwLDnSI0UHjwDDH5XXeOgL/ZUSfZUyec6w4v42VckMifWoKbfzsri59hpaF9jA2+2CyBhiQeO1jW4daxRLRLE1yURTY/n1dFfVhTLz55gQhYleLwGwIJnzzutfvn63OkZnPoZ5OfNu6toxT8vSJ6NbOeh8SkikZCDt2WEbhMgj+fWM0D1YoEAdcyIOMlzFR2YX2wVOfQK60G4K3jLE0S4dqe0CK/HsCAAxjcgDepjoBsHwtJcTx47Ml64dCVLpNHDYula9gQDL4AxWkOXerQISFjIF2wViK5RehUlxeno/juShNsKSqycidTQ+xtKRQ9GR2oCWgke6ZLh3TZCoErjdO/c+YuVbCtz7+x7UhtAVIohqPbAoqf/LIWjs5YUdYUAVnzBRoU8jyqTTXLrlHidyKu2sNYWAVlUYqGNO6qlXAVQr2I9l1dkkYr0KraS6lqHXCSsJPhiODkv95YnkE7PPJQhhRAR+pJiqiT1XP9lhbg9rH79lkq2XKJ7bk+gTJY5nlZtsxH99tUCKXRY+RzwGGQ3vXOiJTgN7x9D8UbN5QcSwH22o1LEt6L9TrGb/e61ArFQgGuMDoPt+TywPt+BgGGxO9wSX+ldFwo1ABQUdaEQAPBIdncEOU9Lw/czJiTT/yw5J8kBAg/6Nt+zTMPvkKb25QCHSlVcKwDa7LgG3fbehjKxOM/AowQLjdo72OBC7Q5nQDWUnKDzC04f/bucnG6a1KKGyeAhjQQgOI/KXVOE5RWV2vzcFb8f1NtAy1/sJl9tdpI8HfOFEjjM2c/qTeX02Au5IqcuSxkNxP/nFUW0YWulSJ5QUR3p2ihO13p1i6LlnHlUekggALxiYQ4lx2v9Mhhc6N7vaiUVRHaCojHqlghcCGIAFVnO8gXdGk0BMYfNu6ro1ZXFrsKuT74Oqnj+sSwJVs1t5zbLtb89WUvrmJ9Qqg+erZDkubcMiaWb+Bh+nUFCC9oBqKZ78lmg88ACp9yeKIfngLbML7ZI0KljCpk7PT1kHo3gdwfn27DkJR+UeOlLAFdTb6cnF+bRkue60DVdItseSHDfxp2V9PqqEopoBES4kY4nOPeRTBraz9jAoeAoi7sl6tU70YXHMADiD0sLGxbqqiy9tBPCHf2vMfAClgT8HbIkX/3bqkCCqBH59h+ro61fV9GOgyYGSS09k2B5N1xk3swsybk9RwnLEeE3r6KwKui5fMfWr030HUdu8CEyHPSzg5XlAs7NFnhfEDizrNIqdczmNsJCvurDz8ul2lxSbhVXxcRVActjLlcexfnt0w9edDcTS6A/vVckOhDPQTRW3Bo/J8RqBJRADX7PAV5Ffg3QsVhD+0ZTr5zWqXYLBQ2NpZ5dI9vOIvOKzLLFA1ziufoIwMhcYB0gcDNrtcm3JdID45IFRPx+9yETLXyzUJpfCnC+WU2MIbRF4XWrN12QDAlzsNntdPeYJK/eT0tGBFPLjoM1tH2/SRpnRg5oTe0WhwRyMJ94I+tFzyY7Ih3G+JsTpCG/iycx+bYEmjExRR4/dqZegsrGnVVe5TTfSgwEA0RxKNdWzodzWXjBhvU1Uv8eTS+PRWgDA495IVi/8PcC6sNWPoG1JeqYUA7dO4cXyUMCCTJPYmlSbXJIhQUgIlOZNyNDCH/r3mr61d0pNGl0oqRsX3NauGxtqbhfZKgdDE5EVI1fH8ZX+KPIa6rB+VRsPa7qkE7bdJkCevD1Ct92BxZt/l/PySJ34nQS5b2RA2M4a9O3DEhE3CfuTae5L58VAFNYPC+ek00VHIDmLylgWRFHQ/oYaRVrPrgf5Ameh4sOx2WR/QS7MJwLGQgCHOgCi4iL6hdmsRaUk1topm94cauYh9HKDVWfhOwyRKkako6lq0skRrz0dGcOnrqWyR/0m2dzhDx8op7mTEtzpYJ/K5CIjv2JsMozBZx6sZUEqrzARZRWrd8EfKpBCvkjp84ttNCn2yobuBkZzkz37opGjJyt107rOFnYf6yGzrNSqKy2UZXJLiA1xZIRzZEAnC+z0UvvFtGCJ7JbBiQmPpFdd/zNRBv4Apd+VCKrreVXHzhWKzXAQNVsuKXdXTG/Y2Sc1A+xi0zZ0uIk79600w06voL8kbpJ2c0N7szJqX6SSrHs6lq7gIXdHPuO1koZDvSCxcMiIqAEK/RCkjW2bQZzyC2ytMy1MZktrB+Ryq3dWkGnzprlxGq1y3Vck1MFvDiAMuX2JJp2R6Lw5cHjdeyedV7BBVmNwpE1LJXWbS1nC3JQcZlVNCauDwWKHpxxTLglwes9MCfIqW9P1tOydSXiKTqtS57hlJinq7jhEJkFavBNEV1ppobd2CpgK4uqcv+H1yDnnzExvWVAYs/OO2vLSKN1Rb1wXQMXOXtqGo27MV4mCxqoR19H1Xj0+fiLCgERwANEm9vyn3k4syF6Yq8RggKC2zsc2CCvECg8MyS8P0C7cbCRxgyPl3mjelTJwCvGB0yTOJtZ/FQ27Wb+BJeWVdok4YA6gFVnpUVIsXpoH2PLgNzM1ogdY43yktO1eqoGkndSvx5RMgHFnVA4wMT8JJBHPwyVGVDAm2tKG/bz2BjJ//11JynIys6yE3W087CJdh6o4ZTVLoENG6O8EgMGtgs/Hxu60AtCGwOW6ee+DpK0EAWRu3jBRw4wSgIB6oElYvHx2oQwdqyFBHLizYn02spiv616yqSx6hmpWsnDTTUuv6nnST88IcWrtIXHcDEqn9dLaUxxJ0YPGwIcHnr1OuTH/A+8vOOASawQgODcCGzKHFyL4mQL09FDE5Jly4zn+1t5QdQa//I8FkMZLtDaKLMBNyFoaHysCKsFV8Kkx/wkjh5fkCtaExXv9CStCFnfggdc25dOI7QqL3dEr1pZM0R0CH5sQQEXwrphtWKpdld90xCpEfBhgRNuTaABPaNd2wZV/tWogOmhtXV2focEUu3jDpgQAtCgXtE0i6NoTrZetogUX7DK5OvqHPT43WleAIlFMoh1ATgSF6I8hi3NazZXkN6tQVXkaoJh0WzuwrBYMfNnb3bZHrxY2K4yYkCMtB5UIYovwUqvjYn0VgMSgtnmLuPDNQHsrEkpdCdzCsQ6Lu7dDaXyOxA6LnJIX4N/O5YtEnpORd4pIyI7ggiky+Y91SJzlKq7WejAQVd3jaSbBsVwhqXj9yDKSo2Q9kRSnDZsACCPrDZvh5A2huMSAYnNmwAHKn8UX8yj96RRtkf79BBLmgNHXXoPVvfTn8RSYpzWr8GF8pcJvRyPQgMWBa6LnHzLnirhQIAIi0e16HZOz8YybaBdm8hpqqdzIG0ENz54V3JYF4pWsLUNb68LCSQKBf9YlCMgIXrHeGQu4KlPWK647h5whe1bhsYFlEjimnbfzIE4+6ilr/ab5DU6d1EBm0VvHRbHaSEHH4PGz7q37aumVz8sEUse3t9IV3cOXf5CS1je35c7na6FVlPLTDKsOhS6bHClGJ/070SeWcQ6LFbZqtLbZ0csrAa3a0BoB8p+nO5WAC4mM0VLy/7QjaaOSeT30/qBiLHvaA0tfLNA5oT8e+nqYnKEES8qTTZpTQSrpV7Sdqwnl4DbPvysTCpCKndJbNSgWD+wTpytp8VvF0okDZSi4Zzg397dDVIQTm6kQo3n4iYkm81VVUd0R/6PvnWoSnlZuas6ryO/Wp4EUN2lAhKWhZ4LLho8hoLCJrY0Y5SriBtr1Aqn+eXp5GpSxQSwLtmmx4/fOzaRbrs+zqu1GyznP8gKwXNB8NipfAtd2y2y0V5PJUszdWM33bTQtcMGEp027Ftcx/k2dsCu3VLRYH2wxhGcFQRqF2BTFfY0Ouz+kREZUE4nvWzQ14RRPMXlVpvsAZptjQeRymo7XeBgGbBoofKXeG3GkVKXZOELwkZlZf6r52T7iFJwBkAPjgscPVG/nHZncsPmAV9gYlhehSuKcbmoJHlyGqwNcqjxdolFbpZSBbDIYOW9NgMSOgzpGdqscEdEWae7OvQAA+UreTyrK0j4rQHAEtfmoNGUC0FLQ2l1gKfHjogPWUhBVnS+3BKwD6MiapXNqGFfAiI2Dqvd6dHe5EjL1oBaZWOTiY5ybWDyLWEByOioxlsNvmNIHwPdMMgocgyLOJOTg0D86xVoKm1ksTgDzhFzstkuIZCwmpzOepEpCB7IRBwM6rMPZzS640KAZC4dzACYrQ6/UltGsjbsvrYi4uf+IoOuYm5V9hSFqqeezrcEbWDBqgPRTpvKHzSCQNwogmal6aXT1q1T6I/EgMWM6B9D2742NUgop3vLc78ehibfKQup839zsqWX4wiBATh012HcRqcOEsCcIdVCqwMJLsJNmHb3jeRN4ZYbBsbQxh1Vsjcc2RK2Az55b7rsa2zOQMkL/NiY5sxjibZhe4UEmght4DJgn+7RrbLxtMn7M1xv2vQ3xiLMYD47sqjOdXerQSN7wYMtBooV2HGL7MWzOAFXlUIH9km6+zlO92YFuCh2CuNWZATG7/PqpSwXTKzjnOhUhurZtAmQLRnQjNM5j8Y9gtidlpKga2TB1GKtkEYoaKAnDeDSOVU1sGRav7VSGm863cXyHqK52eyUNkEdfwX3hsp4sK+pNVLEdvOZFgDpn9tdd7y67nV0SrG4waJVTZcz0ldn1fDavC6yCeKKAPKiyztp37EaaXqhoBztvuGzOQMXDuWBW/fGjoy7soBUBuTX4ZN19LdVJXSG+RASTNuMbSzgXGzL+d1jWdQSmmy3QCpDCTDrt5bTp9urxMxcmwLCez0CTWZKBD3/qyy/Tz24ooD0FPe4kt2Ha+iNj0vobKFZAlY4PAn+nfdIpki0dhG123Io+TaqUJ3SdPTWx6VSeQ+lEaVhx4ELBZmWpojV9CMbXTP19Bxb2NWc0qLY0lgFXQrLWtd+9BYMC4AspB/hgIU+/2gnqbpLWzdIPo2dHHBp3OPdglEIjsSnPU+iH+lALo4PFlm58QJt2lkt9wWp3NtrYKkJMVpaOr9reHepBR+rAeR9/M179CMfAO1knmsL9fE8s3Q1zWyli+ZkN3yORgvGtI6Pz275wMdn58CesYNyTgcezR5PIeFSiAE8ubgDkyaPxW7svP56COrUf+Lj8Q58whp/5eMJJEeKjmzIlviY7Y7gJzpwCjqAzWS3wdk9U8RAT45wPxl/22YguT5GX3eFAmd1B5S95PrDQCspwB8G+n8BBgDuS9U5clp4WwAAAABJRU5ErkJggg==";
//String base64Url="iVBORw0KGgoAAAANSUhEUgAAAFIAAABSCAYAAADHLIObAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyVpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ4IDc5LjE2NDAzNiwgMjAxOS8wOC8xMy0wMTowNjo1NyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEYwQ0U5QjlGN0Q2MTFFQkJCRTNFQTFFRjA5OTI1NzkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEYwQ0U5QkFGN0Q2MTFFQkJCRTNFQTFFRjA5OTI1NzkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4RjBDRTlCN0Y3RDYxMUVCQkJFM0VBMUVGMDk5MjU3OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4RjBDRTlCOEY3RDYxMUVCQkJFM0VBMUVGMDk5MjU3OSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pk1EutgAABU+SURBVHja7F0J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";
String base64Url="iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAIAAADajyQQAAAACXBIWXMAAAsSAAALEgHS3X78AAAEf0lEQVRoge2bT0wTWRzHn01DKXRU2GLLkDgSmgzNGimhtYlpVTBhywU3RL2IcZVk1U1c9WLUGA/in42X9c9B3WTVxF6ErBEuwB6aQPWwS42tUUsTDJakhWoD6tRCFYMhQ2otnXnT2t/g4HyO7a+/97597/3e7837zbLZ2VkEjMs9EhiOsm1YakmzqQK6RYQQrDCPN3TynGsswqR+SBu07ccbaIMWrl1YYS73yJGTPRm/0hQX3Lj8M6g2KGHhcWb73juxd++5DMp1RG/HLoimWRRAfp2dPh5VCKGxCNPVMwTUOqAwl3sEa9PdKzVhTCyRFjAy4vGGIVpnARGWDO6LCIgwUr98qQojNMUFWDOziYRonQUqeDTYK7E29Ta8Tc5ACTuwZz2/gaa4YGtTNVDrgMJIPXH6WAOPQfvxLYRGBdQ6QkgJ55odkAtX7qft1JrigkvnmqBTYfDsnoklunqGPN4wE0sQGlW9rbLBXgk6VixiHFsWBag1JguDQhYmNZasMPw+5vGG2g51ATXv6/8t7ZO2Q/fycpyRp6LUkIVJDVmY1JCFSQ1ZmNT4jnNFQqPK7QFgaIwR8qA7jXzdLQE+Grh6c/DarUF+m4VJcL6Q15jUkIVJDVmY1Fi6G/RA2Bedes1v1FK1Saz+5A2lO+TzTwb53UlR2HecK4qMkKWRirFkjbGUkoAwIUsjlZYqlFGYHO6lBqCw8PjbRfwzQIVlfcrMIwqteiXW26tswtQ3gqJMvQLbk6zClHBgS46EjJg75MvBNfaaC7QoQkEROqyRfzLon8hu0JhYAmsDWhOsoAh9kRL/z90O9MVnpoX7HXyEv5W01AJXvxlL12DtRpnI7aF/hfv1eENYG9CqozlhdatoIabusO9Pb4fAccPWBIPW9M3niuZVtFOpis/gV8XDl4HDA5dbq3/aSNakfeWfCPonX7AHnMBwFPuotNmRuaavtbox/gHfkyRajqg+J6xIWWgna/pG/xfiKD6T+OtJt3OojyL0bPYZZCJBZjw69SY58s5OTBQt1xFclZoUoRfSDSzz2b2DsgoUlpQ3Fyq/3N+MJRQbD7Hz8MAeS156z8N8SlWmXtlStfErfbED6Ox8zP8qQbmOAK0tZfmcKzooK9d8FYJWvYIi9EwsgZ2HZ07wVZ7mi8/CipSF+37cmrPbujI6Yz1pGju3rRPnNasvsntjKdVKN+bmyEFZPd5Qd2+Ax4Y2aI8etOXmP1vSjy0OympfEMqx2Mmawo/qC1ce8Kv6+1LuM+JrhSGE9q1tzkpbkVK1q7rx6s1Bnjc/WFUilAIn4bz4u/u8/+7zASEufl3bPOlTnfrDxWVgNpEXzzaJqQpzo+mfCF5/2hWdesPzeztZs7lww462Di6D/b9YRNi1FoK5qo3PTP8z3M+1d68mdLvLWvb+fi9jJDSbyKMHbdDvYnIh6A761dTr3uB/7rAvNZ80llB109b28+6Fquptla3bRQrrXGR3uf7wZeDZxItRJrKa0C0foVLXFW3Q0oYfzKYKS20FqSdEE5ARhNAn7mCQTwoOq4cAAAAASUVORK5CYII=";
//二维码内容
String content = qrUrl;
try {
ZXingCode zp = new ZXingCode();
BufferedImage bim = zp.getQR_CODEBufferedImage(content, BarcodeFormat.QR_CODE, 400, 400, zp.getDecodeHintType());
// //这个是读取本地文件来生成二维码
// //return zp.addLogo_QRCode(bim, new File(filePath), new LogoConfig(), productName);
// return zp.addLogo_QRCode(bim, base64Url, new LogoConfig(), productName);
//生成不带logo的二维码
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ImageIO.write(bim, "png", baos); // 这里使用 "png" 格式,您可以根据实际情况选择其他格式
//在本地生成二维码图片
// ImageIO.write(bim, "png", new File("e:/erweima/" + new Date().getTime() + "test.png"));
} catch (IOException e) {
e.printStackTrace(); // 处理异常
}
byte[] imageBytes = baos.toByteArray();
return Base64.getEncoder().encodeToString(imageBytes);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @author: wangmenglong
* @date; 2024/3/1 11:13
* @description: 生成带logo的二维码图片
* @param: [qrUrl, request, productName]
* @return: java.awt.image.BufferedImage
**/
public static BufferedImage getQRCodeImage(String qrUrl) {
//二维码内容
String content = qrUrl;
try {
ZXingCode zp = new ZXingCode();
BufferedImage bim = zp.getQR_CODEBufferedImage(content, BarcodeFormat.QR_CODE, 400, 400, zp.getDecodeHintType());
//这个是读取本地文件来生成二维码
return bim;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* base64 编码转换为 BufferedImage
* @param base64
* @return
*/
public static BufferedImage base64ToBufferedImage(String base64) {
Base64.Decoder decoder = Base64.getDecoder();
// BASE64Decoder decoder = new sun.misc.BASE64Decoder();
try {
byte[] bytes1 = decoder.decode(base64);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);
return ImageIO.read(bais);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 给二维码图片添加Logo * *
*/
//public String addLogo_QRCode(BufferedImage bim, File logoPic, LogoConfig logoConfig, String productName) {
public String addLogo_QRCode(BufferedImage bim, String base64, LogoConfig logoConfig, String productName) {
try {
/** * 读取二维码图片,并构建绘图对象 */
BufferedImage image = bim;
Graphics2D g = image.createGraphics();
/** * 读取Logo图片 */
//通过本地文件生成base64
//BufferedImage logo = ImageIO.read(logoPic);
BufferedImage logo = base64ToBufferedImage(base64);
/** * 设置logo的大小,本人设置为二维码图片的20%,因为过大会盖掉二维码 */
int widthLogo = logo.getWidth(null) > image.getWidth() * 3 / 10 ? (image.getWidth() * 3 / 10) : logo.getWidth(null),
heightLogo = logo.getHeight(null) > image.getHeight() * 3 / 10 ? (image.getHeight() * 3 / 10) : logo.getWidth(null);
/** * logo放在中心 */
int x = (image.getWidth() - widthLogo) / 2;
int y = (image.getHeight() - heightLogo) / 2;
/** * logo放在右下角 * int x = (image.getWidth() - widthLogo); * int y = (image.getHeight() - heightLogo); */
//开始绘制图片
g.drawImage(logo, x, y, widthLogo, heightLogo, null);
// g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15);
// g.setStroke(new BasicStroke(logoConfig.getBorder()));
// g.setColor(logoConfig.getBorderColor());
// g.drawRect(x, y, widthLogo, heightLogo);
g.dispose();
//把商品名称添加上去,商品名称不要太长哦,这里最多支持两行。太长就会自动截取啦
if (productName != null && !productName.equals("")) {
//新的图片,把带logo的二维码下面加上文字
BufferedImage outImage = new BufferedImage(400, 445, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D outg = outImage.createGraphics();
//画二维码到新的面板
outg.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
//画文字到新的面板
outg.setColor(Color.BLACK);
outg.setFont(new Font("宋体", Font.BOLD, 20)); //字体、字型、字号
//outg.setFont(new Font(null, Font.BOLD, 20)); //字体、字型、字号
int strWidth = outg.getFontMetrics().stringWidth(productName);
if (strWidth > 399) {
// //长度过长就截取前面部分
// outg.drawString(productName, 0, image.getHeight() + (outImage.getHeight() - image.getHeight())/2 + 5 ); //画文字
//长度过长就换行
String productName1 = productName.substring(0, productName.length() / 2);
String productName2 = productName.substring(productName.length() / 2, productName.length());
int strWidth1 = outg.getFontMetrics().stringWidth(productName1);
int strWidth2 = outg.getFontMetrics().stringWidth(productName2);
outg.drawString(productName1, 200 - strWidth1 / 2, image.getHeight() + (outImage.getHeight() - image.getHeight()) / 2 + 12);
BufferedImage outImage2 = new BufferedImage(400, 485, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D outg2 = outImage2.createGraphics();
outg2.drawImage(outImage, 0, 0, outImage.getWidth(), outImage.getHeight(), null);
outg2.setColor(Color.BLACK);
outg2.setFont(new Font("宋体", Font.BOLD, 20)); //字体、字型、字号
//outg2.setFont(new Font(null, Font.BOLD, 20)); //字体、字型、字号
outg2.drawString(productName2, 200 - strWidth2 / 2, outImage.getHeight() + (outImage2.getHeight() - outImage.getHeight()) / 2 + 5);
outg2.dispose();
outImage2.flush();
outImage = outImage2;
} else {
//修改编码格式,根据linux编码
//String fileEncode = System.getProperty("file.encoding");
//outg.drawString(new String(productName.getBytes("UTF-8"), fileEncode), 200 - strWidth / 2, image.getHeight() + (outImage.getHeight() - image.getHeight()) / 2 + 12); //画文字
//System.out.println("未编译中文字体:"+productName);
//outg.drawString(productName, 200 - strWidth / 2, image.getHeight() + (outImage.getHeight() - image.getHeight()) / 2 + 12); //画文字
//中文转unicode编码 //页面显示的就是\u6d4b\u8bd5\u0035\u0028\u63a5\u7ad9\u4e8c\u7ef4\u7801\u0029 没起作用
//String font = gbEncoding(productName);
//System.out.println(font);
outg.drawString(productName, 200 - strWidth / 2, image.getHeight() + (outImage.getHeight() - image.getHeight()) / 2 + 12); //画文字
}
outg.dispose();
outImage.flush();
image = outImage;
}
logo.flush();
image.flush();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.flush();
ImageIO.write(image, "png", baos);
//二维码生成的路径,但是实际项目中,我们是把这生成的二维码显示到界面上的,因此下面的折行代码可以注释掉
//可以看到这个方法最终返回的是这个二维码的imageBase64字符串
//前端用 <img src="data:image/png;base64,${imageBase64QRCode}"/> 其中${imageBase64QRCode}对应二维码的imageBase64字符串
//ImageIO.write(image, "png", new File("C:/Users/luoguohui/Desktop/TDC-" + new Date().getTime() + "test.png"));
//这行是我重构的
Base64.Encoder encoderinterview = Base64.getEncoder();
String textinterview = encoderinterview.encodeToString(baos.toByteArray());
//这行是原本的
//String imageBase64QRCode = Base64.byteArrayToBase64(baos.toByteArray());
baos.close();
return textinterview;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 构建初始化二维码 * *
* @param bm *
* @return
*/
public BufferedImage fileToBufferedImage(BitMatrix bm) {
BufferedImage image = null;
try {
int w = bm.getWidth(), h = bm.getHeight();
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
image.setRGB(x, y, bm.get(x, y) ? 0xFF000000 : 0xFFCCDDEE);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return image;
}
/**
* 生成二维码bufferedImage图片 * *
* @param content * 编码内容 *
* @param barcodeFormat * 编码类型 *
* @param width * 图片宽度 *
* @param height * 图片高度 *
* @param hints * 设置参数 *
* @return
*/
public BufferedImage getQR_CODEBufferedImage(String content, BarcodeFormat barcodeFormat, int width, int height, Map<EncodeHintType, ?> hints) {
MultiFormatWriter multiFormatWriter = null;
BitMatrix bm = null;
BufferedImage image = null;
try {
multiFormatWriter = new MultiFormatWriter();
// 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
bm = multiFormatWriter.encode(content, barcodeFormat, width, height, hints);
int w = bm.getWidth();
int h = bm.getHeight();
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
// 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
}
}
} catch (WriterException e) {
e.printStackTrace();
}
return image;
}
/**
* 设置二维码的格式参数 * *
* @return
*/
public Map<EncodeHintType, Object> getDecodeHintType() {
// 用于设置QR二维码参数
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
// 设置QR二维码的纠错级别(H为最高级别)具体级别信息
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 设置编码方式
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 0);
hints.put(EncodeHintType.MAX_SIZE, 350);
hints.put(EncodeHintType.MIN_SIZE, 100);
return hints;
}
/*
* 中文转unicode编码
*/
public static String gbEncoding(final String gbString) {
char[] utfBytes = gbString.toCharArray();
String unicodeBytes = "";
for (int i = 0; i < utfBytes.length; i++) {
String hexB = Integer.toHexString(utfBytes[i]);
if (hexB.length() <= 2) {
hexB = "00" + hexB;
}
unicodeBytes = unicodeBytes + "\\u" + hexB;
}
return unicodeBytes;
}
}
package web;
import enums.ExceptionCodeEnum;
import lombok.Getter;
/**
* @author yuetianwang
* @description 基础异常
* @date 2021/7/26 17:13
*/
@Getter
public abstract class BaseException extends RuntimeException {
private ExceptionCodeEnum exceptionCodeEnum;
public BaseException(ExceptionCodeEnum exceptionCodeEnum) {
super(exceptionCodeEnum.getMessage());
this.exceptionCodeEnum = exceptionCodeEnum;
}
}
package web;
import enums.ExceptionCodeEnum;
/**
* @author yuetianwang
* @description 业务异常
* @date 2021/7/26 17:17
*/
public class BusinessException extends BaseException {
public BusinessException(ExceptionCodeEnum exceptionCodeEnum) {
super(exceptionCodeEnum);
}
}
package web;
import base.result.BaseResult;
import enums.ExceptionCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @author yuetianwang
* @description 异常捕捉controller
* @date 2021/7/26 17:19
*/
@Slf4j
@RestControllerAdvice
public class ExceptionCatchAdvice {
@ExceptionHandler(Exception.class)
@ResponseBody
public BaseResult exceptionHandler(Exception e) {
e.printStackTrace();
return BaseResult.error(ExceptionCodeEnum.ERROR_002.getCode());
}
@ExceptionHandler(BaseException.class)
@ResponseBody
public BaseResult exceptionHandler(BaseException e) {
e.printStackTrace();
return BaseResult.error(e.getExceptionCodeEnum());
}
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public BaseResult exceptionHandler(IllegalArgumentException e) {
e.printStackTrace();
ExceptionCodeEnum exceptionCodeEnum = ExceptionCodeEnum.getByCode(e.getMessage());
if (exceptionCodeEnum != null) {
return BaseResult.error(exceptionCodeEnum);
}
return BaseResult.error(e.getMessage());
}
}
package web;
import base.result.BaseResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import util.Paging;
/**
* @author yuetianwang
* @description 封装接口返回值
* @date 2021/7/29 9:53
*/
@RestControllerAdvice
public class ResponseJSONAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (returnType.getParameterType() == Paging.class) {
return BaseResult.success(body);
}
return body;
}
}
package web;
import enums.ExceptionCodeEnum;
/**
* @author yuetianwang
* @description 校验异常
* @date 2021/7/26 17:17
*/
public class ValidationException extends BaseException {
public ValidationException(ExceptionCodeEnum exceptionCodeEnum) {
super(exceptionCodeEnum);
}
}
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAlM0c1GgEIMNcL9O99mN9lV1oULcv8lZscSVJKVvfUglWYfHM
YpgoNQau4UdeoHiq5kVnl54e8vBNgQVD86hE5I+3tYH6/v0I+foCXYhN7ehty5V5
vJB3C0+GPD+xiHy0gJCQ8886aASTimiPIDE+JA3JzLUQe7H43n49+Nr3v4IW11vk
0BgGomj2d8msm94I1YXN3r1GzRcm/kyHMT82Pj9qf81kuMrlYcgHyv0ixPnMlp9I
WBh+6175Kzd6CcZ4RyuDamkVrR9vDbqAlFjs04iIqptd6Afs5enwguGBpNBk8RmK
hOQ3ATPXadk5vOPYNa5L4kfxNkmmJhN/NQBQzwIDAQABAoIBAFgf5awR8ifpK0aT
81PhdjWofSgYZYfzEQQtXdfltiuipgsZpb7aeC13SMjYeL022ZfIkOJlXdTo5i28
DZNXG331c4pGcXzkJJXPL+lu2SBF4AiK/O7k6+vB7DDwU9cOa+QcOgx6tQ93bl2x
MNqS70dw9wuKTDnFnCtAvrkMDV/X5wfh1n6sv4YPqIL/vmlkee8PzHXlaj7+yeL8
HGr6dBq10L0KY9/kDht0G3NU1kM9gAOzU30MmjxqyyBfQpnYD+qOs0A4+a1vdyjI
vX8qJpPdujvCPArEhvgrvVwiq9p2Z2r3apSW8HbeRPVTaX76zHZUlql08Ia+TXFT
iHsGZNkCgYEAy3VlEdIVeb/mMrPj3o8fyUVVVTIavt9yHwcrkwJ2ces3+vRfUkSZ
TUpYuJyThLSBQKtUXDnezx4qMPw0Z8OHWERCGYHYgRsfBN8eplH6fYCd8yCtWBm+
FglhLlHrrprw5+/ROMhk2CArs9yAk+gOHCWR6+mz4FZyKUO70bZOR+0CgYEAuzpU
z5J/fD0K5ZISZVkpeQ+uEFT6fZwguLnLiVg0zeuHh0U7FMECDwdpkKd5quLMCkq8
uUn2BO65uM0iq/RFP1ml677xuQ/Qbvtrhhkv/vw/GDQcE0tHw20D+6kgq5hg7HUJ
4xl7DoE3p9hnObs91QODPe4exIEpRFx4GoTDrCsCgYA4b7j4Z4EDg6KUH+gufR8B
EpVoC3z1wz+Bsdh5b+5xDSE7IHwsctDfaqcPlocpAXT0/lFpP7g5VZG4gsz6l3c8
mbqIHsdykJZbIJT857KHC51EqqTK0mEy9akaUykABwSaIaC0kom+lbXpr1mPLYh0
cEt42BvIN9J09c/sjRhLxQKBgQCONErQcdPUmESbg2vngGZIpgkuLG0pVJlh1PRr
+Av7T2Zb7tBl/gbDRXz/usRlb+dL9eIL1co/itaTL3OjKWAjMsMcIKZWSlWkxd+w
NZdH021Uw9eDLA1wuG9rCNVgn9cWIfsFe4gEx05vdKVKqxXWodlgA2lpFTUz0AwF
EEvSiwKBgDFNm1Oqgtevgcdg1klcRlj1AK3CxLjUnxxDHEml+d/UYZrSAUCY02cq
bcBLdyfo0Dkq0UbYaduVIoEWzxAzbgwV9LEeO9Hv4VnC7l/cKVBiz+breEnR6Yu2
EZOMRSAD/SK2FXfu4MGuGoNwUpnfa6E9m2WgYK5KxzsnlsuapyAU
-----END RSA PRIVATE KEY-----
\ No newline at end of file
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlM0c1GgEIMNcL9O99mN9
lV1oULcv8lZscSVJKVvfUglWYfHMYpgoNQau4UdeoHiq5kVnl54e8vBNgQVD86hE
5I+3tYH6/v0I+foCXYhN7ehty5V5vJB3C0+GPD+xiHy0gJCQ8886aASTimiPIDE+
JA3JzLUQe7H43n49+Nr3v4IW11vk0BgGomj2d8msm94I1YXN3r1GzRcm/kyHMT82
Pj9qf81kuMrlYcgHyv0ixPnMlp9IWBh+6175Kzd6CcZ4RyuDamkVrR9vDbqAlFjs
04iIqptd6Afs5enwguGBpNBk8RmKhOQ3ATPXadk5vOPYNa5L4kfxNkmmJhN/NQBQ
zwIDAQAB
-----END PUBLIC KEY-----
\ No newline at end of file
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if (mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if (mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if (!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
FROM openjdk:8-jdk-oracle
ARG JAR_FILE
ADD ${JAR_FILE} app.jar
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ENV LANG C.UTF-8
EXPOSE $PORT
ENTRYPOINT ["sh","-c","java $JAVA_OPTS -jar app.jar --spring.profiles.active=$ACTIVE --nacos.server-addr=$NACOS_HOST --nacos.namespace=$NACOS_NAMESPACE --nacos.group=$NACOS_GROUP --nacos.port=$PORT --rocketmq.namesrv=$MQ_HOST --rocketmq.instance-id=$MQ_INSTANCE_ID --aliyun.access-key=$ACCESS_KEY --aliyun.secret-key=$SECRET_KEY"]
\ No newline at end of file
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cm.crm</groupId>
<artifactId>cm</artifactId>
<version>1.0</version>
</parent>
<groupId>com.cm.crm</groupId>
<artifactId>cm-crm</artifactId>
<version>1.0</version>
<name>cm_crm</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba.cloud</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.cm.crm</groupId>
<artifactId>cm-crm-lib</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--page helper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--MongoDB-->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>-->
<!--rocketmq-->
<!--<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>
&lt;!&ndash;binder的依赖&ndash;&gt;
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rocketmq</artifactId>
</dependency>-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
</dependency>-->
<!--Security依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- StringUtilS工具 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- JSON工具 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- JWT依赖 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<configuration>
<repository>${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.cm_crm;
//import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
@RefreshScope
@EnableDiscoveryClient
@SpringBootApplication(scanBasePackages = {"com.cm_crm"})
@MapperScan(basePackages = "com.cm_crm.mapper")
public class CmCrmApplication {
public static void main(String[] args) {
SpringApplication.run(CmCrmApplication.class, args);
}
}
package com.cm_crm.bean.auth;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
/**
* @Author wangmenglong
* @Description 用户登录用
* @Date 15:33 2021/7/2
* @Param
* @return
**/
@Data
public class SelfUserEntity implements UserDetails {
/**
* 用户ID
*/
private String userId;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 派遣公司编号
*/
private String baseCode;
/**
* 状态:NORMAL正常 PROHIBIT禁用
*/
private String status;
/**
* 名称
*/
private String name;
private String grayLabel;
/**
* 用户角色
*/
private Collection<GrantedAuthority> authorities;
/**
* 账户是否过期
*/
private boolean isAccountNonExpired = false;
/**
* 账户是否被锁定
*/
private boolean isAccountNonLocked = false;
/**
* 证书是否过期
*/
private boolean isCredentialsNonExpired = false;
/**
* 账户是否有效
*/
private boolean isEnabled = true;
/**
* 账户类型,manage-管理端 person-员工端
*/
private String type;
/**
* 雇员证件号码
*/
private String idNo;
/**
* 角色id
*/
private String roleId;
/**
* 角色标签
*/
private String roleTag;
/**
* 微信openid
*/
private String openId;
/**
* 手机号
*/
private String phone;
/**
* 是否超级管理员
*/
private Boolean superAdmin;
}
package com.cm_crm.bean.auth;
import lombok.Getter;
import lombok.Setter;
/**
* @Author yuetianwang
* @Description 登录用户上下文
* @Date 11:16 2021/7/19
*/
@Getter
@Setter
public class UserContext {
/**
* 用户id
*/
private String userId;
/**
* 用户名称
*/
private String username;
/**
* 账号
*/
private String account;
/**
* 派遣公司basecode
*/
private String baseCode;
/**
* 账户类型,dispatch-派遣公司 channel-渠道 personnel-雇员
*/
private String type;
/**
* 角色id
*/
private String roleId;
/**
* 角色tag
*/
private String roleTag;
/**
* 身份证号
*/
private String idNo;
/**
* 身份证号
*/
private String openId;
/**
* 手机号
*/
private String phone;
/**
* 是否超级管理员
*/
private Boolean superAdmin;
}
package com.cm_crm.config.auth;
import org.springframework.stereotype.Component;
/**
* @Author wangmenglong
* @Description JWT配置类
* @Date 15:51 2021/7/2
* @Param
* @return
**/
@Component
public class JWTConfig {
/**
* 密钥KEY
*/
public static String secret="cm-crm@junying";
/**
* TokenKey
*/
public static String tokenHeader="Authorization";
/**
* Token前缀字符
*/
public static String tokenPrefix="Bearer ";
/**
* 过期时间 单位毫秒 1天后过期=86400000 7天后过期=604800000
*/
public static long expiration=2592000000l;
/**
* 不需要认证的接口
*/
public static String antMatchers="/index/**,/login/**,/favicon.ico,/isPermission,/actuator/**,/statewriter/**,/statereader/**,/hello/**,/public/**";
}
package com.cm_crm.config.auth;
import com.cm_crm.filter.JWTAuthenticationTokenFilter;
import com.cm_crm.handler.auth.*;
import com.cm_crm.service.auth.UserAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
/**
* @Author wangmenglong
* @Description SpringSecurity配置类
* @Date 15:35 2021/7/2
* @Param
* @return
**/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启权限注解,默认是关闭的
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 自定义登录成功处理器
*/
@Autowired
private UserLoginSuccessHandler userLoginSuccessHandler;
/**
* 自定义登录失败处理器
*/
@Autowired
private UserLoginFailureHandler userLoginFailureHandler;
/**
* 自定义注销成功处理器
*/
@Autowired
private UserLogoutSuccessHandler userLogoutSuccessHandler;
/**
* 自定义暂无权限处理器
*/
@Autowired
private UserAuthAccessDeniedHandler userAuthAccessDeniedHandler;
/**
* 自定义未登录的处理器
*/
@Autowired
private UserAuthenticationEntryPointHandler userAuthenticationEntryPointHandler;
/**
* 自定义登录逻辑验证器
*/
@Autowired
private UserAuthenticationProvider userAuthenticationProvider;
/**
* 加密方式
*
* @Author Sans
* @CreateTime 2019/10/1 14:00
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 注入自定义PermissionEvaluator
*/
@Bean
public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() {
DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
handler.setPermissionEvaluator(new UserPermissionEvaluator());
return handler;
}
/**
* 配置登录验证逻辑
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) {
//这里可启用我们自己的登陆验证逻辑
auth.authenticationProvider(userAuthenticationProvider);
}
/**
* 配置security的控制逻辑
*
* @param http
* @return
* @author wml
* @date 2020/4/4
**/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 不进行权限验证的请求或资源(从配置文件中读取)
.antMatchers(JWTConfig.antMatchers.split(",")).permitAll()
// 其他的需要登陆后才能访问 其他url都需要验证
.anyRequest().authenticated()
.and()
// 配置未登录自定义处理类
.httpBasic().authenticationEntryPoint(userAuthenticationEntryPointHandler)
.and()
// 配置登录地址
.formLogin()
//配置security表单登录页面地址 默认是login
//配置security提交form表单请求的接口地址 默认是/login/userLogin 必须使用post提交
.loginProcessingUrl("/loginform")
//设置security提交的用户名属性值是那个 默认是username
.usernameParameter("account")
//设置security提交的密码属性名是那个 默认是password
.passwordParameter("password")
// 配置登录成功自定义处理类
.successHandler(userLoginSuccessHandler)
// 配置登录失败自定义处理类
.failureHandler(userLoginFailureHandler)
.and()
// 配置登出地址
.logout()
.logoutUrl("/logoutapp")
// 配置用户登出自定义处理类
.logoutSuccessHandler(userLogoutSuccessHandler)
.and()
// 配置没有权限自定义处理类
.exceptionHandling().accessDeniedHandler(userAuthAccessDeniedHandler)
.and()
.exceptionHandling().authenticationEntryPoint(userAuthenticationEntryPointHandler)
.and()
// 开启跨域
.cors()
// 禁用frameOptions
.and().headers().frameOptions().disable()
.and()
// 取消跨站请求伪造防护
.csrf().disable();
// 基于Token不需要session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 禁用缓存
http.headers().cacheControl();
// 添加JWT过滤器
http.addFilter(new JWTAuthenticationTokenFilter(authenticationManager()));
}
}
package com.cm_crm.config.auth;
import com.cm_crm.bean.auth.SelfUserEntity;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
* @Author wangmenglong
* @Description 自定义权限注解验证
* @Date 15:35 2021/7/2
* @Param
* @return
**/
@Component
public class UserPermissionEvaluator implements PermissionEvaluator {
/**
* hasPermission鉴权方法
* 这里仅仅判断PreAuthorize注解中的权限表达式
* 实际中可以根据业务需求设计数据库通过targetUrl和permission做更复杂鉴权
* 当然targetUrl不一定是URL可以是数据Id还可以是管理员标识等,这里根据需求自行设计
* @author wml
* @date 2020/4/4
* @param authentication
* @param targetUrl
* @param permission
* @return
**/
@Override
public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
// 获取用户信息
SelfUserEntity selfUserEntity =(SelfUserEntity) authentication.getPrincipal();
// 查询用户权限(这里可以将权限放入缓存中提升效率)
Set<String> permissions = new HashSet<>();
// todo:从数据库获取数据 这个方法暂时没什么用,不管这层,这个类都是自定义注解的,
/*List<SysMenuEntity> sysMenuEntityList = sysUserService.selectSysMenuByUserId(selfUserEntity.getUserId());
for (SysMenuEntity sysMenuEntity:sysMenuEntityList) {
permissions.add(sysMenuEntity.getPermission());
}*/
// 权限对比
if (permissions.contains(permission.toString())){
return true;
}
return false;
}
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
return false;
}
}
package com.cm_crm.config.cors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* @Author wangmenglong
* @Description 处理跨域
* @Date 15:33 2021/7/2
* @Param
* @return
**/
@Configuration
public class CorsConfig {
public CorsConfig() {
}
@Bean
public CorsFilter corsFilter() {
// 1. 添加cors配置信息
CorsConfiguration config = new CorsConfiguration();
// config.addAllowedOrigin("http://localhost:8080");
config.addAllowedOrigin("*");
// 设置是否发送cookie信息
config.setAllowCredentials(true);
// 设置允许请求的方式
config.addAllowedMethod("*");
// 设置允许的header
config.addAllowedHeader("*");
// 2. 为url添加映射路径
UrlBasedCorsConfigurationSource corsSource = new UrlBasedCorsConfigurationSource();
corsSource.registerCorsConfiguration("/**", config);
// 3. 返回重新定义好的corsSource
return new CorsFilter(corsSource);
}
}
package com.cm_crm.controller;
import base.controller.BaseController;
import base.result.BaseResult;
import com.alibaba.fastjson.JSONObject;
import com.cm_crm.service.BranchOfficeService;
import com.cm_crm.service.CountyDistrictService;
import com.github.pagehelper.PageInfo;
import data.system.BranchOffice;
import data.system.CountyDistrict;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
*
* @return: 分公司
* @Author: wml
* @Date 2025/5/9 11:31
*/
@RestController
@RequestMapping("/branch_office")
public class BranchOfficeController extends BaseController {
@Resource
BranchOfficeService branchOfficeService;
/**
* @description: 获取列表
* @author: wangmenglong
* @date; 2023/12/7 10:07
* @param: [req]
* @return: com.github.pagehelper.PageInfo
**/
@GetMapping("/l")
public BaseResult list(HttpServletRequest req, BranchOffice branchOffice){
PageInit(req);
List<BranchOffice> list = branchOfficeService.list(pageNum,pageSize,branchOffice);
PageInfo<BranchOffice> pageInfo = new PageInfo<BranchOffice>(list);
return BaseResult.success(pageInfo);
}
/**
* 获取全部
* @return: base.result.BaseResult
* @Author: wml
*/
@GetMapping("/l/all")
public BaseResult lAll(HttpServletRequest req){
List<BranchOffice> list = branchOfficeService.queryListAll();
return BaseResult.success("normal_001",list);
}
/**
* @description: 新增
* @author: wangmenglong
**/
@PostMapping("/c")
public BaseResult create(@RequestBody BranchOffice branchOffice){
//判断是否重复
if(branchOfficeService.isHave(branchOffice.getName(),branchOffice.getId())){
return BaseResult.error("error_004");
}
return branchOfficeService.create(branchOffice)?BaseResult.success("normal_001"):BaseResult.error("error_001");
}
/**
* @description: 编辑
* @author: wangmenglong
**/
@PostMapping("/u")
public BaseResult update(@RequestBody BranchOffice branchOffice){
//判断重复
if(branchOfficeService.isHave(branchOffice.getName(),branchOffice.getId())){
return BaseResult.error("error_004");
}
return branchOfficeService.update(branchOffice)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @description: 删除
* @author: wangmenglong
**/
@PostMapping("/d")
public BaseResult del(@RequestBody JSONObject jsonObject){
String id = jsonObject.getString("id");
return branchOfficeService.del(id)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @author: wangmenglong
**/
@GetMapping("/details")
public BaseResult details(@RequestParam("id")String id){
BranchOffice branchOffice = branchOfficeService.getDetails(id);
return BaseResult.success(branchOffice);
}
}
package com.cm_crm.controller;
import base.controller.BaseController;
import base.result.BaseResult;
import com.alibaba.fastjson.JSONObject;
import com.cm_crm.service.CooperateService;
import com.github.pagehelper.PageInfo;
import data.system.Cooperate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
*
* @return: 合作伙伴
* @Author: wml
* @Date 2025/5/9 11:31
*/
@RestController
@RequestMapping("/cooperate")
public class CooperateController extends BaseController {
@Resource
CooperateService cooperateService;
/**
* @description: 获取列表
* @author: wangmenglong
* @date; 2023/12/7 10:07
* @param: [req]
* @return: com.github.pagehelper.PageInfo
**/
@GetMapping("/l")
public BaseResult list(HttpServletRequest req, Cooperate cooperate){
PageInit(req);
List<Cooperate> list = cooperateService.list(pageNum,pageSize,cooperate);
PageInfo<Cooperate> pageInfo = new PageInfo<Cooperate>(list);
return BaseResult.success(pageInfo);
}
/**
* 获取全部
* @return: base.result.BaseResult
* @Author: wml
*/
@GetMapping("/l/all")
public BaseResult lAll(HttpServletRequest req){
List<Cooperate> list = cooperateService.queryListAll();
return BaseResult.success("normal_001",list);
}
/**
* @description: 新增
* @author: wangmenglong
**/
@PostMapping("/c")
public BaseResult create(@RequestBody Cooperate cooperate){
//判断是否重复
if(cooperateService.isHave(cooperate.getName(),cooperate.getId())){
return BaseResult.error("error_005");
}
//判断是否重复
if(cooperateService.isHaveCode(cooperate.getCode(),cooperate.getId())){
return BaseResult.error("error_008");
}
return cooperateService.create(cooperate)?BaseResult.success("normal_001"):BaseResult.error("error_001");
}
/**
* @description: 编辑
* @author: wangmenglong
**/
@PostMapping("/u")
public BaseResult update(@RequestBody Cooperate cooperate){
//判断重复
if(cooperateService.isHave(cooperate.getName(),cooperate.getId())){
return BaseResult.error("error_005");
}
//判断是否重复
if(cooperateService.isHaveCode(cooperate.getCode(),cooperate.getId())){
return BaseResult.error("error_008");
}
return cooperateService.update(cooperate)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @description: 删除
* @author: wangmenglong
**/
@PostMapping("/d")
public BaseResult del(@RequestBody JSONObject jsonObject){
String id = jsonObject.getString("id");
return cooperateService.del(id)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @author: wangmenglong
**/
@GetMapping("/details")
public BaseResult details(@RequestParam("id")String id){
Cooperate cooperate = cooperateService.getDetails(id);
return BaseResult.success(cooperate);
}
/**
* 合同名单查询导出
* @return: base.result.BaseResult
* @Author: wml
* @Date 2024/8/27 15:59
*/
@PostMapping("/import")
public BaseResult importCooperate(@RequestParam("file") MultipartFile multipartFile){
BaseResult baseResult = cooperateService.importCooperate(multipartFile);
return baseResult;
}
}
package com.cm_crm.controller;
import base.controller.BaseController;
import base.result.BaseResult;
import com.alibaba.fastjson.JSONObject;
import com.cm_crm.service.CountyDistrictService;
import com.cm_crm.service.UserService;
import com.github.pagehelper.PageInfo;
import data.system.CountyDistrict;
import data.user.User;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
*
* @return: 县区管理
* @Author: wml
* @Date 2025/5/9 11:31
*/
@RestController
@RequestMapping("/county_district")
public class CountyDistrictController extends BaseController {
@Resource
CountyDistrictService countyDistrictService;
/**
* 获取区县
* @return: base.result.BaseResult
* @Author: wml
* @Date 2025/5/9 11:31
*/
@GetMapping("/lall")
public BaseResult listAll(HttpServletRequest req){
List<CountyDistrict> list = countyDistrictService.listAll();
return BaseResult.success(list);
}
}
package com.cm_crm.controller;
import base.controller.BaseController;
import base.result.BaseResult;
import com.alibaba.fastjson.JSONObject;
import com.cm_crm.service.UserService;
import com.github.pagehelper.PageInfo;
import data.user.User;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* @author wangmenglong
* @description: 用户管理
* @date 2023/12/11 11:35
*/
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {
@Resource
UserService userService;
/**
* @description: 获取用户列表
* @author: wangmenglong
* @date; 2023/12/7 10:07
* @param: [req]
* @return: com.github.pagehelper.PageInfo
**/
@GetMapping("/l")
public BaseResult list(HttpServletRequest req,User user){
PageInit(req);
List<User> list = userService.list(pageNum,pageSize,user);
PageInfo<User> pageInfo = new PageInfo<User>(list);
return BaseResult.success(pageInfo);
}
/**
* @description: 新增用户
* @author: wangmenglong
* @date; 2023/12/11 16:50
* @param: [org]
* @return: base.result.BaseResult
**/
@PostMapping("/c")
public BaseResult create(@RequestBody User user){
//判断账号是否重复
if(userService.isHave(user.getAccount(),user.getId())){
return BaseResult.error("error_003");
}
return userService.create(user)?BaseResult.success("normal_001"):BaseResult.error("error_001");
}
/**
* @description: 编辑用户
* @author: wangmenglong
* @date; 2023/12/7 11:05
* @param: [org]
* @return: base.result.BaseResult
**/
@PostMapping("/u")
public BaseResult update(@RequestBody User user){
//判断账号重复
if(userService.isHave(user.getAccount(),user.getId())){
return BaseResult.error("error_003");
}
return userService.update(user)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @description: 重置密码
* @author: wangmenglong
* @date; 2023/12/11 16:59
* @param: [id]
* @return: base.result.BaseResult
**/
@PostMapping("/reset")
public BaseResult reset(@RequestBody JSONObject jsonObject){
String id = jsonObject.getString("id");
return userService.reset(id)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @description: 修改状态 停用/启用
* @author: wangmenglong
* @date; 2023/12/11 16:59
* @param: [id]
* @return: base.result.BaseResult
**/
@PostMapping("/ustate")
public BaseResult uState(@RequestBody JSONObject jsonObject){
String id = jsonObject.getString("id");
String state = jsonObject.getString("state");
return userService.uState(id,state)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @description: 删除用户
* @author: wangmenglong
* @date; 2023/12/7 11:08
* @param: [id]
* @return: base.result.BaseResult
**/
@PostMapping("/d")
public BaseResult del(@RequestBody JSONObject jsonObject){
String id = jsonObject.getString("id");
return userService.del(id)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @description: 修改密码
* @author: wangmenglong
* @date; 2023/12/12 10:55
* @param: [jsonObject]
* @return: base.result.BaseResult
**/
@PostMapping("/upassword")
public BaseResult uPassword(@RequestBody JSONObject jsonObject){
String oldPassword = jsonObject.getString("oldPassword");
String password = jsonObject.getString("password");
String id = jsonObject.getString("id");
return userService.uPassword(oldPassword,password,id)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @author: wangmenglong
* @date; 2024/3/21 15:36
* @description: 修改当前用户的密码
* @param: [jsonObject]
* @return: base.result.BaseResult
**/
@PostMapping("/u/password")
public BaseResult updateUserPassword(@RequestBody JSONObject jsonObject){
String oldPassword = jsonObject.getString("oldPassword");
String password = jsonObject.getString("password");
return userService.updateUserPassword(oldPassword,password);
}
/**
* @author: wangmenglong
* @date; 2024/3/24 17:18
* @description: 获取用户详情
* @param: [id]
* @return: base.result.BaseResult
**/
@GetMapping("/details")
public BaseResult details(@RequestParam("id")String id){
User user = userService.getDetails(id);
return BaseResult.success(user);
}
}
package com.cm_crm.controller;
import base.controller.BaseController;
import base.result.BaseResult;
import com.alibaba.fastjson.JSONObject;
import com.cm_crm.service.VisitRecordService;
import com.github.pagehelper.PageInfo;
import data.visitRecord.VisitRecord;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
*
* @return: 走访记录
* @Author: wml
* @Date 2025/5/9 11:31
*/
@RestController
@RequestMapping("/visit_record")
public class VisitRecordController extends BaseController {
@Resource
VisitRecordService visitRecordService;
/**
* @description: 获取列表
* @author: wangmenglong
* @date; 2023/12/7 10:07
* @param: [req]
* @return: com.github.pagehelper.PageInfo
**/
@GetMapping("/l")
public BaseResult list(HttpServletRequest req, VisitRecord visitRecord){
String startTime = req.getParameter("startTime");
String endTime = req.getParameter("endTime");
PageInit(req);
List<VisitRecord> list = visitRecordService.list(pageNum,pageSize,visitRecord,startTime,endTime);
PageInfo<VisitRecord> pageInfo = new PageInfo<VisitRecord>(list);
return BaseResult.success(pageInfo);
}
/**
* 获取全部
* @return: base.result.BaseResult
* @Author: wml
*/
@GetMapping("/l/all")
public BaseResult lAll(HttpServletRequest req, VisitRecord visitRecord){
String startTime = req.getParameter("startTime");
String endTime = req.getParameter("endTime");
List<VisitRecord> list = visitRecordService.queryListAll(visitRecord,startTime,endTime);
return BaseResult.success("normal_001",list);
}
/**
* @description: 新增
* @author: wangmenglong
**/
@PostMapping("/c")
public BaseResult create(@RequestBody VisitRecord visitRecord){
return visitRecordService.create(visitRecord)?BaseResult.success("normal_001"):BaseResult.error("error_001");
}
/**
* @description: 编辑
* @author: wangmenglong
**/
@PostMapping("/u")
public BaseResult update(@RequestBody VisitRecord visitRecord){
return visitRecordService.update(visitRecord)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @description: 删除
* @author: wangmenglong
**/
@PostMapping("/d")
public BaseResult del(@RequestBody JSONObject jsonObject){
String id = jsonObject.getString("id");
return visitRecordService.del(id)?BaseResult.success("normal_002"):BaseResult.error("error_002");
}
/**
* @author: wangmenglong
**/
@GetMapping("/details")
public BaseResult details(@RequestParam("id")String id){
VisitRecord visitRecord = visitRecordService.getDetails(id);
return BaseResult.success(visitRecord);
}
/**
* 导出
* @return: base.result.BaseResult
* @Author: wml
* @Date 2023/12/13 16:05
*/
@GetMapping("/export")
public void personImportDown(HttpServletRequest req, HttpServletResponse response, VisitRecord visitRecord){
String startTime = req.getParameter("startTime");
String endTime = req.getParameter("endTime");
visitRecordService.export(response,visitRecord,startTime,endTime);
}
}
package com.cm_crm.controller.api;
import base.result.BaseResult;
import data.user.User;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
/**
* @ClassName : TestController
* @Description :
* @Author : wml
* @Date: 2025-05-08 16:08
*/
@RestController
@RequestMapping("/public/")
public class TestController {
/**
* 获取对话记录
* @return: base.result.BaseResult
* @Author: wml
* @Date 2025/4/9 10:05
*/
@GetMapping("/l")
public BaseResult list(HttpServletRequest req, User user){
return BaseResult.success();
}
/**
* 新建对话
* @return: base.result.BaseResult
* @Author: wml
* @Date 2025/4/9 10:05
*/
@PostMapping("/c")
public BaseResult create(@RequestBody User user){
return BaseResult.success("normal_001");
}
}
package com.cm_crm.exception;
/**
* @ClassName : NoUserException
* @Description :
* @Author : wml
* @Date: 2025-04-09 11:01
*/
public class HaveUserException extends RuntimeException{
}
package com.cm_crm.exception;
/**
* @ClassName : NoUserException
* @Description :
* @Author : wml
* @Date: 2025-04-09 11:01
*/
public class NoUserException extends RuntimeException{
}
package com.cm_crm.exception;
/**
* @ClassName : NoUserException
* @Description :
* @Author : wml
* @Date: 2025-04-09 11:01
*/
public class PasswordErrorException extends RuntimeException{
}
package com.cm_crm.filter;
import com.alibaba.fastjson.JSONObject;
import com.cm_crm.bean.auth.SelfUserEntity;
import com.cm_crm.config.auth.JWTConfig;
import com.cm_crm.service.UserService;
import com.cm_crm.util.auth.ExportPrivateKey;
import com.cm_crm.util.auth.InjectUtil;
import com.cm_crm.util.auth.ResultUtil;
import data.user.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import mongo.collection.CollectionName;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class JWTAuthenticationTokenFilter extends BasicAuthenticationFilter {
private UserService userService = InjectUtil.getInstance().getUserService();
public JWTAuthenticationTokenFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
StringBuffer requestURL = request.getRequestURL();
String provider = "";
try {
ClassPathResource classPathResource = new ClassPathResource("cm-crm-jwt.jks");
InputStream inputStream = classPathResource.getInputStream();
ExportPrivateKey export = new ExportPrivateKey();
export.keystoreFile = inputStream;
export.keyStoreType = "JKS";
export.password = JWTConfig.secret.toCharArray();
export.alias = "cm-crm-jwt";
//export.exportedFile=new File("luke");
provider = export.export();
} catch (Exception e) {
System.out.println("Token无效");
return;
}
// 获取请求头中JWT的Token
String tokenHeader = request.getHeader(JWTConfig.tokenHeader);
if (null != tokenHeader && tokenHeader.startsWith(JWTConfig.tokenPrefix)) {
try {
// 截取JWT前缀
String token = tokenHeader.replace(JWTConfig.tokenPrefix, "");
// 解析JWT
Claims claims = Jwts.parser()
.setSigningKey(provider)
.parseClaimsJws(token)
.getBody();
// 获取用户名
String username = claims.getSubject();
String userId = claims.getId();
//查询当前账号的状态,如果是禁用直接返回
//if("manage".equals(claims.get("type"))){
User user = userService.getDetailsByLoginAccount(username);
if (user == null) {
ResultUtil.responseJson(response,ResultUtil.resultCode(102,"账号不存在"));
throw new UsernameNotFoundException("账号不存在");
}
Object state = user.getState();
if (!Objects.equals(state, "normal")) {
ResultUtil.responseJson(response,ResultUtil.resultCode(101,"账号被禁用"));
// 账号被禁用
throw new LockedException("账号被禁用");
}
//}
if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(userId)) {
// 获取角色
List<GrantedAuthority> authorities = new ArrayList<>();
String baseCode = claims.get("baseCode").toString();
if (claims.get("authorities")!=null&&!StringUtils.isEmpty(claims.get("authorities").toString())&&!"null".equals(claims.get("authorities"))) {
String authority = claims.get("authorities").toString();
List<Map<String, String>> authorityMap = JSONObject.parseObject(authority, List.class);
for (Map<String, String> role : authorityMap) {
if (role != null) {
authorities.add(new SimpleGrantedAuthority(role.get("authority")));
}
}
}
//组装参数
SelfUserEntity selfUserEntity = new SelfUserEntity();
selfUserEntity.setUsername(claims.getSubject());
selfUserEntity.setUserId(claims.getId());
selfUserEntity.setAuthorities(authorities);
selfUserEntity.setBaseCode(baseCode);
selfUserEntity.setName(claims.getOrDefault("name", "").toString());
selfUserEntity.setType(claims.getOrDefault("type", "").toString());
selfUserEntity.setRoleId(claims.getOrDefault("roleId", "").toString());
selfUserEntity.setRoleTag(claims.getOrDefault("roleTag", "").toString());
selfUserEntity.setIdNo(claims.getOrDefault("idNo", "").toString());
selfUserEntity.setOpenId(claims.getOrDefault("openId","").toString());
selfUserEntity.setPhone(claims.getOrDefault("phone","").toString());
selfUserEntity.setSuperAdmin(Boolean.parseBoolean(claims.getOrDefault("superAdmin", "false").toString()));
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(selfUserEntity, userId, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (ExpiredJwtException e) {
System.out.println("Token过期");
} catch (LockedException e){
System.out.println("=============================账号被禁用======================");
}catch (UsernameNotFoundException e){
System.out.println("=============================账号不存在======================");
}catch (Exception e) {
//System.out.println("Token无效4");
}
}
filterChain.doFilter(request, response);
return;
}
}
\ No newline at end of file
package com.cm_crm.handler.auth;
import com.cm_crm.util.auth.ResultUtil;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class UserAuthAccessDeniedHandler implements AccessDeniedHandler {
/**
* 暂无权限返回结果
* @author wml
* @date 2020/4/4
* @param request
* @param response
* @param exception
* @return
**/
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exception){
ResultUtil.responseJson(response,ResultUtil.resultCode(403,"未授权"));
}
}
\ No newline at end of file
package com.cm_crm.handler.auth;
import com.cm_crm.util.auth.ResultUtil;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class UserAuthenticationEntryPointHandler implements AuthenticationEntryPoint {
/**
* 用户未登录返回结果
*
* @param request
* @param response
* @param exception
* @return
* @author wangmenglong
* @date 2020/4/4
**/
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) {
ResultUtil.responseJson(response, ResultUtil.resultCode(401, "未登录"));
}
}
package com.cm_crm.handler.auth;
import com.cm_crm.util.auth.ResultUtil;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class UserLoginFailureHandler implements AuthenticationFailureHandler {
/**
* 登录失败返回结果
* @author wml
* @date 2020/4/4
* @param request
* @param response
* @param exception
* @return
**/
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
// 这些对于操作的处理类可以根据不同异常进行不同处理
if (exception instanceof UsernameNotFoundException){
ResultUtil.responseJson(response,ResultUtil.resultCode(500,"账号不存在"));
}
if (exception instanceof LockedException){
ResultUtil.responseJson(response,ResultUtil.resultCode(500,"账号被禁用"));
}
if (exception instanceof BadCredentialsException){
ResultUtil.responseJson(response,ResultUtil.resultCode(500,exception.getMessage()));
}
ResultUtil.responseJson(response,ResultUtil.resultCode(500,"登录失败"));
}
}
package com.cm_crm.handler.auth;
import com.cm_crm.bean.auth.SelfUserEntity;
import com.cm_crm.util.auth.JWTTokenUtil;
import com.cm_crm.util.auth.ResultUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Component
public class UserLoginSuccessHandler implements AuthenticationSuccessHandler {
/**
* 登录成功返回结果
* @author wml
* @date 2020/4/4
* @param request
* @param response
* @param authentication
* @return
**/
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
// 组装JWT
SelfUserEntity selfUserEntity = (SelfUserEntity) authentication.getPrincipal();
String token = JWTTokenUtil.createAccessToken(selfUserEntity);
//token = JWTConfig.tokenPrefix + token;
// 封装返回参数
Map<String,Object> resultData = new HashMap<>();
resultData.put("code","200");
resultData.put("msg", "登录成功");
resultData.put("token",token);
resultData.put("name",selfUserEntity.getName());
resultData.put("phone", selfUserEntity.getPhone());
resultData.put("baseCode", selfUserEntity.getBaseCode());
resultData.put("superAdmin", selfUserEntity.getSuperAdmin());
ResultUtil.responseJson(response,resultData);
}
}
package com.cm_crm.handler.auth;
import com.cm_crm.util.auth.ResultUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
@Component
public class UserLogoutSuccessHandler implements LogoutSuccessHandler {
/**
* 用户登出返回结果
* 这里应该让前端清除掉Token
* @author wml
* @date 2020/4/4
* @param request
* @param response
* @param authentication
* @return
**/
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication){
Map<String,Object> resultData = new HashMap<>();
resultData.put("code","200");
resultData.put("msg", "登出成功");
SecurityContextHolder.clearContext();
ResultUtil.responseJson(response,ResultUtil.resultSuccess(resultData));
}
}
package com.cm_crm.listener.auth;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.AvailabilityState;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
* description: 监听系统事件的类 <br>
* date: 2020/6/4 下午12:57 <br>
* author: willzhao <br>
* email: zq2599@gmail.com <br>
* version: 1.0 <br>
*/
@Component
@Slf4j
public class AvailabilityListener {
/**
* 监听系统消息,
* AvailabilityChangeEvent类型的消息都从会触发此方法被回调
* @param event
*/
@EventListener
public void onStateChange(AvailabilityChangeEvent<? extends AvailabilityState> event) {
log.info(event.getState().getClass().getSimpleName() + " : " + event.getState());
}
}
\ No newline at end of file
package com.cm_crm.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import data.system.BranchOffice;
import data.system.Cooperate;
/**
*
* @Author: wml
* @Date 2025/5/9 10:21
*/
public interface BranchOfficeMapper extends BaseMapper<BranchOffice> {
}
package com.cm_crm.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import data.system.Cooperate;
/**
*
* @Author: wml
* @Date 2025/5/9 10:21
*/
public interface CooperateMapper extends BaseMapper<Cooperate> {
}
package com.cm_crm.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import data.system.BranchOffice;
import data.system.CountyDistrict;
/**
*
* @Author: wml
* @Date 2025/5/9 10:21
*/
public interface CountyDistrictMapper extends BaseMapper<CountyDistrict> {
}
package com.cm_crm.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import data.user.User;
/**
*
* @Author: wml
* @Date 2025/5/9 10:21
*/
public interface UserMapper extends BaseMapper<User> {
}
package com.cm_crm.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import data.system.CountyDistrict;
import data.visitRecord.VisitRecord;
/**
*
* @Author: wml
* @Date 2025/5/9 10:21
*/
public interface VisitRecordMapper extends BaseMapper<VisitRecord> {
}
package com.cm_crm.service;
import data.system.BranchOffice;
import java.util.List;
/**
* @author wangmenglong
* @description: 分公司
*/
public interface BranchOfficeService {
List<BranchOffice> list(int pageNum, int pageSize, BranchOffice branchOffice);
List<BranchOffice> queryListAll();
boolean create(BranchOffice branchOffice);
boolean update(BranchOffice branchOffice);
boolean del(String id);
boolean isHave(String account, String id);
BranchOffice getDetails(String id);
}
package com.cm_crm.service;
import base.result.BaseResult;
import data.system.Cooperate;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* @author wangmenglong
* @description: 合作伙伴
*/
public interface CooperateService {
List<Cooperate> list(int pageNum, int pageSize, Cooperate cooperate);
List<Cooperate> queryListAll();
boolean create(Cooperate cooperate);
boolean update(Cooperate cooperate);
boolean del(String id);
boolean isHave(String name, String id);
boolean isHaveCode(String code, String id);
Cooperate getDetails(String id);
BaseResult importCooperate(MultipartFile multipartFile);
}
package com.cm_crm.service;
import data.system.CountyDistrict;
import java.util.List;
/**
*
* @return: 县区
* @Author: wml
* @Date 2025/5/9 10:20
*/
public interface CountyDistrictService {
public List<CountyDistrict> listAll();
}
package com.cm_crm.service;
import base.result.BaseResult;
import data.user.User;
import java.util.List;
/**
*
* @return: 用户管理
* @Author: wml
* @Date 2025/5/9 10:20
*/
public interface UserService {
User getDetailsByLoginAccount(String account);
List<User> list(int pageNum, int pageSize, User user);
boolean create(User user);
boolean update(User user);
boolean reset(String id);
boolean uState(String id, String state);
boolean del(String id);
boolean uPassword(String oldPassword, String password, String id);
boolean isHave(String account, String id);
BaseResult updateUserPassword(String oldPassword, String password);
User getDetails(String id);
}
package com.cm_crm.service;
import data.visitRecord.VisitRecord;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* @author wangmenglong
* @description: 走访记录
*/
public interface VisitRecordService {
List<VisitRecord> list(int pageNum, int pageSize, VisitRecord visitRecord,String startTime,String endTime);
List<VisitRecord> queryListAll(VisitRecord visitRecord,String startTime,String endTime);
boolean create(VisitRecord visitRecord);
boolean update(VisitRecord visitRecord);
boolean del(String id);
VisitRecord getDetails(String id);
void export(HttpServletResponse response, VisitRecord visitRecord,String startTime,String endTime);
}
package com.cm_crm.service.auth;
import com.cm_crm.bean.auth.SelfUserEntity;
import com.cm_crm.service.UserService;
import data.user.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
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 java.util.Objects;
@Slf4j
@Component
public class SelfUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
/**
* 查询用户信息
* @param username
* @return
* @author wml
* @date 2020/4/4
**/
@Override
public SelfUserEntity loadUserByUsername(String username) throws UsernameNotFoundException {
HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
SelfUserEntity sysUserEntity = new SelfUserEntity();
User user = userService.getDetailsByLoginAccount(username);
if (user == null) {
throw new UsernameNotFoundException("账号不存在");
}
Object state = user.getState();
if (!Objects.equals(state, "normal")) {
// 账号被禁用
log.error("登录失败, 账号被禁用, jsonObject={}", user);
throw new LockedException("账号被禁用");
}
sysUserEntity.setUsername(user.getAccount());
sysUserEntity.setPassword(user.getPassword());
sysUserEntity.setUserId(user.getId());
sysUserEntity.setBaseCode(user.getBaseCode()== null ? "" : user.getBaseCode());
sysUserEntity.setName(user.getName());
sysUserEntity.setType(user.getType());
return sysUserEntity;
}
}
\ No newline at end of file
package com.cm_crm.service.auth;
import com.cm_crm.bean.auth.SelfUserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Component
public class UserAuthenticationProvider implements AuthenticationProvider {
@Autowired
private SelfUserDetailsService selfUserDetailsService;
private static final String SALT = "junying";
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 获取表单输入中返回的用户名
// String username = (String) authentication.getPrincipal();
String username = authentication.getName();
// 获取表单中输入的密码
String password = DigestUtils.md5DigestAsHex(authentication.getCredentials().toString().getBytes());
// 查询用户是否存在
SelfUserEntity userInfo = selfUserDetailsService.loadUserByUsername(username);
//验证密码是否正确
if (!userInfo.getPassword().equals(password)) {
throw new BadCredentialsException("密码不正确");
}
return new UsernamePasswordAuthenticationToken(userInfo, password, userInfo.getAuthorities());
}
@Override
public boolean supports(Class<?> authentication) {
return true;
}
/**
* 字符换MD5
* @param password
* @return
*/
public static String strToMd5(String password) {
if(org.springframework.util.StringUtils.isEmpty(password)){
return password;
}
password = SALT + password + SALT;
String md5Prd = DigestUtils.md5DigestAsHex(password.getBytes());
return md5Prd;
}
}
package com.cm_crm.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cm_crm.bean.auth.UserContext;
import com.cm_crm.mapper.BranchOfficeMapper;
import com.cm_crm.service.BranchOfficeService;
import com.cm_crm.util.auth.UserUtils;
import com.cm_crm.xsnowflake.SnowFlakeFactory;
import com.github.pagehelper.PageHelper;
import data.system.BranchOffice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
*
* @return: 分公司service
* @Author: wml
*/
@Service
@Transactional
public class BranchOfficeServiceImpl extends ServiceImpl<BranchOfficeMapper, BranchOffice> implements BranchOfficeService {
@Autowired
SnowFlakeFactory snowFlakeFactory;
/**
* @description: 获取列表
* @author: wangmenglong
**/
@Override
public List<BranchOffice> list(int pageNum, int pageSize, BranchOffice branchOffice) {
//启动分页工具
PageHelper.startPage(pageNum, pageSize);
//创建查询条件
LambdaQueryWrapper<BranchOffice> qw = new LambdaQueryWrapper<>();
qw.like(StringUtils.isNotBlank(branchOffice.getName()),BranchOffice::getName,branchOffice.getName())
.eq(BranchOffice::getDel,false)
.orderByDesc(BranchOffice::getCreateTime);
List<BranchOffice> branchOfficeList = super.list(qw);
//返回查询结果
return branchOfficeList;
}
@Override
public List<BranchOffice> queryListAll() {
UserContext userContext = UserUtils.getUserContext();
//创建查询条件
LambdaQueryWrapper<BranchOffice> qw = new LambdaQueryWrapper<>();
qw.eq(BranchOffice::getDel,false)
.eq(BranchOffice::getBaseCode, userContext.getBaseCode())
.orderByDesc(BranchOffice::getCreateTime);
List<BranchOffice> orgList = super.list(qw);
//返回查询结果
return orgList;
}
/**
* @description: 新增
* @author: wangmenglong
**/
@Override
public boolean create(BranchOffice branchOffice) {
//校验用户名是否存在
BranchOffice u = super.getOne(new LambdaQueryWrapper<BranchOffice>().eq(BranchOffice::getDel, false )
.eq(BranchOffice::getName, branchOffice.getName()));
if(ObjectUtil.isNotNull(u)){
return false;
}
UserContext userContext = UserUtils.getUserContext();
String baseCode = userContext.getBaseCode();
branchOffice.setId(snowFlakeFactory.nextId());
branchOffice.setBaseCode(baseCode);
branchOffice.setUserId(userContext.getUserId());
branchOffice.setUserName(userContext.getUsername());
branchOffice.setDel(false);
branchOffice.setCreateTime(DateUtil.now());
return super.save(branchOffice);
}
/**
* @description: 编辑
* @author: wangmenglong
**/
@Override
public boolean update(BranchOffice branchOffice) {
branchOffice.setUpdateTime(DateUtil.now());
//判断是否传入id
if(StringUtils.isBlank(branchOffice.getId())){
return false;
}
return super.saveOrUpdate(branchOffice);
}
/**
* @description: 删除
* @author: wangmenglong
**/
@Override
public boolean del(String id) {
if(StringUtils.isBlank(id)){
return false;
}
LambdaUpdateWrapper<BranchOffice> qw = new LambdaUpdateWrapper<>();
qw.eq(BranchOffice::getId,id)
.set(BranchOffice::getDel,true)
.set(BranchOffice::getDelTime, DateUtil.now());
return super.update(qw);
}
/**
* @author: wangmenglong
* @description: 判断是否存在
**/
@Override
public boolean isHave(String name, String id) {
LambdaQueryWrapper<BranchOffice> qw = new LambdaQueryWrapper<>();
qw.eq(BranchOffice::getDel,false)
.eq(BranchOffice::getName, name);
if(StringUtils.isNotBlank(id)){
qw.ne(BranchOffice::getId,id);
}
return super.count(qw)>0;
}
/**
* @author: wangmenglong
* @description: 获取详情
**/
@Override
public BranchOffice getDetails(String id) {
return super.getById(id);
}
}
package com.cm_crm.service.impl;
import base.result.BaseResult;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cm_crm.bean.auth.UserContext;
import com.cm_crm.mapper.CooperateMapper;
import com.cm_crm.service.CooperateService;
import com.cm_crm.service.CountyDistrictService;
import com.cm_crm.util.auth.UserUtils;
import com.cm_crm.xsnowflake.SnowFlakeFactory;
import com.github.pagehelper.PageHelper;
import data.system.Cooperate;
import data.system.CountyDistrict;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import util.CommonUtils;
import util.MultipartFileToFile;
import util.excel.ExcelXlsxReader;
import java.io.File;
import java.util.*;
/**
*
* @return: 合作伙伴service
* @Author: wml
*/
@Service
@Transactional
public class CooperateServiceImpl extends ServiceImpl<CooperateMapper, Cooperate> implements CooperateService {
@Autowired
SnowFlakeFactory snowFlakeFactory;
@Autowired
CountyDistrictService countyDistrictService;
/**
* @description: 获取列表
* @author: wangmenglong
**/
@Override
public List<Cooperate> list(int pageNum, int pageSize, Cooperate cooperate) {
//启动分页工具
PageHelper.startPage(pageNum, pageSize);
//创建查询条件
LambdaQueryWrapper<Cooperate> qw = new LambdaQueryWrapper<>();
qw.like(StringUtils.isNotBlank(cooperate.getName()),Cooperate::getName,cooperate.getName())
.eq(StringUtils.isNotBlank(cooperate.getCode()),Cooperate::getCode,cooperate.getCode())
.eq(Cooperate::getDel,false)
.orderByDesc(Cooperate::getCreateTime);
List<Cooperate> cooperateList = super.list(qw);
//返回查询结果
return cooperateList;
}
@Override
public List<Cooperate> queryListAll() {
UserContext userContext = UserUtils.getUserContext();
//创建查询条件
LambdaQueryWrapper<Cooperate> qw = new LambdaQueryWrapper<>();
qw.eq(Cooperate::getDel,false)
.eq(Cooperate::getBaseCode, userContext.getBaseCode())
.orderByDesc(Cooperate::getCreateTime);
List<Cooperate> orgList = super.list(qw);
//返回查询结果
return orgList;
}
/**
* @description: 新增
* @author: wangmenglong
**/
@Override
public boolean create(Cooperate cooperate) {
//校验用户名是否存在
Cooperate u = super.getOne(new LambdaQueryWrapper<Cooperate>().eq(Cooperate::getDel, false )
.eq(Cooperate::getName, cooperate.getName()));
if(ObjectUtil.isNotNull(u)){
return false;
}
UserContext userContext = UserUtils.getUserContext();
String baseCode = userContext.getBaseCode();
cooperate.setId(snowFlakeFactory.nextId());
cooperate.setBaseCode(baseCode);
cooperate.setUserId(userContext.getUserId());
cooperate.setUserName(userContext.getUsername());
cooperate.setDel(false);
cooperate.setCreateTime(DateUtil.now());
return super.save(cooperate);
}
/**
* @description: 编辑
* @author: wangmenglong
**/
@Override
public boolean update(Cooperate cooperate) {
cooperate.setUpdateTime(DateUtil.now());
//判断是否传入id
if(StringUtils.isBlank(cooperate.getId())){
return false;
}
return super.saveOrUpdate(cooperate);
}
/**
* @description: 删除
* @author: wangmenglong
**/
@Override
public boolean del(String id) {
if(StringUtils.isBlank(id)){
return false;
}
LambdaUpdateWrapper<Cooperate> qw = new LambdaUpdateWrapper<>();
qw.eq(Cooperate::getId,id)
.set(Cooperate::getDel,true)
.set(Cooperate::getDelTime, DateUtil.now());
return super.update(qw);
}
/**
* @author: wangmenglong
* @description: 判断是否存在
**/
@Override
public boolean isHave(String name, String id) {
LambdaQueryWrapper<Cooperate> qw = new LambdaQueryWrapper<>();
qw.eq(Cooperate::getDel,false)
.eq(Cooperate::getName, name);
if(StringUtils.isNotBlank(id)){
qw.ne(Cooperate::getId,id);
}
return super.count(qw)>0;
}
/**
* @author: wangmenglong
* @description: 判断是否存在
**/
@Override
public boolean isHaveCode(String code, String id) {
LambdaQueryWrapper<Cooperate> qw = new LambdaQueryWrapper<>();
qw.eq(Cooperate::getDel,false)
.eq(Cooperate::getCode, code);
if(StringUtils.isNotBlank(id)){
qw.ne(Cooperate::getId,id);
}
return super.count(qw)>0;
}
/**
* @author: wangmenglong
* @description: 获取详情
**/
@Override
public Cooperate getDetails(String id) {
return super.getById(id);
}
@Override
public BaseResult importCooperate(MultipartFile multipartFile) {
try {
UserContext userContext = UserUtils.getUserContext();
String baseCode = userContext.getBaseCode();
File file = MultipartFileToFile.multipartFileToFile(multipartFile);
ExcelXlsxReader excelXlsxReader = new ExcelXlsxReader();
Map<String, List<List<String>>> map = excelXlsxReader.process(file);
List<List<String>> rowList = map.get("1");
//上传的文件没有数据,请重新上传
if (rowList.size() == 0 || rowList.size() == 1) {
return BaseResult.error("error_007");
}
rowList.remove(0);
List<CountyDistrict> countyDistrictList = countyDistrictService.listAll();
List<Cooperate> cooperateList = new ArrayList<>();
//此次导入的编号集合
Set<String> nameSet = new HashSet<>();
Set<String> codeSet = new HashSet<>();
int rowNum = 1;
// 校验导入数据
for (List<String> colList : rowList) {
Cooperate cooperate = new Cooperate();
String name = CommonUtils.replaceBlank(colList.get(0));
String code = CommonUtils.replaceBlank(colList.get(1));
String countyDistrictInsert = CommonUtils.replaceBlank(colList.get(2));
if(nameSet.contains(name)||isHave(name,null)){
return BaseResult.error("error_009","第"+rowNum+"行有错误数据,名称重复:["+name+"]");
}
if(codeSet.contains(code)||isHaveCode(name,null)){
return BaseResult.error("error_009","第"+rowNum+"行有错误数据,编号重复:["+code+"]");
}
if(StringUtils.isBlank(name)||StringUtils.isBlank(code)||StringUtils.isBlank(countyDistrictInsert)){
return BaseResult.error("error_009","第"+rowNum+"行有错误数据,值为空值");
}
nameSet.add(name);
codeSet.add(code);
rowNum++;
cooperate.setId(snowFlakeFactory.nextId());
cooperate.setBaseCode(baseCode);
cooperate.setUserId(userContext.getUserId());
cooperate.setUserName(userContext.getUsername());
cooperate.setDel(false);
cooperate.setCreateTime(DateUtil.now());
//excel导入的
cooperate.setCode(code);
cooperate.setName(name);
cooperate.setCountyDistrict(countyDistrictInsert);
for (CountyDistrict countyDistrict:countyDistrictList) {
if(countyDistrict.equals(countyDistrictInsert)) cooperate.setCountyDistrictId(countyDistrict.getId());
}
cooperateList.add(cooperate);
}
super.saveBatch(cooperateList);
return BaseResult.success();
}catch (Exception e){
e.printStackTrace();
return BaseResult.error("error_006");
}
}
}
package com.cm_crm.service.impl;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cm_crm.bean.auth.UserContext;
import com.cm_crm.mapper.CountyDistrictMapper;
import com.cm_crm.service.CountyDistrictService;
import com.cm_crm.util.auth.UserUtils;
import com.cm_crm.xsnowflake.SnowFlakeFactory;
import com.github.pagehelper.PageHelper;
import data.system.CountyDistrict;
import data.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
*
* @return: 用户管理
* @Author: wml
* @Date 2025/5/9 10:22
*/
@Service
@Transactional
public class CountyDistrictServiceImpl extends ServiceImpl<CountyDistrictMapper, CountyDistrict> implements CountyDistrictService {
@Autowired
SnowFlakeFactory snowFlakeFactory;
/**
* @description: 所有区县
* @author: wangmenglong
**/
@Override
public List<CountyDistrict> listAll() {
//创建查询条件
LambdaQueryWrapper<CountyDistrict> qw = new LambdaQueryWrapper<>();
//返回查询结果
return super.list();
}
}
package com.cm_crm.service.impl;
import base.result.BaseResult;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cm_crm.bean.auth.SelfUserEntity;
import com.cm_crm.bean.auth.UserContext;
import com.cm_crm.mapper.UserMapper;
import com.cm_crm.service.UserService;
import com.cm_crm.util.auth.JWTTokenUtil;
import com.cm_crm.util.auth.UserUtils;
import com.cm_crm.xsnowflake.SnowFlakeFactory;
import com.github.pagehelper.PageHelper;
import data.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import redis.RedisKey;
import util.MD5Utils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
*
* @return: 用户管理
* @Author: wml
* @Date 2025/5/9 10:22
*/
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
SnowFlakeFactory snowFlakeFactory;
/**
* @author: wangmenglong
* @date; 2025/5/9 10:22
* @description: 获取用户详情,登陆用
* @param: [id]
* @return: data.user.User
**/
@Override
public User getDetailsByLoginAccount(String account) {
//创建查询条件
LambdaQueryWrapper<User> qw = new LambdaQueryWrapper<>();
qw.eq(User::getAccount,account)
.eq(User::getDel,false);
return super.getOne(qw);
}
/**
* @description: 获取用户列表
* @author: wangmenglong
* @date; 2023/12/11 16:46
* @param: [pageNum, pageSize]
* @return: java.util.List<data.user.User>
**/
@Override
public List<User> list(int pageNum, int pageSize, User user) {
UserContext userContext = UserUtils.getUserContext();
String baseCode = userContext.getBaseCode();
//启动分页工具
PageHelper.startPage(pageNum, pageSize);
//创建查询条件
LambdaQueryWrapper<User> qw = new LambdaQueryWrapper<>();
qw.like(StringUtils.isNotBlank(user.getName()),User::getName,user.getName())
.like(StringUtils.isNotBlank(user.getAccount()),User::getAccount,user.getAccount())
.eq(StringUtils.isNotBlank(user.getState()), User::getState,user.getState())
.eq(User::getDel,false)
.eq(User::getBaseCode, baseCode)
.orderByDesc(User::getCreateTime);
List<User> orgList = super.list(qw);
//返回查询结果
return orgList;
}
/**
* @description: 新增用户
* @author: wangmenglong
* @date; 2023/12/11 16:51
* @param: [user]
* @return: boolean
**/
@Override
public boolean create(User user) {
//校验用户名是否存在
User u = super.getOne(new LambdaQueryWrapper<User>().eq(User::getDel, false )
.eq(User::getState, "normal")
.eq(User::getAccount, user.getAccount()));
if(ObjectUtil.isNotNull(u)){
return false;
}
UserContext userContext = UserUtils.getUserContext();
String baseCode = userContext.getBaseCode();
user.setId(snowFlakeFactory.nextId());
user.setBaseCode(baseCode);
user.setUserId(userContext.getUserId());
user.setUserName(userContext.getUsername());
user.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
user.setState("normal");
user.setDel(false);
user.setCreateTime(DateUtil.now());
return super.save(user);
}
/**
* @description: 编辑用户
* @author: wangmenglong
* @date; 2023/12/11 16:55
* @param: [org]
* @return: boolean
**/
@Override
public boolean update(User user) {
user.setUpdateTime(DateUtil.now());
//判断是否传入id
if(StringUtils.isBlank(user.getId())){
return false;
}
return super.saveOrUpdate(user);
}
/**
* @description: 重置密码
* @author: wangmenglong
* @date; 2023/12/11 17:00
* @param: [id]
* @return: boolean
**/
@Override
public boolean reset(String id) {
if(StringUtils.isBlank(id)){
return false;
}
User user = super.getById(id);
user.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
user.setUpdateTime(DateUtil.now());
return super.saveOrUpdate(user);
}
/**
* @description: 修改状态
* @author: wangmenglong
* @date; 2023/12/11 17:04
* @param: [id, state]
* @return: boolean
**/
@Override
public boolean uState(String id, String state) {
if(StringUtils.isBlank(id)){
return false;
}
User user = super.getById(id);
user.setState(state);
user.setUpdateTime(DateUtil.now());
return super.saveOrUpdate(user);
}
/**
* @description: 删除用户
* @author: wangmenglong
* @date; 2023/12/11 17:06
* @param: [id]
* @return: boolean
**/
@Override
public boolean del(String id) {
if(StringUtils.isBlank(id)){
return false;
}
LambdaUpdateWrapper<User> qw = new LambdaUpdateWrapper<>();
qw.eq(User::getId,id)
.set(User::getDel,true)
.set(User::getDelTime, DateUtil.now());
User user = super.getById(id);
return super.update(qw);
}
/**
* @description: 修改密码
* @author: wangmenglong
* @date; 2023/12/12 11:05
* @param: [oldPassword, password, id]
* @return: boolean
**/
@Override
public boolean uPassword(String oldPassword, String password, String id) {
User user = super.getById(id);
oldPassword = DigestUtils.md5DigestAsHex(oldPassword.getBytes());
if(!oldPassword.equals(user.getPassword())){
return false;
}
password = DigestUtils.md5DigestAsHex(password.getBytes());
user.setPassword(password);
user.setUpdateTime(DateUtil.now());
return super.saveOrUpdate(user);
}
/**
* @author: wangmenglong
* @date; 2024/3/21 15:39
* @description: 修改当前用户的密码
* @param: [oldPassword, password]
* @return: base.result.BaseResult
**/
@Override
public BaseResult updateUserPassword(String oldPassword, String password) {
UserContext userContext = UserUtils.getUserContext();
String id = userContext.getUserId();
User user = super.getById(id);
oldPassword = DigestUtils.md5DigestAsHex(oldPassword.getBytes());
if(!oldPassword.equals(user.getPassword())){
return BaseResult.error("error_035");
}
LambdaUpdateWrapper<User> qw = new LambdaUpdateWrapper<>();
qw.eq(User::getId,id)
.set(User::getPassword,DigestUtils.md5DigestAsHex(password.getBytes()))
.set(User::getUpdateTime, DateUtil.now());
return super.update(qw) ? BaseResult.success("normal_002") : BaseResult.error("error_002");
}
/**
* @author: wangmenglong
* @date; 2024/1/2 14:30
* @description: 判断用户名是否存在
* @param: [account, id]
* @return: boolean
**/
@Override
public boolean isHave(String account, String id) {
LambdaQueryWrapper<User> qw = new LambdaQueryWrapper<>();
qw.eq(User::getDel,false)
.eq(User::getState, "normal")
.eq(User::getAccount,account);
//如果传了id就是编辑,编辑的时候要加个条件,不能把名字跟别人重复
if(StringUtils.isNotBlank(id)){
qw.ne(User::getId,id);
}
return super.count(qw)>0;
}
/**
* @author: wangmenglong
* @date; 2024/3/24 17:19
* @description: 获取用户详情
* @param: [id]
* @return: data.user.User
**/
@Override
public User getDetails(String id) {
return super.getById(id);
}
}
package com.cm_crm.service.impl;
import cn.hutool.core.date.DateUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cm_crm.bean.auth.UserContext;
import com.cm_crm.mapper.VisitRecordMapper;
import com.cm_crm.service.VisitRecordService;
import com.cm_crm.util.auth.UserUtils;
import com.cm_crm.xsnowflake.SnowFlakeFactory;
import com.github.pagehelper.PageHelper;
import data.visitRecord.VisitRecord;
import excel.ExportVisitRecord;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
*
* @return: 走访记录service
* @Author: wml
*/
@Service
@Transactional
public class VisitRecordServiceImpl extends ServiceImpl<VisitRecordMapper, VisitRecord> implements VisitRecordService {
@Autowired
SnowFlakeFactory snowFlakeFactory;
/**
* @description: 获取列表
* @author: wangmenglong
**/
@Override
public List<VisitRecord> list(int pageNum, int pageSize, VisitRecord visitRecord,String startTime,String endTime) {
//启动分页工具
PageHelper.startPage(pageNum, pageSize);
//创建查询条件
LambdaQueryWrapper<VisitRecord> qw = new LambdaQueryWrapper<>();
qw.eq(StringUtils.isNotBlank(visitRecord.getBranchOfficeId()),VisitRecord::getBranchOfficeId,visitRecord.getBranchOfficeId())
.eq(StringUtils.isNotBlank(visitRecord.getCooperateId()),VisitRecord::getCooperateId,visitRecord.getCooperateId())
.eq(StringUtils.isNotBlank(visitRecord.getCooperateCode()),VisitRecord::getCooperateCode,visitRecord.getCooperateCode())
.like(StringUtils.isNotBlank(visitRecord.getBusinessTitle()),VisitRecord::getBusinessTitle,visitRecord.getBusinessTitle())
.eq(VisitRecord::getDel,false)
.ge(startTime != null, VisitRecord::getCreateTime, startTime)
.le(endTime != null, VisitRecord::getCreateTime, endTime)
.orderByDesc(VisitRecord::getCreateTime);
List<VisitRecord> visitRecordList = super.list(qw);
//返回查询结果
return visitRecordList;
}
@Override
public List<VisitRecord> queryListAll(VisitRecord visitRecord,String startTime,String endTime) {
UserContext userContext = UserUtils.getUserContext();
//创建查询条件
LambdaQueryWrapper<VisitRecord> qw = new LambdaQueryWrapper<>();
qw.eq(StringUtils.isNotBlank(visitRecord.getBranchOfficeId()),VisitRecord::getBranchOfficeId,visitRecord.getBranchOfficeId())
.eq(StringUtils.isNotBlank(visitRecord.getCooperateId()),VisitRecord::getCooperateId,visitRecord.getCooperateId())
.eq(StringUtils.isNotBlank(visitRecord.getCooperateCode()),VisitRecord::getCooperateCode,visitRecord.getCooperateCode())
.like(StringUtils.isNotBlank(visitRecord.getBusinessTitle()),VisitRecord::getBusinessTitle,visitRecord.getBusinessTitle())
.eq(VisitRecord::getDel,false)
.ge(startTime != null, VisitRecord::getCreateTime, startTime)
.le(endTime != null, VisitRecord::getCreateTime, endTime)
.orderByDesc(VisitRecord::getCreateTime);
//返回查询结果
return super.list(qw);
}
/**
* @description: 新增
* @author: wangmenglong
**/
@Override
public boolean create(VisitRecord visitRecord) {
UserContext userContext = UserUtils.getUserContext();
String baseCode = userContext.getBaseCode();
visitRecord.setId(snowFlakeFactory.nextId());
visitRecord.setBaseCode(baseCode);
visitRecord.setUserId(userContext.getUserId());
visitRecord.setUserName(userContext.getUsername());
visitRecord.setDel(false);
visitRecord.setCreateTime(DateUtil.now());
return super.save(visitRecord);
}
/**
* @description: 编辑
* @author: wangmenglong
**/
@Override
public boolean update(VisitRecord visitRecord) {
visitRecord.setUpdateTime(DateUtil.now());
//判断是否传入id
if(StringUtils.isBlank(visitRecord.getId())){
return false;
}
return super.saveOrUpdate(visitRecord);
}
/**
* @description: 删除
* @author: wangmenglong
**/
@Override
public boolean del(String id) {
if(StringUtils.isBlank(id)){
return false;
}
LambdaUpdateWrapper<VisitRecord> qw = new LambdaUpdateWrapper<>();
qw.eq(VisitRecord::getId,id)
.set(VisitRecord::getDel,true)
.set(VisitRecord::getDelTime, DateUtil.now());
return super.update(qw);
}
/**
* @author: wangmenglong
* @description: 获取详情
**/
@Override
public VisitRecord getDetails(String id) {
return super.getById(id);
}
@Override
public void export(HttpServletResponse response, VisitRecord visitRecord,String startTime,String endTime){
UserContext userContext = UserUtils.getUserContext();
List<VisitRecord> list = queryListAll(visitRecord,startTime,endTime);
List<ExportVisitRecord> exportVisitRecordList = new ArrayList<>();
for (VisitRecord export:list) {
ExportVisitRecord exportVisitRecord = new ExportVisitRecord();
BeanUtils.copyProperties(export, exportVisitRecord,"photoUrl");
if(export.getInteract()!=null||export.getInteract()){
exportVisitRecord.setInteract("是");
}else {
exportVisitRecord.setInteract("否");
}
try {
exportVisitRecord.setPhotoUrl(new URL(export.getPhotoUrl()));
}catch (Exception e){
e.printStackTrace();
}
exportVisitRecordList.add(exportVisitRecord);
}
try {
// response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String now = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss");
String fileName = URLEncoder.encode("走访记录" + now, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-Type","application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
ServletOutputStream outputStream = response.getOutputStream();
EasyExcel.write(outputStream).sheet(0, "走访记录").head(ExportVisitRecord.class).doWrite(exportVisitRecordList);
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.cm_crm.util.auth;
import sun.misc.BASE64Encoder;
import java.io.File;
import java.io.InputStream;
import java.security.*;
import java.security.cert.Certificate;
public class ExportPrivateKey {
public InputStream keystoreFile;
public String keyStoreType;
public char[] password;
public String alias;
public File exportedFile;
public static KeyPair getPrivateKey(KeyStore keystore, String alias, char[] password) {
try {
Key key=keystore.getKey(alias,password);
if(key instanceof PrivateKey) {
Certificate cert=keystore.getCertificate(alias);
PublicKey publicKey=cert.getPublicKey();
return new KeyPair(publicKey,(PrivateKey)key);
}
} catch (UnrecoverableKeyException e) {
} catch (NoSuchAlgorithmException e) {
} catch (KeyStoreException e) {
}
return null;
}
public String export() throws Exception{
KeyStore keystore=KeyStore.getInstance(keyStoreType);
BASE64Encoder encoder=new BASE64Encoder();
keystore.load(keystoreFile,password);
KeyPair keyPair=getPrivateKey(keystore,alias,password);
PrivateKey privateKey=keyPair.getPrivate();
String encoded=encoder.encode(privateKey.getEncoded());
return encoded;
}
public static void main(String args[]) throws Exception{
ExportPrivateKey export=new ExportPrivateKey();
//export.keystoreFile=new File("/Users/Luke/Workspace/StringTest/src/com/lukejin/stringtest/keystore.jks");
export.keyStoreType="JKS";
export.password="changeit".toCharArray();
export.alias="tom_server";
//export.exportedFile=new File("luke");
export.export();
}
}
package com.cm_crm.util.auth;
import com.cm_crm.service.UserService;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @author wangmenglong
* @description: TODO
* @date 2024/1/31 16:51
*/
@Component
@Getter
public class InjectUtil {
@Autowired
private UserService userService;
@PostConstruct
public void init(){
InjectUtil.getInstance().userService = this.userService;
}
//实现单例 start
private static class SingletonHolder {
private static final InjectUtil INSTANCE = new InjectUtil();
}
private InjectUtil(){}
public static final InjectUtil getInstance() {
return SingletonHolder.INSTANCE;
}
//实现单例 end
}
package com.cm_crm.util.auth;
import com.alibaba.fastjson.JSON;
import com.cm_crm.bean.auth.SelfUserEntity;
import com.cm_crm.config.auth.JWTConfig;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.core.io.ClassPathResource;
import java.io.InputStream;
import java.util.Date;
public class JWTTokenUtil {
/**
* 私有化构造器
*/
private JWTTokenUtil(){}
/**
* 生成Token
* @author wml
* @date 2020/4/4
* @param selfUserEntity
* @return
**/
public static String createAccessToken(SelfUserEntity selfUserEntity){
String provider="";
try {
ClassPathResource classPathResource = new ClassPathResource("cm-crm-jwt.jks");
InputStream inputStream =classPathResource.getInputStream();
ExportPrivateKey export=new ExportPrivateKey();
export.keystoreFile=inputStream;
export.keyStoreType="JKS";
export.password= JWTConfig.secret.toCharArray();
export.alias="cm-crm-jwt";
//export.exportedFile=new File("luke");
provider=export.export();
} catch (Exception e) {
System.out.println("Token无效1");
return null;
}
// 登陆成功生成JWT
String token = Jwts.builder()
// 放入用户名和用户ID
.setId(selfUserEntity.getUserId()+"")
// 主题
.setSubject(selfUserEntity.getUsername())
// 签发时间
.setIssuedAt(new Date())
// 签发者
.setIssuer("sans")
// 自定义属性 放入用户拥有权限/派遣公司
.claim("authorities", JSON.toJSONString(selfUserEntity.getAuthorities()))
.claim("baseCode",selfUserEntity.getBaseCode())
.claim("type",selfUserEntity.getType())
.claim("name",selfUserEntity.getName())
.claim("roleId",selfUserEntity.getRoleId())
.claim("roleTag",selfUserEntity.getRoleTag())
.claim("idNo",selfUserEntity.getIdNo())
.claim("openId",selfUserEntity.getOpenId())
.claim("phone", selfUserEntity.getPhone())
.claim("superAdmin", selfUserEntity.getSuperAdmin())
// 失效时间
.setExpiration(new Date(System.currentTimeMillis() + JWTConfig.expiration))
// 签名算法和密钥
.signWith(SignatureAlgorithm.HS512, provider)
.compact();
return token;
}
}
package com.cm_crm.util.auth;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import javax.security.auth.x500.X500Principal;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Date;
/**
* @author wangmenglong
* @description: 生成jks文件
* @date 2024/1/3 18:43
*/
public class JksGenerator {
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, null);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
X509Certificate cert = generateCertificate(keyPair);
keyStore.setKeyEntry("cm-crm-jwt", keyPair.getPrivate(), "cm-crm@junying".toCharArray(), new Certificate[]{cert});
FileOutputStream fos = new FileOutputStream("cm-crm-jwt.jks");
keyStore.store(fos, "cm-crm@junying".toCharArray());
fos.close();
}
private static X509Certificate generateCertificate(KeyPair keyPair) throws CertificateEncodingException, NoSuchAlgorithmException, SignatureException, NoSuchProviderException, InvalidKeyException {
// 创建证书生成器
X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
// 设置证书的基本信息
certGenerator.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
certGenerator.setSubjectDN(new X500Principal("CN=Test Certificate"));
certGenerator.setIssuerDN(new X500Principal("CN=Test CA Certificate"));
certGenerator.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24));
certGenerator.setNotAfter(new Date(System.currentTimeMillis() + 1000L * 60 * 60 * 24 * 365));
certGenerator.setPublicKey(keyPair.getPublic());
certGenerator.setSignatureAlgorithm("SHA256WithRSAEncryption");
// 生成证书
return certGenerator.generate(keyPair.getPrivate(), "BC");
}
}
package com.cm_crm.util.auth;
import com.alibaba.fastjson.JSON;
import javax.servlet.ServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
public class ResultUtil {
/**
* 私有化构造器
*/
private ResultUtil(){}
/**
* 使用response输出JSON
* @author wml
* @date 2020-04-04
**/
public static void responseJson(ServletResponse response, Map<String, Object> resultMap){
PrintWriter out = null;
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
out = response.getWriter();
out.println(JSON.toJSONString(resultMap));
} catch (Exception e) {
System.out.println("【JSON输出异常】"+e);
}finally{
if(out!=null){
out.flush();
out.close();
}
}
}
/**
* 返回成功示例
* @author wml
* @date 2020/4/4
* @param resultMap
* @return
**/
public static Map<String, Object> resultSuccess(Map<String, Object> resultMap){
resultMap.put("message","操作成功");
resultMap.put("code", 200);
return resultMap;
}
/**
* 返回失败示例
* @author wml
* @date 2020/4/4
* @param resultMap
* @return
**/
public static Map<String, Object> resultError(Map<String, Object> resultMap){
resultMap.put("message","操作失败");
resultMap.put("code",500);
return resultMap;
}
/**
* 通用示例
* @author wml
* @date 2020/4/4
* @param code
* @param msg
* @return
**/
public static Map<String, Object> resultCode(Integer code,String msg){
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("message",msg);
resultMap.put("code",code);
return resultMap;
}
}
package com.cm_crm.util.auth;
import com.alibaba.fastjson.JSONObject;
import com.cm_crm.bean.auth.SelfUserEntity;
import com.cm_crm.bean.auth.UserContext;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* @Author zhangziyuan
* @Description
* @Date 2021/7/16
**/
public class UserUtils {
public static JSONObject getCurrentUser(){
SelfUserEntity principal = (SelfUserEntity) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
JSONObject jsonObject = new JSONObject();
jsonObject.put("username",principal.getUsername());
jsonObject.put("userid",principal.getUserId());
jsonObject.put("baseCode",principal.getBaseCode());
jsonObject.put("type",principal.getAuthorities().toArray()[0].toString().split("_")[1]);
return jsonObject;
}
/**
* 获取登录用户上下文
*
* @return
*/
public static UserContext getUserContext() {
SelfUserEntity principal = (SelfUserEntity) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserContext userContext = new UserContext();
userContext.setUserId(principal.getUserId());
userContext.setAccount(principal.getUsername());
userContext.setBaseCode(principal.getBaseCode());
userContext.setType(principal.getType());
userContext.setRoleId(principal.getRoleId());
userContext.setIdNo(principal.getIdNo());
userContext.setUsername(principal.getName());
userContext.setRoleTag(principal.getRoleTag());
userContext.setPhone(principal.getPhone());
userContext.setOpenId(principal.getOpenId());
userContext.setSuperAdmin(principal.getSuperAdmin());
return userContext;
}
/**
* 获取登录用户上下文
* @return
*/
public static SelfUserEntity getSelfUserEntity() {
SelfUserEntity principal = (SelfUserEntity) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return principal;
}
}
package com.cm_crm.util.httpUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
* @ClassName : HttpUtils
* @Description :
* @Author : wml
* @Date: 2025-05-06 12:52
*/
public class HttpUtils {
/**
* 发送 GET 请求
* @param url 请求地址
* @param headers 请求头 (key-value形式)
* @return 响应内容
* @throws IOException
*/
public static String get(String url, Map<String, String> headers) throws IOException {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
// 创建连接
URL requestUrl = new URL(url);
connection = (HttpURLConnection) requestUrl.openConnection();
connection.setRequestMethod("GET");
// 设置请求头
if (headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
}
// 获取响应
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
reader = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
return response.toString();
} else {
throw new IOException("GET request failed with response code: " + responseCode);
}
} finally {
// 关闭资源
if (reader != null) {
reader.close();
}
if (connection != null) {
connection.disconnect();
}
}
}
/**
* 发送 POST 请求
* @param url 请求地址
* @param headers 请求头 (key-value形式)
* @param body 请求体内容
* @return 响应内容
* @throws IOException
*/
public static String post(String url, Map<String, String> headers, String body) throws IOException {
HttpURLConnection connection = null;
BufferedReader reader = null;
OutputStream outputStream = null;
try {
// 创建连接
URL requestUrl = new URL(url);
connection = (HttpURLConnection) requestUrl.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
// 设置请求头
if (headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
}
// 发送请求体
if (body != null && !body.isEmpty()) {
outputStream = connection.getOutputStream();
outputStream.write(body.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
}
// 获取响应
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK ||
responseCode == HttpURLConnection.HTTP_CREATED) {
reader = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
return response.toString();
} else {
throw new IOException("POST request failed with response code: " + responseCode);
}
} finally {
// 关闭资源
if (outputStream != null) {
outputStream.close();
}
if (reader != null) {
reader.close();
}
if (connection != null) {
connection.disconnect();
}
}
}
}
package com.cm_crm.xsnowflake;
public enum BRStyle {
CO("CO", "社区模块"),
;
private final String code;
private final String info;
BRStyle(String code, String info) {
this.code = code;
this.info = info;
}
public String getCode() {
return code;
}
public String getInfo() {
return info;
}
}
package com.cm_crm.xsnowflake;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
public class SnowFlakeFactory {
/**
* 起始的时间戳
* 2020-01-01 00:00:00 毫秒
*/
private final static long START_STMP = 1577808000000L;
/**
* 每一部分占用的位数
*/
private final static long SEQUENCE_BIT = 12; //序列号占用的位数
private final static long MACHINE_BIT = 5; //机器标识占用的位数
private final static long DATACENTER_BIT = 5;//数据中心占用的位数
/**
* 每一部分的最大值
* MAX_DATACENTER_NUM = 31
* MAX_MACHINE_NUM = 31
* MAX_SEQUENCE = 4095
*/
private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
/**
* 每一部分向左的位移
*/
private final static long MACHINE_LEFT = SEQUENCE_BIT;
private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
private long datacenterId = 0; //数据中心
private long machineId = 0; //机器标识
private long sequence = 0L; //序列号
private long lastStmp = -1L;//上一次时间戳
/**
* 最大容忍时间, 单位毫秒, 即如果时钟只是回拨了该变量指定的时间, 那么等待相应的时间即可;
* 考虑到sequence服务的高性能, 这个值不易过大
*/
private static final long MAX_BACKWARD_MS = 5;
//最大扩展字段
private long maxExtension = 2L;
/**
* 保留machineId和lastTimestamp, 以及备用machineId和其对应的lastTimestamp
*/
private static Map<Long, Long> machineIdLastTimeMap = new ConcurrentHashMap<Long, Long>();
/**
* 初始化数据中心位,和机器标识
* 0 < datacenterId < MAX_DATACENTER_NUM 31
* 0 < machineId < MAX_MACHINE_NUM 31
*
* @param datacenterId
* @param machineId
*/
public SnowFlakeFactory(long datacenterId, long machineId) {
if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
throw new IllegalArgumentException(" datacenterId 必须介于[0,31] ");
}
if (machineId > MAX_MACHINE_NUM || machineId < 0) {
throw new IllegalArgumentException(" machineId 必须介于[0,31] ");
}
this.datacenterId = datacenterId;
this.machineId = machineId;
//初始化时间 machineIdLastTimeMap
machineIdLastTimeMap.put(machineId, getNewstmp());
}
/**
* 产生下一个ID
*
* @return
*/
public synchronized String nextId() {
// public synchronized String nextId(BRStyle brStyle) {
//现存的扩展字段
long extension = 0L;
//获取当前时间毫秒数
long currStmp = getNewstmp();
//lastStmp = currStmp + 100;
if (currStmp < lastStmp) {
//throw new RuntimeException("时钟向后移动,拒绝生成id");
// 如果时钟回拨在可接受范围内, 等待即可
long offset = lastStmp - currStmp;
//如果回拨时间不超过5毫秒,就等待相应的时间
if (offset <= MAX_BACKWARD_MS) {
try {
//睡(lastTimestamp - currentTimestamp)ms让其追上
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(offset));
currStmp = getNewstmp();
//如果时间还小于当前时间,那么利用扩展字段加1
//或者是采用抛异常并上报
if (currStmp < lastStmp) {
//扩展字段
extension += 1;
if (extension > maxExtension) {
//服务器时钟被调整了,ID生成器停止服务.
throw new RuntimeException(String.format("时钟向后移动。拒绝生成的id %d 毫秒", lastStmp - currStmp));
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
//扩展字段
extension += 1;
if (extension > maxExtension) {
//服务器时钟被调整了,ID生成器停止服务.
throw new RuntimeException(String.format("时钟向后移动,超出扩展位,拒绝生成的id %d 毫秒", lastStmp - currStmp));
}
//获取可以用的workid,对应的时间戳,必须大于当前时间戳
tryGenerateKeyOnBackup(currStmp);
}
}
if (currStmp == lastStmp) {
//相同毫秒内,序列号自增
sequence = (sequence + 1) & MAX_SEQUENCE;
//同一毫秒的序列数已经达到最大
if (sequence == 0L) {
currStmp = getNextMill();
}
} else {
//不同毫秒内,序列号置为0
sequence = 0L;
}
lastStmp = currStmp;
long id = (currStmp - START_STMP) << (TIMESTMP_LEFT - extension) //时间戳部分
| datacenterId << DATACENTER_LEFT //数据中心部分
| machineId << MACHINE_LEFT //机器标识部分
| sequence; //序列号部分
//如果时间戳回拨就让时间少移动一位
// return brStyle.getCode() + id;
return Long.toString(id);
}
/**
* 自旋锁获取当前时间戳
*
* @return
*/
private long getNextMill() {
long mill = getNewstmp();
while (mill <= lastStmp) {
mill = getNewstmp();
}
return mill;
}
/**
* 获取当前时间毫秒数
*
* @return
*/
private long getNewstmp() {
return System.currentTimeMillis();
//测试时间回拨
//return 53501026489350000l;
}
/**
* 尝试在machineId的备份machineId上生成
* 核心优化代码在方法tryGenerateKeyOnBackup()中,BACKUP_COUNT即备份machineId数越多,
* sequence服务避免时钟回拨影响的能力越强,但是可部署的sequence服务越少,
* 设置BACKUP_COUNT为3,最多可以部署1024/(3+1)即256个sequence服务,完全够用,
* 抗时钟回拨影响的能力也得到非常大的保障。
*
* @param currentMillis 当前时间
*/
private long tryGenerateKeyOnBackup(long currentMillis) {
// 遍历所有machineId(包括备用machineId, 查看哪些machineId可用)
for (Map.Entry<Long, Long> entry : machineIdLastTimeMap.entrySet()) {
this.machineId = entry.getKey();
// 取得备用machineId的lastTime
Long tempLastTime = entry.getValue();
lastStmp = tempLastTime == null ? 0L : tempLastTime;
// 如果找到了合适的machineId,返回合适的时间,
if (lastStmp <= currentMillis) {
return lastStmp;
}
}
// 如果所有machineId以及备用machineId都处于时钟回拨, 那么抛出异常
throw new IllegalStateException("时钟在向后移动,当前时间是 " + currentMillis + " 毫秒,machineId映射 = " + machineIdLastTimeMap);
}
}
package com.cm_crm.xsnowflake;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "snowflake")
public class SnowflakeConfig {
//数据中心[0,31] 配置文件中不配置就是0
private long datacenterId;
//机器标识[0,31] 配置文件中不配置就是0
private long machineId;
@Bean
public SnowFlakeFactory getSnowFlakeFactory() {
SnowFlakeFactory snowFlakeFactory = new SnowFlakeFactory(datacenterId, machineId);
return snowFlakeFactory;
}
public long getDatacenterId() {
return datacenterId;
}
public void setDatacenterId(long datacenterId) {
this.datacenterId = datacenterId;
}
public long getMachineId() {
return machineId;
}
public void setMachineId(long machineId) {
this.machineId = machineId;
}
}
nacos:
server-addr: 192.168.0.100:8848
namespace: cm_crm
group: cm-crm-group
port: 8000
profiles:
active:
#---------------------------------------------------
management:
endpoint:
health:
probes:
enabled: true
health:
livenessstate:
enabled: true
readinessstate:
enabled: true
server:
port: ${nacos.port}
snowflake:
machine-id: 1
data-center-id: 1
spring:
profiles:
active: #必须在application上面
application:
name: cm_crm
#毕竟各个不同的组件都是独立开发的,集成到一起后总会遇到各种惊喜。spring.main.allow-bean-definition-overriding=true就是解决bean重复定义的。设置为true时,后定义的bean会覆盖之前定义的相同名称的bean。
# main:
# allow-bean-definition-overriding: true
cloud:
nacos:
bootstrap.enabled: true
discovery:
server-addr: ${nacos.server-addr}
namespace: ${nacos.namespace}
group: ${nacos.group} #服务分组
username: nacos
password: nacos
config:
username: nacos
password: nacos
server-addr: ${nacos.server-addr}
namespace: ${nacos.namespace}
group: ${nacos.group}
file-extension: yaml
shared-configs[0]:
namespace: ${nacos.namespace}
data-id: cm-crm-datasource-config.yaml
group: ${nacos.group}
refresh: true
shared-configs[1]:
namespace: ${nacos.namespace}
data-id: cm-crm-redis-config.yaml
group: ${nacos.group}
refresh: true
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
\ No newline at end of file
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<groupId>com.cm.crm</groupId>
<artifactId>cm</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<properties>
<hutool-all.version>5.4.3</hutool-all.version>
<lombok.version>1.18.8</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.2.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.9.RELEASE</spring-cloud-alibaba.version>
<sys-lib.version>1.0-SNAPSHOT</sys-lib.version>
<druid.version>1.2.21</druid.version>
<fastjson.version>1.2.75</fastjson.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<cm-crm-lib.version>1.0</cm-crm-lib.version>
<log4j.version>1.2.17</log4j.version>
<easyexcel.version>2.2.10</easyexcel.version>
<mybatisplus.version>3.5.5</mybatisplus.version>
<pagehelper.version>1.3.1</pagehelper.version>
<com.google.zxing.version>3.3.0</com.google.zxing.version>
<druid.starter.version>1.2.21</druid.starter.version>
<dockerfile.version>1.4.10</dockerfile.version>
<okhttp.version>3.12.0</okhttp.version>
<thumbnailator.version>0.4.8</thumbnailator.version>
<pagehelper.version>1.3.0</pagehelper.version>
<mysql-connector.version>8.3.0</mysql-connector.version>
<protobuf.version>3.18.1</protobuf.version>
<org.apache.lang3.version>3.9</org.apache.lang3.version>
<aliyun-sdk-oss.version>3.10.2</aliyun-sdk-oss.version>
<com.tencentcloudapi.ocr.version>3.1.931</com.tencentcloudapi.ocr.version>
<com.tencentcloudapi.sms.version>3.1.893</com.tencentcloudapi.sms.version>
<cos_api.version>5.6.155</cos_api.version>
<wechatpay-apiv3.version>0.2.12</wechatpay-apiv3.version>
<tencentcloud-sdk-java.version>3.1.213</tencentcloud-sdk-java.version>
<nacos-client.version>2.0.3</nacos-client.version>
<spring-cloud-stream-binder-rocketmq.version>0.9.0.RELEASE</spring-cloud-stream-binder-rocketmq.version>
<aliyun-ocr.version>2.0.3</aliyun-ocr.version>
<spring-security-jwt.version>1.0.9.RELEASE</spring-security-jwt.version>
<jjwt.version>0.9.0</jjwt.version>
<spring-cloud-starter-bootstrap.version>3.1.3</spring-cloud-starter-bootstrap.version>
<spring-test.version>5.3.9</spring-test.version>
<facebody20191230.version>5.1.0</facebody20191230.version>
<canal-spring-boot-starter.version>1.2.1-RELEASE</canal-spring-boot-starter.version>
<sharding.version>4.1.1</sharding.version>
<cm-crm-auth.version>1.0</cm-crm-auth.version>
</properties>
<modules>
<module>cm-crm-lib</module>
<module>cm-crm</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.starter.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.cm.crm</groupId>
<artifactId>cm-crm-lib</artifactId>
<version>${cm-crm-lib.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
<dependency>
<groupId>com.cm_crm</groupId>
<artifactId>cm-crm-auth</artifactId>
<version>${cm-crm-auth.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>${com.google.zxing.version}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>${com.google.zxing.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>${thumbnailator.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-sdk-oss.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${org.apache.lang3.version}</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-ocr</artifactId>
<version>${com.tencentcloudapi.ocr.version}</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-sms</artifactId>
<version>${com.tencentcloudapi.sms.version}</version>
</dependency>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>${cos_api.version}</version>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>${wechatpay-apiv3.version}</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>${tencentcloud-sdk-java.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos-client.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rocketmq</artifactId>
<version>${spring-cloud-stream-binder-rocketmq.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>ocr_api20210707</artifactId>
<version>${aliyun-ocr.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>${spring-security-jwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>${spring-cloud-starter-bootstrap.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-test.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>facebody20191230</artifactId>
<version>${facebody20191230.version}</version>
</dependency>
<dependency>
<groupId>top.javatool</groupId>
<artifactId>canal-spring-boot-starter</artifactId>
<version>${canal-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>${sharding.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论