Commit e333a9ea by xlx

删除冗余代码,调整框架版本

parent 18554882
Showing with 2814 additions and 1182 deletions
......@@ -11,7 +11,7 @@
## 平台简介
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
快速开发平台,毫无保留给个人及企业免费使用。
* 采用前后端分离的模式,微服务版本前端(基于 [matchtech-Vue](https://gitee.com/y_project/matchtech-Vue))。
* 后端采用Spring Boot、Spring Cloud & Alibaba。
......@@ -19,8 +19,6 @@
* 流量控制框架选型Sentinel,分布式事务选型Seata。
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[matchtech-Cloud-Vue3](https://gitcode.com/yangzongzhuan/matchtech-Cloud-Vue3),保持同步更新。
* 如需不分离应用,请移步 [matchtech](https://gitee.com/y_project/matchtech),如需分离应用,请移步 [matchtech-Vue](https://gitee.com/y_project/matchtech-Vue)
* 阿里云优惠券:[点我进入](http://aly.matchtech.vip),腾讯云优惠券:[点我进入](http://txy.matchtech.vip)  
## 系统模块
~~~
......@@ -50,10 +48,6 @@ com.matchtech
├──pom.xml // 公共依赖
~~~
## 架构图
<img src="https://oscimg.oschina.net/oscnet/up-82e9722ecb846786405a904bafcf19f73f3.png"/>
## 内置功能
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
......@@ -73,57 +67,3 @@ com.matchtech
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
16. 在线构建器:拖动表单元素生成相应的HTML代码。
17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
## 在线体验
- admin/admin123
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
演示地址:http://matchtech.vip
文档地址:http://doc.matchtech.vip
## 演示图
<table>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-4148b24f58660a9dc347761e4cf6162f28f.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-ece3fd37a3d4bb75a3926e905a3c5629055.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-92ffb7f3835855cff100fa0f754a6be0d99.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-ff9e3066561574aca73005c5730c6a41f15.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
</tr>
</table>
## 若依微服务交流群
QQ群: [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/已满-158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) [![加入QQ群](https://img.shields.io/badge/112869560-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Kuaw0Xdlw2Nlgn6s8h9elzuquHGxGObD&authKey=cSrQcWQ%2BzQZAFFrwxaR%2BbzcumX4WRduZnd1O6JO1dlclQMiu%2BKwxAy8t2JfNp67V&noverify=0&group_code=112869560) 点击按钮入群。
\ No newline at end of file
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-api</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import com.matchtech.common.core.constant.ServiceNameConstants;
import com.matchtech.common.core.constants.ServiceNameConstants;
import com.matchtech.common.core.domain.R;
import com.matchtech.system.api.domain.SysFile;
import com.matchtech.system.api.factory.RemoteFileFallbackFactory;
......
......@@ -4,8 +4,8 @@ import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constant.ServiceNameConstants;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.common.core.constants.ServiceNameConstants;
import com.matchtech.common.core.domain.R;
import com.matchtech.system.api.domain.SysLogininfor;
import com.matchtech.system.api.domain.SysOperLog;
......
package com.matchtech.system.api;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.common.core.constants.ServiceNameConstants;
import com.matchtech.common.core.domain.R;
import com.matchtech.system.api.domain.SysUser;
import com.matchtech.system.api.factory.RemoteUserFallbackFactory;
import com.matchtech.system.api.model.LoginUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
......@@ -7,21 +13,14 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constant.ServiceNameConstants;
import com.matchtech.common.core.domain.R;
import com.matchtech.system.api.domain.SysUser;
import com.matchtech.system.api.factory.RemoteUserFallbackFactory;
import com.matchtech.system.api.model.LoginUser;
/**
* 用户服务
*
*
* @author matchtech
*/
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService
{
public interface RemoteUserService {
/**
* 通过用户名查询用户信息
*
......@@ -51,4 +50,5 @@ public interface RemoteUserService
*/
@PutMapping("/user/recordlogin")
public R<Boolean> recordUserLogin(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}
......@@ -2,13 +2,14 @@ package com.matchtech.system.api.domain;
import java.util.ArrayList;
import java.util.List;
import com.matchtech.common.core.domain.BaseEntity;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.matchtech.common.core.web.domain.BaseEntity;
/**
* 部门表 sys_dept
......@@ -181,23 +182,4 @@ public class SysDept extends BaseEntity
this.children = children;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("deptId", getDeptId())
.append("parentId", getParentId())
.append("ancestors", getAncestors())
.append("deptName", getDeptName())
.append("orderNum", getOrderNum())
.append("leader", getLeader())
.append("phone", getPhone())
.append("email", getEmail())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}
package com.matchtech.system.api.domain;
import com.matchtech.common.core.domain.BaseEntity;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.matchtech.common.core.annotation.Excel;
import com.matchtech.common.core.annotation.Excel.ColumnType;
import com.matchtech.common.core.constant.UserConstants;
import com.matchtech.common.core.web.domain.BaseEntity;
import com.matchtech.common.core.constants.UserConstants;
/**
* 字典数据表 sys_dict_data
......@@ -153,24 +153,4 @@ public class SysDictData extends BaseEntity
{
this.status = status;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("dictCode", getDictCode())
.append("dictSort", getDictSort())
.append("dictLabel", getDictLabel())
.append("dictValue", getDictValue())
.append("dictType", getDictType())
.append("cssClass", getCssClass())
.append("listClass", getListClass())
.append("isDefault", getIsDefault())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}
package com.matchtech.system.api.domain;
import com.matchtech.common.core.domain.BaseEntity;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
......@@ -7,7 +8,6 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.matchtech.common.core.annotation.Excel;
import com.matchtech.common.core.annotation.Excel.ColumnType;
import com.matchtech.common.core.web.domain.BaseEntity;
/**
* 字典类型表 sys_dict_type
......@@ -78,19 +78,5 @@ public class SysDictType extends BaseEntity
{
this.status = status;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("dictId", getDictId())
.append("dictName", getDictName())
.append("dictType", getDictType())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}
......@@ -4,7 +4,7 @@ import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.matchtech.common.core.annotation.Excel;
import com.matchtech.common.core.annotation.Excel.ColumnType;
import com.matchtech.common.core.web.domain.BaseEntity;
import com.matchtech.common.core.domain.BaseEntity;
/**
* 系统访问记录表 sys_logininfor
......
......@@ -4,7 +4,7 @@ import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.matchtech.common.core.annotation.Excel;
import com.matchtech.common.core.annotation.Excel.ColumnType;
import com.matchtech.common.core.web.domain.BaseEntity;
import com.matchtech.common.core.domain.BaseEntity;
/**
* 操作日志记录表 oper_log
......
package com.matchtech.system.api.domain;
import java.util.Set;
import com.matchtech.common.core.domain.BaseEntity;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
......@@ -8,7 +10,6 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.matchtech.common.core.annotation.Excel;
import com.matchtech.common.core.annotation.Excel.ColumnType;
import com.matchtech.common.core.web.domain.BaseEntity;
/**
* 角色表 sys_role
......@@ -218,24 +219,4 @@ public class SysRole extends BaseEntity
{
this.permissions = permissions;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("roleId", getRoleId())
.append("roleName", getRoleName())
.append("roleKey", getRoleKey())
.append("roleSort", getRoleSort())
.append("dataScope", getDataScope())
.append("menuCheckStrictly", isMenuCheckStrictly())
.append("deptCheckStrictly", isDeptCheckStrictly())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}
......@@ -2,15 +2,16 @@ package com.matchtech.system.api.domain;
import java.util.Date;
import java.util.List;
import com.matchtech.common.core.domain.BaseEntity;
import jakarta.validation.constraints.*;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.matchtech.common.core.annotation.Excel;
import com.matchtech.common.core.annotation.Excel.ColumnType;
import com.matchtech.common.core.annotation.Excel.Type;
import com.matchtech.common.core.constant.UserConstants;
import com.matchtech.common.core.constants.UserConstants;
import com.matchtech.common.core.annotation.Excels;
import com.matchtech.common.core.web.domain.BaseEntity;
import com.matchtech.common.core.xss.Xss;
/**
......@@ -310,30 +311,5 @@ public class SysUser extends BaseEntity
{
this.roleId = roleId;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("userId", getUserId())
.append("deptId", getDeptId())
.append("userName", getUserName())
.append("nickName", getNickName())
.append("email", getEmail())
.append("phonenumber", getPhonenumber())
.append("sex", getSex())
.append("avatar", getAvatar())
.append("password", getPassword())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("loginIp", getLoginIp())
.append("loginDate", getLoginDate())
.append("pwdUpdateDate", getPwdUpdateDate())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("dept", getDept())
.toString();
}
}
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>rapidplatform-cloud</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
package com.matchtech.matchtechauthidm.controller;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.v3.oas.annotations.tags.Tag;
@Tag(name = "统一平台单点登录")
@RestController
@RequestMapping("/idm/sso")
@RequiredArgsConstructor
public class IdmController {
}
......@@ -4,71 +4,19 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>rapidplatform-cloud</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>matchtech-auth</artifactId>
<packaging>pom</packaging>
<description>
matchtech-auth认证授权中心
</description>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- matchtech Common Security-->
<dependency>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common-security</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<modules>
<module>matchtech-auth-idm</module>
<module>matchtech-auth-local</module>
</modules>
</project>
package com.matchtech.auth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import com.matchtech.common.security.annotation.EnableRyFeignClients;
/**
* 认证授权中心
*
* @author matchtech
*/
@EnableRyFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class MatchtechAuthApplication
{
public static void main(String[] args)
{
SpringApplication.run(MatchtechAuthApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 认证授权中心启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}
package com.matchtech.auth.controller;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.matchtech.auth.form.LoginBody;
import com.matchtech.auth.form.RegisterBody;
import com.matchtech.auth.service.SysLoginService;
import com.matchtech.common.core.domain.R;
import com.matchtech.common.core.utils.JwtUtils;
import com.matchtech.common.core.utils.StringUtils;
import com.matchtech.common.security.auth.AuthUtil;
import com.matchtech.common.security.service.TokenService;
import com.matchtech.common.security.utils.SecurityUtils;
import com.matchtech.system.api.model.LoginUser;
/**
* token 控制
*
* @author matchtech
*/
@RestController
public class TokenController
{
@Autowired
private TokenService tokenService;
@Autowired
private SysLoginService sysLoginService;
@PostMapping("login")
public R<?> login(@RequestBody LoginBody form)
{
// 用户登录
LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
// 获取登录token
return R.ok(tokenService.createToken(userInfo));
}
@DeleteMapping("logout")
public R<?> logout(HttpServletRequest request)
{
String token = SecurityUtils.getToken(request);
if (StringUtils.isNotEmpty(token))
{
String username = JwtUtils.getUserName(token);
// 删除用户缓存记录
AuthUtil.logoutByToken(token);
// 记录用户退出日志
sysLoginService.logout(username);
}
return R.ok();
}
@PostMapping("refresh")
public R<?> refresh(HttpServletRequest request)
{
LoginUser loginUser = tokenService.getLoginUser(request);
if (StringUtils.isNotNull(loginUser))
{
// 刷新令牌有效期
tokenService.refreshToken(loginUser);
return R.ok();
}
return R.ok();
}
@PostMapping("register")
public R<?> register(@RequestBody RegisterBody registerBody)
{
// 用户注册
sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
return R.ok();
}
}
package com.matchtech.auth.form;
/**
* 用户登录对象
*
* @author matchtech
*/
public class LoginBody
{
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}
package com.matchtech.auth.form;
/**
* 用户注册对象
*
* @author matchtech
*/
public class RegisterBody extends LoginBody
{
}
package com.matchtech.auth.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.matchtech.common.core.constant.CacheConstants;
import com.matchtech.common.core.constant.Constants;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constant.UserConstants;
import com.matchtech.common.core.domain.R;
import com.matchtech.common.core.enums.UserStatus;
import com.matchtech.common.core.exception.ServiceException;
import com.matchtech.common.core.text.Convert;
import com.matchtech.common.core.utils.DateUtils;
import com.matchtech.common.core.utils.StringUtils;
import com.matchtech.common.core.utils.ip.IpUtils;
import com.matchtech.common.redis.service.RedisService;
import com.matchtech.common.security.utils.SecurityUtils;
import com.matchtech.system.api.RemoteUserService;
import com.matchtech.system.api.domain.SysUser;
import com.matchtech.system.api.model.LoginUser;
/**
* 登录校验方法
*
* @author matchtech
*/
@Component
public class SysLoginService
{
@Autowired
private RemoteUserService remoteUserService;
@Autowired
private SysPasswordService passwordService;
@Autowired
private SysRecordLogService recordLogService;
@Autowired
private RedisService redisService;
/**
* 登录
*/
public LoginUser login(String username, String password)
{
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password))
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
throw new ServiceException("用户/密码必须填写");
}
// 密码如果不在指定范围内 错误
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
throw new ServiceException("用户密码不在指定范围");
}
// 用户名不在指定范围内 错误
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
throw new ServiceException("用户名不在指定范围");
}
// IP黑名单校验
String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单");
throw new ServiceException("很遗憾,访问IP已被列入系统黑名单");
}
// 查询用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode())
{
throw new ServiceException(userResult.getMsg());
}
LoginUser userInfo = userResult.getData();
SysUser user = userResult.getData().getSysUser();
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
}
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
passwordService.validate(user, password);
recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
recordLoginInfo(user.getUserId());
return userInfo;
}
/**
* 记录登录信息
*
* @param userId 用户ID
*/
public void recordLoginInfo(Long userId)
{
SysUser sysUser = new SysUser();
sysUser.setUserId(userId);
// 更新用户登录IP
sysUser.setLoginIp(IpUtils.getIpAddr());
// 更新用户登录时间
sysUser.setLoginDate(DateUtils.getNowDate());
remoteUserService.recordUserLogin(sysUser, SecurityConstants.INNER);
}
public void logout(String loginName)
{
recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
}
/**
* 注册
*/
public void register(String username, String password)
{
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password))
{
throw new ServiceException("用户/密码必须填写");
}
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
throw new ServiceException("账户长度必须在2到20个字符之间");
}
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
throw new ServiceException("密码长度必须在5到20个字符之间");
}
// 注册用户信息
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPwdUpdateDate(DateUtils.getNowDate());
sysUser.setPassword(SecurityUtils.encryptPassword(password));
R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);
if (R.FAIL == registerResult.getCode())
{
throw new ServiceException(registerResult.getMsg());
}
recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功");
}
}
package com.matchtech.auth.service;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.matchtech.common.core.constant.CacheConstants;
import com.matchtech.common.core.constant.Constants;
import com.matchtech.common.core.exception.ServiceException;
import com.matchtech.common.redis.service.RedisService;
import com.matchtech.common.security.utils.SecurityUtils;
import com.matchtech.system.api.domain.SysUser;
/**
* 登录密码方法
*
* @author matchtech
*/
@Component
public class SysPasswordService
{
@Autowired
private RedisService redisService;
private int maxRetryCount = CacheConstants.PASSWORD_MAX_RETRY_COUNT;
private Long lockTime = CacheConstants.PASSWORD_LOCK_TIME;
@Autowired
private SysRecordLogService recordLogService;
/**
* 登录账户密码错误次数缓存键名
*
* @param username 用户名
* @return 缓存键key
*/
private String getCacheKey(String username)
{
return CacheConstants.PWD_ERR_CNT_KEY + username;
}
public void validate(SysUser user, String password)
{
String username = user.getUserName();
Integer retryCount = redisService.getCacheObject(getCacheKey(username));
if (retryCount == null)
{
retryCount = 0;
}
if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
{
String errMsg = String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime);
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL,errMsg);
throw new ServiceException(errMsg);
}
if (!matches(user, password))
{
retryCount = retryCount + 1;
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, String.format("密码输入错误%s次", retryCount));
redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
throw new ServiceException("用户不存在/密码错误");
}
else
{
clearLoginRecordCache(username);
}
}
public boolean matches(SysUser user, String rawPassword)
{
return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
}
public void clearLoginRecordCache(String loginName)
{
if (redisService.hasKey(getCacheKey(loginName)))
{
redisService.deleteObject(getCacheKey(loginName));
}
}
}
package com.matchtech.auth.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.matchtech.common.core.constant.Constants;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.utils.StringUtils;
import com.matchtech.common.core.utils.ip.IpUtils;
import com.matchtech.system.api.RemoteLogService;
import com.matchtech.system.api.domain.SysLogininfor;
/**
* 记录日志方法
*
* @author matchtech
*/
@Component
public class SysRecordLogService
{
@Autowired
private RemoteLogService remoteLogService;
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
* @return
*/
public void recordLogininfor(String username, String status, String message)
{
SysLogininfor logininfor = new SysLogininfor();
logininfor.setUserName(username);
logininfor.setIpaddr(IpUtils.getIpAddr());
logininfor.setMsg(message);
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
{
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
}
else if (Constants.LOGIN_FAIL.equals(status))
{
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
}
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
}
}
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_ _ _
(_) | | | |
_ __ _ _ ___ _ _ _ ______ __ _ _ _ | |_ | |__
| '__|| | | | / _ \ | | | || ||______| / _` || | | || __|| '_ \
| | | |_| || (_) || |_| || | | (_| || |_| || |_ | | | |
|_| \__,_| \___/ \__, ||_| \__,_| \__,_| \__||_| |_|
__/ |
|___/
\ No newline at end of file
# Tomcat
server:
port: 9200
# Spring
spring:
application:
# 应用名称
name: matchtech-auth
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/matchtech-auth" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.matchtech" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>
\ No newline at end of file
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......@@ -53,10 +53,29 @@
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<!-- Mybatis Spring -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<!-- MyBatis 测试 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
</dependency>
<!-- Hibernate Validator -->
......@@ -120,6 +139,37 @@
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common-swagger</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</dependency>
</dependencies>
</project>
package com.matchtech.common.core.async;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean("logAsync")
public ThreadPoolTaskExecutor logAsync() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(4);
threadPoolTaskExecutor.setMaxPoolSize(4);
threadPoolTaskExecutor.setQueueCapacity(10000);
threadPoolTaskExecutor.setThreadNamePrefix("log-thread");
threadPoolTaskExecutor.setKeepAliveSeconds(60);
threadPoolTaskExecutor.setTaskDecorator(new MyTaskDecorator());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
@Bean("fileAsync")
public ThreadPoolTaskExecutor fileAsync() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(4);
threadPoolTaskExecutor.setMaxPoolSize(4);
threadPoolTaskExecutor.setQueueCapacity(10000);
threadPoolTaskExecutor.setThreadNamePrefix("fileAsync-thread");
threadPoolTaskExecutor.setKeepAliveSeconds(60);
threadPoolTaskExecutor.setTaskDecorator(new MyTaskDecorator());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
@Bean("processAsyncExecutor")
public ThreadPoolTaskExecutor processAsync() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(4);
threadPoolTaskExecutor.setMaxPoolSize(4);
threadPoolTaskExecutor.setQueueCapacity(10000);
threadPoolTaskExecutor.setThreadNamePrefix("async-thread");
threadPoolTaskExecutor.setKeepAliveSeconds(60);
threadPoolTaskExecutor.setTaskDecorator(new MyTaskDecorator());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
package com.matchtech.common.core.async;
import org.springframework.core.task.TaskDecorator;
/** 实现TaskDecorator传递MyThreadLocal到子线程
* @author Administrator
*
*/
public class MyTaskDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
String token = MyThreadLocal.getToken();
String tenantId = MyThreadLocal.getTenantId();
return () -> {
try {
MyThreadLocal.setToken(token);
MyThreadLocal.setTenantId(tenantId);
runnable.run();
} finally {
MyThreadLocal.remove();
}
};
}
}
package com.matchtech.common.core.async;
public class MyThreadLocal {
private static ThreadLocal<String> tokenThreadLocal = new ThreadLocal<String>();
private static ThreadLocal<String> tenantIdThreadLocal = new ThreadLocal<String>();
/**
* 设置登录token
*
* @param token
*/
public static void setToken(String token) {
tokenThreadLocal.set(token);
}
/**
* 设置租户id
*
* @param tenantId
*/
public static void setTenantId(String tenantId) {
tenantIdThreadLocal.set(tenantId);
}
/**获取token
* @return
*/
public static String getToken() {
return tokenThreadLocal.get();
}
/**获取tenantid
* @return
*/
public static String getTenantId() {
return tenantIdThreadLocal.get();
}
public static void remove() {
tokenThreadLocal.remove();
tenantIdThreadLocal.remove();
}
}
package com.matchtech.common.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import java.util.List;
import java.util.Map;
@Data
@Component
@ConfigurationProperties(prefix = "matchtech")
public class MatchtechProperties {
private static final AntPathMatcher matcher = new AntPathMatcher();
private Map<String, List<String>> white;
private String tokenTimeout;
private String adminPath;
private String frontPath;
private String validateFlag;
private String signFlag;
private String frontUrl;
private Map<String, List<String>> tenant;
/**
* 异步 Excel 导出过期时间,单位:天
*/
private Integer asyncExcelExportExpire;
/**校验path是否进行登录校验
* @param path
* @return
*/
public boolean containPath(String path) {
List<String> urls = white.get("loginurls");
if (urls == null || urls.size() < 0) {
return false;
}
for (String url : urls) {
if (matcher.match(url, path)) {
return true;
}
}
return false;
}
public String[] toUrlArray() {
return white.get("loginurls") == null ? new String[0] : white.get("loginurls").toArray(new String[0]);
}
}
\ No newline at end of file
package com.matchtech.common.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "redisson.singleserverconfig")
public class RedissionProperties {
private String address;
private String connectionPoolSize;
private String connectionMinimumIdleSize;
private String subscriptionsPerConnection;
private String subscriptionConnectionPoolSize;
private Integer database;
private String auth;
}
\ No newline at end of file
package com.matchtech.common.core.constant;
package com.matchtech.common.core.constants;
/**
* 通用常量信息
......@@ -142,4 +142,41 @@ public class Constants
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.matchtech.common.core.utils.file" };
/**
* 树路径分隔符
*/
public static final String TREE_PATH_SEPARATOR = ",";
/**
* 超管id
*/
public static final String SUPER_ADMIN_ID = "1";
/**
* 树形结构一级节点
*/
public static final String SUPER_NODE = "0";
/**
* 是
*/
public static final String YES = "1";
/**
* 否
*/
public static final String NO = "0";
/**
* 基地固资干事角色code
*/
public static final String BASE_FA_ROLE_CODE = "BaseFa" ;
/**
* 部门负责人角色code
*/
public static final String DEPARTMENT_HEAD_ROLE_CODE = "DepartmentHead";
/**
* 固资管理员角色code
*/
public static final String FA_ADMIN_ROLE_CODE = "FaAdmin";
}
package com.matchtech.common.core.constants;
/**
* 信息编号常量
*
* @author chenyingyi 信息类型: info, error, warning, notice 格式: validation + 信息类型 +
* 模块 + 信息 请按模块区分 例如VALIDATION_ERROR_EXCEPTION
*/
public enum GlobalCodeMessageEnum {
/**
* 系统业务编码 100 - 999编码
*/
// 系统编码
// 成功
SUCCESS(200, "success"),
//部分外部接口响应需要返回0
SUCCESS2(0, "success"),
// 未知异常
SYSTEM_ERROR_EXCEPTION(500, "system.error.exception"),
// 请求方法不对
SYSTEM_ERROR_NOT_ALLOWED(405, "请求方法不对,请检查请求方法(post,get等)"),
// 未找到
SYSTEM_ERROR_NOT_FOUND(404, "请求地址不存在,请检查请求链接"),
// 无权限访问
SYSTEM_ERROR_NOT_AUTH(403, "无权限访问"),
// token错误
SYSTEM_ERROR_TOKEN(101, "system.error.token"),
// 签名错误
SYSTEM_ERROR_SIGN(102, "system.error.sign"),
// 解密错误
SYSTEM_ERROR_DECRYPT(103, "system.error.decrypt"),
// 空指针
SYSTEM_ERROR_NULLPOINTER(104, "未找到数据"),
// 非法参数
SYSTEM_ERROR_ILLEGAL_ARGUMENT(105, "非法参数,请检查参数"),
// 参数类型不匹配
SYSTEM_ERROR_TYPE_MISMATCH(106, "参数类型不匹配"),
// 请求参数缺失
SYSTEM_ERROR_MISSING_SERVLET_REQUEST_PARAMETER(107, "请求参数缺失,必填参数不能为空"),
//body传参异常
SYSTEM_ERROR_BODY_MISMATCH(108, "body参数异常,采用body传参,格式json"),
SYSTEM_ERROR_FILEURL(109, "本地存储不支持获取下载路径"),
SYSTEM_USER_NOT_FOUND(110, "用户未找到"),
SYSTEM_USER_LOGIN_NAME_EXISTS(111, "登录名已存在"),
SYSTEM_TOKEN_NOT_FOUND(112, "token不能为空"),
SYSTEM_TOKEN_OVERDUE(113, "token已失效,请重新登录"),
SYSTEM_CONNECT_TIME_OUT(114, "第三方接口超时"),
SYS_USERNAME_OR_PASSWORD_ERROR(115, "用户名或密码错误"),
SYS_USER_LOGIN_FORBIDDEN(116, "该用户已被禁止登录"),
SYS_USER_OLD_PASSWORD_ERROR(117, "旧密码错误"),
SYS_USER_LOCKED(118, "该用户已被锁定,请稍后再试"),
SYS_USER_INCORRECT_CAPTCHA(119, "验证码错误"),
SYSTEM_ROLE_NOT_FOUND(130, "角色不存在"),
SYSTEM_ROLE_LOGIN_NAME_EXISTS(131, "角色名称已存在"),
SYSTEM_ROLE_IS_SYSTEM_DATA(132, "越权操作,该角色为系统数据"),
SYSTEM_OFFICE_NOT_FOUND(150, "机构不存在"),
SYSTEM_OFFICE_PARENT_NOT_FOUND(151, "父级机构不存在"),
SYSTEM_OFFICE_EXIST_CHILDREN_NOT_ALLOWED(152, "存在下级机构,不可删除"),
SYSTEM_OFFICE_EXIST_USER_NOT_ALLOWED(153, "该机构下存在用户,不可删除"),
DATA_NOT_FOUND(154, "数据未找到"),
SYSTEM_NOT_ADMIN_USER(155, "非admin账号,无法删除角色"),
/**
* 字典
*/
SYS_DICTIONARY_CATEGORY_CODE_EXIT(500, "编码已存在"),
SYS_DICTIONARY_CODE_EXIT(500, "编码已存在"),
SYS_DICTIONARY_VALUE_EXIT(500, "数据值已存在"),
/**
* 用户角色
*/
SYS_USER_ROLE_NOT_USER_EMPTY(500, "请至少选择一个用户或者角色"),
VALIDATION_ERROR_EXCEPTION(1000, "数据校验编码"),
SUB_LIBRARY_CODE_ERROR(2001,"子库编码需为字母+数字组合"),
;
/**
* 消息码
*/
private int code;
/**
* 消息内容
*/
private String message;
private GlobalCodeMessageEnum(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@ package com.matchtech.common.core.context;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.common.core.text.Convert;
import com.matchtech.common.core.utils.StringUtils;
......
package com.matchtech.common.core.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.ibatis.type.JdbcType;
import java.io.Serializable;
import java.util.Date;
@Data
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "ID", type = IdType.ASSIGN_ID)
private String id;
/**
* 创建时间
*/
@TableField(value = "CREATE_TIME",fill = FieldFill.INSERT,jdbcType=JdbcType.DATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private Date createTime;
/**
* 创建者
*
*/
@TableField(value = "CREATE_USER_ID",fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
private String createUserId;
/**
* 创建人姓名
*/
@TableField(value = "CREATE_USER",fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
private String createUser;
/**
* 最后更新时间
*/
@TableField(value = "UPDATE_TIME",fill = FieldFill.INSERT_UPDATE,jdbcType=JdbcType.DATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private Date updateTime;
/**
* 更新者
*
*/
@TableField(value = "UPDATE_USER_ID",fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
private String updateUserId;
/**
* 修改人姓名
*/
@TableField(value = "UPDATE_USER",fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
private String updateUser;
/**
* 逻辑删除 0(false)未删除,1(true)已删除
*/
//@TableLogic(value="0",delval = "UNIX_TIMESTAMP()")
@TableLogic(value = "0", delval = "1")
@TableField(value = "IS_DELETE",select = false, fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
private String isDelete;
}
package com.matchtech.common.core.domain;
import java.io.Serializable;
import com.matchtech.common.core.constant.Constants;
import com.matchtech.common.core.constants.Constants;
/**
* 响应信息主体
......
package com.matchtech.common.core.exception;
import com.matchtech.common.core.constants.GlobalCodeMessageEnum;
/**
* 全局异常
*
* @author matchtech
* 自定义异常rest
*
*/
public class GlobalException extends RuntimeException
{
public class GlobalException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 错误提示
*/
private String message;
private int code = 500;
/**
* 错误明细,内部调试错误
*
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
*/
private String detailMessage;
public GlobalException(String message) {
super(message);
this.message = message;
}
/**
* 空构造方法,避免反序列化问题
*/
public GlobalException()
{
public GlobalException(String message, Throwable e) {
super(message, e);
this.message = message;
}
public GlobalException(String message)
{
public GlobalException(String message, int code) {
super(message);
this.message = message;
this.code = code;
}
public String getDetailMessage()
{
return detailMessage;
public GlobalException(String message, int code, Throwable e) {
super(message, e);
this.message = message;
this.code = code;
}
public GlobalException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
public GlobalException(GlobalCodeMessageEnum globalCodeMessageEnum) {
super(globalCodeMessageEnum.getMessage());
this.message = globalCodeMessageEnum.getMessage();
this.code = globalCodeMessageEnum.getCode();
}
@Override
public String getMessage()
{
public String getMessage() {
return message;
}
public GlobalException setMessage(String message)
{
public void setMessage(String message) {
this.message = message;
return this;
}
}
\ No newline at end of file
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
package com.matchtech.common.core.mybatis;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.matchtech.common.core.page.PageParam;
import com.matchtech.common.core.page.PageReqDto;
import com.matchtech.common.core.page.PageResult;
import com.matchtech.common.core.page.SortingField;
import com.matchtech.common.core.text.Convert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Mapper
public interface BaseMapperX<T> extends BaseMapper<T> {
default PageResult<T> selectPage(PageParam pageParam,
@Param("ew") Wrapper<T> queryWrapper) {
Collection<SortingField> sortingFields = null;
if (null != pageParam.getAscDesc() || null != pageParam.getOrderBy()) {
sortingFields = new ArrayList<>();
SortingField sortingField = new SortingField(Convert.humpConversionUnderscore(pageParam.getOrderBy()), pageParam.getAscDesc());
//StringUtil.humpToUnderline(pageParam.getOrderBy())
sortingFields.add(sortingField);
}
// MyBatis Plus 查询
IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
selectPage(mpPage, queryWrapper);
// 转换返回
return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
}
default PageResult<T> selectPage(PageReqDto pageParam,
@Param("ew") Wrapper<T> queryWrapper) {
Collection<SortingField> sortingFields = null;
if (null != pageParam.getAscDesc() || null != pageParam.getOrderBy()) {
sortingFields = new ArrayList<>();
SortingField sortingField = new SortingField(Convert.humpConversionUnderscore(pageParam.getOrderBy()), pageParam.getAscDesc());
//StringUtil.humpToUnderline(pageParam.getOrderBy())
sortingFields.add(sortingField);
}
// MyBatis Plus 查询
IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
selectPage(mpPage, queryWrapper);
// 转换返回
return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
}
default T selectOne(String field, Object value) {
return selectOne(new QueryWrapper<T>().eq(field, value));
}
default T selectOne(SFunction<T, ?> field, Object value) {
return selectOne(new LambdaQueryWrapper<T>().eq(field, value));
}
default T selectOne(String field1, Object value1, String field2, Object value2) {
return selectOne(new QueryWrapper<T>().eq(field1, value1).eq(field2, value2));
}
default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
}
default Long selectCount() {
return selectCount(new QueryWrapper<T>());
}
default Long selectCount(String field, Object value) {
return selectCount(new QueryWrapper<T>().eq(field, value));
}
default Long selectCount(SFunction<T, ?> field, Object value) {
return selectCount(new LambdaQueryWrapper<T>().eq(field, value));
}
default List<T> selectList() {
return selectList(new QueryWrapper<>());
}
default List<T> selectList(String field, Object value) {
return selectList(new QueryWrapper<T>().eq(field, value));
}
default List<T> selectList(SFunction<T, ?> field, Object value) {
return selectList(new LambdaQueryWrapper<T>().eq(field, value));
}
default List<T> selectList(String field, Collection<?> values) {
return selectList(new QueryWrapper<T>().in(field, values));
}
default List<T> selectList(SFunction<T, ?> field, Collection<?> values) {
return selectList(new LambdaQueryWrapper<T>().in(field, values));
}
default void updateBatch(T update) {
update(update, new QueryWrapper<>());
}
default void insertBatch(Collection<T> entities) {
Db.saveBatch(entities);
}
default void updateBatch(Collection<T> entities) {
Db.updateBatchById(entities);
}
default void updateBatch(Collection<T> entities, int size) {
Db.updateBatchById(entities, size);
}
default void saveOrUpdateBatch(Collection<T> collection) {
Db.saveOrUpdateBatch(collection);
}
}
package com.matchtech.common.core.mybatis;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.function.Consumer;
/**
* 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能:
*
* 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
*
* @param <T> 数据类型
*/
public class LambdaQueryWrapperX<T> extends LambdaQueryWrapper<T> {
public LambdaQueryWrapperX<T> likeIfPresent(SFunction<T, ?> column, String val) {
if (StringUtils.hasText(val)) {
return (LambdaQueryWrapperX<T>) super.like(column, val);
}
return this;
}
public LambdaQueryWrapperX<T> inIfPresent(SFunction<T, ?> column, Collection<?> values) {
if (!CollectionUtils.isEmpty(values)) {
return (LambdaQueryWrapperX<T>) super.in(column, values);
}
return this;
}
public LambdaQueryWrapperX<T> inIfPresent(SFunction<T, ?> column, Object... values) {
if (!ArrayUtil.isEmpty(values)) {
return (LambdaQueryWrapperX<T>) super.in(column, values);
}
return this;
}
public LambdaQueryWrapperX<T> eqIfPresent(SFunction<T, ?> column, Object val) {
if (val != null && StringUtils.hasText(val + "")) {
return (LambdaQueryWrapperX<T>) super.eq(column, val);
}
return this;
}
public LambdaQueryWrapperX<T> neIfPresent(SFunction<T, ?> column, Object val) {
if (val != null && StringUtils.hasText(val + "")) {
return (LambdaQueryWrapperX<T>) super.ne(column, val);
}
return this;
}
public LambdaQueryWrapperX<T> gtIfPresent(SFunction<T, ?> column, Object val) {
if (val != null && StringUtils.hasText(val + "")) {
return (LambdaQueryWrapperX<T>) super.gt(column, val);
}
return this;
}
public LambdaQueryWrapperX<T> geIfPresent(SFunction<T, ?> column, Object val) {
if (val != null && StringUtils.hasText(val + "")) {
return (LambdaQueryWrapperX<T>) super.ge(column, val);
}
return this;
}
public LambdaQueryWrapperX<T> ltIfPresent(SFunction<T, ?> column, Object val) {
if (val != null && StringUtils.hasText(val + "")) {
return (LambdaQueryWrapperX<T>) super.lt(column, val);
}
return this;
}
public LambdaQueryWrapperX<T> leIfPresent(SFunction<T, ?> column, Object val) {
if (val != null && StringUtils.hasText(val + "")) {
return (LambdaQueryWrapperX<T>) super.le(column, val);
}
return this;
}
public LambdaQueryWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object val1, Object val2) {
if (val1 != null && val2 != null && StringUtils.hasText(val1 + "") && StringUtils.hasText(val2 + "")) {
return (LambdaQueryWrapperX<T>) super.between(column, val1, val2);
}
if (val1 != null && StringUtils.hasText(val1 + "")) {
return (LambdaQueryWrapperX<T>) ge(column, val1);
}
if (val2 != null && StringUtils.hasText(val2 + "")) {
return (LambdaQueryWrapperX<T>) le(column, val2);
}
return this;
}
public LambdaQueryWrapperX<T> greaterIfPresent(SFunction<T, ?> column, Object val1) {
if (val1 != null && StringUtils.hasText(val1 + "")) {
return (LambdaQueryWrapperX<T>) ge(column, val1);
}
return this;
}
public LambdaQueryWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object[] values) {
Object val1 = ArrayUtils.get(values, 0);
Object val2 = ArrayUtils.get(values, 1);
return betweenIfPresent(column, val1, val2);
}
// ========== 重写父类方法,方便链式调用 ==========
@Override
public LambdaQueryWrapperX<T> eq(boolean condition, SFunction<T, ?> column, Object val) {
super.eq(condition, column, val);
return this;
}
@Override
public LambdaQueryWrapperX<T> eq(SFunction<T, ?> column, Object val) {
super.eq(column, val);
return this;
}
@Override
public LambdaQueryWrapperX<T> orderByDesc(SFunction<T, ?> column) {
super.orderByDesc(true, column);
return this;
}
@Override
public LambdaQueryWrapperX<T> orderByAsc(SFunction<T, ?> column) {
super.orderByAsc(true, column);
return this;
}
@Override
public LambdaQueryWrapperX<T> last(String lastSql) {
super.last(lastSql);
return this;
}
@Override
public LambdaQueryWrapperX<T> in(SFunction<T, ?> column, Collection<?> coll) {
super.in(column, coll);
return this;
}
public LambdaQueryWrapperX<T> existIfPresent(String sql, Object val) {
if (val != null && StringUtils.hasText(val + "")) {
return (LambdaQueryWrapperX<T>) super.exists(sql, val);
}
return this;
}
public LambdaQueryWrapperX<T> andIfPresent(Consumer consumer,String val) {
if (val != null && StringUtils.hasText(val + "")) {
return (LambdaQueryWrapperX<T>) super.and(consumer);
}
return this;
}
}
package com.matchtech.common.core.mybatis;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.matchtech.common.core.page.PageParam;
import com.matchtech.common.core.page.PageReqDto;
import com.matchtech.common.core.page.PageResult;
import com.matchtech.common.core.page.SortingField;
import com.matchtech.common.core.text.Convert;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* MyBatis 工具类
*/
public class MyBatisUtils {
private static final String MYSQL_ESCAPE_CHARACTER = "`";
public static <T> Page<T> buildPage(PageParam pageParam) {
List<SortingField> sortingFields = new ArrayList<>();
if (StringUtils.isNotEmpty(pageParam.getOrderBy())) {
sortingFields.add(new SortingField(pageParam.getOrderBy(), pageParam.getAscDesc()));
}
return buildPage(pageParam, sortingFields);
}
public static <T> Page<T> buildPage(PageReqDto pageParam) {
List<SortingField> sortingFields = new ArrayList<>();
if (StringUtils.isNotEmpty(pageParam.getOrderBy())) {
sortingFields.add(new SortingField(Convert.humpConversionUnderscore(pageParam.getOrderBy()) , pageParam.getAscDesc()));
}
return buildPage(pageParam, sortingFields);
}
public static <T> Page<T> buildPage(PageParam pageParam, Collection<SortingField> sortingFields) {
// 页码 + 数量
Page<T> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
// 排序字段
if (!CollectionUtil.isEmpty(sortingFields)) {
page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder()) ?
OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField()))
.collect(Collectors.toList()));
}
return page;
}
public static <T> Page<T> buildPage(PageReqDto pageParam, Collection<SortingField> sortingFields) {
// 页码 + 数量
Page<T> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
// 排序字段
if (!CollectionUtil.isEmpty(sortingFields)) {
page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder()) ?
OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField()))
.collect(Collectors.toList()));
}
return page;
}
/**
* 将拦截器添加到链中
* 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置
*
* @param interceptor 链
* @param inner 拦截器
* @param index 位置
*/
public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner, int index) {
List<InnerInterceptor> inners = new ArrayList<>(interceptor.getInterceptors());
inners.add(index, inner);
interceptor.setInterceptors(inners);
}
/**
* 获得 Table 对应的表名
*
* 兼容 MySQL 转义表名 `t_xxx`
*
* @param table 表
* @return 去除转移字符后的表名
*/
public static String getTableName(Table table) {
String tableName = table.getName();
if (tableName.startsWith(MYSQL_ESCAPE_CHARACTER) && tableName.endsWith(MYSQL_ESCAPE_CHARACTER)) {
tableName = tableName.substring(1, tableName.length() - 1);
}
return tableName;
}
/**
* 构建 Column 对象
*
* @param tableName 表名
* @param tableAlias 别名
* @param column 字段名
* @return Column 对象
*/
public static Column buildColumn(String tableName, Alias tableAlias, String column) {
if (tableAlias != null) {
tableName = tableAlias.getName();
}
return new Column(tableName + StringPool.DOT + column);
}
public static <T> PageResult<T> toPageResult(IPage<T> page) {
return new PageResult<>(page.getRecords(), page.getTotal());
}
}
package com.matchtech.common.core.mybatis;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author zhengwensheng
* @date 2021/07/28
**/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface QueryCondition {
/**
* 默认查询方式
*
* @return
*/
QueryConditionEnum value() default QueryConditionEnum.LIKE;
/**
* 是否填充默认查询条件
*
* @return
*/
boolean isCondition() default true;
}
package com.matchtech.common.core.mybatis;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import java.lang.reflect.Method;
import java.util.Collection;
public enum QueryConditionEnum {
// 条件
EQ("eq"),
NE("ne"),
GT("gt"),
GE("ge"),
LT("lt"),
LE("le"),
LIKE("like"),
NOT_LIKE("notLike"),
LIKE_LEFT("likeLeft"),
LIKE_RIGHT("likeRight"),
IN("in");
private final String name;
private Method method;
QueryConditionEnum(String name) {
this.name = name;
try {
Method method = null;
if (name.equals("in")) {
method = AbstractWrapper.class.getDeclaredMethod(name, boolean.class, Object.class, Collection.class);
} else {
method = AbstractWrapper.class.getDeclaredMethod(name, boolean.class, Object.class, Object.class);
}
this.method = method;
} catch (NoSuchMethodException e) {
}
}
Method getMethod() {
return method;
}
}
package com.matchtech.common.core.mybatis;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.Collection;
/**
* 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能:
*
* 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
*
* @param <T> 数据类型
*/
public class QueryWrapperX<T> extends QueryWrapper<T> {
public QueryWrapperX<T> likeIfPresent(String column, String val) {
if (StringUtils.hasText(val)) {
return (QueryWrapperX<T>) super.like(column, val);
}
return this;
}
public QueryWrapperX<T> inIfPresent(String column, Collection<?> values) {
if (!CollectionUtils.isEmpty(values)) {
return (QueryWrapperX<T>) super.in(column, values);
}
return this;
}
public QueryWrapperX<T> inIfPresent(String column, Object... values) {
if (!ArrayUtils.isEmpty(values)) {
return (QueryWrapperX<T>) super.in(column, values);
}
return this;
}
public QueryWrapperX<T> eqIfPresent(String column, Object val) {
if (val != null) {
return (QueryWrapperX<T>) super.eq(column, val);
}
return this;
}
public QueryWrapperX<T> neIfPresent(String column, Object val) {
if (val != null) {
return (QueryWrapperX<T>) super.ne(column, val);
}
return this;
}
public QueryWrapperX<T> gtIfPresent(String column, Object val) {
if (val != null) {
return (QueryWrapperX<T>) super.gt(column, val);
}
return this;
}
public QueryWrapperX<T> geIfPresent(String column, Object val) {
if (val != null) {
return (QueryWrapperX<T>) super.ge(column, val);
}
return this;
}
public QueryWrapperX<T> ltIfPresent(String column, Object val) {
if (val != null) {
return (QueryWrapperX<T>) super.lt(column, val);
}
return this;
}
public QueryWrapperX<T> leIfPresent(String column, Object val) {
if (val != null) {
return (QueryWrapperX<T>) super.le(column, val);
}
return this;
}
public QueryWrapperX<T> betweenIfPresent(String column, Object val1, Object val2) {
if (val1 != null && val2 != null) {
return (QueryWrapperX<T>) super.between(column, val1, val2);
}
if (val1 != null) {
return (QueryWrapperX<T>) ge(column, val1);
}
if (val2 != null) {
return (QueryWrapperX<T>) le(column, val2);
}
return this;
}
public QueryWrapperX<T> betweenIfPresent(String column, Object[] values) {
if (values != null && values.length != 0 && values[0] != null && values[1] != null) {
return (QueryWrapperX<T>) super.between(column, values[0], values[1]);
}
if (values != null && values.length != 0 && values[0] != null) {
return (QueryWrapperX<T>) ge(column, values[0]);
}
if (values != null && values.length != 0 && values[1] != null) {
return (QueryWrapperX<T>) le(column, values[1]);
}
return this;
}
// ========== 重写父类方法,方便链式调用 ==========
@Override
public QueryWrapperX<T> eq(boolean condition, String column, Object val) {
super.eq(condition, column, val);
return this;
}
@Override
public QueryWrapperX<T> eq(String column, Object val) {
super.eq(column, val);
return this;
}
@Override
public QueryWrapperX<T> orderByDesc(String column) {
super.orderByDesc(true, column);
return this;
}
@Override
public QueryWrapperX<T> last(String lastSql) {
super.last(lastSql);
return this;
}
@Override
public QueryWrapperX<T> in(String column, Collection<?> coll) {
super.in(column, coll);
return this;
}
// /**
// * 设置只返回最后一条
// *
// *
// * @return this
// */
// public QueryWrapperX<T> limit1() {
// Assert.notNull(SqlConstants.DB_TYPE, "获取不到数据库的类型");
// switch (SqlConstants.DB_TYPE) {
// case ORACLE:
// case ORACLE_12C:
// super.eq("ROWNUM", 1);
// break;
// case SQL_SERVER:
// case SQL_SERVER2005:
// super.select("TOP 1 *"); // 由于 SQL Server 是通过 SELECT TOP 1 实现限制一条,所以只好使用 * 查询剩余字段
// break;
// default:
// super.last("LIMIT 1");
// }
// return this;
// }
}
package com.matchtech.common.core.page;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serializable;
@Schema(description = "分页参数")
@Data
public class PageParam implements Serializable {
private static final Integer PAGE_NUM = 1;
private static final Integer PAGE_SIZE = 10;
@Schema(description = "页码,从 1 开始", required = true, example = "1")
@NotNull(message = "页码不能为空")
@Min(value = 1, message = "页码最小值为 1")
private Integer pageNo = PAGE_NUM;
@Schema(description = "每页条数,最大值为 100", required = true, example = "10")
@NotNull(message = "每页条数不能为空")
@Min(value = 1, message = "每页条数最小值为 1")
@Max(value = 100, message = "每页条数最大值为 100")
private Integer pageSize = PAGE_SIZE;
@Schema(description = "排序字段")
private String orderBy;
@Schema(description = "排序类型")
private String ascDesc;
}
package com.matchtech.common.core.page;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Data
public class PageReqDto<T> implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "当前页")
private Integer pageNo;
@Schema(description = "每页条数")
private Integer pageSize;
@Schema(description = "查询参数")
private T search;
@Schema(description = "排序字段")
private String orderBy;
@Schema(description = "排序类型")
private String ascDesc;
}
package com.matchtech.common.core.page;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
public final class PageResult<T> implements Serializable {
@Schema(description = "数据", required = true)
private List<T> list;
@Schema(description = "总量", required = true)
private Long count;
public PageResult() {
}
public PageResult(List<T> list, Long count) {
this.list = list;
this.count = count;
}
public PageResult(Long count) {
this.list = new ArrayList<>();
this.count = count;
}
public static <T> PageResult<T> empty() {
return new PageResult<>(0L);
}
public static <T> PageResult<T> empty(Long total) {
return new PageResult<>(total);
}
@Schema(description = "当前页")
private Integer pageNo;
@Schema(description = "总页数")
private Integer pages;
@Schema(description = "每页条数")
private Integer pageSize;
public PageResult(List<T> list, Long count, Integer pageNo, Integer pages, Integer pageSize) {
this.list = list;
this.count = count;
this.pageNo = pageNo;
this.pageSize = pageSize;
this.pages = pages;
}
public PageResult(Page<?> page, List<T> list) {
this.list = list;
this.count = page.getTotal();
this.pageNo = (int) page.getCurrent();
this.pageSize = (int) page.getSize();
this.pages = (int) page.getPages();
}
public static <T> PageVO<T> getPage(Page<T> pages) {
PageVO<T> data = new PageVO<>();
data.setList(pages.getRecords());
data.setCount(pages.getTotal());
data.setPageNo((int) pages.getCurrent());
data.setPages((int) pages.getPages());
data.setPageSize((int) pages.getSize());
return data;
}
public static <T> PageVO<T> getPage(Page<?> pages, List<T> list) {
PageVO<T> data = new PageVO<>();
data.setList(list);
data.setCount(pages.getTotal());
data.setPageNo((int) pages.getCurrent());
data.setPages((int) pages.getPages());
data.setPageSize((int) pages.getSize());
return data;
}
}
package com.matchtech.common.core.page;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
@Schema(description = "分页响应VO")
public class PageVO<T> implements Serializable {
private static final long serialVersionUID = -5165369386930215118L;
@Schema(description = "返回数据")
private List<T> list;
@Schema(description = "总条数")
private Long count;
@Schema(description = "当前页")
private Integer pageNo;
@Schema(description = "总页数")
private Integer pages;
@Schema(description = "每页条数")
private Integer pageSize;
public PageVO(List<T> list, Long count, Integer pageNo, Integer pages, Integer pageSize) {
this.list = list;
this.count = count;
this.pageNo = pageNo;
this.pageSize = pageSize;
this.pages = pages;
}
public PageVO(Page<?> page, List<T> list) {
this.list = list;
this.count = page.getTotal();
this.pageNo = (int) page.getCurrent();
this.pageSize = (int) page.getSize();
this.pages = (int) page.getPages();
}
public static <T> PageVO<T> getPage(Page<T> pages) {
PageVO<T> data = new PageVO<>();
data.setList(pages.getRecords());
data.setCount(pages.getTotal());
data.setPageNo((int) pages.getCurrent());
data.setPages((int) pages.getPages());
data.setPageSize((int) pages.getSize());
return data;
}
public static <T> PageVO<T> getPage(Page<?> pages, List<T> list) {
PageVO<T> data = new PageVO<>();
data.setList(list);
data.setCount(pages.getTotal());
data.setPageNo((int) pages.getCurrent());
data.setPages((int) pages.getPages());
data.setPageSize((int) pages.getSize());
return data;
}
public PageVO() {
}
}
package com.matchtech.common.core.page;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Data
public class ReqDTO<T> implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "参数")
private T param;
}
package com.matchtech.common.core.page;
import java.io.Serializable;
/**
* 排序字段 DTO
*
* 类名加了 ing 的原因是,避免和 ES SortField 重名。
*/
public class SortingField implements Serializable {
/**
* 顺序 - 升序
*/
public static final String ORDER_ASC = "asc";
/**
* 顺序 - 降序
*/
public static final String ORDER_DESC = "desc";
/**
* 字段
*/
private String field;
/**
* 顺序
*/
private String order;
// 空构造方法,解决反序列化
public SortingField() {
}
public SortingField(String field, String order) {
this.field = field;
this.order = order;
}
public String getField() {
return field;
}
public SortingField setField(String field) {
this.field = field;
return this;
}
public String getOrder() {
return order;
}
public SortingField setOrder(String order) {
this.order = order;
return this;
}
}
package com.matchtech.common.core.page.resp;
import com.alibaba.fastjson2.JSONObject;
import com.matchtech.common.core.constants.GlobalCodeMessageEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.FieldNameConstants;
import java.io.Serializable;
/**
* 返回数据
*
*/
@Schema(description = "统一响应模型")
@Data
@FieldNameConstants
public class ApiResponseEntity<T> implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "返回标识", defaultValue = "10001", title = "注解-编码")
private int code;
@Schema(description = "描述信息", defaultValue = "XXXXXX")
private String message;
@Schema(description = "业务数据")
private T data;
@Schema(description = "错误信息")
private String errorMsg;
public ApiResponseEntity(String message, int code) {
this.code = code;
this.message = message;
}
public ApiResponseEntity(String message, int code, T data) {
this.code = code;
this.message = message;
this.data = data;
}
public ApiResponseEntity() {
}
@Override
public String toString() {
JSONObject jSONObject = JSONObject.from(this);
return JSONObject.toJSONString(jSONObject);
//return "ApiResponse{" + "code=" + code + ", message='" + message + '\'' + ", data=" + data + '}';
}
public static <T> ApiResponseEntity<T> success(T data) {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(GlobalCodeMessageEnum.SUCCESS.getCode());
res.setMessage(String.valueOf(GlobalCodeMessageEnum.SUCCESS.getMessage()));
res.setData(data);
return res;
}
public static <T> ApiResponseEntity<T> success() {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(GlobalCodeMessageEnum.SUCCESS.getCode());
res.setMessage(String.valueOf(GlobalCodeMessageEnum.SUCCESS.getMessage()));
return res;
}
public static <T> ApiResponseEntity<T> fail(int code, String message) {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(code);
res.setMessage(message);
return res;
}
public static <T> ApiResponseEntity<T> fail(int code, String message, String errorMsg) {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(code);
res.setMessage(message);
res.setErrorMsg(errorMsg);
return res;
}
public static <T> ApiResponseEntity<T> fail(GlobalCodeMessageEnum globalCodeMessageEnum) {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(globalCodeMessageEnum.getCode());
res.setMessage(globalCodeMessageEnum.getMessage());
return res;
}
}
package com.matchtech.common.core.page.resp;
import com.matchtech.common.core.constants.GlobalCodeMessageEnum;
/**
* @author Administrator
*
*/
public class ApiResponseUtils {
public static <T> ApiResponseEntity<T> success(T data) {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(GlobalCodeMessageEnum.SUCCESS.getCode());
res.setMessage(String.valueOf(GlobalCodeMessageEnum.SUCCESS.getMessage()));
res.setData(data);
return res;
}
public static <T> ApiResponseEntity<T> success() {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(GlobalCodeMessageEnum.SUCCESS.getCode());
res.setMessage(String.valueOf(GlobalCodeMessageEnum.SUCCESS.getMessage()));
return res;
}
public static <T> ApiResponseEntity<T> success(GlobalCodeMessageEnum code) {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(code.getCode());
res.setMessage(String.valueOf(code.getMessage()));
return res;
}
public static <T> ApiResponseEntity<T> fail(int code, String message) {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(code);
res.setMessage(message);
return res;
}
public static <T> ApiResponseEntity<T> fail(int code, String message, String errorMsg) {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(code);
res.setMessage(message);
res.setErrorMsg(errorMsg);
return res;
}
public static <T> ApiResponseEntity<T> fail(GlobalCodeMessageEnum globalCodeMessageEnum) {
ApiResponseEntity<T> res = new ApiResponseEntity<>();
res.setCode(globalCodeMessageEnum.getCode());
res.setMessage(globalCodeMessageEnum.getMessage());
return res;
}
}
package com.matchtech.common.core.page.result;
import com.matchtech.common.core.utils.LocaleUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
@Data
@Schema(description = "excel导入错误信息VO")
public class ExcelErrorVo implements Serializable {
@Schema(description = "行数")
private Integer row;
@Schema(description = "标题")
private String title;
@Schema(description = "错误信息")
private String msg;
public ExcelErrorVo(Integer row, String title, String msg) {
this.row = row;
this.title = title;
this.msg = LocaleUtil.getMessage(msg);
}
public ExcelErrorVo() {
}
public static void isNotNull(String value, List<ExcelErrorVo> errorVoList, int i, String title) {
if (StringUtils.isBlank(value)) {
errorVoList.add(new ExcelErrorVo(i, title, "数据不为空"));
}
}
public static void notExists(String value, List<ExcelErrorVo> errorVoList, int i, String title) {
if (StringUtils.isBlank(value)) {
errorVoList.add(new ExcelErrorVo(i, title, "数据库数据不存在"));
}
}
public static void exists(Map<String, String> emailMap, String key, List<ExcelErrorVo> errorVoList, int i, String title) {
if (StringUtils.isBlank(key)) {
return;
}
String value = emailMap.get(key);
if (StringUtils.isNotBlank(value)) {
errorVoList.add(new ExcelErrorVo(i, title, "数据重复"));
} else {
emailMap.put(key, "system");
}
}
}
package com.matchtech.common.core.page.result;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
@Schema(description = "excel导入VO")
public class ExcelImportVo implements Serializable {
@Schema(description = "错误信息导入")
private String message;
@Schema(description = "总条数")
private Integer totalCount;
@Schema(description = "错误条数")
private Integer errorCount;
@Schema(description = "成功条数")
private Integer successCount;
@Schema(description = "错误信息")
private List<?> list;
@Schema(description = "成功返回的信息")
private List<?> successList;
}
......@@ -1015,4 +1015,17 @@ public class Convert
}
return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
}
public static String humpConversionUnderscore(String value) {
StringBuilder stringBuilder = new StringBuilder();
char[] chars = value.toCharArray();
for (char character : chars) {
if (Character.isUpperCase(character)) {
stringBuilder.append("_");
character = Character.toLowerCase(character);
}
stringBuilder.append(character);
}
return stringBuilder.toString();
}
}
package com.matchtech.common.core.utils;
import java.util.Map;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constant.TokenConstants;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.common.core.constants.TokenConstants;
import com.matchtech.common.core.text.Convert;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
......
package com.matchtech.common.core.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.function.Supplier;
@Component
public class LocaleUtil {
private static MessageSource messageSource;
private static final Locale ZH_CN_LOCALE = new Locale("zh", "CN");
private static final Locale EN_US_LOCALE = new Locale("en", "US");
private static final List<Locale> LOCALE_LIST = Arrays.asList(
ZH_CN_LOCALE,
EN_US_LOCALE
);
private static final ThreadLocal<Locale> TMP = new ThreadLocal<>();
public static Locale getLocale() {
//return LocaleContextHolder.getLocale();
return ZH_CN_LOCALE;
}
public static void execute(Locale locale, Runnable runnable) {
TMP.set(getLocale());
LocaleContextHolder.setLocale(locale);
try {
runnable.run();
} finally {
LocaleContextHolder.setLocale(null);
LocaleContextHolder.resetLocaleContext();
LocaleContextHolder.setLocale(TMP.get());
TMP.remove();
}
}
public static <T> T execute(Locale locale, Supplier<T> supplier) {
TMP.set(getLocale());
LocaleContextHolder.setLocale(locale);
try {
return supplier.get();
} finally {
LocaleContextHolder.setLocale(null);
LocaleContextHolder.resetLocaleContext();
LocaleContextHolder.setLocale(TMP.get());
TMP.remove();
}
}
public static boolean isZhCnLocale() {
return isZhCnLocale(getLocale());
}
public static boolean isZhCnLocale(Locale locale) {
return ZH_CN_LOCALE.equals(locale);
}
public static String getMessageZhCn(String code) {
return getMessage(ZH_CN_LOCALE, code, null, "");
}
public static String getMessageEnUs(String code) {
return getMessage(EN_US_LOCALE, code, null, "");
}
public static List<String> getMessageChoose(List<String> cnMessage, List<String> enMessage) {
return getMessageChoose(cnMessage, cnMessage, enMessage);
}
public static String getMessageChoose(String cnMessage, String enMessage) {
return getMessageChoose(cnMessage, cnMessage, enMessage);
}
public static String getMessageChooseNoDefault(String cnMessage, String enMessage) {
Locale locale = getLocale();
if (locale == null) {
return cnMessage;
}
if (EN_US_LOCALE.equals(locale)) {
return enMessage;
}
if (ZH_CN_LOCALE.equals(locale)) {
return cnMessage;
}
return cnMessage;
}
public static String getMessageChoose(String defaultMessage, String cnMessage, String enMessage) {
Locale locale = getLocale();
if (locale == null) {
return defaultMessage;
}
if (EN_US_LOCALE.equals(locale) && StringUtils.isNotBlank(enMessage)) {
return enMessage;
}
if (ZH_CN_LOCALE.equals(locale) && StringUtils.isNotBlank(defaultMessage)) {
return cnMessage;
}
return defaultMessage;
}
public static List<String> getMessageChoose(List<String> defaultMessage, List<String> cnMessage, List<String> enMessage) {
Locale locale = getLocale();
if (locale == null) {
return defaultMessage;
}
if (EN_US_LOCALE.equals(locale)) {
return enMessage;
}
if (ZH_CN_LOCALE.equals(locale)) {
return cnMessage;
}
return defaultMessage;
}
public static String getMessage(String code) {
return getMessage(code, null);
}
public static String getMessage(String code, Object[] args) {
return getMessage(code, args, "");
}
public static String getMessage(Locale locale, String code, Object[] args, String defaultMessage) {
String message = messageSource.getMessage(code, args, defaultMessage, locale);
if (null == message || "".equals(message)) {
message = code;
}
return message;
}
public static String getMessage(String code, Object[] args, String defaultMessage) {
//这里使用比较方便的方法,不依赖request.
Locale locale = getLocale();
return getMessage(locale, code, args, defaultMessage);
}
@Autowired
public void setMessageSource(MessageSource messageSource) {
LocaleUtil.messageSource = messageSource;
}
}
......@@ -22,7 +22,7 @@ import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson2.JSON;
import com.matchtech.common.core.constant.Constants;
import com.matchtech.common.core.constants.Constants;
import com.matchtech.common.core.domain.R;
import com.matchtech.common.core.text.Convert;
import reactor.core.publisher.Mono;
......
......@@ -4,7 +4,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.springframework.util.AntPathMatcher;
import com.matchtech.common.core.constant.Constants;
import com.matchtech.common.core.constants.Constants;
import com.matchtech.common.core.text.StrFormatter;
/**
......
package com.matchtech.common.core.utils.sign;
import org.apache.commons.lang3.Validate;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.SecureRandom;
/**
* 支持SHA-1/MD5消息摘要的工具类.
* <p>
* 返回ByteSource,可进一步被编码为Hex, Base64或UrlSafeBase64
*
*/
public class DigestUtils {
private static final String SHA1 = "SHA-1";
private static final String MD5 = "MD5";
private static SecureRandom random = new SecureRandom();
/**
* 对输入字符串进行md5散列.
*/
public static byte[] md5(byte[] input) {
return digest(input, MD5, null, 1);
}
public static byte[] md5(byte[] input, int iterations) {
return digest(input, MD5, null, iterations);
}
/**
* 对输入字符串进行sha1散列.
*/
public static byte[] sha1(byte[] input) {
return digest(input, SHA1, null, 1);
}
public static byte[] sha1(byte[] input, byte[] salt) {
return digest(input, SHA1, salt, 1);
}
public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
return digest(input, SHA1, salt, iterations);
}
/**
* 对字符串进行散列, 支持md5与sha1算法.
*/
private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
try {
MessageDigest digest = MessageDigest.getInstance(algorithm);
if (salt != null) {
digest.update(salt);
}
byte[] result = digest.digest(input);
for (int i = 1; i < iterations; i++) {
digest.reset();
result = digest.digest(result);
}
return result;
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
/**
* 生成随机的Byte[]作为salt.
*
* @param numBytes byte数组的大小
*/
public static byte[] generateSalt(int numBytes) {
Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);
byte[] bytes = new byte[numBytes];
random.nextBytes(bytes);
return bytes;
}
/**
* 对文件进行md5散列.
*/
public static byte[] md5(InputStream input) throws IOException {
return digest(input, MD5);
}
/**
* 对文件进行sha1散列.
*/
public static byte[] sha1(InputStream input) throws IOException {
return digest(input, SHA1);
}
private static byte[] digest(InputStream input, String algorithm) throws IOException {
try {
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
int bufferLength = 8 * 1024;
byte[] buffer = new byte[bufferLength];
int read = input.read(buffer, 0, bufferLength);
while (read > -1) {
messageDigest.update(buffer, 0, read);
read = input.read(buffer, 0, bufferLength);
}
return messageDigest.digest();
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
public static String string2MD5(String inStr) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
e.printStackTrace();
return "";
}
char[] charArray = inStr.toCharArray();
byte[] byteArray = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++)
byteArray[i] = (byte) charArray[i];
byte[] md5Bytes = md5.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16)
hexValue.append("0");
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
}
package com.matchtech.common.core.utils.sign;
import org.springframework.web.bind.annotation.RequestBody;
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class RsaUtil {
private static final String publicKey ="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDyQ/k8jihQkLbRwzIRTQBCO9B/SeW7vXD4lylSXd0M7e8vjN3H5D5Nezrt7PptJzV6KLzConUxlQ6cY00FSYsYbVyCubMDy4vWZf80KERDUuJVl/nTM+5/gqCd+IgfE/AMJjMwwIyMS+d/DoGr8B83VwwBqjW9cM1VeXueavimvQIDAQAB";
private static final String privateKey ="MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPJD+TyOKFCQttHDMhFNAEI70H9J5bu9cPiXKVJd3Qzt7y+M3cfkPk17Ou3s+m0nNXoovMKidTGVDpxjTQVJixhtXIK5swPLi9Zl/zQoRENS4lWX+dMz7n+CoJ34iB8T8AwmMzDAjIxL538OgavwHzdXDAGqNb1wzVV5e55q+Ka9AgMBAAECgYEAuQQUWZyvSSfblsKdf/zwT6Tii/NhkUkR96dplU+9u1wSqJvJ3BiBRCbyUDYE4ktpWcu2rGXpXl5ZdDGZ5onNwPOP5zgJaRJNQIwuHNRF3eNIYz00mY7+SQzd4jWzG054EMgGo7lfSgEEyu6gQfl+F9XEnUs9xhmUE34skQU/l7kCQQD6xzZ1lCGWd9KkTy4ab9lYJr98NXlO4ftrSQZTKHZQFc94vOJm+gXmrecoj4Hyo+uCpermuGRvHQKD5UCi8qlrAkEA909iODCDmpjFtKlmWuhR/rXydGYHXO6vjTRtWRgBOVrW3DcTvlSWP/6o7wtbXD1ZIQxT1gp9vrlKQ0L/cX8ydwJAdV3mzwCU96b8nomwOg8+2VLJK4ibTZ/V21BB9YlqVfDfONKt4yQAvwWEuibv2m99OZgNaA3Ec3xQQQp6RcjsIQJBAN1jpx198JH4qSPtcb93sc8+uekRXQ4IbgcOI8VaA96AP0+rznTX7Bkls70qgYK1OJCpJHO7uI1/+cb0tw+3OkkCQDUX352oEFNBo3HzGBPJh0mAy7DAQzN7Mmt21M32KK8+lO9UUg2afxwx0uktP9nGYiXTFaJ5Y1tJcaTTnv5gwwQ=";
// 加密算法模式定义
private static final String TRANSFORMATION = "RSA/ECB/PKCS1Padding";
private static final String ALGORITHM = "RSA";
public static void main(String[] args) {
Map<String, String> stringStringMap = RsaUtil.setKeys(null);
System.out.println(stringStringMap);
String encrypt = RsaUtil.encrypt("T5&fX8#kL2@pN");
System.out.println(encrypt);
String encrypt2 = "2VLGVKCdxGRf5IV2o4cUb51N3jEXIhIhItPZpQYf9iu0F+pwBiZyXt4OBfHxvLSGEKnAgL25QjcEZQHUz+g8xHKIoqWGfxImErXEMYfU5gTBhJL/MBDOI7i6TeDzgJVRIdlg4vPBRRMCqMPkbm+S15z+LVUb5FWkkFkvS3WQVc0=";
String decrypt = RsaUtil.decrypt(encrypt2);
System.out.println(decrypt);
}
/**
* 设置已有的RSA密钥对
*/
public static Map<String, String> setKeys(@RequestBody Map<String, String> keys) {
Map<String, String> response = new HashMap<>();
try {
// 验证密钥是否存在
if (publicKey == null || publicKey.trim().isEmpty() ||
privateKey == null || privateKey.trim().isEmpty()) {
throw new IllegalArgumentException("公钥和私钥不能为空");
}
// 验证密钥格式有效性
validateKeys();
response.put("status", "success");
response.put("message", "密钥设置成功,使用加密模式: " + TRANSFORMATION);
} catch (Exception e) {
response.put("status", "error");
response.put("message", "密钥设置失败: " + e.getMessage());
}
return response;
}
/**
* 使用RSA/ECB/PKCS1Padding模式加密
*/
public static String encrypt(String plainText) {
try {
checkKeysInitialized();
if (plainText == null || plainText.trim().isEmpty()) {
throw new IllegalArgumentException("请提供要加密的文本");
}
// 获取公钥对象
PublicKey pubKey = getPublicKeyFromString(publicKey);
// 初始化加密器,使用RSA/ECB/PKCS1Padding模式
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
// 执行加密
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
return encryptedText;
} catch (Exception e) {
throw new IllegalArgumentException("加密失败: " + e.getMessage());
}
}
/**
* 使用RSA/ECB/PKCS1Padding模式解密
*/
public static String decrypt(String encryptedText) {
try {
checkKeysInitialized();
if (encryptedText == null || encryptedText.trim().isEmpty()) {
throw new IllegalArgumentException("请提供要解密的文本");
}
// 获取私钥对象
PrivateKey priKey = getPrivateKeyFromString(privateKey);
// 初始化解密器,使用RSA/ECB/PKCS1Padding模式
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, priKey);
// 执行解密
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
String decryptedText = new String(decryptedBytes, StandardCharsets.UTF_8);
return decryptedText;
} catch (Exception e) {
throw new IllegalArgumentException("解密失败: " + e.getMessage());
}
}
/**
* 验证密钥对有效性
*/
private static void validateKeys() throws NoSuchAlgorithmException, InvalidKeySpecException {
getPublicKeyFromString(publicKey);
getPrivateKeyFromString(privateKey);
}
/**
* 检查密钥是否已初始化
*/
private static void checkKeysInitialized() {
if (publicKey == null || privateKey == null) {
throw new IllegalStateException("请先通过/set-keys接口设置RSA密钥对");
}
}
/**
* 从Base64字符串获取公钥对象
*/
private static PublicKey getPublicKeyFromString(String publicKeyString)
throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
return keyFactory.generatePublic(keySpec);
}
/**
* 从Base64字符串获取私钥对象
*/
private static PrivateKey getPrivateKeyFromString(String privateKeyString)
throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
return keyFactory.generatePrivate(keySpec);
}
public static void main2(String[] args) {
}
}
\ No newline at end of file
package com.matchtech.common.core.web.controller;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
import com.matchtech.common.core.config.MatchtechProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageInfo;
import com.matchtech.common.core.constant.HttpStatus;
import com.matchtech.common.core.utils.DateUtils;
import com.matchtech.common.core.utils.PageUtils;
import com.matchtech.common.core.web.domain.AjaxResult;
import com.matchtech.common.core.web.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
/**
* web层通用数据处理
*
* @author matchtech
*/
public class BaseController
{
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
public abstract class BaseController {
/**
* 将前台传递过来的日期格式的字符串,自动转化为Date类型
*/
@InitBinder
public void initBinder(WebDataBinder binder)
{
// Date 类型转换
binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
{
@Override
public void setAsText(String text)
{
setValue(DateUtils.parseDate(text));
}
});
}
/**
* 设置请求分页数据
*/
protected void startPage()
{
PageUtils.startPage();
}
/**
* 清理分页的线程变量
*/
protected void clearPage()
{
PageUtils.clearPage();
}
/**
* 响应请求分页数据
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable(List<?> list)
{
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setRows(list);
rspData.setMsg("查询成功");
rspData.setTotal(new PageInfo(list).getTotal());
return rspData;
}
/**
* 返回成功
*/
public AjaxResult success()
{
return AjaxResult.success();
}
/**
* 返回成功消息
*/
public AjaxResult success(String message)
{
return AjaxResult.success(message);
}
/**
* 返回成功消息
*/
public AjaxResult success(Object data)
{
return AjaxResult.success(data);
}
/**
* 返回失败消息
* 日志对象
*/
public AjaxResult error()
{
return AjaxResult.error();
}
protected Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
protected MatchtechProperties matchtechProperties;
/**
* 返回失败消息
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message);
}
/**
* 返回警告消息
*/
public AjaxResult warn(String message)
{
return AjaxResult.warn(message);
}
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult toAjax(int rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
* 响应返回结果
*
* @param result 结果
* @return 操作结果
*/
protected AjaxResult toAjax(boolean result)
{
return result ? success() : error();
}
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ package com.matchtech.common.core.web.domain;
import java.util.HashMap;
import java.util.Objects;
import com.matchtech.common.core.constant.HttpStatus;
import com.matchtech.common.core.constants.HttpStatus;
import com.matchtech.common.core.utils.StringUtils;
/**
......
package com.matchtech.common.core.web.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* Entity基类
*
* @author matchtech
*/
public class BaseEntity implements Serializable
{
private static final long serialVersionUID = 1L;
/** 搜索值 */
@JsonIgnore
private String searchValue;
/** 创建者 */
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 备注 */
private String remark;
/** 请求参数 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Map<String, Object> params;
public String getSearchValue()
{
return searchValue;
}
public void setSearchValue(String searchValue)
{
this.searchValue = searchValue;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public Date getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
public Map<String, Object> getParams()
{
if (params == null)
{
params = new HashMap<>();
}
return params;
}
public void setParams(Map<String, Object> params)
{
this.params = params;
}
}
package com.matchtech.common.core.web.domain;
import com.matchtech.common.core.domain.BaseEntity;
import java.util.ArrayList;
import java.util.List;
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -2,15 +2,16 @@ package com.matchtech.common.datascope.aspect;
import java.util.ArrayList;
import java.util.List;
import com.matchtech.common.core.domain.BaseEntity;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import com.matchtech.common.core.constant.UserConstants;
import com.matchtech.common.core.constants.UserConstants;
import com.matchtech.common.core.context.SecurityContextHolder;
import com.matchtech.common.core.text.Convert;
import com.matchtech.common.core.utils.StringUtils;
import com.matchtech.common.core.web.domain.BaseEntity;
import com.matchtech.common.datascope.annotation.DataScope;
import com.matchtech.common.security.utils.SecurityUtils;
import com.matchtech.system.api.domain.SysRole;
......@@ -164,7 +165,7 @@ public class DataScopeAspect
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
//baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
}
}
}
......@@ -178,7 +179,7 @@ public class DataScopeAspect
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, "");
//baseEntity.getParams().put(DATA_SCOPE, "");
}
}
}
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......@@ -27,9 +27,14 @@
<!-- Dynamic DataSource -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${dynamic-ds.version}</version>
</dependency>
<dependency>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common-core</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.matchtech.common.datasource.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
/**
* MyBatis Plus 配置类 - 针对Oracle数据库
*
* @author matchtech
*/
@Configuration
public class MyBatisPlusConfig {
/**
* MyBatis Plus 拦截器配置
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件 - Oracle
// interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.ORACLE));
// 乐观锁插件
// interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 性能监控插件(生产环境建议关闭)
// interceptor.addInnerInterceptor(new PerformanceInterceptor());
return interceptor;
}
/**
* 元数据处理器
*/
@Configuration
public static class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
}
\ No newline at end of file
package com.matchtech.common.dto.login;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "系统用户登录vo")
public class SysLoginVo {
@Schema(description = "token")
private String token;
@Schema(description = "用户详情")
private SysUserDetailVo sysUserDetailVo;
}
package com.matchtech.common.dto.login;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "用户详情模型")
public class SysUserDetailVo {
@Schema(description = "用户ID")
private String id;
@Schema(description = "公司ID")
private String companyId;
@Schema(description = "公司名称")
private String companyName;
@Schema(description = "机构ID")
private String officeId;
@Schema(description = "机构名称")
private String officeName;
@Schema(description = "登录名称")
private String loginName;
@Schema(description = "工号")
private String no;
@Schema(description = "姓名")
private String name;
@Schema(description = "邮箱")
private String email;
@Schema(description = "电话")
private String phone;
@Schema(description = "手机")
private String mobile;
@Schema(description = "头像")
private String photo;
@Schema(description = "最后登陆IP")
private String loginIp;
@Schema(description = "最后登陆时间")
private String loginDate;
@Schema(description = "是否可登录")
private String loginFlag;
@Schema(description = "备注")
private String remarks;
@Schema(description = "部门全路径")
private String tmDeptPath;
@Schema(description = "部门全路径ID")
private String tmDeptDeptid;
}
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -3,7 +3,7 @@ package com.matchtech.common.log.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.system.api.RemoteLogService;
import com.matchtech.system.api.domain.SysOperLog;
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......@@ -28,6 +28,10 @@
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common-core</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
......@@ -7,7 +7,7 @@ import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.Filter;
import com.matchtech.common.core.constant.Constants;
import com.matchtech.common.core.constants.Constants;
/**
* Redis使用FastJson序列化
......
package com.matchtech.common.redis.configure;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* redis配置
*
* @author matchtech
*/
@Configuration
@EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class)
@SuppressWarnings("deprecation")
public class RedisConfig extends CachingConfigurerSupport
{
@Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
// 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
package com.matchtech.common.redis.constant;
public class RedisConstants {
/**
* 系统用户token前缀
*/
public static final String SYS_USER_TOKEN_PREFIX = "token:sys:";
/**
* 系统用户ID token前缀
*/
public static final String SYS_USER_ID_TOKEN_PREFIX = "user:token:";
/**
* 用户登录失败次数key
*/
public static final String USER_LOGIN_FAILED_ATTEMPTS = "user:login:failed:attempts:";
/**
* 用户锁定标识
*/
public static final String USER_LOGIN_LOCKED = "user:login:locked:";
/**
* 验证码
*/
public static final String CAPTCHA_CACHE_NAME = "captcha:";
/**
* 验证码
*/
public static final String PERMISSIONS_MENU = "permissions:menu:";
/**
* 物理地址树
*/
public static final String PHYSICAL_ADDRESS_TREE = "physical:address:tree";
/**
* 物理地址列表
*/
public static final String PHYSICAL_ADDRESS_LIST = "physical:address:list";
/**
* 用户编号名称映射
*/
public static final String USER_NO_NAME_MAP = "user:no:name:map";
/**
* 用户权限
*/
public static final String USER_PERMISSION = "user:permission:";
}
package com.matchtech.common.redis.service;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.matchtech.common.core.utils.DateUtils;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RKeys;
import org.redisson.api.RList;
import org.redisson.api.RLock;
import org.redisson.api.RQueue;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtils {
public final static long NOT_EXPIRE = -1;
/**
* 默认过期时长,单位:分
*/
public final static long DEFAULT_EXPIRE = 60 * 24;
/**
* 默认锁过期时长,单位:秒
*/
public final static long DEFAULT_LOCK_EXPIRE = 5;
/**
* redis锁
***/
public final static String LOCK = "lock";
private static RedissonClient client;
private static String projectName;
/**
* 会自动注入,在其它场景也可自己构造
*/
public RedisUtils(RedissonClient redissonClient) {
client = redissonClient;
redissonClient.getConfig();
System.out.println(redissonClient.getConfig());
}
/**
* 创建锁带默认过期时间
*/
public static RLock lock(String key, long expire) {
RLock lock = client.getLock(RedisUtils.LOCK + key);
lock.lock(expire, TimeUnit.SECONDS);
return lock;
}
/**
* 创建锁带默认过期时间5秒
*/
public static RLock lock(String key) {
RLock lock = client.getLock(RedisUtils.LOCK + key);
lock.lock(RedisUtils.DEFAULT_LOCK_EXPIRE, TimeUnit.SECONDS);
return lock;
}
/**
* 创建锁带默认过期时间30秒
*/
public static RLock defaultLock(String key) {
RLock lock = client.getLock(RedisUtils.LOCK + key);
lock.lock();
return lock;
}
/**
* 创建锁带默认过期时间30秒
*/
public static RLock getLock(String key) {
RLock lock = client.getLock(RedisUtils.LOCK + key);
return lock;
}
/**
* 关闭锁
*/
public static void unlock(RLock lock) {
lock.unlock();
}
/**
* 设置具体过期时间的缓存,如果时间在当前时间之前则不成功
*
* @param key 键
* @param value 值
* @param expireAt 具体过期时间(精确到毫秒)
* @param <T>
*/
public static <T> void set(String key, T value, LocalDateTime expireAt) {
LocalDateTime now = LocalDateTime.now();
if (now.isAfter(expireAt)) {
return;
} else {
//long expire = LocalDateTimeUtils.getMilliSecond(expireAt) - LocalDateTimeUtils.getMilliSecond(now);
long expire = LocalDateTimeUtil.between(now, expireAt, ChronoUnit.MILLIS);
set(key, value, expire, TimeUnit.MILLISECONDS);
}
}
/**
* 设置字符串
*
* @param <T>
* @param key
* @param value 值
* @param expire 超时时间(秒)
*/
public static <T> void set(String key, T value, long expire) {
RBucket<T> bucket = client.getBucket(key);
bucket.set(value, expire, TimeUnit.SECONDS);
}
/**
* 设置key过期时间
*
* @param <T>
* @param key
* @param expire 超时时间(秒)
*/
public static <T> void setExpire(String key, long expire) {
client.getBucket(key).expire(Duration.ofSeconds(expire));
}
public static <T> void set(String key, T value, long expire, TimeUnit timeUnit) {
RBucket<T> bucket = client.getBucket(key);
bucket.set(value);
bucket.expireAsync(expire, timeUnit);
}
public static <T> void setSync(String key, T value, long expire, TimeUnit timeUnit) {
RBucket<T> bucket = client.getBucket(key);
bucket.set(value, expire, timeUnit);
}
/**
* 设置字符串
*/
public static <T> void set(String key, T value) {
RBucket<T> bucket = client.getBucket(key);
bucket.set(value);
}
/**
* 设置字符串
*/
public static <T> void set(String key, T value, boolean isString) {
if (isString) {
RBucket<String> bucket = client.getBucket(key);
bucket.set(JSONObject.toJSONString(value));
} else {
set(key, value);
}
}
/**
* 设置字符串
*/
public static <T> void set(String key, T value, boolean isString, Long minutes) {
if (isString) {
RBucket<String> bucket = client.getBucket(key);
bucket.set(JSONObject.toJSONString(value));
bucket.expireAsync(minutes, TimeUnit.MINUTES);
} else {
set(key, value, minutes / 60L);
}
}
/**
* 获取字符串
*/
/**
* 获取字符串
*/
public static <T> T get(String key) {
try {
RBucket<T> bucket = client.getBucket(key);
return bucket.get();
} catch (Exception e) {
if (e.getCause() instanceof com.esotericsoftware.kryo.io.KryoBufferUnderflowException) {
// 清理损坏的数据
delete(key);
return null;
}
throw e;
}
}
/**
* 获取字符串
*/
public static <T> T get(String key, TypeReference typeReference) {
RBucket<String> bucket = client.getBucket(key);
String str = bucket.get();
return (T) JSONObject.parseObject(str, typeReference);
}
/**
* 删除字符串
*/
public static <T> boolean delete(String key) {
RBucket<T> bucket = client.getBucket(key);
return bucket.delete();
}
/**
* 模糊删除key
* 慎用
*
* @param key redis键
*/
public static void deleteLike(String key) {
RKeys keys = client.getKeys();
keys.deleteByPattern("*" + key + "*");
}
/**
* 获取字符串对象
*/
public static <T> RBucket<T> getRBucket(String name) {
RBucket<T> bucket = client.getBucket(name);
return bucket;
}
/**
* 判断是否存在
*/
public static <T> boolean exist(String key) {
RBucket<T> bucket = client.getBucket(key);
return bucket.isExists();
}
/**
* 获取队列
*
* @param objectName
* @return
*/
public static <V> RQueue<V> getRQueue(String objectName) {
RQueue<V> rQueue = client.getQueue(objectName);
return rQueue;
}
/**
* 获取递增序号
*
* @param key
* @return
*/
public static long increment(String key) {
RAtomicLong rAtomicLong = client.getAtomicLong(key);
RBucket<String> rBucket = client.getBucket(key + "_key");
if (!rBucket.isExists()) {
rAtomicLong.delete();
rBucket.set(key, residueDayTime(), TimeUnit.SECONDS);
}
return rAtomicLong.incrementAndGet();
}
public static long residueDayTime(){
Date date = new Date();
DateTime endOfDay = DateUtil.endOfDay(date);
long between = DateUtil.between(date, endOfDay, DateUnit.SECOND);
return between;
}
public static long setAndIncrement(String key, Long val) {
RAtomicLong rAtomicLong = client.getAtomicLong(key);
rAtomicLong.set(val);
return rAtomicLong.incrementAndGet();
}
/**
* 获取递增序号
*
* @param key
* @return
*/
public static long increment(String key, long expire, TimeUnit timeUnit) {
RAtomicLong rAtomicLong = client.getAtomicLong(key);
rAtomicLong.expire(expire, timeUnit);
return rAtomicLong.incrementAndGet();
}
public static <T> void setList(String key, List<T> value, long expire, TimeUnit timeUnit) {
RList<T> bucket = client.getList(key);
bucket.clear();
bucket.addAll(value);
bucket.expireAsync(expire, timeUnit);
}
public static <T> List<T> getList(String key) {
return new ArrayList<>(client.getList(key));
}
public static <T> void sendPublishMessage(String topicName, T message) {
RTopic topic = client.getTopic(topicName);
topic.publish(message);
}
}
com.matchtech.common.redis.configure.RedisConfig
com.matchtech.common.redis.service.RedisService
com.matchtech.common.redis.service.RedisUtils
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -6,7 +6,6 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.EnableAsync;
......@@ -20,7 +19,7 @@ import com.matchtech.common.security.feign.FeignAutoConfiguration;
// 表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
// 指定要扫描的Mapper类的包的路径
@MapperScan("com.matchtech.**.mapper")
//@MapperScan("com.matchtech.**.mapper")
// 开启线程异步执行
@EnableAsync
// 自动加载类
......
......@@ -5,7 +5,7 @@ import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.common.core.exception.InnerAuthException;
import com.matchtech.common.core.utils.ServletUtils;
import com.matchtech.common.core.utils.StringUtils;
......
......@@ -3,7 +3,7 @@ package com.matchtech.common.security.feign;
import java.util.Map;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.common.core.utils.ServletUtils;
import com.matchtech.common.core.utils.StringUtils;
import com.matchtech.common.core.utils.ip.IpUtils;
......
......@@ -10,7 +10,7 @@ import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import com.matchtech.common.core.constant.HttpStatus;
import com.matchtech.common.core.constants.HttpStatus;
import com.matchtech.common.core.exception.DemoModeException;
import com.matchtech.common.core.exception.InnerAuthException;
import com.matchtech.common.core.exception.ServiceException;
......
......@@ -4,7 +4,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.common.core.context.SecurityContextHolder;
import com.matchtech.common.core.utils.ServletUtils;
import com.matchtech.common.core.utils.StringUtils;
......
......@@ -8,8 +8,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.matchtech.common.core.constant.CacheConstants;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constants.CacheConstants;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.common.core.utils.JwtUtils;
import com.matchtech.common.core.utils.ServletUtils;
import com.matchtech.common.core.utils.StringUtils;
......
......@@ -3,7 +3,7 @@ package com.matchtech.common.security.utils;
import java.util.Collection;
import java.util.List;
import com.alibaba.fastjson2.JSONArray;
import com.matchtech.common.core.constant.CacheConstants;
import com.matchtech.common.core.constants.CacheConstants;
import com.matchtech.common.core.utils.SpringUtils;
import com.matchtech.common.core.utils.StringUtils;
import com.matchtech.common.redis.service.RedisService;
......
......@@ -2,8 +2,8 @@ package com.matchtech.common.security.utils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.matchtech.common.core.constant.SecurityConstants;
import com.matchtech.common.core.constant.TokenConstants;
import com.matchtech.common.core.constants.SecurityConstants;
import com.matchtech.common.core.constants.TokenConstants;
import com.matchtech.common.core.context.SecurityContextHolder;
import com.matchtech.common.core.utils.ServletUtils;
import com.matchtech.common.core.utils.StringUtils;
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -8,7 +8,7 @@ import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.matchtech.common.core.constant.UserConstants;
import com.matchtech.common.core.constants.UserConstants;
import com.matchtech.common.core.context.SecurityContextHolder;
import com.matchtech.common.sensitive.annotation.Sensitive;
import com.matchtech.common.sensitive.enums.DesensitizedType;
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>matchtech-common</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.matchtech</groupId>
<artifactId>rapidplatform-cloud</artifactId>
<version>3.6.7</version>
<version>3.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......@@ -18,6 +18,7 @@
<module>matchtech-common-sensitive</module>
<module>matchtech-common-datascope</module>
<module>matchtech-common-datasource</module>
<module>matchtech-common-dto</module>
</modules>
<artifactId>matchtech-common</artifactId>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment