29 Commits

Author SHA1 Message Date
cuijiawang
8ccfe35b49 rename 2025-08-13 10:17:02 +08:00
cuijiawang
b12f104161 del 2025-08-13 10:03:56 +08:00
cuijiawang
a9bb36dacc 添加后台系统模块 2025-08-13 09:59:58 +08:00
wol
8a73e9bec4 Merge branch 'dev-cloud-v3.5.4' into dev-boot-v3.5.4
# Conflicts:
#	pom.xml
2025-08-12 23:33:57 +08:00
wol
0002cf457d 1 2025-08-12 23:30:14 +08:00
wol
01748fe738 Merge branch 'refs/heads/dev-boot-v3.5.4-module-ai' into dev-boot-v3.5.4 2025-08-12 23:12:24 +08:00
wol
bf2956c51c Merge branch 'refs/heads/dev-boot-v3.5.4-auth' into dev-boot-v3.5.4 2025-08-12 23:11:32 +08:00
wol
1e9baade51 Merge branch 'dev-boot-v3.5.4-redis' into dev-boot-v3.5.4 2025-08-12 22:56:01 +08:00
wol
0babec14cf add RedisConfiguration 2025-08-12 22:55:45 +08:00
wol
4806918ef9 auth 2025-08-12 22:50:03 +08:00
wol
0c87b1d63e 1 2025-08-12 22:42:10 +08:00
wol
cbaa3e7c42 module-ai 2025-08-12 22:10:00 +08:00
wol
30f8584d33 run 2025-08-12 22:09:14 +08:00
cuijiawang
29e43f6e36 boot-start 2025-08-12 18:12:47 +08:00
cuijiawang
985b82c604 modules 2025-08-12 17:46:36 +08:00
cuijiawang
54cc4c4ba5 server-cloud 2025-08-12 17:40:09 +08:00
cuijiawang
302e085a18 common-json 2025-08-12 17:21:44 +08:00
cuijiawang
ff174056a0 common-web 2025-08-12 16:50:21 +08:00
cuijiawang
c2a9f58926 del 2025-08-12 16:40:37 +08:00
wol
c80d8909dd common-redis 2025-08-11 23:49:28 +08:00
wol
e04a663fdb common-mybatis 2025-08-11 23:01:07 +08:00
wol
b92f6a6f53 common-doc 2025-08-10 22:28:58 +08:00
wol
99e64a9295 aop 2025-08-10 21:53:29 +08:00
wol
c13efa788c common-core 2025-08-10 21:48:49 +08:00
wol
ea916df3ce fix 2025-08-10 19:52:35 +08:00
wol
3b7501458a fix 2025-08-10 19:49:54 +08:00
wol
f301ea5840 javax -> jakarta 2025-08-10 19:24:38 +08:00
wol
084dad491e del test 2025-08-10 17:22:49 +08:00
cuijiawang
0bb060b273 refactor(admin): 重构开发环境配置并添加 Docker 支持
- 修改应用端口为 18080
- 更新数据库配置,使用加密凭据
- 调整 Redis 配置
- 添加 Jasypt 加密器配置
- 新增 Dockerfile 用于构建 Docker 镜像
- 更新 Maven 依赖,添加 Jasypt 支持
2025-07-31 16:06:55 +08:00
213 changed files with 4520 additions and 4234 deletions

View File

@@ -1,36 +0,0 @@
---
name: Bug 报告
about: 创建BUG报告以改进项目
title: ''
labels: ''
assignees: ''
---
**BUG描述**
关于BUG清晰简洁的描述。
**复现步骤**
详细的复现步骤。
**正确的行为**
你认为这个修复这个BUG后正确的行为应该是什么。
**详细截图**
如果可以的话请添加截图以帮助调查BUG.
**桌面端:**
- 操作系统: [例如. iOS]
- 浏览器及版本 [例如. chrome 11]
- 项目版本 [例如. 1.6.0]
**手机端:**
- 设备: [例如. iPhone6]
- 操作系统: [例如. iOS8.1]
- 浏览器及版本 [例如.safari 8]
- 项目版本 [例如. 1.6.0]
**Additional context**
任何其他你认为有助于排查错误的信息,或者你的猜测。

View File

@@ -1,20 +0,0 @@
---
name: 功能建议
about: 关于该项目的建议
title: ''
labels: ''
assignees: ''
---
**您的功能请求是否与问题相关? 请描述。**
清楚简明地描述问题所在。
**描述您想要的解决方案**
对您所设想的问题的清晰简洁的描述。
**描述您考虑过的替代方案**
对您考虑过的任何替代解决方案或功能的清晰简洁的描述。
**附加上下文**
在此处添加有关功能请求的任何其他上下文或屏幕截图。

View File

@@ -1,116 +0,0 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
# 权限声明,确保 workflow 有权限写 checks 和 security-events
permissions:
contents: read
checks: write
security-events: write
name: Java CI with Maven
on:
push:
branches: [ "main" ]
paths-ignore:
- 'README.md'
- 'LICENSE'
- '.gitignore'
- '.gitattributes'
- 'picture'
pull_request:
branches: [ "main" ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
java-version: ['8', '17', '21']
fail-fast: false
name: Build with Java ${{ matrix.java-version }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java-version }}
distribution: 'temurin'
cache: 'maven'
# 优化Maven本地仓库缓存策略
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}-${{ matrix.java-version }}
restore-keys: |
${{ runner.os }}-m2-
# 编译和测试去掉failOnWarning避免因为警告导致失败
- name: Build and Test with Maven
run: |
mvn -B verify --file pom.xml -Dmaven.test.failure.ignore=false -Dgpg.skip -Dmaven.javadoc.skip=false
env:
MAVEN_OPTS: -Xmx4g -XX:MaxMetaspaceSize=1g
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"
- name: Publish Test Report
uses: mikepenz/action-junit-report@v4
if: success() || failure()
with:
report_paths: '**/target/surefire-reports/TEST-*.xml'
detailed_summary: true
include_passed: true
fail_on_failure: true
- name: Run SonarQube Analysis
if: matrix.java-version == '17' && github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
continue-on-error: true
run: |
if [[ ! -z "${{ secrets.SONAR_TOKEN }}" ]]; then
mvn sonar:sonar \
-Dsonar.projectKey=agileboot \
-Dsonar.organization=${{ secrets.SONAR_ORGANIZATION || 'default' }} \
-Dsonar.host.url=${{ secrets.SONAR_HOST_URL || 'https://sonarcloud.io' }} \
-Dsonar.login=${{ secrets.SONAR_TOKEN }} \
-Dsonar.java.source=${{ matrix.java-version }}
else
echo "Skipping SonarQube analysis - SONAR_TOKEN not configured"
fi
# 上传构建产物if-no-files-found 改为 warn
- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
name: agileboot-artifacts-java-${{ matrix.java-version }}
path: |
**/target/*.jar
!**/target/original-*.jar
retention-days: 5
if-no-files-found: warn
# # 只在 Java 17 版本上更新依赖图权限和token已修复
# - name: Update dependency graph
# uses: advanced-security/maven-dependency-submission-action@v4
# if: matrix.java-version == '17' && success()
# with:
# token: ${{ secrets.GITHUB_TOKEN }}
# # 发送构建状态通知
# - name: Notify Build Status
# if: always()
# uses: rtCamp/action-slack-notify@v2.2.1
# env:
# SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK || '' }}
# SLACK_CHANNEL: build-notifications
# SLACK_COLOR: ${{ job.status }}
# SLACK_TITLE: Build Status for Java ${{ matrix.java-version }}
# SLACK_MESSAGE: 'Build ${{ job.status }} on Java ${{ matrix.java-version }}'

Binary file not shown.

View File

@@ -1,18 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

8
Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
FROM amazoncorretto:17
ADD agileboot-admin/target/agileboot-admin-1.0.0.jar /agileboot-admin.jar
EXPOSE 18080
#ENV CONTEXT_PATH /
# ENV NACOS_ENABLED true
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ENTRYPOINT ["java", "-jar", "/agileboot-admin.jar"]

21
LICENSE
View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2022 valarchie
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -16,7 +16,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;

View File

@@ -12,8 +12,8 @@ import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;

View File

@@ -13,7 +13,7 @@ import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.validation.constraints.NotNull;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;

View File

@@ -16,9 +16,9 @@ import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;

View File

@@ -16,8 +16,8 @@ import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;

View File

@@ -17,8 +17,8 @@ import com.baomidou.dynamic.datasource.annotation.DS;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;

View File

@@ -15,9 +15,9 @@ import com.agileboot.domain.system.post.query.PostQuery;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;

View File

@@ -19,8 +19,8 @@ import com.agileboot.common.enums.common.BusinessTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;

View File

@@ -22,7 +22,7 @@ import com.agileboot.domain.system.user.db.SearchUserDO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;

View File

@@ -3,7 +3,6 @@ package com.agileboot.admin.customize.aop.accessLog;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil;
import com.agileboot.common.utils.ServletHolderUtil;
import com.agileboot.infrastructure.user.AuthenticationUtils;
@@ -18,8 +17,8 @@ import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Map;
@@ -35,7 +34,7 @@ public class OperationLogModel extends SysOperationLogEntity {
public void fillOperatorInfo() {
// 获取当前的用户
String ip = ServletUtil.getClientIP(request);
String ip = ServletHolderUtil.getClientIp();
setOperatorIp(ip);
SystemLoginUser loginUser = AuthenticationUtils.getSystemLoginUser();
if (loginUser != null) {

View File

@@ -1,7 +1,6 @@
package com.agileboot.admin.customize.async;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.agileboot.common.utils.ServletHolderUtil;
import com.agileboot.common.utils.ip.IpRegionUtil;
@@ -38,7 +37,7 @@ public class AsyncTaskFactory {
ServletHolderUtil.getRequest().getHeader("User-Agent"));
// 获取客户端浏览器
final String browser = userAgent.getBrowser() != null ? userAgent.getBrowser().getName() : "";
final String ip = ServletUtil.getClientIP(ServletHolderUtil.getRequest());
final String ip = ServletHolderUtil.getClientIp();
final String address = IpRegionUtil.getBriefLocationByIp(ip);
// 获取客户端操作系统
final String os = userAgent.getOperatingSystem() != null ? userAgent.getOperatingSystem().getName() : "";

View File

@@ -4,10 +4,10 @@ import com.agileboot.infrastructure.user.AuthenticationUtils;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.login.TokenService;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

View File

@@ -9,7 +9,7 @@ import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.extra.servlet.ServletUtil;
import com.agileboot.common.utils.ServletHolderUtil;
import com.agileboot.common.config.AgileBootConfig;
import com.agileboot.common.constant.Constants.Captcha;
import com.agileboot.common.exception.ApiException;
@@ -31,7 +31,7 @@ import com.agileboot.common.enums.common.LoginStatusEnum;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.google.code.kaptcha.Producer;
import java.awt.image.BufferedImage;
import javax.annotation.Resource;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
@@ -203,7 +203,7 @@ public class LoginService {
SysUserEntity entity = redisCache.userCache.getObjectById(loginUser.getUserId());
entity.setLoginIp(ServletUtil.getClientIP(ServletHolderUtil.getRequest()));
entity.setLoginIp(ServletHolderUtil.getClientIp());
entity.setLoginDate(DateUtil.date());
entity.updateById();
}

View File

@@ -16,7 +16,7 @@ import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

View File

@@ -2,6 +2,7 @@ package com.agileboot.admin.customize.service.login;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import java.util.Collections;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
@@ -24,7 +25,6 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.SetUtils;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
@@ -86,7 +86,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
Set<Long> allMenuIds = allMenus.stream().map(SysMenuEntity::getMenuId).collect(Collectors.toSet());
return new RoleInfo(RoleInfo.ADMIN_ROLE_ID, RoleInfo.ADMIN_ROLE_KEY, DataScopeEnum.ALL, SetUtils.emptySet(),
return new RoleInfo(RoleInfo.ADMIN_ROLE_ID, RoleInfo.ADMIN_ROLE_KEY, DataScopeEnum.ALL, Collections.emptySet(),
RoleInfo.ADMIN_PERMISSIONS, allMenuIds);
}
@@ -104,7 +104,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
DataScopeEnum dataScopeEnum = BasicEnumUtil.fromValue(DataScopeEnum.class, roleEntity.getDataScope());
Set<Long> deptIdSet = SetUtils.emptySet();
Set<Long> deptIdSet = Collections.emptySet();
if (StrUtil.isNotEmpty(roleEntity.getDeptIdSet())) {
deptIdSet = StrUtil.split(roleEntity.getDeptIdSet(), ",").stream()
.map(Convert::toLong).collect(Collectors.toSet());

View File

@@ -11,7 +11,7 @@ import com.agileboot.admin.customize.service.permission.model.checker.OnlySelfDa
import com.agileboot.admin.customize.service.permission.model.checker.SingleDeptDataPermissionChecker;
import com.agileboot.infrastructure.user.web.DataScopeEnum;
import com.agileboot.domain.system.dept.db.SysDeptService;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Component;
/**

View File

@@ -50,25 +50,21 @@ spring:
datasource:
# 主库数据源
master:
url: jdbc:mysql://localhost:33067/agileboot-pure?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 12345
url: jdbc:mysql://mysql2.sqlpub.com:3307/agileboot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&sslMode=REQUIRED
username: ENC(s4kjpEsplGGLeV3YRNvJpJhDSOAO0tEf)
password: ENC(hg/hxmducWsI8u83/eXgAi8yHBDFbB5z0xzwNtBejPc=)
# 从库数据源
# slave:
# url: jdbc:mysql://localhost:33067/agileboot2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: root
# password: 12345
# slave:
# url: jdbc:mysql://localhost:33067/agileboot2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: root
# password: 12345
# redis 配置
redis:
# 地址
host: localhost
# 端口默认为6379
port: 36379
# 数据库索引
database: 0
# 密码
password: 12345
host: redis
port: 6379
database: 1
password: ENC(s3HU866TUAjzrWStN7kpQQ==)
# 连接超时时间
timeout: 10s
lettuce:
@@ -84,7 +80,7 @@ spring:
logging:
file:
path: D:/logs/agileboot-dev
path: ./logs/agileboot-dev
springdoc:
@@ -103,3 +99,6 @@ agileboot:
# 前端url请求转发前缀
api-prefix: /dev-api
demo-enabled: false
jasypt:
encryptor:
password: ${JASYPT_ENCRYPTOR_PASSWORD:}

View File

@@ -1,7 +1,7 @@
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080
port: 8080
port: 18080
servlet:
# 应用的访问路径
context-path: /

View File

@@ -1,44 +0,0 @@
package com.agileboot.admin.config;
import com.agileboot.admin.AgileBootAdminApplication;
import com.agileboot.common.config.AgileBootConfig;
import com.agileboot.common.constant.Constants.UploadSubDir;
import java.io.File;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest(classes = AgileBootAdminApplication.class)
@RunWith(SpringRunner.class)
public class AgileBootConfigTest {
@Resource
private AgileBootConfig config;
@Test
public void testConfig() {
String fileBaseDir = "D:\\agileboot\\profile";
Assertions.assertEquals("AgileBoot", config.getName());
Assertions.assertEquals("1.8.0", config.getVersion());
Assertions.assertEquals("2022", config.getCopyrightYear());
Assertions.assertFalse(config.isDemoEnabled());
Assertions.assertEquals(fileBaseDir, AgileBootConfig.getFileBaseDir());
Assertions.assertFalse(AgileBootConfig.isAddressEnabled());
Assertions.assertEquals("math", AgileBootConfig.getCaptchaType());
Assertions.assertEquals("math", AgileBootConfig.getCaptchaType());
Assertions.assertEquals(fileBaseDir + "\\import",
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.IMPORT_PATH);
Assertions.assertEquals(fileBaseDir + "\\avatar",
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.AVATAR_PATH);
Assertions.assertEquals(fileBaseDir + "\\download",
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.DOWNLOAD_PATH);
Assertions.assertEquals(fileBaseDir + "\\upload",
AgileBootConfig.getFileBaseDir() + File.separator + UploadSubDir.UPLOAD_PATH);
}
}

View File

@@ -1,83 +0,0 @@
package com.agileboot.admin.customize.service.permission;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.agileboot.admin.customize.service.permission.model.checker.CustomDataPermissionChecker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import org.apache.commons.collections4.SetUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class CustomDataPermissionCheckerTest {
private final SysDeptService deptService = mock(SysDeptService.class);
public SystemLoginUser loginUser = mock(SystemLoginUser.class);
@BeforeEach
public void mockBefore() {
when(loginUser.getRoleInfo()).thenReturn(RoleInfo.EMPTY_ROLE);
}
@Test
void testCheckWhenParameterNull() {
CustomDataPermissionChecker customChecker = new CustomDataPermissionChecker(deptService);
boolean check1 = customChecker.check(null, null);
boolean check2 = customChecker.check(loginUser, null);
boolean check3 = customChecker.check(null, new DataCondition());
assertFalse(check1);
assertFalse(check2);
assertFalse(check3);
}
@Test
void testCheckWhenTargetDeptIdNull() {
CustomDataPermissionChecker customChecker = new CustomDataPermissionChecker(deptService);
boolean check = customChecker.check(loginUser, new DataCondition(null, 1L));
assertFalse(check);
}
@Test
void testCheckWhenRoleIsNull() {
CustomDataPermissionChecker customChecker = new CustomDataPermissionChecker(deptService);
when(loginUser.getRoleInfo()).thenReturn(null);
boolean check = customChecker.check(loginUser, new DataCondition(1L, 1L));
assertFalse(check);
}
@Test
void testCheckWhenNotContainTargetDeptId() {
CustomDataPermissionChecker customChecker = new CustomDataPermissionChecker(deptService);
loginUser.getRoleInfo().setDeptIdSet(SetUtils.hashSet(2L));
boolean check = customChecker.check(loginUser, new DataCondition(1L, 1L));
assertFalse(check);
}
@Test
void testCheckWhenContainTargetDeptId() {
CustomDataPermissionChecker customChecker = new CustomDataPermissionChecker(deptService);
loginUser.getRoleInfo().setDeptIdSet(SetUtils.hashSet(1L));
boolean check = customChecker.check(loginUser, new DataCondition(1L, 1L));
assertTrue(check);
}
}

View File

@@ -1,92 +0,0 @@
package com.agileboot.admin.customize.service.permission;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.agileboot.admin.customize.service.permission.model.checker.DeptTreeDataPermissionChecker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class DeptTreeDataPermissionCheckerTest {
private final SysDeptService deptService = mock(SysDeptService.class);
public SystemLoginUser loginUser = mock(SystemLoginUser.class);
@BeforeEach
public void mockBefore() {
when(loginUser.getRoleInfo()).thenReturn(RoleInfo.EMPTY_ROLE);
}
@Test
void testCheckWhenParameterNull() {
DeptTreeDataPermissionChecker checker = new DeptTreeDataPermissionChecker(deptService);
boolean check1 = checker.check(null, null);
boolean check2 = checker.check(new SystemLoginUser(), null);
boolean check3 = checker.check(null, new DataCondition());
boolean check4 = checker.check(loginUser, new DataCondition());
assertFalse(check1);
assertFalse(check2);
assertFalse(check3);
assertFalse(check4);
}
@Test
void testCheckWhenIsChildOfDept() {
DeptTreeDataPermissionChecker checker = new DeptTreeDataPermissionChecker(deptService);
when(deptService.isChildOfTheDept(any(), any())).thenReturn(true);
when(loginUser.getDeptId()).thenReturn(1L);
DataCondition dataCondition = new DataCondition();
dataCondition.setTargetDeptId(2L);
boolean check = checker.check(loginUser, dataCondition);
assertTrue(check);
}
@Test
void testCheckWhenIsSameDept() {
DeptTreeDataPermissionChecker checker = new DeptTreeDataPermissionChecker(deptService);
when(deptService.isChildOfTheDept(any(), any())).thenReturn(false);
when(loginUser.getDeptId()).thenReturn(1L);
DataCondition dataCondition = new DataCondition();
dataCondition.setTargetDeptId(1L);
boolean check = checker.check(loginUser, dataCondition);
assertTrue(check);
}
@Test
void testCheckWhenFailed() {
DeptTreeDataPermissionChecker checker = new DeptTreeDataPermissionChecker(deptService);
when(deptService.isChildOfTheDept(any(), any())).thenReturn(false);
when(loginUser.getDeptId()).thenReturn(1L);
DataCondition dataCondition = new DataCondition();
dataCondition.setTargetDeptId(2L);
boolean check = checker.check(loginUser, dataCondition);
assertFalse(check);
}
}

View File

@@ -1,59 +0,0 @@
package com.agileboot.admin.customize.service.permission;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import com.agileboot.admin.customize.service.permission.model.checker.OnlySelfDataPermissionChecker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import org.junit.jupiter.api.Test;
class OnlySelfDataPermissionCheckerTest {
private final SysDeptService deptService = mock(SysDeptService.class);
@Test
void testCheckWhenParameterNull() {
OnlySelfDataPermissionChecker checker = new OnlySelfDataPermissionChecker(deptService);
boolean check1 = checker.check(null, null);
boolean check2 = checker.check(new SystemLoginUser(), null);
boolean check3 = checker.check(null, new DataCondition());
boolean check4 = checker.check(new SystemLoginUser(), new DataCondition());
assertFalse(check1);
assertFalse(check2);
assertFalse(check3);
assertFalse(check4);
}
@Test
void testCheckWhenSameUserId() {
OnlySelfDataPermissionChecker checker = new OnlySelfDataPermissionChecker(deptService);
SystemLoginUser loginUser = new SystemLoginUser();
loginUser.setUserId(1L);
DataCondition dataCondition = new DataCondition();
dataCondition.setTargetUserId(1L);
boolean check = checker.check(loginUser, dataCondition);
assertTrue(check);
}
@Test
void testCheckWhenDifferentUserId() {
OnlySelfDataPermissionChecker checker = new OnlySelfDataPermissionChecker(deptService);
SystemLoginUser loginUser = new SystemLoginUser();
loginUser.setUserId(1L);
DataCondition dataCondition = new DataCondition();
dataCondition.setTargetDeptId(2L);
boolean check = checker.check(loginUser, dataCondition);
assertFalse(check);
}
}

View File

@@ -1,72 +0,0 @@
package com.agileboot.admin.customize.service.permission;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.agileboot.admin.customize.service.permission.model.checker.SingleDeptDataPermissionChecker;
import com.agileboot.infrastructure.user.web.SystemLoginUser;
import com.agileboot.infrastructure.user.web.RoleInfo;
import com.agileboot.admin.customize.service.permission.model.DataCondition;
import com.agileboot.domain.system.dept.db.SysDeptService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class SingleDeptDataPermissionCheckerTest {
private final SysDeptService deptService = mock(SysDeptService.class);
public SystemLoginUser loginUser = mock(SystemLoginUser.class);
@BeforeEach
public void mockBefore() {
when(loginUser.getRoleInfo()).thenReturn(RoleInfo.EMPTY_ROLE);
}
@Test
void testCheckWhenParameterNull() {
SingleDeptDataPermissionChecker checker = new SingleDeptDataPermissionChecker(deptService);
boolean check1 = checker.check(null, null);
boolean check2 = checker.check(new SystemLoginUser(), null);
boolean check3 = checker.check(null, new DataCondition());
boolean check4 = checker.check(loginUser, new DataCondition());
assertFalse(check1);
assertFalse(check2);
assertFalse(check3);
assertFalse(check4);
}
@Test
void testCheckWhenSameDeptId() {
SingleDeptDataPermissionChecker checker = new SingleDeptDataPermissionChecker(deptService);
when(loginUser.getDeptId()).thenReturn(1L);
DataCondition dataCondition = new DataCondition();
dataCondition.setTargetDeptId(1L);
boolean check = checker.check(loginUser, dataCondition);
assertTrue(check);
}
@Test
void testCheckWhenDifferentDeptId() {
SingleDeptDataPermissionChecker checker = new SingleDeptDataPermissionChecker(deptService);
when(loginUser.getDeptId()).thenReturn(1L);
DataCondition dataCondition = new DataCondition();
dataCondition.setTargetUserId(2L);
boolean check = checker.check(loginUser, dataCondition);
assertFalse(check);
}
}

View File

@@ -4,10 +4,10 @@ import com.agileboot.api.customize.service.JwtTokenService;
import com.agileboot.infrastructure.user.app.AppLoginUser;
import io.jsonwebtoken.Claims;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -13,7 +13,7 @@ import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

View File

@@ -0,0 +1,24 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agileboot</groupId>
<artifactId>agileboot</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>agileboot-boot-start</artifactId>
<dependencies>
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>wol-common-web</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>wol-module-ai</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,24 @@
package com.agileboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author cuiJiaWang
* @Create 2025-08-12 18:07
*/
@SpringBootApplication
public class AgilebootBootApplication {
public static void main(String[] args) {
SpringApplication.run(AgilebootBootApplication.class, args);
String successMsg = " ____ _ _ __ _ _ \n"
+ " / ___| | |_ __ _ _ __ | |_ _ _ _ __ ___ _ _ ___ ___ ___ ___ ___ / _| _ _ | || |\n"
+ " \\___ \\ | __|/ _` || '__|| __| | | | || '_ \\ / __|| | | | / __|/ __|/ _ \\/ __|/ __|| |_ | | | || || |\n"
+ " ___) || |_| (_| || | | |_ | |_| || |_) | \\__ \\| |_| || (__| (__| __/\\__ \\\\__ \\| _|| |_| || ||_|\n"
+ " |____/ \\__|\\__,_||_| \\__| \\__,_|| .__/ |___/ \\__,_| \\___|\\___|\\___||___/|___/|_| \\__,_||_|(_)\n"
+ " |_| ";
System.out.println(successMsg);
}
}

View File

@@ -0,0 +1,4 @@
server:
port: 8080
servlet:
context-path: /api

View File

@@ -0,0 +1,18 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agileboot</groupId>
<artifactId>agileboot-cloud</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>agileboot-cloud-start</artifactId>
<dependencies>
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>wol-common-web</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,11 @@
package com.agileboot;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author cuiJiaWang
* @Create 2025-08-12 17:35
*/
@SpringBootApplication
public class AgilebootCloudApplication {
}

15
agileboot-cloud/pom.xml Normal file
View File

@@ -0,0 +1,15 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agileboot</groupId>
<artifactId>agileboot</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>agileboot-cloud</artifactId>
<packaging>pom</packaging>
<modules>
<module>agileboot-cloud-start</module>
</modules>
</project>

View File

@@ -9,6 +9,17 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<modules>
<module>wol-common-box</module>
<module>wol-common-core</module>
<module>wol-common-doc</module>
<module>wol-common-web</module>
<module>wol-common-mybatis</module>
<module>wol-common-redis</module>
<module>wol-common-json</module>
</modules>
<packaging>pom</packaging>
<artifactId>agileboot-common</artifactId>
<description>
@@ -17,171 +28,78 @@
<dependencies>
<!-- Spring框架基本的核心工具 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- SpringWeb模块 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- spring security 安全认证 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- JSON工具类 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-security</artifactId>-->
<!-- </dependency>-->
<!-- 文件上传工具类 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>commons-fileupload</groupId>-->
<!-- <artifactId>commons-fileupload</artifactId>-->
<!-- </dependency>-->
<!-- yml解析器 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.yaml</groupId>-->
<!-- <artifactId>snakeyaml</artifactId>-->
<!-- </dependency>-->
<!-- Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.jsonwebtoken</groupId>-->
<!-- <artifactId>jjwt</artifactId>-->
<!-- </dependency>-->
<!-- Jaxb -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>javax.xml.bind</groupId>-->
<!-- <artifactId>jaxb-api</artifactId>-->
<!-- </dependency>-->
<!-- redis 缓存操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- pool 对象池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-redis</artifactId>-->
<!-- </dependency>-->
<!-- 解析客户端操作系统、浏览器等 -->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>eu.bitwalker</groupId>-->
<!-- <artifactId>UserAgentUtils</artifactId>-->
<!-- </dependency>-->
<!-- servlet包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>it.ozimov</groupId>-->
<!-- <artifactId>embedded-redis</artifactId>-->
<!-- &lt;!&ndash; 不排除掉slf4j的话 会冲突&ndash;&gt;-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-simple</artifactId>-->
<!-- </exclusion>-->
<!-- &lt;!&ndash; 排除掉guava依赖以本项目的guava依赖为准 &ndash;&gt;-->
<!-- <exclusion>-->
<!-- <groupId>com.google.guava</groupId>-->
<!-- <artifactId>guava</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
</dependency>
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>embedded-redis</artifactId>
<!-- 不排除掉slf4j的话 会冲突-->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
<!-- 排除掉guava依赖以本项目的guava依赖为准 -->
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 多数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.baomidou</groupId>-->
<!-- <artifactId>dynamic-datasource-spring-boot-starter</artifactId>-->
<!-- </dependency>-->
<!-- swagger注解 -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<!--ENC加密-->
<!-- <dependency>-->
<!-- <groupId>com.github.ulisesbocchio</groupId>-->
<!-- <artifactId>jasypt-spring-boot-starter</artifactId>-->
<!-- <version>2.1.1</version>-->
<!-- </dependency>-->
</dependencies>

View File

@@ -1,86 +0,0 @@
package com.agileboot.common.constant;
/**
* 通用常量信息
*
* @author valarchie
*/
public class Constants {
private Constants() {
}
public static final int KB = 1024;
public static final int MB = KB * 1024;
public static final int GB = MB * 1024;
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
public static class Token {
private Token() {
}
/**
* 令牌前缀
*/
public static final String PREFIX = "Bearer ";
/**
* 令牌前缀
*/
public static final String LOGIN_USER_KEY = "login_user_key";
}
public static class Captcha {
private Captcha() {
}
/**
* 令牌
*/
public static final String MATH_TYPE = "math";
/**
* 令牌前缀
*/
public static final String CHAR_TYPE = "char";
}
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "profile";
public static class UploadSubDir {
private UploadSubDir() {
}
public static final String IMPORT_PATH = "import";
public static final String AVATAR_PATH = "avatar";
public static final String DOWNLOAD_PATH = "download";
public static final String UPLOAD_PATH = "upload";
}
}

View File

@@ -1,46 +0,0 @@
package com.agileboot.common.core.base;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* Entity基类
*
* @author valarchie
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class BaseEntity<T extends Model<?>> extends Model<T> {
@ApiModelProperty("创建者ID")
@TableField(value = "creator_id", fill = FieldFill.INSERT)
private Long creatorId;
@ApiModelProperty("创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
@ApiModelProperty("更新者ID")
@TableField(value = "updater_id", fill = FieldFill.UPDATE, updateStrategy = FieldStrategy.NOT_NULL)
private Long updaterId;
@ApiModelProperty("更新时间")
@TableField(value = "update_time", fill = FieldFill.UPDATE)
private Date updateTime;
/**
* deleted字段请在数据库中 设置为tinyInt 并且非null 默认值为0
*/
@ApiModelProperty("删除标志0代表存在 1代表删除")
@TableField("deleted")
@TableLogic
private Boolean deleted;
}

View File

@@ -1,59 +0,0 @@
package com.agileboot.common.core.dto;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 响应信息主体
*
* @author valarchie
*/
@Data
@AllArgsConstructor
public class ResponseDTO<T> {
private Integer code;
private String msg;
@JsonInclude
private T data;
public static <T> ResponseDTO<T> ok() {
return build(null, ErrorCode.SUCCESS.code(), ErrorCode.SUCCESS.message());
}
public static <T> ResponseDTO<T> ok(T data) {
return build(data, ErrorCode.SUCCESS.code(), ErrorCode.SUCCESS.message());
}
public static <T> ResponseDTO<T> fail() {
return build(null, ErrorCode.FAILED.code(), ErrorCode.FAILED.message());
}
public static <T> ResponseDTO<T> fail(T data) {
return build(data, ErrorCode.FAILED.code(), ErrorCode.FAILED.message());
}
public static <T> ResponseDTO<T> fail(ApiException exception) {
return build(null, exception.getErrorCode().code(), exception.getMessage());
}
public static <T> ResponseDTO<T> fail(ApiException exception, T data) {
return build(data, exception.getErrorCode().code(), exception.getMessage());
}
public static <T> ResponseDTO<T> build(T data, Integer code, String msg) {
return new ResponseDTO<>(code, msg, data);
}
// 去掉直接填充错误码的方式, 这种方式不能拿到i18n的错误消息 统一通过ApiException来构造错误消息
// public static <T> ResponseDTO<T> fail(ErrorCodeInterface code, Object... args) {
// return build(null, code, args);
// }
}

View File

@@ -1,44 +0,0 @@
package com.agileboot.common.core.page;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import javax.validation.constraints.Max;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author valarchie
*/
@EqualsAndHashCode(callSuper = true)
@Data
public abstract class AbstractPageQuery<T> extends AbstractQuery<T> {
/**
* 最大分页页数
*/
public static final int MAX_PAGE_NUM = 200;
/**
* 单页最大大小
*/
public static final int MAX_PAGE_SIZE = 500;
/**
* 默认分页页数
*/
public static final int DEFAULT_PAGE_NUM = 1;
/**
* 默认分页大小
*/
public static final int DEFAULT_PAGE_SIZE = 10;
@Max(MAX_PAGE_NUM)
protected Integer pageNum;
@Max(MAX_PAGE_SIZE)
protected Integer pageSize;
public Page<T> toPage() {
pageNum = ObjectUtil.defaultIfNull(pageNum, DEFAULT_PAGE_NUM);
pageSize = ObjectUtil.defaultIfNull(pageSize, DEFAULT_PAGE_SIZE);
return new Page<>(pageNum, pageSize);
}
}

View File

@@ -1,90 +0,0 @@
package com.agileboot.common.core.page;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.utils.time.DatePickUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import java.util.Date;
import lombok.Data;
/**
* 如果是简单的排序 和 时间范围筛选 可以使用内置的这几个字段
* @author valarchie
*/
@Data
public abstract class AbstractQuery<T> {
protected String orderColumn;
protected String orderDirection;
protected String timeRangeColumn;
@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd")
private Date beginTime;
@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd")
private Date endTime;
private static final String ASC = "ascending";
private static final String DESC = "descending";
/**
* 生成query conditions
*
* @return 添加条件后的QueryWrapper
*/
public QueryWrapper<T> toQueryWrapper() {
QueryWrapper<T> queryWrapper = addQueryCondition();
addSortCondition(queryWrapper);
addTimeCondition(queryWrapper);
return queryWrapper;
}
public abstract QueryWrapper<T> addQueryCondition();
public void addSortCondition(QueryWrapper<T> queryWrapper) {
if (queryWrapper == null || StrUtil.isEmpty(orderColumn)) {
return;
}
Boolean sortDirection = convertSortDirection();
if (sortDirection != null) {
queryWrapper.orderBy(StrUtil.isNotEmpty(orderColumn), sortDirection,
StrUtil.toUnderlineCase(orderColumn));
}
}
public void addTimeCondition(QueryWrapper<T> queryWrapper) {
if (queryWrapper != null
&& StrUtil.isNotEmpty(this.timeRangeColumn)) {
queryWrapper
.ge(beginTime != null, StrUtil.toUnderlineCase(timeRangeColumn),
DatePickUtil.getBeginOfTheDay(beginTime))
.le(endTime != null, StrUtil.toUnderlineCase(timeRangeColumn), DatePickUtil.getEndOfTheDay(endTime));
}
}
/**
* 获取前端传来的排序方向 转换成MyBatisPlus所需的排序参数 boolean=isAsc
* @return 排序顺序, null为无排序
*/
public Boolean convertSortDirection() {
Boolean isAsc = null;
if (StrUtil.isEmpty(this.orderDirection)) {
return isAsc;
}
if (ASC.equals(this.orderDirection)) {
isAsc = true;
}
if (DESC.equals(this.orderDirection)) {
isAsc = false;
}
return isAsc;
}
}

View File

@@ -1,38 +0,0 @@
package com.agileboot.common.core.page;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import lombok.Data;
/**
* 分页模型类
* @author valarchie
*/
@Data
public class PageDTO<T> {
/**
* 总记录数
*/
private Long total;
/**
* 列表数据
*/
private List<T> rows;
public PageDTO(List<T> list) {
this.rows = list;
this.total = (long) list.size();
}
public PageDTO(Page<T> page) {
this.rows = page.getRecords();
this.total = page.getTotal();
}
public PageDTO(List<T> list, Long count) {
this.rows = list;
this.total = count;
}
}

View File

@@ -1,29 +0,0 @@
package com.agileboot.common.core.exception;
import org.junit.Assert;
import org.junit.Test;
public class ApiExceptionTest {
@Test
public void testVarargsWithArrayArgs() {
String errorMsg = "these parameters are null: %s, %s, %s.";
Object[] array = new Object[] { "param1" , "param2" , "param3"};
String formatWithArray = String.format(errorMsg, array);
String formatWithVarargs = String.format(errorMsg, "param1", "param2", "param3");
Assert.assertEquals(formatWithVarargs, formatWithArray);
}
@Test
public void testVarargsWithNullArgs() {
String errorMsg = "these parameters are null: %s, %s, %s.";
String format = String.format(errorMsg, "param1", null, null);
Assert.assertEquals("these parameters are null: param1, null, null.", format);
}
}

View File

@@ -1,20 +0,0 @@
package com.agileboot.common.enums;
import com.agileboot.common.enums.common.YesOrNoEnum;
import org.junit.Assert;
import org.junit.Test;
public class BasicEnumUtilTest {
@Test
public void testFromValue() {
YesOrNoEnum yes = BasicEnumUtil.fromValue(YesOrNoEnum.class, 1);
YesOrNoEnum no = BasicEnumUtil.fromValue(YesOrNoEnum.class, 0);
Assert.assertEquals(yes.description(), "");
Assert.assertEquals(no.description(), "");
}
}

View File

@@ -1,14 +0,0 @@
package com.agileboot.common.exception.error;
import com.agileboot.common.exception.error.ErrorCode.Client;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class ErrorCodeInterfaceTest {
@Test
void testI18nKey() {
String i18nKey = Client.COMMON_FORBIDDEN_TO_CALL.i18nKey();
Assertions.assertEquals("20001_COMMON_FORBIDDEN_TO_CALL", i18nKey);
}
}

View File

@@ -1,80 +0,0 @@
package com.agileboot.common.query;
import com.agileboot.common.core.page.AbstractQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.Date;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class AbstractQueryTest {
private AbstractQuery query;
@BeforeEach
public void getNewQuery() {
query = new AbstractQuery<Object>() {
@Override
public QueryWrapper addQueryCondition() {
return new QueryWrapper();
}
};
}
@Test
void addTimeConditionWithNull() {
query.setTimeRangeColumn("loginTime");
QueryWrapper<Object> queryWrapper = query.toQueryWrapper();
String targetSql = queryWrapper.getTargetSql();
Assertions.assertEquals("", targetSql);
}
@Test
void addTimeConditionWithBothValue() {
query.setBeginTime(new Date());
query.setEndTime(new Date());
query.setTimeRangeColumn("loginTime");
QueryWrapper<Object> queryWrapper = query.toQueryWrapper();
String targetSql = queryWrapper.getTargetSql();
Assertions.assertEquals("(login_time >= ? AND login_time <= ?)", targetSql);
}
@Test
void addTimeConditionWithBeginValueOnly() {
query.setBeginTime(new Date());
query.setTimeRangeColumn("loginTime");
QueryWrapper<Object> queryWrapper = query.toQueryWrapper();
String targetSql = queryWrapper.getTargetSql();
Assertions.assertEquals("(login_time >= ?)", targetSql);
}
@Test
void testConvertSortDirection() {
query.setOrderDirection("ascending");
Assertions.assertTrue(query.convertSortDirection());
query.setOrderDirection("descending");
Assertions.assertFalse(query.convertSortDirection());
query.setOrderDirection("");
Assertions.assertNull(query.convertSortDirection());
query.setOrderDirection(null);
Assertions.assertNull(query.convertSortDirection());
}
}

View File

@@ -1,119 +0,0 @@
package com.agileboot.common.utils.file;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.config.AgileBootConfig;
import com.agileboot.common.constant.Constants.UploadSubDir;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode.Business;
import com.agileboot.common.exception.error.ErrorCode.Internal;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.web.multipart.MultipartFile;
class FileUploadUtilsTest {
@Test
void testIsAllowedExtension() {
String[] imageTypes = new String[]{"img", "gif"};
boolean isAllow = FileUploadUtils.isExtensionAllowed("img", imageTypes);
boolean isNotAllow = FileUploadUtils.isExtensionAllowed("png", imageTypes);
Assertions.assertTrue(isAllow);
Assertions.assertFalse(isNotAllow);
}
@Test
void testIsAllowedExtensionWhenNull() {
String[] imageTypes = null;
boolean isAllow = FileUploadUtils.isExtensionAllowed("img", imageTypes);
Assertions.assertTrue(isAllow);
}
@Test
void testGetRelativeFileUrl() {
String relativeFilePath = FileUploadUtils.getRelativeFileUrl(UploadSubDir.UPLOAD_PATH, "test.jpg");
Assertions.assertEquals("/profile/upload/test.jpg", relativeFilePath);
}
@Test
void testSaveFileToLocal() {
MultipartFile fileMock = Mockito.mock(MultipartFile.class);
ApiException exceptionWithNullSubDir = Assertions.assertThrows(ApiException.class,
() -> FileUploadUtils.saveFileToLocal(fileMock, "", ""));
ApiException exceptionWitEmptyFileName = Assertions.assertThrows(ApiException.class,
() -> FileUploadUtils.saveFileToLocal(fileMock, "", ""));
Assertions.assertEquals(Internal.INVALID_PARAMETER, exceptionWithNullSubDir.getErrorCode());
Assertions.assertEquals(Internal.INVALID_PARAMETER, exceptionWitEmptyFileName.getErrorCode());
}
@Test
void testIsAllowedUploadWhenFileNameTooLong() {
MultipartFile fileMock = Mockito.mock(MultipartFile.class);
String longFileName = "this is a very very long sentence, this is a very very long sentence, "
+ "this is a very very long sentence, this is a very very long sentence, ";
Mockito.when(fileMock.getOriginalFilename()).thenReturn(longFileName);
ApiException exception = Assertions.assertThrows(ApiException.class,
() -> FileUploadUtils.isAllowedUpload(fileMock, null));
Assertions.assertEquals(Business.UPLOAD_FILE_NAME_EXCEED_MAX_LENGTH, exception.getErrorCode());
}
@Test
void testIsAllowedUploadWhenFileTooBig() {
MultipartFile fileMock = Mockito.mock(MultipartFile.class);
Mockito.when(fileMock.getOriginalFilename()).thenReturn("test.jpg");
Mockito.when(fileMock.getSize()).thenReturn(FileUploadUtils.MAX_FILE_SIZE + 1);
ApiException exception = Assertions.assertThrows(ApiException.class,
() -> FileUploadUtils.isAllowedUpload(fileMock, null));
Assertions.assertEquals(Business.UPLOAD_FILE_SIZE_EXCEED_MAX_SIZE, exception.getErrorCode());
}
@Test
void testisAllowDownload() {
Assertions.assertFalse(FileUploadUtils.isAllowDownload("../test.jpg"));
Assertions.assertFalse(FileUploadUtils.isAllowDownload("../test.exe"));
}
@Test
void testGetFileExtension() {
MultipartFile fileMock = Mockito.mock(MultipartFile.class);
Mockito.when(fileMock.getOriginalFilename()).thenReturn("test.jpg");
String fileExtension = FileUploadUtils.getFileExtension(fileMock);
Assertions.assertEquals("jpg", fileExtension);
}
@Test
void testGenerateFilename() {
String fileName = "test.jpg";
MultipartFile fileMock = Mockito.mock(MultipartFile.class);
Mockito.when(fileMock.getOriginalFilename()).thenReturn(fileName);
String randomFileName = FileUploadUtils.generateFilename(fileMock);
String[] nameParts = randomFileName.split("_");
Assertions.assertEquals("test", nameParts[1]);
Assertions.assertTrue(StrUtil.endWith(nameParts[2], ".jpg"));
}
@Test
void getFileAbsolutePath() {
AgileBootConfig agileBootConfig = new AgileBootConfig();
agileBootConfig.setFileBaseDir("D:\\agileboot");
String fileAbsolutePath = FileUploadUtils.getFileAbsolutePath(UploadSubDir.AVATAR_PATH, "test.jpg");
Assertions.assertEquals("D:\\agileboot\\profile\\avatar\\test.jpg", fileAbsolutePath);
}
}

View File

@@ -1,65 +0,0 @@
package com.agileboot.common.utils.ip;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class IpRegionUtilTest {
@Test
void testGetIpRegion() {
IpRegion ipRegion = IpRegionUtil.getIpRegion("110.81.189.80");
Assertions.assertEquals("中国", ipRegion.getCountry());
Assertions.assertEquals("福建省", ipRegion.getProvince());
Assertions.assertEquals("泉州市", ipRegion.getCity());
}
@Test
void testGetIpRegionWhenLocalHost() {
IpRegion ipRegion = IpRegionUtil.getIpRegion("127.0.0.1");
Assertions.assertEquals("内网IP", ipRegion.briefLocation());
}
@Test
void testGetIpRegionWithIpv6() {
IpRegion ipRegion = IpRegionUtil.getIpRegion("2001:0DB8:0000:0023:0008:0800:200C:417A");
Assertions.assertNotNull(ipRegion);
Assertions.assertNull(ipRegion.getCountry());
Assertions.assertEquals("未知 未知", ipRegion.briefLocation());
}
@Test
void testGetIpRegionWithEmpty() {
IpRegion ipRegion = IpRegionUtil.getIpRegion("");
Assertions.assertNotNull(ipRegion);
Assertions.assertNull(ipRegion.getCountry());
Assertions.assertEquals("未知 未知", ipRegion.briefLocation());
}
@Test
void testGetIpRegionWithNull() {
IpRegion ipRegion = IpRegionUtil.getIpRegion(null);
Assertions.assertNotNull(ipRegion);
Assertions.assertNull(ipRegion.getCountry());
Assertions.assertEquals("未知 未知", ipRegion.briefLocation());
}
@Test
void testGetIpRegionWithWrongIpString() {
IpRegion ipRegion = IpRegionUtil.getIpRegion("xsdfwefsfsd");
Assertions.assertNotNull(ipRegion);
Assertions.assertNull(ipRegion.getCountry());
Assertions.assertEquals("未知 未知", ipRegion.briefLocation());
}
@Test
void getBriefLocationByIp() {
String briefLocationByIp = IpRegionUtil.getBriefLocationByIp("110.81.189.80");
Assertions.assertEquals("福建省 泉州市", briefLocationByIp);
}
}

View File

@@ -1,41 +0,0 @@
package com.agileboot.common.utils.ip;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class IpUtilTest {
@Test
void isInnerIp() {
boolean innerIp1 = IpUtil.isLocalHost("127.0.0.1");
boolean innerIp2 = IpUtil.isLocalHost("0:0:0:0:0:0:0:1");
boolean innerIp3 = IpUtil.isLocalHost("localhost");
boolean innerIp4 = IpUtil.isLocalHost("192.168.1.1");
boolean innerIp5 = IpUtil.isLocalHost("10.32.1.1");
boolean innerIp6 = IpUtil.isLocalHost("172.16.1.1");
boolean notInnerIP = IpUtil.isLocalHost("110.81.189.80");
Assertions.assertTrue(innerIp1);
Assertions.assertTrue(innerIp2);
Assertions.assertTrue(innerIp3);
Assertions.assertTrue(innerIp4);
Assertions.assertTrue(innerIp5);
Assertions.assertTrue(innerIp6);
Assertions.assertFalse(notInnerIP);
}
@Test
void isLocalHost() {
boolean localHost1 = IpUtil.isLocalHost("127.0.0.1");
boolean localHost2 = IpUtil.isLocalHost("0:0:0:0:0:0:0:1");
boolean localHost4 = IpUtil.isLocalHost("localhost");
boolean notLocalHost = IpUtil.isLocalHost("110.81.189.80");
Assertions.assertTrue(localHost1);
Assertions.assertTrue(localHost2);
Assertions.assertTrue(localHost4);
Assertions.assertFalse(notLocalHost);
}
}

View File

@@ -1,52 +0,0 @@
package com.agileboot.common.utils.ip;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class OfflineIpRegionUtilTest {
@Test
void testGetIpRegionWhenIpv4() {
IpRegion ipRegion = OfflineIpRegionUtil.getIpRegion("110.81.189.80");
Assertions.assertEquals("中国", ipRegion.getCountry());
Assertions.assertEquals("福建省", ipRegion.getProvince());
Assertions.assertEquals("泉州市", ipRegion.getCity());
}
@Test
void testGetIpRegionWithIpv6() {
IpRegion region = Assertions.assertDoesNotThrow(() ->
OfflineIpRegionUtil.getIpRegion("2001:0DB8:0000:0023:0008:0800:200C:417A")
);
Assertions.assertNull(region);
}
@Test
void testGetIpRegionWithEmpty() {
IpRegion region = Assertions.assertDoesNotThrow(() ->
OfflineIpRegionUtil.getIpRegion("")
);
Assertions.assertNull(region);
}
@Test
void testGetIpRegionWithNull() {
IpRegion region = Assertions.assertDoesNotThrow(() ->
OfflineIpRegionUtil.getIpRegion(null)
);
Assertions.assertNull(region);
}
@Test
void testGetIpRegionWithWrongIpString() {
IpRegion region = Assertions.assertDoesNotThrow(() ->
OfflineIpRegionUtil.getIpRegion("asfdsfdsff")
);
Assertions.assertNull(region);
}
}

View File

@@ -1,63 +0,0 @@
package com.agileboot.common.utils.ip;
import com.agileboot.common.config.AgileBootConfig;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class OnlineIpRegionUtilTest {
@BeforeEach
public void enableOnlineAddressQuery() {
AgileBootConfig agileBootConfig = new AgileBootConfig();
agileBootConfig.setAddressEnabled(true);
}
@Test
void getIpRegionWithIpv6() {
IpRegion region = Assertions.assertDoesNotThrow(() ->
OnlineIpRegionUtil.getIpRegion("ABCD:EF01:2345:6789:ABCD:EF01:2345:6789")
);
Assertions.assertNull(region);
}
@Test
void getIpRegionWithIpv4() {
IpRegion ipRegion = OnlineIpRegionUtil.getIpRegion("120.42.247.130");
Assertions.assertEquals("福建省", ipRegion.getProvince());
Assertions.assertEquals("泉州市", ipRegion.getCity());
}
@Test
void getIpRegionWithEmpty() {
IpRegion region = Assertions.assertDoesNotThrow(() ->
OnlineIpRegionUtil.getIpRegion("")
);
Assertions.assertNull(region);
}
@Test
void getIpRegionWithNull() {
IpRegion region = Assertions.assertDoesNotThrow(() ->
OnlineIpRegionUtil.getIpRegion(null)
);
Assertions.assertNull(region);
}
@Test
void getIpRegionWithWrongIpString() {
IpRegion region = Assertions.assertDoesNotThrow(() ->
OnlineIpRegionUtil.getIpRegion("seffsdfsdf")
);
Assertions.assertNull(region);
}
}

View File

@@ -1,61 +0,0 @@
package com.agileboot.common.utils.jackson;
import cn.hutool.core.date.DateUtil;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
/**
* @author duanxinyuan 2019/1/21 18:17
*/
public class JacksonUtilTest {
@Test
public void testObjectToJson() {
Person person = Person.newPerson();
String jacksonStr = JacksonUtil.to(person);
Assert.assertEquals(DateUtil.formatDateTime(person.getDate()), JacksonUtil.getAsString(jacksonStr, "date"));
Assert.assertEquals(DateUtil.formatLocalDateTime(person.getLocalDateTime()),
JacksonUtil.getAsString(jacksonStr, "localDateTime"));
Assert.assertEquals(person.getName(), JacksonUtil.getAsString(jacksonStr, "name"));
Assert.assertEquals(person.getAge(), JacksonUtil.getAsInt(jacksonStr, "age"));
Assert.assertEquals(person.isMan(), JacksonUtil.getAsBoolean(jacksonStr, "man"));
Assert.assertEquals(person.getMoney(), JacksonUtil.getAsBigDecimal(jacksonStr, "money"));
Assert.assertEquals(person.getTrait(), JacksonUtil.getAsList(jacksonStr, "trait", String.class));
Assert.assertNotNull(JacksonUtil.getAsString(jacksonStr, "name"));
}
/**
* 测试兼容情况
*/
@Test
public void testAllPrimitiveTypeToJson() {
String json = "{\n"
+ "\"code\": \"200\",\n"
+ "\"id\": \"2001215464647687987\",\n"
+ "\"message\": \"success\",\n"
+ "\"amount\": \"1.12345\",\n"
+ "\"amount1\": \"0.12345\",\n"
+ "\"isSuccess\": \"true\",\n"
+ "\"isSuccess1\": \"1\",\n"
+ "\"key\": \"8209167202090377654857374178856064487200234961995543450245362822537162918731039965956758726661669012305745755921310000297396309887550627402157318910581311\"\n"
+ "}";
Assert.assertEquals(200, JacksonUtil.getAsInt(json, "code"));
Assert.assertEquals(2001215464647687987L,JacksonUtil.getAsLong(json, "id"));
Assert.assertEquals("success", JacksonUtil.getAsString(json, "message"));
Assert.assertEquals(new BigDecimal("1.12345"), JacksonUtil.getAsBigDecimal(json, "amount"));
Assert.assertEquals(new BigDecimal("0.12345"), JacksonUtil.getAsBigDecimal(json, "amount1"));
Assert.assertEquals(1.12345d, JacksonUtil.getAsDouble(json, "amount"), 0.00001);
Assert.assertEquals(0.12345d, JacksonUtil.getAsDouble(json, "amount1"), 0.00001);
Assert.assertTrue(JacksonUtil.getAsBoolean(json, "isSuccess"));
Assert.assertTrue(JacksonUtil.getAsBoolean(json, "isSuccess1"));
Assert.assertEquals(new BigInteger(
"8209167202090377654857374178856064487200234961995543450245362822537162918731039965956758726661669012305745755921310000297396309887550627402157318910581311"),
JacksonUtil.getAsBigInteger(json, "key"));
Assert.assertEquals("1", JacksonUtil.getAsString(json, "isSuccess1"));
}
}

View File

@@ -1,42 +0,0 @@
package com.agileboot.common.utils.jackson;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import lombok.Data;
/**
* @author duanxinyuan
* 2018/6/29 14:17
*/
@Data
public class Person {
public String name;
public Date date;
public LocalDateTime localDateTime;
public int age;
public BigDecimal money;
public boolean man;
public ArrayList<String> trait;
public HashMap<String, String> cards;
public static Person newPerson() {
Person person = new Person();
person.name = "张三";
person.date = new Date();
person.localDateTime = LocalDateTime.now();
person.age = 100;
person.money = BigDecimal.valueOf(500.21);
person.man = true;
person.trait = new ArrayList<>();
person.trait.add("淡然");
person.trait.add("温和");
person.cards = new HashMap<>();
person.cards.put("身份证", "4a6d456as");
person.cards.put("建行卡", "649874545");
return person;
}
}

View File

@@ -1,40 +0,0 @@
package com.agileboot.common.utils.poi;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HtmlUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class CustomExcelUtilTest {
@Test
void testImportAndExport() {
PostDTO post1 = new PostDTO(1L, "admin1", "管理员1", "1", "无备注", "1", "正常");
PostDTO post2 = new PostDTO(2L, "admin2", "管理员2<script>alert(1)</script>", "2", "无备注", "1", "正常");
List<PostDTO> postDTOList = new ArrayList<>();
postDTOList.add(post1);
postDTOList.add(post2);
File file = FileUtil.createTempFile();
CustomExcelUtil.writeToOutputStream(postDTOList, PostDTO.class, FileUtil.getOutputStream(file));
List<PostDTO> postListFromExcel = CustomExcelUtil.readFromInputStream(PostDTO.class, FileUtil.getInputStream(file));
PostDTO post1fromExcel = postListFromExcel.get(0);
PostDTO post2fromExcel = postListFromExcel.get(1);
Assertions.assertEquals(post1.getPostId(), post1fromExcel.getPostId());
Assertions.assertEquals(post1.getPostCode(), post1fromExcel.getPostCode());
Assertions.assertEquals(post2.getPostId(), post2fromExcel.getPostId());
Assertions.assertEquals(post2.getPostCode(), post2fromExcel.getPostCode());
// 检查脚本注入的字符串是否被去除
Assertions.assertNotEquals(post2.getPostName(), post2fromExcel.getPostName());
Assertions.assertEquals(HtmlUtil.cleanHtmlTag(post2.getPostName()), post2fromExcel.getPostName());
}
}

View File

@@ -1,37 +0,0 @@
package com.agileboot.common.utils.poi;
import com.agileboot.common.annotation.ExcelColumn;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
@EqualsAndHashCode
public class PostDTO {
@ExcelColumn(name = "岗位ID")
private Long postId;
@ExcelColumn(name = "岗位编码")
private String postCode;
@ExcelColumn(name = "岗位名称")
private String postName;
@ExcelColumn(name = "岗位排序")
private String postSort;
@ExcelColumn(name = "备注")
private String remark;
private String status;
@ExcelColumn(name = "状态")
private String statusStr;
}

View File

@@ -1,46 +0,0 @@
package com.agileboot.common.utils.time;
import java.util.Calendar;
import java.util.Date;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class DatePickUtilTest {
@Test
void testGetBeginOfTheDay() {
Date beginOfTheDay = DatePickUtil.getBeginOfTheDay(new Date());
Calendar instance = Calendar.getInstance();
instance.setTime(beginOfTheDay);
Assertions.assertEquals(0, instance.get(Calendar.HOUR));
Assertions.assertEquals(0, instance.get(Calendar.MINUTE));
Assertions.assertEquals(0, instance.get(Calendar.SECOND));
}
@Test
void testGetBeginOfTheDayWhenNull() {
Assertions.assertDoesNotThrow(() -> DatePickUtil.getBeginOfTheDay(null)
);
}
@Test
void testGetEndOfTheDay() {
Date endOfTheDay = DatePickUtil.getEndOfTheDay(new Date());
Calendar instance = Calendar.getInstance();
instance.setTime(endOfTheDay);
Assertions.assertEquals(23, instance.get(Calendar.HOUR_OF_DAY));
Assertions.assertEquals(59, instance.get(Calendar.MINUTE));
Assertions.assertEquals(59, instance.get(Calendar.SECOND));
}
@Test
void testGetEndOfTheDayWhenNull() {
Assertions.assertDoesNotThrow(() -> DatePickUtil.getEndOfTheDay(null)
);
}
}

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.agileboot</groupId>
<artifactId>wol-common-box</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
<properties>
<revision>1.0.0</revision>
</properties>
<dependencyManagement>
<dependencies>
<!-- 核心模块 -->
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>wol-common-core</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>wol-common-doc</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>wol-common-mybatis</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>wol-common-redis</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>wol-common-web</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.agileboot</groupId>
<artifactId>wol-common-json</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agileboot</groupId>
<artifactId>agileboot-common</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>wol-common-core</artifactId>
<dependencies>
<!-- Spring框架基本的核心工具 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- servlet包 -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
<!-- SpringWeb模块 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- pool 对象池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<!-- io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<!-- swagger注解 -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.annotation;
package com.agileboot.common.core.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.annotation;
package com.agileboot.common.core.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View File

@@ -1,6 +1,6 @@
package com.agileboot.common.config;
package com.agileboot.common.core.config;
import com.agileboot.common.constant.Constants;
import com.agileboot.common.core.constant.Constants;
import java.io.File;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

View File

@@ -0,0 +1,85 @@
package com.agileboot.common.core.constant;
/**
* 通用常量信息
*
* @author ruoyi
*/
public interface Constants {
int KB = 1024;
int MB = KB * 1024;
int GB = MB * 1024;
/**
* 资源映射路径 前缀
*/
String RESOURCE_PREFIX = "profile";
/**
* UTF-8 字符集
*/
String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
String GBK = "GBK";
/**
* www主域
*/
String WWW = "www.";
/**
* http请求
*/
String HTTP = "http://";
/**
* https请求
*/
String HTTPS = "https://";
/**
* 通用成功标识
*/
String SUCCESS = "0";
/**
* 通用失败标识
*/
String FAIL = "1";
/**
* 登录成功
*/
String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
String LOGOUT = "Logout";
/**
* 注册
*/
String REGISTER = "Register";
/**
* 登录失败
*/
String LOGIN_FAIL = "Error";
/**
* 验证码有效期(分钟)
*/
Integer CAPTCHA_EXPIRATION = 2;
/**
* 顶级部门id
*/
Long TOP_PARENT_ID = 0L;
}

View File

@@ -0,0 +1,93 @@
package com.agileboot.common.core.constant;
/**
* 返回状态码
*
* @author Lion Li
*/
public interface HttpStatus {
/**
* 操作成功
*/
int SUCCESS = 200;
/**
* 对象创建成功
*/
int CREATED = 201;
/**
* 请求已经被接受
*/
int ACCEPTED = 202;
/**
* 操作已经执行成功,但是没有返回数据
*/
int NO_CONTENT = 204;
/**
* 资源已被移除
*/
int MOVED_PERM = 301;
/**
* 重定向
*/
int SEE_OTHER = 303;
/**
* 资源没有被修改
*/
int NOT_MODIFIED = 304;
/**
* 参数列表错误(缺少,格式不匹配)
*/
int BAD_REQUEST = 400;
/**
* 未授权
*/
int UNAUTHORIZED = 401;
/**
* 访问受限,授权过期
*/
int FORBIDDEN = 403;
/**
* 资源,服务未找到
*/
int NOT_FOUND = 404;
/**
* 不允许的http方法
*/
int BAD_METHOD = 405;
/**
* 资源冲突,或者资源被锁
*/
int CONFLICT = 409;
/**
* 不支持的数据,媒体类型
*/
int UNSUPPORTED_TYPE = 415;
/**
* 系统内部错误
*/
int ERROR = 500;
/**
* 接口未实现
*/
int NOT_IMPLEMENTED = 501;
/**
* 系统警告消息
*/
int WARN = 601;
}

View File

@@ -0,0 +1,120 @@
package com.agileboot.common.core.core;
import com.agileboot.common.core.constant.HttpStatus;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* 响应信息主体
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public class R<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 成功
*/
public static final int SUCCESS = 200;
/**
* 失败
*/
public static final int FAIL = 500;
/**
* 消息状态码
*/
private int code;
/**
* 消息内容
*/
private String msg;
/**
* 数据对象
*/
private T data;
public static <T> R<T> ok() {
return restResult(null, SUCCESS, "操作成功");
}
public static <T> R<T> ok(T data) {
return restResult(data, SUCCESS, "操作成功");
}
public static <T> R<T> ok(String msg) {
return restResult(null, SUCCESS, msg);
}
public static <T> R<T> ok(String msg, T data) {
return restResult(data, SUCCESS, msg);
}
public static <T> R<T> fail() {
return restResult(null, FAIL, "操作失败");
}
public static <T> R<T> fail(String msg) {
return restResult(null, FAIL, msg);
}
public static <T> R<T> fail(T data) {
return restResult(data, FAIL, "操作失败");
}
public static <T> R<T> fail(String msg, T data) {
return restResult(data, FAIL, msg);
}
public static <T> R<T> fail(int code, String msg) {
return restResult(null, code, msg);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static <T> R<T> warn(String msg) {
return restResult(null, HttpStatus.WARN, msg);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static <T> R<T> warn(String msg, T data) {
return restResult(data, HttpStatus.WARN, msg);
}
private static <T> R<T> restResult(T data, int code, String msg) {
R<T> r = new R<>();
r.setCode(code);
r.setData(data);
r.setMsg(msg);
return r;
}
public static <T> Boolean isError(R<T> ret) {
return !isSuccess(ret);
}
public static <T> Boolean isSuccess(R<T> ret) {
return R.SUCCESS == ret.getCode();
}
}

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.core.base;
package com.agileboot.common.core.core.base;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.enums;
package com.agileboot.common.core.enums;
/**
* @author valarchie

View File

@@ -1,9 +1,9 @@
package com.agileboot.common.enums;
package com.agileboot.common.core.enums;
import cn.hutool.core.convert.Convert;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.enums.BasicEnum;
import com.agileboot.common.core.exception.ApiException;
import com.agileboot.common.core.exception.error.ErrorCode;
import com.agileboot.common.core.enums.BasicEnum;
import java.util.Objects;

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.enums;
package com.agileboot.common.core.enums;
/**
* 字典类型 接口

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
/**
* 对应sys_operation_log的business_type

View File

@@ -1,6 +1,6 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.BasicEnum;
import com.agileboot.common.core.enums.BasicEnum;
/**
* 系统配置

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
/**
* 对应sys_user的sex字段

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
/**
* 用户状态

View File

@@ -1,6 +1,6 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.BasicEnum;
import com.agileboot.common.core.enums.BasicEnum;
/**
*

View File

@@ -1,6 +1,6 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.BasicEnum;
import com.agileboot.common.core.enums.BasicEnum;
/**
* @author valarchie

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
/**
* 对应sys_notice的 status字段

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
/**
* 对应sys_notice的 notice_type字段

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
/**
* 对应sys_operation_log的status字段

View File

@@ -1,7 +1,7 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.BasicEnum;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.BasicEnum;
/**
* 操作者类型

View File

@@ -1,6 +1,6 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.BasicEnum;
import com.agileboot.common.core.enums.BasicEnum;
/**
* Http Method

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
/**
* 除非表有特殊指明的话一般用这个枚举代表 status字段

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
/**
* 对应sys_user的status字段

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
/**
* 对应sys_menu表的is_visible字段

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.enums.common;
package com.agileboot.common.core.enums.common;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.enums.dictionary.CssTag;
import com.agileboot.common.enums.dictionary.Dictionary;
import com.agileboot.common.core.enums.DictionaryEnum;
import com.agileboot.common.core.enums.dictionary.CssTag;
import com.agileboot.common.core.enums.dictionary.Dictionary;
/**
* 系统内代表是与否的枚举

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.enums.dictionary;
package com.agileboot.common.core.enums.dictionary;
/**
* Css 样式

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.enums.dictionary;
package com.agileboot.common.core.enums.dictionary;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;

View File

@@ -1,6 +1,6 @@
package com.agileboot.common.enums.dictionary;
package com.agileboot.common.core.enums.dictionary;
import com.agileboot.common.enums.DictionaryEnum;
import com.agileboot.common.core.enums.DictionaryEnum;
import lombok.Data;
/**

View File

@@ -1,8 +1,8 @@
package com.agileboot.common.exception;
package com.agileboot.common.core.exception;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.exception.error.ErrorCodeInterface;
import com.agileboot.common.utils.i18n.MessageUtils;
import com.agileboot.common.core.exception.error.ErrorCodeInterface;
import com.agileboot.common.core.utils.i18n.MessageUtils;
import java.util.HashMap;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@@ -0,0 +1,45 @@
package com.agileboot.common.core.exception;
import cn.hutool.core.text.StrFormatter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.io.Serial;
/**
* @Author cuiJiaWang
* @Create 2025-08-12 16:32
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class BizException extends RuntimeException {
@Serial
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
public BizException(String message) {
this.message = message;
}
public BizException(String message, Integer code) {
this.message = message;
this.code = code;
}
public BizException(String message, Object... args) {
this.message = StrFormatter.format(message, args);
}
}

View File

@@ -0,0 +1,52 @@
package com.agileboot.common.core.exception;
import cn.hutool.core.text.StrFormatter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.io.Serial;
/**
* 业务异常(支持占位符 {}
*
* @author ruoyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public final class ServiceException extends RuntimeException {
@Serial
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*/
private String detailMessage;
public ServiceException(String message) {
this.message = message;
}
public ServiceException(String message, Integer code) {
this.message = message;
this.code = code;
}
public ServiceException(String message, Object... args) {
this.message = StrFormatter.format(message, args);
}
}

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.exception.error;
package com.agileboot.common.core.exception.error;
import org.springframework.util.Assert;

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.exception.error;
package com.agileboot.common.core.exception.error;
/**
* @author valarchie

View File

@@ -0,0 +1,31 @@
package com.agileboot.common.core.factory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import java.io.IOException;
/**
* yml 配置源工厂
*
* @author Lion Li
*/
public class YmlPropertySourceFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
String sourceName = resource.getResource().getFilename();
if (StringUtils.isNotBlank(sourceName) && StringUtils.endsWithAny(sourceName, ".yml", ".yaml")) {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return new PropertiesPropertySource(sourceName, factory.getObject());
}
return super.createPropertySource(name, resource);
}
}

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.utils;
package com.agileboot.common.core.utils;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
@@ -6,8 +6,8 @@ import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
@@ -73,5 +73,24 @@ public class ServletHolderUtil {
}
/**
* 获取客户端IP地址兼容代理头
*/
public static String getClientIp() {
HttpServletRequest request = getRequest();
String xForwardedFor = request.getHeader("X-Forwarded-For");
if (StrUtil.isNotEmpty(xForwardedFor)) {
// 可能存在多个IP取第一个
int commaIndex = xForwardedFor.indexOf(',');
return commaIndex > 0 ? xForwardedFor.substring(0, commaIndex).trim() : xForwardedFor.trim();
}
String realIp = request.getHeader("X-Real-IP");
if (StrUtil.isNotEmpty(realIp)) {
return realIp.trim();
}
return request.getRemoteAddr();
}
}

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.utils.file;
package com.agileboot.common.core.utils.file;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
@@ -7,12 +7,12 @@ import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.agileboot.common.config.AgileBootConfig;
import com.agileboot.common.constant.Constants;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.exception.error.ErrorCode.Business;
import com.agileboot.common.exception.error.ErrorCode.Internal;
import com.agileboot.common.core.config.AgileBootConfig;
import com.agileboot.common.core.constant.Constants;
import com.agileboot.common.core.exception.ApiException;
import com.agileboot.common.core.exception.error.ErrorCode;
import com.agileboot.common.core.exception.error.ErrorCode.Business;
import com.agileboot.common.core.exception.error.ErrorCode.Internal;
import org.apache.commons.io.FilenameUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.util.MimeType;

View File

@@ -1,4 +1,4 @@
package com.agileboot.common.utils.i18n;
package com.agileboot.common.core.utils.i18n;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.context.MessageSource;

Some files were not shown because too many files have changed in this diff Show More