File: README.md
[Binary file]
File: AGENTS.md
Repository Guidelines
Project Structure & Module Organization
pig aggregates the open-source Spring Cloud services through the root pom.xml. Runtime services sit under dedicated
folders: pig-register (Nacos), pig-gateway (edge routing), pig-auth (authorization), pig-upms (user and
permission), pig-boot (single-service launcher), and pig-visual (monitor, codegen, quartz). Shared libraries and
DTOs live in pig-common. Sample SQL and Docker build contexts reside in db/, while infra manifests live indocker-compose.yml. Every module uses the standard src/main/java and src/test/java layout.
The open-source edition intentionally excludes workflow, app server, MP, payment, report, BI, multi-tenant, data-scope,
and dynamic gateway route management code. Gateway routes are maintained through normal configuration files.
Build, Test, and Development Commands
Run
mvn clean install -T 4 -Pcloudfrom the project root to compile the full cloud edition with the managed BOM.docker compose build && docker compose upbuilds images and starts the local service stack.
Testing Guidelines
Use spring-boot-starter-test (JUnit 5, AssertJ, Mockito) for unit and slice tests. Name classes *Tests.java and
colocate fixtures in src/test/resources. Focus coverage on authentication, gateway filters, user/permission logic,
scheduled jobs, and code generation. Run mvn verify before opening a PR to exercise the full plugin stack.
Commit & Pull Request Guidelines
Follow the repo’s type(scope): summary history, e.g. fix(upms): clear login failure cache orfeat(codegen): add template option. Each PR must describe the impact area, list affected modules, and reference
issues when applicable. Attach curl/Postman snippets or screenshots whenever UI or OpenAPI responses change. Avoid
committing generated artifacts, and call out schema/config updates explicitly.
Security & Configuration Tips
Never commit environment secrets; rely on docker-compose.yml plus .env overrides ignored by Git. Keep db/ seed
data sanitized, and drive end-to-end checks against pig-register (ports 8848/9848) with pig-gateway (9999) so
discovery behavior matches production.
Behavioral Guidelines
The following four rules apply to all tasks and take precedence over other default behaviors.
1. Think Before Coding
- When requirements are ambiguous, ask first — never make silent assumptions
- If a simpler solution exists, say so explicitly rather than quietly picking a direction
- When something is unclear, surface the confusion instead of pushing forward with guesswork
2. Prefer Simplicity
- Use the minimum code needed to solve the current problem; add nothing unrequested
- Do not introduce abstractions for one-off code or design for hypothetical future needs
- Ask yourself: would a senior engineer call this over-engineered?
3. Surgical Changes
- Only touch what the task requires; do not refactor adjacent code as a side effect
- Do not alter style or structure unrelated to the current task
- Every changed line must trace directly to a stated requirement
4. Goal-Driven Execution
- Convert vague instructions into verifiable goals — prefer tests as the success criterion
- "Fix a bug" → write a failing test that reproduces it, then make it pass
- "Add validation" → write tests covering invalid inputs, then make them pass
File: docker-compose-boot.yml
使用说明 V6.0 - 单体架构版本
1. 先构建单体 JAR: mvn clean install -Pboot -DskipTests
2. 启动服务: docker compose -f docker-compose-boot.yml up -d
3. 静静等待服务启动
services:
pig-mysql:
build:
context: ./db
environment:
MYSQL_ROOT_HOST: "%"
MYSQL_ROOT_PASSWORD: root
restart: always
container_name: pig-mysql
image: pig-mysql
command: --lower_case_table_names=1
networks:
- spring_cloud_default
pig-redis:
container_name: pig-redis
image: registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/redis
restart: always
networks:
- spring_cloud_default
单体的时候注意,服务名称命名为 pig-gateway 对应前端nginx 配置
pig-gateway:
build:
context: ./pig-boot
restart: always
container_name: pig-boot
image: pig-boot
ports:
- 9999:9999
networks:
- spring_cloud_default
networks:
spring_cloud_default:
name: spring_cloud_default
driver: bridge
File: docker-compose.yml
使用说明 4.0 - 微服务架构版本
1. 使用docker-compose 宿主机不需要配置host来发现
2. 无需修改源码,根目录 docker-compose up 即可
3. 静静等待服务启动
services:
pig-mysql:
build:
context: ./db
environment:
MYSQL_ROOT_HOST: "%"
MYSQL_ROOT_PASSWORD: root
restart: always
container_name: pig-mysql
image: pig-mysql
command: --lower_case_table_names=1
networks:
- spring_cloud_default
pig-redis:
container_name: pig-redis
image: registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/redis
restart: always
networks:
- spring_cloud_default
pig-register:
build:
context: ./pig-register
restart: always
container_name: pig-register
image: pig-register
ports:
- 8848:8848
- 9848:9848
- 18080:18080
networks:
- spring_cloud_default
pig-gateway:
build:
context: ./pig-gateway
restart: always
container_name: pig-gateway
image: pig-gateway
ports:
- 9999:9999
networks:
- spring_cloud_default
pig-auth:
build:
context: ./pig-auth
restart: always
container_name: pig-auth
image: pig-auth
networks:
- spring_cloud_default
pig-upms:
build:
context: ./pig-upms/pig-upms-biz
restart: always
container_name: pig-upms
image: pig-upms
networks:
- spring_cloud_default
pig-monitor:
build:
context: ./pig-visual/pig-monitor
restart: always
image: pig-monitor
container_name: pig-monitor
ports:
- 5001:5001
networks:
- spring_cloud_default
pig-quartz:
build:
context: ./pig-visual/pig-quartz
restart: always
image: pig-quartz
container_name: pig-quartz
networks:
- spring_cloud_default
pig-codegen:
build:
context: ./pig-visual/pig-codegen
restart: always
image: pig-codegen
container_name: pig-codegen
networks:
- spring_cloud_default
networks:
spring_cloud_default:
name: spring_cloud_default
driver: bridge
File: pig-auth/src/main/resources/application.yml
server:
port: 3000
spring:
application:
name: @artifactId@
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: ${NACOS_HOST:pig-register}:${NACOS_PORT:8848}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
config:
import:
- optional:nacos:[email protected]@.yml
- optional:nacos:${spring.application.name}[email protected]@.yml
File: pig-boot/src/main/resources/application-dev.yml
spring:
data:
redis:
host: pig-redis
database: 5
数据库相关配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://pig-mysql:3306/pig?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
文件上传配置
file:
type: local
local:
base-path: /Users/lengleng/Downloads/img
验证码配置
aj:
captcha:
water-mark: pig4cloud
登录报文加密根密钥 ,必须是16位
security:
encodeKey: thanks,pig4cloud
配置文件加密根密码
jasypt:
encryptor:
password: pig
swagger token url 配置
swagger:
token-url: ${swagger.gateway}/admin/oauth2/token
File: pig-boot/src/main/resources/application.yml
server:
port: 9999
servlet:
context-path: /admin
spring:
application:
name: @project.artifactId@
缓存相关配置
cache:
type: redis
上传文件大小限制
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
cloud:
discovery:
enabled: false
nacos:
config.enabled: false
discovery.enabled: false
gateway:
server.webflux:
enabled: false
redis.enabled: false
sentinel.enabled: false
openfeign.okhttp.enabled: true
freemarker: # freemarker 配置,授权码模式页面渲染使用
suffix: .ftl
template-loader-path: classpath:/templates/
request-context-attribute: request
main:
allow-bean-definition-overriding: true
jackson:
use-jackson2-defaults: true
profiles:
active: dev
spring security 对外暴露接口设置
security:
micro: false
oauth2:
client:
ignore-urls:
- /webjars/**
- /v3/api-docs/**
- /doc.html
- /swagger-ui.html
- /swagger-ui/**
- /swagger-resources
- /token/**
- /error
- /druid/**
- /actuator/**
- /code/**
#--------------如下配置尽量不要变动-------------
management.endpoints.access.default: none # 默认所有端点都不允许访问
mybatis-plus 配置
mybatis-plus:
mapper-locations: classpath*:/mapper/*Mapper.xml
global-config:
banner: false
db-config:
id-type: auto
where-strategy: not_empty
insert-strategy: not_empty
update-strategy: not_null
# 雪花算法随机 worker-id / datacenter-id,避免多实例生成重复 ID (mybatis-plus#7135)
sequence:
worker-id: ${random.int(1,31)}
datacenter-id: ${random.int(1,31)}
type-handlers-package: com.pig4cloud.pig.common.data.handler
configuration:
jdbc-type-for-null: 'null'
call-setters-on-nulls: true
shrink-whitespaces-in-sql: true
查询以下前缀的表,不输出日志
pig.mybatis.skip-table:
- QRTZ_ #quartz 定时任务的表
File: pig-common/pig-common-core/src/main/resources/banner.txt
${AnsiColor.BRIGHT_YELLOW}
.______ __ _______ ______ __ ______ __ __ _______
| _ \ | | / __| / || | / __ \ | | | | |
| |) | | | | | __ | ,----'| | | | | | | | | | | .--. |
| / | | | | | | | | | | | | | | | | | | | | | |
| | | | | || | | ----.| ----.| --' | | --' | | '--' |
| _| |__| ____| _||| __/ __/ |___/
www.pig4cloud.com
PIGCLOUD Microservice Architecture${AnsiColor.DEFAULT}
File: pig-common/pig-common-core/src/main/resources/common-config.yml
很多第三方组件的配置默认值一般均不需要改动,写在nacos 中比较混乱冗余,就可以写在此处
sms4j配置
sms:
is-print: false
config-type: interface
sms-oa:
config-type: yaml
行为验证码配置
aj:
captcha:
cache-type: redis
配置文件加密方法
jasypt:
encryptor:
algorithm: PBEWithMD5AndDES
iv-generator-classname: org.jasypt.iv.NoIvGenerator
关闭连表插件的banner
mybatis-plus-join:
banner: false
sa-token 配置
sa-token:
is-print: false # 不输出 banner
token-name: pig # token 存储的前缀
is-concurrent: true # 是否允许同时在线
is-share: false # 是否允许复用token (同一账号同时登录的情况)
File: pig-common/pig-common-excel/src/main/resources/META-INF/spring-configuration-metadata.json
{
"groups": [
{
"name": "excel",
"type": "com.pig4cloud.pig.common.excel.config.ExcelConfigProperties",
"sourceType": "com.pig4cloud.pig.common.excel.config.ExcelConfigProperties"
}
],
"properties": [
{
"name": "excel.template-path",
"type": "java.lang.String",
"description": "模板路径",
"defaultValue": "excel",
"sourceType": "com.pig4cloud.pig.common.excel.config.ExcelConfigProperties"
}
],
"hints": []
}
File: pig-common/pig-common-oss/src/main/resources/META-INF/spring-configuration-metadata.json
{
"groups": [
{
"name": "file",
"type": "com.pig4cloud.pig.common.file.core.FileProperties",
"sourceType": "com.pig4cloud.pig.common.file.core.FileProperties"
},
{
"name": "file.local",
"type": "com.pig4cloud.pig.common.file.local.LocalFileProperties",
"sourceType": "com.pig4cloud.pig.common.file.core.FileProperties"
},
{
"name": "file.oss",
"type": "com.pig4cloud.pig.common.file.oss.OssProperties",
"sourceType": "com.pig4cloud.pig.common.file.core.FileProperties"
}
],
"properties": [
{
"name": "file.type",
"type": "com.pig4cloud.pig.common.file.core.FileType",
"description": "文件存储类型,可选 local 或 oss。",
"sourceType": "com.pig4cloud.pig.common.file.core.FileProperties",
"defaultValue": "local"
},
{
"name": "file.bucket-name",
"type": "java.lang.String",
"description": "默认的存储桶名称。",
"sourceType": "com.pig4cloud.pig.common.file.core.FileProperties",
"defaultValue": "local"
},
{
"name": "file.local.base-path",
"type": "java.lang.String",
"description": "本地文件存储根路径。",
"sourceType": "com.pig4cloud.pig.common.file.local.LocalFileProperties"
},
{
"name": "file.local.enable",
"type": "java.lang.Boolean",
"description": "旧版本地文件开关,已由 file.type=local 替代。",
"sourceType": "com.pig4cloud.pig.common.file.local.LocalFileProperties",
"deprecated": true,
"deprecation": {
"reason": "使用 file.type=local 替代 file.local.enable",
"replacement": "file.type"
}
},
{
"name": "file.oss.enable",
"type": "java.lang.Boolean",
"description": "旧版 OSS 文件开关,已由 file.type=oss 替代。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties",
"deprecated": true,
"deprecation": {
"reason": "使用 file.type=oss 替代 file.oss.enable",
"replacement": "file.type"
}
},
{
"name": "file.oss.endpoint",
"type": "java.lang.String",
"description": "对象存储服务 Endpoint,例如 http://127.0.0.1:9000。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties"
},
{
"name": "file.oss.custom-domain",
"type": "java.lang.String",
"description": "对象访问自定义域名。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties"
},
{
"name": "file.oss.app-id",
"type": "java.lang.String",
"description": "对象存储应用 ID。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties"
},
{
"name": "file.oss.path-style-access",
"type": "java.lang.Boolean",
"description": "是否使用 path-style 访问模式。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties",
"defaultValue": true
},
{
"name": "file.oss.region",
"type": "java.lang.String",
"description": "对象存储区域。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties"
},
{
"name": "file.oss.access-key",
"type": "java.lang.String",
"description": "对象存储 Access Key。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties"
},
{
"name": "file.oss.secret-key",
"type": "java.lang.String",
"description": "对象存储 Secret Key。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties"
},
{
"name": "file.oss.max-connections",
"type": "java.lang.Integer",
"description": "对象存储客户端最大并发连接数。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties",
"defaultValue": 100
},
{
"name": "file.oss.skip-md5-check",
"type": "java.lang.Boolean",
"description": "是否跳过 MD5 校验。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties",
"defaultValue": false
},
{
"name": "file.oss.chunked-encoding-enabled",
"type": "java.lang.Boolean",
"description": "是否启用 AWS S3 streaming chunked encoding,S3 兼容服务建议关闭。",
"sourceType": "com.pig4cloud.pig.common.file.oss.OssProperties",
"defaultValue": false
}
],
"hints": [
{
"name": "file.type",
"values": [
{
"value": "local",
"description": "使用本地文件系统。"
},
{
"value": "oss",
"description": "使用 S3 兼容对象存储。"
}
]
}
]
}
File: pig-common/pig-common-swagger/src/main/resources/openapi-config.yaml
swagger 配置
swagger:
enabled: true
title: Pig Swagger API
gateway: http://${GATEWAY-HOST:pig-gateway}:${GATEWAY-PORT:9999}
token-url: ${swagger.gateway}/auth/oauth2/token
scope: server
File: pig-gateway/src/main/resources/application.yml
server:
port: 9999
spring:
application:
name: @artifactId@
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: ${NACOS_HOST:pig-register}:${NACOS_PORT:8848}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
gateway:
server:
webflux:
routes:
- id: openapi
uri: lb://pig-gateway
predicates:
- Path=/v3/api-docs/**
filters:
- RewritePath=/v3/api-docs/(?.), /${path}/${path}/v3/api-docs
- id: pig-auth
uri: lb://pig-auth
predicates:
- Path=/auth/*
- id: pig-upms-biz
uri: lb://pig-upms-biz
predicates:
- Path=/admin/**
metadata:
response-timeout: 30000
- id: pig-codegen
uri: lb://pig-codegen
predicates:
- Path=/gen/**
- id: pig-quartz
uri: lb://pig-quartz
predicates:
- Path=/job/**
- id: pig-monitor
uri: lb://pig-monitor
predicates:
- Path=/monitor/**
config:
import:
- optional:nacos:[email protected]@.yml
- optional:nacos:${spring.application.name}[email protected]@.yml
File: pig-upms/pig-upms-biz/src/main/resources/application.yml
server:
port: 4000
spring:
application:
name: @artifactId@
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: ${NACOS_HOST:pig-register}:${NACOS_PORT:8848}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
gateway.server.webflux: # 关闭 Spring Cloud Gateway 的能力,避免与 Spring MVC 冲突。
redis.enabled: false
enabled: false
config:
import:
- optional:nacos:[email protected]@.yml
- optional:nacos:${spring.application.name}[email protected]@.yml
File: pig-visual/pig-codegen/src/main/resources/application.yml
server:
port: 5003
spring:
application:
name: @artifactId@
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: ${NACOS_HOST:pig-register}:${NACOS_PORT:8848}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
config:
import:
- optional:nacos:[email protected]@.yml
- optional:nacos:${spring.application.name}[email protected]@.yml
File: pig-visual/pig-monitor/src/main/resources/application.yml
server:
port: 5001
spring:
application:
name: @artifactId@
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: ${NACOS_HOST:pig-register}:${NACOS_PORT:8848}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
config:
import:
- optional:nacos:[email protected]@.yml
- optional:nacos:${spring.application.name}[email protected]@.yml
File: pig-visual/pig-quartz/src/main/resources/application.yml
server:
port: 5007
quartz:
enabled: true
spring:
application:
name: @artifactId@
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: ${NACOS_HOST:pig-register}:${NACOS_PORT:8848}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
config:
import:
- optional:nacos:[email protected]@.yml
- optional:nacos:${spring.application.name}[email protected]@.yml
File: pig-visual/pig-quartz/src/main/resources/quartz-config.yml
如下配置为使用数据库存储定时任务,属性不经常修改,所以不放在 application.yml 中统一管理
spring:
quartz:
security.enabled: true # 启用quartz安全验证
properties:
org:
quartz:
auto-startup: true #默认就是true
overwrite-existing-jobs: true #默认true
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore # 数据库存储
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate # 数据库代理
tablePrefix: QRTZ_ # 表前缀
isClustered: false # 集群
clusterCheckinInterval: 30000 # 集群检查间隔
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool # 线程池
threadCount: 3 # 线程数量
threadPriority: 5 # 线程优先级
threadsInheritContextClassLoaderOfInitializingThread: true # 是否继承类加载器
job-store-type: jdbc # 持久化到数据库
jdbc:
initialize-schema: never # 不初始化表结构
File: .github/dependabot.yml
[Binary file]
File: .github/workflows/ci.yml
name: CI
on:
workflow_dispatch:
push:
pull_request:
permissions:
contents: read
jobs:
maven-build:
name: Maven build (Java ${{ matrix.java-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
java-version: ['17', '25']
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: ${{ matrix.java-version }}
cache: maven
- name: Add JDK 25 annotation processor profile
if: matrix.java-version == '25'
run: |
python - <<'PY'
from pathlib import Path
pom = Path('pom.xml')
content = pom.read_text()
profile = '''\
jdk25-annotation-processor
<activation>
<jdk>[25,)</jdk>
</activation>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</annotationProcessorPaths>
</configuration>
'''
marker = ' '
if marker not in content:
raise SystemExit('Cannot find root pom.xml profiles section.')
if 'jdk25-annotation-processor' not in content:
content = content.replace(marker, profile + marker, 1)
pom.write_text(content)
PY
- name: Build with Maven
run: mvn -B -ntp clean installFile: .github/workflows/mirror-gitee.yml
name: Mirror to Gitee
on:
workflow_dispatch:
push:
branches:
- dev
- master
permissions:
contents: read
concurrency:
group: gitee-mirror-${{ github.ref }}
cancel-in-progress: false
jobs:
mirror:
name: Push ${{ github.ref_name }} to Gitee
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Configure SSH
env:
GITEE_SSH_PRIVATE_KEY: ${{ secrets.GITEE_SSH_PRIVATE_KEY }}
run: |
if [ -z "$GITEE_SSH_PRIVATE_KEY" ]; then
echo "GITEE_SSH_PRIVATE_KEY is not configured."
exit 1
fi
mkdir -p ~/.ssh
chmod 700 ~/.ssh
printf '%s\n' "$GITEE_SSH_PRIVATE_KEY" > ~/.ssh/gitee_deploy_key
chmod 600 ~/.ssh/gitee_deploy_key
ssh-keyscan gitee.com >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
cat > ~/.ssh/config <<'EOF'
Host gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/gitee_deploy_key
IdentitiesOnly yes
EOF
- name: Mirror branch
run: |
git remote add gitee [email protected]:log4j/pig.git
if git ls-remote --exit-code --heads gitee "${GITHUB_REF_NAME}" >/dev/null 2>&1; then
git fetch --no-tags gitee "+refs/heads/${GITHUB_REF_NAME}:refs/remotes/gitee/${GITHUB_REF_NAME}"
fi
git push --force-with-lease gitee "HEAD:refs/heads/${GITHUB_REF_NAME}"File: .gogs/ISSUE_TEMPLATE.md
提问务必按以下模板,提交详细信息。
错误信息多多益善、错误截图多多益善。
环境信息
pigx版本:
是否修改包名: