33 changed files with 3016 additions and 0 deletions
@ -0,0 +1,62 @@ |
|||||
|
# 作者 |
||||
|
AUTHOR = "snail" |
||||
|
# 微信公众号 |
||||
|
WECHAT = "ot_bus" |
||||
|
# 子项目默认项目包名 |
||||
|
BASE_PACKAGE = "com.xr.api" |
||||
|
# 默认模块名称,控制controller的URL的前缀 |
||||
|
DEFAULT_PREFIX_URL = "models" |
||||
|
# 项目主目录 |
||||
|
# health-ai 主项目; |
||||
|
MAIN_MODULE = "health-ai" |
||||
|
#health-user-api 模块(子项目) |
||||
|
MODULE_NAME = "health-user-api" |
||||
|
# 项目根目录 |
||||
|
BASE_DIR = "./" |
||||
|
# 输出目录 |
||||
|
# 是否生成REST风格 |
||||
|
REST_CONTROLLER_STYLE = True |
||||
|
# 默认的GROUP_ID |
||||
|
GROUP_ID = "com.xr.health" |
||||
|
OUTPUT_DIR = f"./{MAIN_MODULE}/{MODULE_NAME}/src/main" |
||||
|
|
||||
|
DB = { |
||||
|
"host": "192.168.1.80", |
||||
|
"user": "root", |
||||
|
"password": "Khq#P9hZ4L@EwCZw", |
||||
|
"database": "health_ai_b", |
||||
|
"port": 3728 |
||||
|
} |
||||
|
|
||||
|
APPLICATION = { |
||||
|
"name": MODULE_NAME, |
||||
|
"version": "1.0.0", |
||||
|
"author": AUTHOR, |
||||
|
"package": {"base": BASE_PACKAGE}, |
||||
|
"redis": { |
||||
|
"host": "192.168.1.87", |
||||
|
"port": 6379, |
||||
|
"password": "redis_Hkhtz7", |
||||
|
"database": 4 |
||||
|
}, |
||||
|
"minio": { |
||||
|
"host": "192.168.1.88", |
||||
|
"port": "9001", |
||||
|
"accessKey": "BHB4X5zgZXuzQE6ku31e", |
||||
|
"secretKey": "NZgHX5LhtAVD1KdaucL0EVWy6IQk4owdZLA2A7wi", |
||||
|
"bucketName": "health-bucket", |
||||
|
"downloadDir": "/data/excel" |
||||
|
}, |
||||
|
"xxlJob":{ |
||||
|
"addresses": "http://192.168.1.88:8800/xxl-job-admin", |
||||
|
"accessToken": "xxljobTokenQ", |
||||
|
"address": "192.168.1.88:9999", |
||||
|
"ip": "192.168.1.88", |
||||
|
"port": "9998", |
||||
|
}, |
||||
|
"eureka":{ |
||||
|
"host": "92.168.1.87", |
||||
|
"port": "8761" |
||||
|
}, |
||||
|
"db": DB |
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
# =============================== |
||||
|
# 基础项目信息 |
||||
|
# =============================== |
||||
|
mainModule: test-ai |
||||
|
moduleName: test-user-api |
||||
|
groupId: com.test.ai |
||||
|
author: snail |
||||
|
wechat: ot_bus |
||||
|
baseDir: "./" |
||||
|
outputDir: /${mainModule}/${moduleName}/src/main |
||||
|
# 是否启用 Lombok |
||||
|
entityLombokModel: true |
||||
|
|
||||
|
# 是否生成 REST 风格 Controller |
||||
|
restControllerStyle: true |
||||
|
|
||||
|
# =============================== |
||||
|
# 包路径配置 |
||||
|
# =============================== |
||||
|
package: |
||||
|
Models: models |
||||
|
Base: com.test.api |
||||
|
Common: ${package.Base}.${package.Models}.common |
||||
|
Entity: ${package.Base}.${package.Models}.entity |
||||
|
Service: ${package.Base}.${package.Models}.service |
||||
|
ServiceImpl: ${package.Base}.${package.Models}.service.impl |
||||
|
Controller: ${package.Base}.${package.Models}.controller |
||||
|
Mapper: ${package.Base}.${package.Models}.mapper |
||||
|
|
||||
|
# =============================== |
||||
|
# 数据库配置 |
||||
|
# =============================== |
||||
|
db: |
||||
|
host: 192.168.1.80 |
||||
|
port: 3728 |
||||
|
user: root |
||||
|
password: Khq#P9hZ4L@EwCZw |
||||
|
database: health_ai_b |
||||
|
|
||||
|
# =============================== |
||||
|
# 应用级配置 |
||||
|
# =============================== |
||||
|
application: |
||||
|
name: ${moduleName} |
||||
|
version: 1.0.0 |
||||
|
author: snail |
||||
|
|
||||
|
package: |
||||
|
base: ${package.Base} |
||||
|
|
||||
|
# ---------- Redis ---------- |
||||
|
redis: |
||||
|
host: 192.168.1.1 |
||||
|
port: 6379 |
||||
|
password: redis_Hkhtz7 |
||||
|
database: 4 |
||||
|
|
||||
|
# ---------- MinIO ---------- |
||||
|
minio: |
||||
|
host: 192.168.1.1 |
||||
|
port: 9001 |
||||
|
accessKey: BHB4X5zgZXuzQE6ku31e |
||||
|
secretKey: NZgHX5LhtAVD1KdaucL0EVWy6IQk4owdZLA2A7wi |
||||
|
bucketName: health-bucket |
||||
|
downloadDir: /data/excel |
||||
|
|
||||
|
# ---------- XXL-JOB ---------- |
||||
|
xxlJob: |
||||
|
addresses: http://192.168.1.88:8800/xxl-job-admin |
||||
|
accessToken: xxljobTokenQ |
||||
|
address: 192.168.1.1:9999 |
||||
|
ip: 192.168.1.1 |
||||
|
port: 9998 |
||||
|
|
||||
|
# ---------- Eureka ---------- |
||||
|
eureka: |
||||
|
host: 192.168.1.1 |
||||
|
port: 8761 |
||||
|
|
||||
|
# ---------- DB(应用内复用) ---------- |
||||
|
db: |
||||
|
host: 192.168.1.80 |
||||
|
port: 3728 |
||||
|
user: root |
||||
|
password: Khq#P9hZ4L@EwCZw |
||||
|
database: health_ai_b |
||||
@ -0,0 +1,41 @@ |
|||||
|
import pymysql |
||||
|
from config import DB |
||||
|
|
||||
|
def get_conn(): |
||||
|
return pymysql.connect( |
||||
|
**DB, |
||||
|
cursorclass=pymysql.cursors.DictCursor |
||||
|
) |
||||
|
|
||||
|
def get_table(table_name): |
||||
|
sql = """ |
||||
|
SELECT table_name, table_comment |
||||
|
FROM information_schema.tables |
||||
|
WHERE table_schema=%s AND table_name=%s |
||||
|
""" |
||||
|
with get_conn() as conn: |
||||
|
with conn.cursor() as cur: |
||||
|
cur.execute(sql, (DB["database"], table_name)) |
||||
|
return cur.fetchone() |
||||
|
|
||||
|
def get_columns(table_name): |
||||
|
sql = """ |
||||
|
SELECT column_name, data_type, column_comment |
||||
|
FROM information_schema.columns |
||||
|
WHERE table_schema=%s AND table_name=%s |
||||
|
ORDER BY ordinal_position |
||||
|
""" |
||||
|
with get_conn() as conn: |
||||
|
with conn.cursor() as cur: |
||||
|
cur.execute(sql, (DB["database"], table_name)) |
||||
|
return cur.fetchall() |
||||
|
|
||||
|
def mysql_to_java(mysql_type): |
||||
|
mapping = { |
||||
|
"bigint": "Long", |
||||
|
"int": "Integer", |
||||
|
"varchar": "String", |
||||
|
"datetime": "LocalDateTime", |
||||
|
"decimal": "BigDecimal" |
||||
|
} |
||||
|
return mapping.get(mysql_type, "String") |
||||
@ -0,0 +1,312 @@ |
|||||
|
import logging |
||||
|
import os |
||||
|
from datetime import datetime |
||||
|
from jinja2 import Environment, FileSystemLoader |
||||
|
# from config import * |
||||
|
from db import get_table, get_columns |
||||
|
from utils import * |
||||
|
import argparse |
||||
|
import yaml |
||||
|
|
||||
|
env = Environment(loader=FileSystemLoader("templates")) |
||||
|
|
||||
|
def build_fields(table_name): |
||||
|
columns = get_columns(table_name) |
||||
|
fields = [] |
||||
|
for c in columns: |
||||
|
fields.append({ |
||||
|
"java_name": to_camel(c["column_name"]), |
||||
|
"tab_name": c["column_name"], |
||||
|
"tab_type": c["data_type"], |
||||
|
"java_get_name": to_m_camel(c["column_name"]), |
||||
|
"java_type": mysql_to_java(c["data_type"]), |
||||
|
"comment": c["column_comment"] |
||||
|
}) |
||||
|
return fields |
||||
|
|
||||
|
def render(template_name, out_path, context, overwrite=False): |
||||
|
""" |
||||
|
:param template_name: 模板文件名 |
||||
|
:param out_path: 输出文件路径 |
||||
|
:param context: 渲染上下文 |
||||
|
:param overwrite: 是否覆盖已存在文件,默认 False |
||||
|
""" |
||||
|
# 文件存在且不允许覆盖 → 直接跳过 |
||||
|
if os.path.exists(out_path) and not overwrite: |
||||
|
logging.info("Skip exists file: %s", out_path) |
||||
|
return |
||||
|
|
||||
|
tpl = env.get_template(template_name) |
||||
|
content = tpl.render(**context) |
||||
|
|
||||
|
os.makedirs(os.path.dirname(out_path), exist_ok=True) |
||||
|
with open(out_path, "w", encoding="utf-8") as f: |
||||
|
f.write(content) |
||||
|
|
||||
|
logging.info("Generated file: %s", out_path) |
||||
|
|
||||
|
def generate(table_names: list[str], model_names: list[str], conf_name: str, over_write: bool): |
||||
|
|
||||
|
# context = { |
||||
|
# "mainModule": MAIN_MODULE, |
||||
|
# "moduleName": MODULE_NAME, |
||||
|
# "groupId": GROUP_ID, |
||||
|
# "author": AUTHOR, |
||||
|
# "wechat": WECHAT, |
||||
|
# "date": datetime.now().strftime("%Y-%m-%d"), |
||||
|
# "entityLombokModel": True, |
||||
|
# "package": { |
||||
|
# "Base": BASE_PACKAGE, |
||||
|
# "Common": f"{BASE_PACKAGE}.{DEFAULT_PREFIX_URL}.common", |
||||
|
# "Entity": f"{BASE_PACKAGE}.{DEFAULT_PREFIX_URL}.entity", |
||||
|
# "Service": f"{BASE_PACKAGE}.{DEFAULT_PREFIX_URL}.service", |
||||
|
# "Controller": f"{BASE_PACKAGE}.{DEFAULT_PREFIX_URL}.controller", |
||||
|
# "ServiceImpl": f"{BASE_PACKAGE}.{DEFAULT_PREFIX_URL}.service.impl", |
||||
|
# "Mapper": f"{BASE_PACKAGE}.{DEFAULT_PREFIX_URL}.mapper" |
||||
|
# }, |
||||
|
# "db": DB, |
||||
|
# "application": APPLICATION, |
||||
|
# "restControllerStyle": REST_CONTROLLER_STYLE |
||||
|
# } |
||||
|
|
||||
|
with open(conf_name, "r", encoding="utf-8") as f: |
||||
|
cfg = yaml.safe_load(f) |
||||
|
cfg = resolve_config(cfg) |
||||
|
|
||||
|
context = { |
||||
|
"mainModule": cfg["mainModule"], |
||||
|
"moduleName": cfg["moduleName"], |
||||
|
"groupId": cfg["groupId"], |
||||
|
"author": cfg["author"], |
||||
|
"wechat": cfg["wechat"], |
||||
|
"date": datetime.now().strftime("%Y-%m-%d"), |
||||
|
"entityLombokModel": cfg["entityLombokModel"], |
||||
|
"package": cfg["package"], |
||||
|
"db": cfg["db"], |
||||
|
"application": cfg["application"], |
||||
|
"restControllerStyle": cfg["restControllerStyle"] |
||||
|
} |
||||
|
# MAIN_BASE_PACKAGE_DIR = f"{OUTPUT_DIR}/java/{to_path(BASE_PACKAGE)}" |
||||
|
# MAIN_OUTPUT_DIR = f"{MAIN_BASE_PACKAGE_DIR}/{DEFAULT_PREFIX_URL}" |
||||
|
|
||||
|
BASE_DIR = cfg["baseDir"] |
||||
|
BASE_PACKAGE = cfg["package"]["Base"] |
||||
|
OUTPUT_DIR = cfg["outputDir"] |
||||
|
MAIN_MODULE = cfg["mainModule"] |
||||
|
MODULE_NAME = cfg["moduleName"] |
||||
|
MAIN_BASE_PACKAGE_DIR = f"{cfg['outputDir']}/java/{to_path(BASE_PACKAGE)}" |
||||
|
MAIN_OUTPUT_DIR = f"{MAIN_BASE_PACKAGE_DIR}/{cfg['package']['Models']}" |
||||
|
|
||||
|
|
||||
|
# ========= 按表循环 ========= |
||||
|
for table_name in table_names: |
||||
|
table = get_table(table_name) |
||||
|
entity = to_class(table_name) |
||||
|
|
||||
|
context = dict(context) |
||||
|
context.update({ |
||||
|
"fields": build_fields(table_name), |
||||
|
"table": { |
||||
|
"entity": entity, |
||||
|
"lowerEntity": lower_first(entity), |
||||
|
"name": table_name, |
||||
|
"comment": table["table_comment"] |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
# ========= 需要循环生成的模板 ========= |
||||
|
render( |
||||
|
"entity.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/entity/{entity}.java", |
||||
|
context, |
||||
|
over_write |
||||
|
) |
||||
|
|
||||
|
render( |
||||
|
"controller.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/controller/{entity}Controller.java", |
||||
|
context, |
||||
|
over_write |
||||
|
) |
||||
|
|
||||
|
render( |
||||
|
"service.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/service/{entity}Service.java", |
||||
|
context, |
||||
|
over_write |
||||
|
) |
||||
|
|
||||
|
render( |
||||
|
"serviceImpl.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/service/impl/{entity}MPJBaseServiceImpl.java", |
||||
|
context, |
||||
|
over_write |
||||
|
) |
||||
|
|
||||
|
render( |
||||
|
"mapper.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/mapper/{entity}Mapper.java", |
||||
|
context, |
||||
|
over_write |
||||
|
) |
||||
|
|
||||
|
render( |
||||
|
"mapper.xml.j2", |
||||
|
f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/mappers/{entity}Mapper.xml", |
||||
|
context, |
||||
|
over_write |
||||
|
) |
||||
|
|
||||
|
# ========= 生成固定模板 ========= |
||||
|
# BaseEntity |
||||
|
render( |
||||
|
"baseEntity.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/entity/BaseEntity.java", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
# common MybatisPlusConfig |
||||
|
render( |
||||
|
"mybatisPlusConfig.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/MybatisPlusConfig.java", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
# common MybatisPlusConfig |
||||
|
render( |
||||
|
"webLogAspect.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/WebLogAspect.java", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
# common 基础输出result |
||||
|
render( |
||||
|
"result.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/vo/Result.java", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
#Util 公共功能 |
||||
|
for file in ["Md5HashUtil.java.j2","FilesUtil.java.j2"]: |
||||
|
render( |
||||
|
file, |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/unit/{file.replace('.j2', '')}", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
# application 启动的方法 |
||||
|
render( |
||||
|
"application.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_BASE_PACKAGE_DIR}/Application.java", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
# test 测试类 |
||||
|
render( |
||||
|
"applicationTests.java.j2", |
||||
|
f"{BASE_DIR}{OUTPUT_DIR}/test/{to_path(BASE_PACKAGE)}/ApplicationTests.java", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
# 主pom文件 |
||||
|
render( |
||||
|
"main.pom.xml.j2", |
||||
|
f"{BASE_DIR}{MAIN_MODULE}/pom.xml", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
# 子项目pom文件 |
||||
|
render( |
||||
|
"project.pom.xml.j2", |
||||
|
f"{BASE_DIR}{MAIN_MODULE}/{MODULE_NAME}/pom.xml", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
#项目的yml配置文件 resources 生成环境配置为了最低限度能将项目跑起来 |
||||
|
render( |
||||
|
"application.yml.j2", |
||||
|
f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/application.yml", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
#项目开发环境的yml配置文件 resources yml 只生成dev环境配置为了最低限度能将项目跑起来 |
||||
|
render( |
||||
|
"application-dev.yml.j2", |
||||
|
f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/application-dev.yml", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
#项目开发环境的yml配置文件 resources yml 只生成dev环境配置为了最低限度能将项目跑起来 |
||||
|
render( |
||||
|
"logback.xml.j2", |
||||
|
f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/logback.xml", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
# ========= 功能模块 ========= |
||||
|
for model_name in model_names: |
||||
|
match model_name: |
||||
|
case "swagger": |
||||
|
# common Swagger2 |
||||
|
render( |
||||
|
"swagger2.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/Swagger2.java", |
||||
|
context |
||||
|
) |
||||
|
case "saToken": |
||||
|
# common GlobalException soToken 报错自定义 |
||||
|
render( |
||||
|
"globalException.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/GlobalException.java", |
||||
|
context |
||||
|
) |
||||
|
render( |
||||
|
"saTokenConfigure.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/SaTokenConfig.java", |
||||
|
context |
||||
|
) |
||||
|
case "minio": |
||||
|
#MinioConfig |
||||
|
render( |
||||
|
"MinioConfig.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/MinioConfig.java", |
||||
|
context |
||||
|
) |
||||
|
render( |
||||
|
"MinioUpController.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/controller/MinioUpController.java", |
||||
|
context |
||||
|
) |
||||
|
render( |
||||
|
"MinioUpComponent.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/unit/MinioUpComponent.java", |
||||
|
context |
||||
|
) |
||||
|
case "xxlJob": |
||||
|
# common XxlJobConfig |
||||
|
render( |
||||
|
"xxlJobConfig.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/XxlJobConfig.java", |
||||
|
context |
||||
|
) |
||||
|
# common xxjob的测试类 |
||||
|
render( |
||||
|
"testJob.java.j2", |
||||
|
f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/job/TestJob.java", |
||||
|
context |
||||
|
) |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
args = parse_args() |
||||
|
|
||||
|
tables = [t.strip() for t in args.tab.split(",") if t.strip()] |
||||
|
models = [m.strip() for m in args.model.split(",") if m.strip()] |
||||
|
conf = args.conf |
||||
|
re = args.re |
||||
|
|
||||
|
generate( |
||||
|
table_names=tables, |
||||
|
model_names=models, |
||||
|
conf_name=conf, |
||||
|
over_write=re |
||||
|
) |
||||
@ -0,0 +1,142 @@ |
|||||
|
package {{ package.Common }}.unit; |
||||
|
|
||||
|
import org.apache.commons.io.FileUtils; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
import sun.misc.BASE64Encoder; |
||||
|
|
||||
|
import java.io.*; |
||||
|
import java.util.Base64; |
||||
|
|
||||
|
public class FilesUtil { |
||||
|
|
||||
|
/** |
||||
|
* 根据文件路径获取文件字节流 |
||||
|
* @return |
||||
|
* filePath 文件路径 |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static byte[] toByteArray(String filePath) throws IOException { |
||||
|
File f = new File(filePath); |
||||
|
if (!f.exists()) { |
||||
|
throw new FileNotFoundException("文件不存在"); |
||||
|
} |
||||
|
|
||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length()); |
||||
|
BufferedInputStream in = null; |
||||
|
try { |
||||
|
in = new BufferedInputStream(new FileInputStream(f)); |
||||
|
int buf_size = 1024; |
||||
|
byte[] buffer = new byte[buf_size]; |
||||
|
int len = 0; |
||||
|
while (-1 != (len = in.read(buffer, 0, buf_size))) { |
||||
|
bos.write(buffer, 0, len); |
||||
|
} |
||||
|
return bos.toByteArray(); |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
throw e; |
||||
|
} finally { |
||||
|
try { |
||||
|
in.close(); |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
bos.close(); |
||||
|
} |
||||
|
} |
||||
|
public static File multipartFileToFile(MultipartFile file) throws Exception { |
||||
|
File toFile = null; |
||||
|
if (file.equals("") || file.getSize() <= 0) { |
||||
|
file = null; |
||||
|
} else { |
||||
|
InputStream ins = null; |
||||
|
ins = file.getInputStream(); |
||||
|
toFile = new File(file.getOriginalFilename()); |
||||
|
inputStreamToFile(ins, toFile); |
||||
|
ins.close(); |
||||
|
} |
||||
|
return toFile; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
private static void inputStreamToFile(InputStream ins, File file) { |
||||
|
try { |
||||
|
OutputStream os = new FileOutputStream(file); |
||||
|
int bytesRead = 0; |
||||
|
byte[] buffer = new byte[8192]; |
||||
|
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { |
||||
|
os.write(buffer, 0, bytesRead); |
||||
|
} |
||||
|
os.close(); |
||||
|
ins.close(); |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static String TransformPhotoToBase64Data(String path){ |
||||
|
Base64.Encoder encoder= Base64.getEncoder(); //获取Base64编码器 |
||||
|
byte [] ImgContainer = null ; //数据集缓存器 |
||||
|
FileInputStream fileInputStream = null; //文件输入流 |
||||
|
try { |
||||
|
System.out.println(path); |
||||
|
File file=new File(path); |
||||
|
fileInputStream = new FileInputStream(file); //到指定路径寻找文件 |
||||
|
ImgContainer = new byte[fileInputStream.available()]; //设置图片字节数据缓冲区大小 |
||||
|
fileInputStream.read(ImgContainer); //将数据流中的图片数据读进缓冲区 |
||||
|
String Base64ImgData =encoder.encodeToString(ImgContainer); //将图片编码转换成Base64格式的数据集 |
||||
|
fileInputStream.close(); //关闭数据流 |
||||
|
return Base64ImgData; //将缓冲区数据转换成字符数据返回 |
||||
|
} catch (FileNotFoundException e) { |
||||
|
return "找不到指定文件!"; |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
return "null"; |
||||
|
} |
||||
|
|
||||
|
public static String getBase64String(MultipartFile multiPartFile) throws IOException { |
||||
|
String baseStr = null; |
||||
|
|
||||
|
//把MultipartFile转化为File |
||||
|
File file = new File(multiPartFile.getOriginalFilename()); |
||||
|
FileUtils.copyInputStreamToFile(multiPartFile.getInputStream(), file); |
||||
|
|
||||
|
try {//file转base64 |
||||
|
FileInputStream inputStream = new FileInputStream(file); |
||||
|
byte[] buffer = new byte[(int) file.length()]; |
||||
|
inputStream.read(buffer); |
||||
|
inputStream.close(); |
||||
|
baseStr = new BASE64Encoder().encode(buffer); |
||||
|
|
||||
|
} catch (FileNotFoundException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
//删除临时文件 |
||||
|
if (file.exists()) { |
||||
|
file.delete(); |
||||
|
} |
||||
|
baseStr = baseStr.replaceAll("\r\n", ""); |
||||
|
return baseStr; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 返回文件扩展名,带。 |
||||
|
* @param file |
||||
|
* @return |
||||
|
*/ |
||||
|
public static String getFileExtension(MultipartFile file) { |
||||
|
String fileName = file.getOriginalFilename(); |
||||
|
int dotIndex = fileName.lastIndexOf("."); |
||||
|
if (dotIndex == -1) { |
||||
|
return ""; |
||||
|
} else { |
||||
|
return "."+fileName.substring(dotIndex + 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
package {{ package.Common }}.unit; |
||||
|
|
||||
|
import java.security.MessageDigest; |
||||
|
import java.security.NoSuchAlgorithmException; |
||||
|
|
||||
|
public class Md5HashUtil { |
||||
|
|
||||
|
public static String getMD5Hash(byte[] input) { |
||||
|
try { |
||||
|
MessageDigest md = MessageDigest.getInstance("MD5"); |
||||
|
byte[] digest = md.digest(input); |
||||
|
StringBuilder sb = new StringBuilder(); |
||||
|
for (byte b : digest) { |
||||
|
sb.append(String.format("%02x", b)); |
||||
|
} |
||||
|
return sb.toString(); |
||||
|
} catch (NoSuchAlgorithmException e) { |
||||
|
throw new RuntimeException("Could not find MD5 algorithm", e); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,84 @@ |
|||||
|
package {{ package.Common }}.config; |
||||
|
import {{ package.Common }}.unit.MinioUpComponent; |
||||
|
|
||||
|
|
||||
|
import io.minio.MinioClient; |
||||
|
import lombok.Data; |
||||
|
import org.springframework.beans.factory.annotation.Value; |
||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
/** |
||||
|
* @Description: minio配置类 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @wechat: {{ wechat }} |
||||
|
*/ |
||||
|
|
||||
|
@Component |
||||
|
@Data |
||||
|
@ConditionalOnClass(MinioUpComponent.class) |
||||
|
public class MinioConfig implements Serializable { |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* API调用地址ip |
||||
|
*/ |
||||
|
@Value("${minio.config.ip}") |
||||
|
private String ip; |
||||
|
|
||||
|
/** |
||||
|
* API调用地址端口 |
||||
|
*/ |
||||
|
@Value("${minio.config.port}") |
||||
|
private String port; |
||||
|
|
||||
|
/** |
||||
|
* 连接账号 |
||||
|
*/ |
||||
|
@Value("${minio.config.accessKey}") |
||||
|
private String accessKey; |
||||
|
|
||||
|
/** |
||||
|
* 连接秘钥 |
||||
|
*/ |
||||
|
@Value("${minio.config.secretKey}") |
||||
|
private String secretKey; |
||||
|
|
||||
|
/** |
||||
|
* minio存储桶的名称 |
||||
|
*/ |
||||
|
@Value("${minio.config.bucketName}") |
||||
|
private String bucketName; |
||||
|
|
||||
|
/** |
||||
|
* 文件下载到本地的路径 |
||||
|
*/ |
||||
|
@Value("${minio.config.downloadDir}") |
||||
|
private String downloadDir; |
||||
|
|
||||
|
/** |
||||
|
* #如果是true,则用的是https而不是http,默认值是true |
||||
|
*/ |
||||
|
@Value("${minio.config.secure}") |
||||
|
private Boolean secure; |
||||
|
|
||||
|
@Value("${minio.config.readPath}") |
||||
|
private String readPath; |
||||
|
|
||||
|
@Value("${minio.config.endpoint}") |
||||
|
private String endpoint; |
||||
|
|
||||
|
@Bean |
||||
|
public MinioClient buildClient() { |
||||
|
//1.创建minio链接客户端 |
||||
|
return MinioClient |
||||
|
.builder() |
||||
|
.credentials(accessKey, secretKey) |
||||
|
.endpoint(endpoint) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,191 @@ |
|||||
|
package {{ package.Common }}.unit; |
||||
|
import {{ package.Common }}.config.MinioConfig; |
||||
|
|
||||
|
import io.minio.*; |
||||
|
import io.minio.http.Method; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang.StringUtils; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import java.io.ByteArrayOutputStream; |
||||
|
import java.io.IOException; |
||||
|
import java.io.InputStream; |
||||
|
import java.text.SimpleDateFormat; |
||||
|
import java.util.Date; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
|
||||
|
/**** |
||||
|
* @Description: 上传 文件组件 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Component |
||||
|
public class MinioUpComponent { |
||||
|
|
||||
|
private final static String separator = "/"; |
||||
|
@Autowired |
||||
|
private MinioConfig minioConfig; |
||||
|
@Autowired |
||||
|
private MinioClient minioClient; |
||||
|
|
||||
|
/** |
||||
|
* @param dirPath |
||||
|
* @param filename yyyy/mm/dd/file.jpg |
||||
|
* @return |
||||
|
*/ |
||||
|
public static String builderFilePath(String dirPath, String filename) { |
||||
|
StringBuilder stringBuilder = new StringBuilder(50); |
||||
|
if (!StringUtils.isEmpty(dirPath)) { |
||||
|
stringBuilder.append(dirPath).append(separator); |
||||
|
} |
||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); |
||||
|
String todayStr = sdf.format(new Date()); |
||||
|
stringBuilder.append(todayStr).append(separator); |
||||
|
stringBuilder.append(filename); |
||||
|
return stringBuilder.toString(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 上传图片文件 |
||||
|
* |
||||
|
* @param prefix 文件前缀 |
||||
|
* @param filename 文件名 |
||||
|
* @param inputStream 文件流 |
||||
|
* @return 文件全路径 |
||||
|
*/ |
||||
|
public String uploadImg(String prefix, String filename, InputStream inputStream) { |
||||
|
String filePath = builderFilePath(prefix, filename); |
||||
|
try { |
||||
|
PutObjectArgs putObjectArgs = PutObjectArgs.builder() |
||||
|
.object(filePath) |
||||
|
.contentType("image/jpg") |
||||
|
.bucket(minioConfig.getBucketName()).stream(inputStream, inputStream.available(), -1) |
||||
|
.build(); |
||||
|
minioClient.putObject(putObjectArgs); |
||||
|
StringBuilder urlPath = new StringBuilder(minioConfig.getReadPath()); |
||||
|
urlPath.append(separator + minioConfig.getBucketName()); |
||||
|
urlPath.append(separator); |
||||
|
urlPath.append(filePath); |
||||
|
return urlPath.toString(); |
||||
|
} catch (Exception ex) { |
||||
|
log.error("minio put file error.", ex); |
||||
|
throw new RuntimeException("上传文件失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 上传html文件 |
||||
|
* |
||||
|
* @param prefix 文件前缀 |
||||
|
* @param filename 文件名 |
||||
|
* @param inputStream 文件流 |
||||
|
* @return 文件全路径 |
||||
|
*/ |
||||
|
public String uploadHtml(String prefix, String filename, InputStream inputStream) { |
||||
|
String filePath = builderFilePath(prefix, filename); |
||||
|
try { |
||||
|
PutObjectArgs putObjectArgs = PutObjectArgs.builder() |
||||
|
.object(filePath) |
||||
|
.contentType("text/html") |
||||
|
.bucket(minioConfig.getBucketName()) |
||||
|
.stream(inputStream, inputStream.available(), -1) |
||||
|
.build(); |
||||
|
minioClient.putObject(putObjectArgs); |
||||
|
StringBuilder urlPath = new StringBuilder(minioConfig.getReadPath()); |
||||
|
urlPath.append(separator + minioConfig.getBucketName()); |
||||
|
urlPath.append(separator); |
||||
|
urlPath.append(filePath); |
||||
|
return urlPath.toString(); |
||||
|
} catch (Exception ex) { |
||||
|
log.error("minio put file error.", ex); |
||||
|
ex.printStackTrace(); |
||||
|
throw new RuntimeException("上传文件失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 防盗链接有效期按分钟 |
||||
|
* |
||||
|
* @param filePath 文件前缀 |
||||
|
* @param expiry 超时分钟 |
||||
|
* @return 文件全路径 |
||||
|
*/ |
||||
|
public String getPresignObjectUrl(String filePath, Integer expiry) { |
||||
|
try { |
||||
|
filePath = filePath.replace("http://health.reglory.com.cn:9001/health-bucket/", ""); |
||||
|
GetPresignedObjectUrlArgs putObjectArgs = GetPresignedObjectUrlArgs.builder() |
||||
|
.object(filePath) |
||||
|
.bucket(minioConfig.getBucketName()) |
||||
|
.method(Method.GET) |
||||
|
// .region("health.reglory.com.cn:9001") |
||||
|
.expiry(expiry, TimeUnit.MINUTES) |
||||
|
.build(); |
||||
|
return minioClient.getPresignedObjectUrl(putObjectArgs); |
||||
|
} catch (Exception ex) { |
||||
|
log.error("minio put file error.", ex); |
||||
|
ex.printStackTrace(); |
||||
|
throw new RuntimeException("上传文件失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除文件 |
||||
|
* |
||||
|
* @param pathUrl 文件全路径 |
||||
|
*/ |
||||
|
public void delete(String pathUrl) { |
||||
|
String key = pathUrl.replace(minioConfig.getEndpoint() + "/", ""); |
||||
|
int index = key.indexOf(separator); |
||||
|
String bucket = key.substring(0, index); |
||||
|
String filePath = key.substring(index + 1); |
||||
|
// 删除Objects |
||||
|
RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(filePath).build(); |
||||
|
try { |
||||
|
minioClient.removeObject(removeObjectArgs); |
||||
|
} catch (Exception e) { |
||||
|
log.error("minio remove file error. pathUrl:{}", pathUrl); |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 下载文件 |
||||
|
* |
||||
|
* @param pathUrl 文件全路径 |
||||
|
* @return 文件流 |
||||
|
*/ |
||||
|
public byte[] downLoadFile(String pathUrl) { |
||||
|
String key = pathUrl.replace(minioConfig.getEndpoint() + "/", ""); |
||||
|
int index = key.indexOf(separator); |
||||
|
//String bucket = key.substring(0, index); |
||||
|
String filePath = key.substring(index + 1); |
||||
|
InputStream inputStream = null; |
||||
|
try { |
||||
|
inputStream = minioClient.getObject( |
||||
|
GetObjectArgs.builder().bucket(minioConfig.getBucketName()).object(filePath).build() |
||||
|
); |
||||
|
} catch (Exception e) { |
||||
|
log.error("minio down file error. pathUrl:{}", pathUrl); |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
||||
|
byte[] buff = new byte[100]; |
||||
|
int rc = 0; |
||||
|
while (true) { |
||||
|
try { |
||||
|
if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break; |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
byteArrayOutputStream.write(buff, 0, rc); |
||||
|
} |
||||
|
return byteArrayOutputStream.toByteArray(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,53 @@ |
|||||
|
package {{ package.Controller }}; |
||||
|
import {{ package.Common }}.unit.FilesUtil; |
||||
|
import {{ package.Common }}.unit.Md5HashUtil; |
||||
|
import {{ package.Common }}.unit.MinioUpComponent; |
||||
|
import {{ package.Common }}.vo.Result; |
||||
|
|
||||
|
import io.swagger.annotations.Api; |
||||
|
import io.swagger.annotations.ApiOperation; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
|
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* 上传控制器 |
||||
|
* </p> |
||||
|
* |
||||
|
* @author tiger |
||||
|
* @since 2024-06-04 |
||||
|
*/ |
||||
|
@Api(tags = "文件上传") |
||||
|
@RestController |
||||
|
@CrossOrigin(origins = "*") |
||||
|
@RequestMapping("/models/file") |
||||
|
public class MinioUpController { |
||||
|
|
||||
|
@Autowired |
||||
|
private MinioUpComponent minioUpComponent; |
||||
|
|
||||
|
@ApiOperation(value = "图片上传") |
||||
|
@CrossOrigin(origins = "*") |
||||
|
@PostMapping(value = "/upImg") |
||||
|
public Result<?> up(@RequestParam("file") MultipartFile file) { |
||||
|
if (file.isEmpty()) { |
||||
|
return Result.error("请选择一个文件上传"); |
||||
|
} |
||||
|
// 文件上传路径 可以为空 默认 bucketName: "health-bucket" 桶的名字为根目录 |
||||
|
// String path = "/tmp/user"; |
||||
|
String path = ""; |
||||
|
String url = ""; |
||||
|
try { |
||||
|
url = minioUpComponent.uploadImg(path,Md5HashUtil.getMD5Hash(file.getBytes()) + |
||||
|
FilesUtil.getFileExtension(file), file.getInputStream()); |
||||
|
} catch (IOException e) { |
||||
|
return Result.error("上传失败"); |
||||
|
} |
||||
|
return Result.OK(url); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,137 @@ |
|||||
|
server: |
||||
|
port: 8060 |
||||
|
servlet: |
||||
|
context-path: /api |
||||
|
|
||||
|
spring: |
||||
|
############## datasource 相关 |
||||
|
datasource: |
||||
|
type: com.zaxxer.hikari.HikariDataSource |
||||
|
driver-class-name: com.mysql.cj.jdbc.Driver |
||||
|
url: jdbc:mysql://{{ application.db.host }}:{{ application.db.port }}/{{ application.db.database }}?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false |
||||
|
username: {{ application.db.user }} |
||||
|
password: {{ application.db.password }} |
||||
|
#Hikari连接池配置 |
||||
|
hikari: |
||||
|
#池中维护的最小空闲连接数 |
||||
|
minimum-idle: 5 |
||||
|
#池中最大连接数,包括闲置和使用中的连接 |
||||
|
maximum-pool-size: 15 |
||||
|
#自动提交从池中返回的连接 |
||||
|
auto-commit: true |
||||
|
#连接允许在池中闲置的最长时间 |
||||
|
idle-timeout: 30000 |
||||
|
#连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置 |
||||
|
pool-name: DatebookHikariCP |
||||
|
#池中连接最长生命周期 |
||||
|
max-lifetime: 18000000 |
||||
|
#等待来自池的连接的最大毫秒数 |
||||
|
connection-timeout: 30000 |
||||
|
#验证该连接是否是有效的查询语句 |
||||
|
connection-test-query: select 1 from dual |
||||
|
cloud: |
||||
|
inetutils: |
||||
|
timeout-seconds: 10 |
||||
|
config: |
||||
|
enabled: false |
||||
|
############## redis 相关 |
||||
|
redis: |
||||
|
host: {{ application.redis.host }} |
||||
|
port: {{ application.redis.port }} |
||||
|
password: {{ application.redis.password }} |
||||
|
timeout: 10000 |
||||
|
jedis: |
||||
|
pool: |
||||
|
max-active: 1000 |
||||
|
max-wait: -1ms |
||||
|
max-idle: 10 |
||||
|
min-idle: 5 |
||||
|
database: {{application.redis.database}} |
||||
|
############## eureka 相关 |
||||
|
eureka: |
||||
|
instance: |
||||
|
instance-id: ${spring.cloud.client.ip-address}:${server.port} |
||||
|
prefer-ip-address: true |
||||
|
client: |
||||
|
healthcheck: |
||||
|
enabled: true |
||||
|
service-url: |
||||
|
defaultZone: http://{{ application.eureka.host }}:{{ application.eureka.port }}/eureka |
||||
|
|
||||
|
############## mybatis-plus配置 |
||||
|
mybatis-plus: |
||||
|
# 启动检查MyBatis配置文件 |
||||
|
check-config-location: false |
||||
|
# MyBatis配置文件位置 |
||||
|
config-location: |
||||
|
# MyBaits别名包扫描路径 |
||||
|
type-aliases-package: com.qiangesoft.mybatisplusjoin.entity |
||||
|
# Mapper所对应的XML文件位置 默认【classpath*:/mapper/**/*.xml】 |
||||
|
mapper-locations: classpath*:/mapper/*Mapper.xml |
||||
|
# TypeHandler扫描路径 |
||||
|
type-handlers-package: |
||||
|
configuration: |
||||
|
# 日志打印 |
||||
|
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl |
||||
|
# 是否开启自动驼峰命名规则 |
||||
|
map-underscore-to-camel-case: true |
||||
|
# 开启Mybatis二级缓存,默认为true |
||||
|
cache-enabled: true |
||||
|
global-config: |
||||
|
# 控制台mybatis-plus的logo |
||||
|
banner: true |
||||
|
db-config: |
||||
|
# 全局默认主键类型 |
||||
|
id-type: auto |
||||
|
# 逻辑删除配置 |
||||
|
logic-delete-field: deleted |
||||
|
logic-delete-value: 1 |
||||
|
logic-not-delete-value: 0 |
||||
|
|
||||
|
############## Sa-Token 配置 (文档: https://sa-token.cc) ############## |
||||
|
sa-token: |
||||
|
# token 名称(同时也是 cookie 名称) |
||||
|
token-name: Token |
||||
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效 |
||||
|
timeout: 2592000 |
||||
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 |
||||
|
active-timeout: -1 |
||||
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) |
||||
|
is-concurrent: true |
||||
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token) |
||||
|
is-share: true |
||||
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) |
||||
|
token-style: uuid |
||||
|
# 是否输出操作日志 |
||||
|
is-log: true |
||||
|
|
||||
|
############## swagger |
||||
|
swagger: |
||||
|
show: true |
||||
|
|
||||
|
############## minio |
||||
|
minio: |
||||
|
config: |
||||
|
ip: {{ application.minio.host }} #ip地址 |
||||
|
port: {{ application.minio.port }} # 端口号 |
||||
|
accessKey: {{ application.minio.accessKey }} # 账号 |
||||
|
secretKey: {{ application.minio.secretKey }} # 密码 |
||||
|
secure: false #如果是true,则用的是https而不是http,默认值是true |
||||
|
bucketName: "{{ application.minio.bucketName }}" # 桶的名字 |
||||
|
downloadDir: "{{ application.minio.downloadDir }}" #保存到本地的路径 |
||||
|
readPath: "http://{{ application.minio.host }}:{{ application.minio.port }}" #保存到本地的路径 |
||||
|
endpoint: "http://{{ application.minio.host }}:{{ application.minio.port }}" #保存到本地的路径 |
||||
|
|
||||
|
############## xxl-job |
||||
|
xxl: |
||||
|
job: |
||||
|
admin: |
||||
|
addresses: {{ application.xxlJob.addresses }} # 调度中心部署根地址 |
||||
|
accessToken: "{{ application.xxlJob.accessToken }}" # 执行器通讯TOKEN,非空时启用 |
||||
|
executor: |
||||
|
appname: xxl-{{ application.name }} # 执行器AppName |
||||
|
address: {{ application.xxlJob.address }} # 执行器注册地址,为空时使用内嵌服务IP:PORT |
||||
|
ip: {{ application.xxlJob.ip }} # 执行器IP,默认为空自动获取 |
||||
|
port: {{ application.xxlJob.port }} # 执行器端口号 |
||||
|
logpath: /data/applogs/xxl-job/jobhandler # 执行器运行日志文件存储磁盘路径 |
||||
|
logretentiondays: 30 # 执行器日志文件保存天数 |
||||
@ -0,0 +1,48 @@ |
|||||
|
package {{ package.Base }}; |
||||
|
|
||||
|
//-- 固定引入 --// |
||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
|
import org.springframework.boot.SpringApplication; |
||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
import org.springframework.cache.annotation.EnableCaching; |
||||
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; |
||||
|
import org.springframework.cloud.openfeign.EnableFeignClients; |
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.web.cors.CorsConfiguration; |
||||
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; |
||||
|
import org.springframework.web.filter.CorsFilter; |
||||
|
//-- 固定引入 --// |
||||
|
|
||||
|
/** |
||||
|
* @Description: 启动类 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
@SpringBootApplication |
||||
|
@EnableDiscoveryClient |
||||
|
@EnableFeignClients |
||||
|
@EnableCaching |
||||
|
public class Application { |
||||
|
|
||||
|
public static void main(String[] args) throws JsonProcessingException { |
||||
|
SpringApplication.run(Application.class, args); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
@Bean |
||||
|
public CorsFilter corsFilter() { |
||||
|
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); |
||||
|
final CorsConfiguration config = new CorsConfiguration(); |
||||
|
config.setAllowCredentials(true); // 允许cookies跨域 |
||||
|
config.addAllowedOrigin("*");// 允许向该服务器提交请求的URI,*表示全部允许。。这里尽量限制来源域,比如http://xxxx:8080 ,以降低安全风险。。 |
||||
|
config.addAllowedHeader("*");// 允许访问的头信息,*表示全部 |
||||
|
config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 |
||||
|
config.addAllowedMethod("*");// 允许提交请求的方法,*表示全部允许,也可以单独设置GET、PUT等 |
||||
|
source.registerCorsConfiguration("/**", config); |
||||
|
return new CorsFilter(source); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
spring: |
||||
|
profiles: |
||||
|
active: dev #开发环境 |
||||
|
#active: test #测试环境 |
||||
|
#active: pro #生产环境 |
||||
|
application: |
||||
|
name: {{ application.name }} |
||||
|
devtools: |
||||
|
restart: |
||||
|
log-condition-evaluation-delta: false |
||||
|
security: |
||||
|
user: |
||||
|
name: admin |
||||
|
password: admin |
||||
|
servlet: |
||||
|
multipart: |
||||
|
max-file-size: 30MB |
||||
|
max-request-size: 30MB |
||||
|
logging: |
||||
|
level: |
||||
|
root: info |
||||
|
{{ application.package.base }}: debug |
||||
|
org: |
||||
|
springframework: |
||||
|
boot: |
||||
|
autoconfigure: error |
||||
@ -0,0 +1,23 @@ |
|||||
|
package {{ package.Base }}; |
||||
|
|
||||
|
/*** |
||||
|
* @description {{ projectName }} |
||||
|
* @version 1.0.0 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
|
||||
|
import org.junit.jupiter.api.Test; |
||||
|
import org.springframework.boot.test.context.SpringBootTest; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
@SpringBootTest |
||||
|
class ApplicationTests { |
||||
|
|
||||
|
@Test |
||||
|
void contextLoads() throws IOException { |
||||
|
System.out.println("test start"); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
package {{ package.Entity }}; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.annotation.*; |
||||
|
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
|
import io.swagger.annotations.ApiModel; |
||||
|
import io.swagger.annotations.ApiModelProperty; |
||||
|
import lombok.Getter; |
||||
|
import lombok.Setter; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
/** |
||||
|
* 基础Entity类 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
|
||||
|
@ApiModel("基础Entity类") |
||||
|
@Setter |
||||
|
@Getter |
||||
|
public class BaseEntity implements Serializable { |
||||
|
|
||||
|
@ApiModelProperty(value = "主键id") |
||||
|
@TableId(value = "id", type = IdType.AUTO) |
||||
|
private Integer id; |
||||
|
|
||||
|
@ApiModelProperty(value = "创建者", hidden = true) |
||||
|
protected Integer createdBy; |
||||
|
|
||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
||||
|
@ApiModelProperty(value = "创建日期", hidden = true, example = "yyyy-MM-dd HH:mm:ss") |
||||
|
@TableField(value = "created_at", fill = FieldFill.INSERT) |
||||
|
protected Date createdAt; |
||||
|
|
||||
|
@ApiModelProperty(value = "更新者", hidden = true) |
||||
|
protected Integer updatedBy; |
||||
|
|
||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
||||
|
@ApiModelProperty(value = "更新日期", hidden = true, example = "yyyy-MM-dd HH:mm:ss") |
||||
|
@TableField(value = "updated_at", fill = FieldFill.INSERT, update = "NOW()") |
||||
|
protected Date updatedAt; |
||||
|
|
||||
|
@ApiModelProperty(value = "删除标记", hidden = true) |
||||
|
@TableField(value = "deleted_flag") |
||||
|
@TableLogic(value = "0", delval = "1") |
||||
|
protected Integer deletedFlag; |
||||
|
|
||||
|
@ApiModelProperty(value = "页码", required = false) |
||||
|
@TableField(exist = false) |
||||
|
private Integer pageNum; //页码 |
||||
|
|
||||
|
@ApiModelProperty(value = "每页条数", required = false) |
||||
|
@TableField(exist = false) |
||||
|
private Integer pageSize;//每页条数 |
||||
|
|
||||
|
@ApiModelProperty(value = "排序方式排序[true:正序; false:倒序]", required = false) |
||||
|
@TableField(exist = false) |
||||
|
private Boolean sort; |
||||
|
|
||||
|
@ApiModelProperty(value = "排序字段,参照返回字段", required = false) |
||||
|
@TableField(exist = false) |
||||
|
private String sortName; |
||||
|
|
||||
|
@ApiModelProperty(value = "用户ID") |
||||
|
@TableField(value = "user_id") |
||||
|
private Integer userId; |
||||
|
|
||||
|
@ApiModelProperty(value = "创建者用户名") |
||||
|
@TableField(exist = false) |
||||
|
private String createdByName; |
||||
|
|
||||
|
@ApiModelProperty(value = "更新者用户名") |
||||
|
@TableField(exist = false) |
||||
|
private String updatedByName; |
||||
|
|
||||
|
public BaseEntity() { |
||||
|
if (this.pageSize == null) { |
||||
|
this.setPageSize(10); |
||||
|
} |
||||
|
if (this.pageNum == null) { |
||||
|
this.setPageNum(1); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,107 @@ |
|||||
|
package {{ package.Controller }}; |
||||
|
import {{ package.Entity }}.{{ table.entity }}; |
||||
|
import {{ package.Service }}.{{ table.entity }}Service; |
||||
|
import {{ package.Common }}.vo.Result; |
||||
|
|
||||
|
//--- import 固定引入 ---// |
||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
import io.swagger.annotations.Api; |
||||
|
import io.swagger.annotations.ApiOperation; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import javax.validation.Valid; |
||||
|
import java.util.List; |
||||
|
//--- import 固定引入 ---// |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* {{ table.comment }} 前端控制器 |
||||
|
* </p> |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
@Api(tags = "{{ table.comment }}") |
||||
|
{% if restControllerStyle %} |
||||
|
@RestController |
||||
|
{% else %} |
||||
|
@Controller |
||||
|
{% endif %} |
||||
|
@RequestMapping("{{ table.name }}") |
||||
|
public class {{ table.entity }}Controller { |
||||
|
|
||||
|
@Resource |
||||
|
private {{ table.entity }}Service {{table.lowerEntity}}Service; |
||||
|
|
||||
|
@ApiOperation(value = "{{ table.comment }}分页列表查询", response = {{ table.entity }}.class) |
||||
|
@PostMapping(value = "/page") |
||||
|
public Result<Page<{{ table.entity }}>> page(@Valid @RequestBody {{ table.entity }} param,@RequestHeader("token") String token, |
||||
|
@RequestHeader(value = "version", defaultValue = "1.0") String version) { |
||||
|
Page<{{ table.entity }}> page = {{table.lowerEntity}}Service.page(param); |
||||
|
return Result.OK(page); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@ApiOperation(value = "{{ table.comment }}根据条件查询") |
||||
|
@PostMapping(value = "/info") |
||||
|
public Result<Object> info(@Valid @RequestBody {{ table.entity }} param, |
||||
|
@RequestHeader("token") String token, |
||||
|
@RequestHeader(value = "version", defaultValue = "1.0") String version) { |
||||
|
if (token ==null) { |
||||
|
return Result.error("token不能为空"); |
||||
|
} |
||||
|
{{ table.entity }} data = {{table.lowerEntity}}Service.info(param); |
||||
|
return Result.OK(data); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@ApiOperation(value = "{{ table.comment }}新增") |
||||
|
@PostMapping(value = "/add") |
||||
|
public Result add(@Valid @RequestBody {{ table.entity }} param, |
||||
|
@RequestHeader("token") String token, |
||||
|
@RequestHeader(value = "version", defaultValue = "1.0") String version) { |
||||
|
if (token ==null) { |
||||
|
return Result.error("token不能为空"); |
||||
|
} |
||||
|
{{table.lowerEntity}}Service.add(param); |
||||
|
return Result.OK(); |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "{{ table.comment }}修改") |
||||
|
@PostMapping(value = "/modify") |
||||
|
public Result modify(@Valid @RequestBody {{ table.entity }} param, |
||||
|
@RequestHeader("token") String token, |
||||
|
@RequestHeader(value = "version", defaultValue = "1.0") String version) { |
||||
|
if (token ==null) { |
||||
|
return Result.error("token不能为空"); |
||||
|
} |
||||
|
{{table.entity}} info = {{table.lowerEntity}}Service.info(Integer.valueOf(param.getId())); |
||||
|
if (info ==null) { |
||||
|
return Result.error(String.format("[%s]记录不存在", info)); |
||||
|
} |
||||
|
{{table.lowerEntity}}Service.modify(param); |
||||
|
return Result.OK(); |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "{{ table.comment }}删除(单个条目)") |
||||
|
@GetMapping(value = "/remove/{id}") |
||||
|
public Result remove(@PathVariable Integer id, |
||||
|
@RequestHeader("token") String token, |
||||
|
@RequestHeader(value = "version", defaultValue = "1.0") String version) { |
||||
|
|
||||
|
{{table.lowerEntity}}Service.remove(id); |
||||
|
return Result.OK(); |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "{{ table.comment }}删除(多个条目)") |
||||
|
@PostMapping(value = "/removes") |
||||
|
public Result removes(@Valid @RequestBody List<Integer> ids, |
||||
|
@RequestHeader("token") String token, |
||||
|
@RequestHeader(value = "version", defaultValue = "1.0") String version) { |
||||
|
{{table.lowerEntity}}Service.removes(ids); |
||||
|
return Result.OK(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
package {{ package.Entity }}; |
||||
|
import {{ package.Entity }}.BaseEntity; |
||||
|
|
||||
|
//--- import 固定引入 ---// |
||||
|
import com.baomidou.mybatisplus.annotation.*; |
||||
|
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
|
import io.swagger.annotations.ApiModel; |
||||
|
import io.swagger.annotations.ApiModelProperty; |
||||
|
import lombok.Data; |
||||
|
import lombok.EqualsAndHashCode; |
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }} |
||||
|
* |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
|
||||
|
{% if entityLombokModel %} |
||||
|
@Data |
||||
|
@EqualsAndHashCode(callSuper = true) |
||||
|
@TableName("{{ table.name }}") |
||||
|
@ApiModel(value = "{{ table.name }}对象", description = "{{ table.comment }}"){% endif %} |
||||
|
public class {{ table.entity }} extends BaseEntity { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
{% for field in fields %} |
||||
|
{% if field.java_type == 'Date' and field.tab_type == 'date' %}@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8"){% endif %} |
||||
|
{% if field.java_type == 'Date' and field.tab_type == 'datetime' %}@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8"){% endif %} |
||||
|
@TableField("{{ field.tab_name }}") |
||||
|
@ApiModelProperty("{{ field.comment }}") |
||||
|
private {{ field.java_type }} {{ field.java_name }}; |
||||
|
{% endfor %} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,74 @@ |
|||||
|
package {{ package.Common }}.config; |
||||
|
import {{ package.Common }}.vo.Result; |
||||
|
|
||||
|
//--- 固定引入 ---// |
||||
|
import cn.dev33.satoken.exception.*; |
||||
|
import org.springframework.web.bind.annotation.ExceptionHandler; |
||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice; |
||||
|
//--- 固定引入 ---// |
||||
|
|
||||
|
/** |
||||
|
* 全局异常处理 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
@RestControllerAdvice |
||||
|
public class GlobalException { |
||||
|
|
||||
|
// 拦截:未登录异常 |
||||
|
@ExceptionHandler(NotLoginException.class) |
||||
|
public Result handlerException(NotLoginException e) { |
||||
|
|
||||
|
// 打印堆栈,以供调试 |
||||
|
e.printStackTrace(); |
||||
|
|
||||
|
// 返回给前端 |
||||
|
return Result.error(1000,e.getMessage()); |
||||
|
} |
||||
|
|
||||
|
// 拦截:缺少权限异常 |
||||
|
@ExceptionHandler(NotPermissionException.class) |
||||
|
public Result handlerException(NotPermissionException e) { |
||||
|
e.printStackTrace(); |
||||
|
return Result.error("缺少权限:" + e.getPermission()); |
||||
|
} |
||||
|
|
||||
|
// 拦截:缺少角色异常 |
||||
|
@ExceptionHandler(NotRoleException.class) |
||||
|
public Result handlerException(NotRoleException e) { |
||||
|
e.printStackTrace(); |
||||
|
return Result.error("缺少角色:" + e.getRole()); |
||||
|
} |
||||
|
|
||||
|
// 拦截:二级认证校验失败异常 |
||||
|
@ExceptionHandler(NotSafeException.class) |
||||
|
public Result handlerException(NotSafeException e) { |
||||
|
e.printStackTrace(); |
||||
|
return Result.error("二级认证校验失败:" + e.getService()); |
||||
|
} |
||||
|
|
||||
|
// 拦截:服务封禁异常 |
||||
|
@ExceptionHandler(DisableServiceException.class) |
||||
|
public Result handlerException(DisableServiceException e) { |
||||
|
e.printStackTrace(); |
||||
|
return Result.error("当前账号 " + e.getService() + " 服务已被封禁 (level=" + e.getLevel() + "):" + e.getDisableTime() + "秒后解封"); |
||||
|
} |
||||
|
|
||||
|
// 拦截:Http Basic 校验失败异常 |
||||
|
@ExceptionHandler(NotBasicAuthException.class) |
||||
|
public Result handlerException(NotBasicAuthException e) { |
||||
|
e.printStackTrace(); |
||||
|
return Result.error(1003,e.getMessage()); |
||||
|
} |
||||
|
|
||||
|
// 拦截:其它所有异常 |
||||
|
@ExceptionHandler(Exception.class) |
||||
|
public Result handlerException(Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return Result.error(1002,e.getMessage()); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<configuration debug="false"> |
||||
|
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--> |
||||
|
<property name="LOG_HOME" value="/home" /> |
||||
|
<!--控制台日志, 控制台输出 --> |
||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> |
||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> |
||||
|
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符--> |
||||
|
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> |
||||
|
</encoder> |
||||
|
</appender> |
||||
|
<!--文件日志, 按照每天生成日志文件 --> |
||||
|
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
||||
|
<!--日志文件输出的文件名--> |
||||
|
<FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern> |
||||
|
<!--日志文件保留天数--> |
||||
|
<MaxHistory>30</MaxHistory> |
||||
|
</rollingPolicy> |
||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> |
||||
|
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> |
||||
|
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> |
||||
|
</encoder> |
||||
|
<!--日志文件最大的大小--> |
||||
|
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> |
||||
|
<MaxFileSize>10MB</MaxFileSize> |
||||
|
</triggeringPolicy> |
||||
|
</appender> |
||||
|
|
||||
|
<!-- show parameters for hibernate sql 专为 Hibernate 定制 --> |
||||
|
<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" /> |
||||
|
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" /> |
||||
|
<logger name="org.hibernate.SQL" level="DEBUG" /> |
||||
|
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG" /> |
||||
|
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" /> |
||||
|
|
||||
|
<!--myibatis log configure--> |
||||
|
<logger name="com.apache.mybatis" level="TRACE"/> |
||||
|
<logger name="java.sql.Connection" level="DEBUG"/> |
||||
|
<logger name="java.sql.Statement" level="DEBUG"/> |
||||
|
<logger name="java.sql.PreparedStatement" level="DEBUG"/> |
||||
|
|
||||
|
<!-- 日志输出级别 --> |
||||
|
<root level="DEBUG"> |
||||
|
<appender-ref ref="STDOUT" /> |
||||
|
<appender-ref ref="FILE"/> |
||||
|
</root> |
||||
|
</configuration> |
||||
@ -0,0 +1,229 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
<groupId>{{ groupId }}</groupId> |
||||
|
<artifactId>{{ mainModule }}</artifactId> |
||||
|
<version>1.0.0</version> |
||||
|
<name>${project.artifactId}</name> |
||||
|
<packaging>pom</packaging> |
||||
|
<modules> |
||||
|
<module>{{ moduleName }}</module> |
||||
|
</modules> |
||||
|
|
||||
|
<properties> |
||||
|
<spring-boot.version>2.0.8.RELEASE</spring-boot.version> |
||||
|
<spring-cloud.version>Finchley.SR4</spring-cloud.version> |
||||
|
<spring-platform.version>Cairo-SR7</spring-platform.version> |
||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
|
<maven.compiler.source>1.8</maven.compiler.source> |
||||
|
<maven.compiler.target>1.8</maven.compiler.target> |
||||
|
<spring-boot-admin.version>2.0.5</spring-boot-admin.version> |
||||
|
<hutool.version>4.5.0</hutool.version> |
||||
|
<oracle.version>11.2.0.4.0-atlassian-hosted</oracle.version> |
||||
|
<ndsjdbc.version>1.0</ndsjdbc.version> |
||||
|
<avtiviti.version>5.22.0</avtiviti.version> |
||||
|
<kaptcha.version>0.0.9</kaptcha.version> |
||||
|
<elastic-job.version>2.0.0</elastic-job.version> |
||||
|
<curator.version>2.10.0</curator.version> |
||||
|
<velocity.version>1.7</velocity.version> |
||||
|
<lcn.version>4.1.0</lcn.version> |
||||
|
<jasypt.version>2.1.0</jasypt.version> |
||||
|
<logstash.version>4.11</logstash.version> |
||||
|
<truelicense.version>1.33</truelicense.version> |
||||
|
<elastic-job-lite.version>2.1.5</elastic-job-lite.version> |
||||
|
<jackson.modules>2.9.8</jackson.modules> |
||||
|
<kafka-collector.version>2.4.1</kafka-collector.version> |
||||
|
<skywalking.version>6.0.0-GA</skywalking.version> |
||||
|
<registry.url>192.168.0.13:5000</registry.url> |
||||
|
<shiro.version>1.3.2</shiro.version> |
||||
|
<druid.version>1.1.6</druid.version> |
||||
|
<fastjson.version>1.2.78</fastjson.version> |
||||
|
<barcode4j.version>2.1</barcode4j.version> |
||||
|
<flying-saucer-pdf.version>9.1.5</flying-saucer-pdf.version> |
||||
|
<axis2.version>1.6.1</axis2.version> |
||||
|
<mybatisplus.version>3.5.3.2</mybatisplus.version> |
||||
|
</properties> |
||||
|
|
||||
|
<dependencyManagement> |
||||
|
<dependencies> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-dependencies</artifactId> |
||||
|
<version>${spring-boot.version}</version> |
||||
|
<type>pom</type> |
||||
|
<scope>import</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>io.spring.platform</groupId> |
||||
|
<artifactId>platform-bom</artifactId> |
||||
|
<version>${spring-platform.version}</version> |
||||
|
<type>pom</type> |
||||
|
<scope>import</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.cloud</groupId> |
||||
|
<artifactId>spring-cloud-dependencies</artifactId> |
||||
|
<version>${spring-cloud.version}</version> |
||||
|
<type>pom</type> |
||||
|
<scope>import</scope> |
||||
|
</dependency> |
||||
|
<!--jackson模块 --> |
||||
|
<dependency> |
||||
|
<groupId>com.fasterxml.jackson.module</groupId> |
||||
|
<artifactId>jackson-modules-java8</artifactId> |
||||
|
<version>${jackson.modules}</version> |
||||
|
<type>pom</type> |
||||
|
<scope>import</scope> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
</dependencyManagement> |
||||
|
|
||||
|
<dependencies> |
||||
|
<!-- Sleuth --> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.cloud</groupId> |
||||
|
<artifactId>spring-cloud-starter-sleuth</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.aspectj</groupId> |
||||
|
<artifactId>aspectjweaver</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.skywalking</groupId> |
||||
|
<artifactId>apm-toolkit-logback-1.x</artifactId> |
||||
|
<version>${skywalking.version}</version> |
||||
|
</dependency> |
||||
|
<!--监控 --> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-actuator</artifactId> |
||||
|
</dependency> |
||||
|
<!--监控客户端 --> |
||||
|
<dependency> |
||||
|
<groupId>de.codecentric</groupId> |
||||
|
<artifactId>spring-boot-admin-starter-client</artifactId> |
||||
|
<version>${spring-boot-admin.version}</version> |
||||
|
</dependency> |
||||
|
<!--断路器依赖 --> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.cloud</groupId> |
||||
|
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId> |
||||
|
</dependency> |
||||
|
<!-- Postgresql --> |
||||
|
<dependency> |
||||
|
<groupId>org.postgresql</groupId> |
||||
|
<artifactId>postgresql</artifactId> |
||||
|
</dependency> |
||||
|
<!-- logstash --> |
||||
|
<dependency> |
||||
|
<groupId>net.logstash.logback</groupId> |
||||
|
<artifactId>logstash-logback-encoder</artifactId> |
||||
|
<version>${logstash.version}</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- truelicense --> |
||||
|
<dependency> |
||||
|
<groupId>de.schlichtherle.truelicense</groupId> |
||||
|
<artifactId>truelicense-core</artifactId> |
||||
|
<version>${truelicense.version}</version> |
||||
|
</dependency> |
||||
|
<!--Lombok --> |
||||
|
<dependency> |
||||
|
<groupId>org.projectlombok</groupId> |
||||
|
<artifactId>lombok</artifactId> |
||||
|
<version>1.18.24</version> |
||||
|
<scope>provided</scope> |
||||
|
</dependency> |
||||
|
<!--测试依赖 --> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-test</artifactId> |
||||
|
<scope>test</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.shiro</groupId> |
||||
|
<artifactId>shiro-spring</artifactId> |
||||
|
<version>${shiro.version}</version> |
||||
|
</dependency> |
||||
|
<!-- 新增阿里 --> |
||||
|
<dependency> |
||||
|
<groupId>com.alibaba</groupId> |
||||
|
<artifactId>druid</artifactId> |
||||
|
<version>${druid.version}</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.alibaba</groupId> |
||||
|
<artifactId>fastjson</artifactId> |
||||
|
<version>${fastjson.version}</version> |
||||
|
</dependency> |
||||
|
<!-- 新增 barcode4j--> |
||||
|
<dependency> |
||||
|
<groupId>net.sf.barcode4j</groupId> |
||||
|
<artifactId>barcode4j</artifactId> |
||||
|
<version>${barcode4j.version}</version> |
||||
|
</dependency> |
||||
|
<!--flying-saucer-pdf-9.1.5.jar--> |
||||
|
<dependency> |
||||
|
<groupId>org.xhtmlrenderer</groupId> |
||||
|
<artifactId>flying-saucer-pdf</artifactId> |
||||
|
<version>${flying-saucer-pdf.version}</version> |
||||
|
</dependency> |
||||
|
<!-- 新增axis2 --> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.axis2</groupId> |
||||
|
<artifactId>axis2</artifactId> |
||||
|
<version>${axis2.version}</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.baomidou</groupId> |
||||
|
<artifactId>mybatis-plus-boot-starter</artifactId> |
||||
|
<version>${mybatisplus.version}</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.apache.poi</groupId> |
||||
|
<artifactId>poi-ooxml</artifactId> |
||||
|
<version>3.9</version> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
|
||||
|
<build> |
||||
|
<finalName>${project.name}</finalName> |
||||
|
<pluginManagement> |
||||
|
<plugins> |
||||
|
<plugin> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
|
<version>${spring-boot.version}</version> |
||||
|
<configuration> |
||||
|
<finalName>${project.build.finalName}</finalName> |
||||
|
</configuration> |
||||
|
<executions> |
||||
|
<execution> |
||||
|
<goals> |
||||
|
<goal>repackage</goal> |
||||
|
</goals> |
||||
|
</execution> |
||||
|
</executions> |
||||
|
</plugin> |
||||
|
</plugins> |
||||
|
</pluginManagement> |
||||
|
<plugins> |
||||
|
<plugin> |
||||
|
<artifactId>maven-compiler-plugin</artifactId> |
||||
|
<version>3.8.0</version> |
||||
|
<configuration> |
||||
|
<target>${maven.compiler.target}</target> |
||||
|
<source>${maven.compiler.source}</source> |
||||
|
<encoding>UTF-8</encoding> |
||||
|
</configuration> |
||||
|
</plugin> |
||||
|
<plugin> |
||||
|
<groupId>pl.project13.maven</groupId> |
||||
|
<artifactId>git-commit-id-plugin</artifactId> |
||||
|
<version>2.2.5</version> |
||||
|
</plugin> |
||||
|
</plugins> |
||||
|
</build> |
||||
|
</project> |
||||
@ -0,0 +1,20 @@ |
|||||
|
package {{ package.Mapper }}; |
||||
|
|
||||
|
import {{package.Entity}}.{{ table.entity }}; |
||||
|
|
||||
|
//--- import 固定引入 ---// |
||||
|
import com.github.yulichang.base.MPJBaseMapper; |
||||
|
//--- import 固定引入 ---// |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* 操作记录 Mapper 接口 |
||||
|
* </p> |
||||
|
* |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
public interface {{ table.entity }}Mapper extends MPJBaseMapper<{{ table.entity }}> { |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
<mapper namespace="{{ package.Mapper }}.{{ table.entity }}Mapper"> |
||||
|
<!-- 通用查询映射结果 --> |
||||
|
<resultMap id="BaseResultMap" type="{{ package.Entity }}.{{ table.entity }}"> |
||||
|
{% for field in fields %} |
||||
|
<result column="{{ field.tab_name }}" property="{{ field.java_name }}" /> |
||||
|
{% endfor %} |
||||
|
</resultMap> |
||||
|
|
||||
|
</mapper> |
||||
@ -0,0 +1,12 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> |
||||
|
<configuration> |
||||
|
<typeAliases> |
||||
|
<typeAlias alias="Integer" type="java.lang.Integer" /> |
||||
|
<typeAlias alias="Long" type="java.lang.Long" /> |
||||
|
<typeAlias alias="HashMap" type="java.util.HashMap" /> |
||||
|
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" /> |
||||
|
<typeAlias alias="ArrayList" type="java.util.ArrayList" /> |
||||
|
<typeAlias alias="LinkedList" type="java.util.LinkedList" /> |
||||
|
</typeAliases> |
||||
|
</configuration> |
||||
@ -0,0 +1,37 @@ |
|||||
|
package {{ package.Common }}.config; |
||||
|
|
||||
|
//--- 固定引入 ---// |
||||
|
import com.baomidou.mybatisplus.annotation.DbType; |
||||
|
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer; |
||||
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
||||
|
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; |
||||
|
import org.mybatis.spring.annotation.MapperScan; |
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
//--- 固定引入 ---// |
||||
|
|
||||
|
/** |
||||
|
* MybatisPlus 配置 |
||||
|
* |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
|
||||
|
@Configuration |
||||
|
@MapperScan(basePackages = {"{{package.Mapper}}"}) |
||||
|
public class MybatisPlusConfig { |
||||
|
@Bean |
||||
|
public MybatisPlusInterceptor mybatisPlusInterceptor() { |
||||
|
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); |
||||
|
//向Mybatis过滤器链中添加分页拦截器 |
||||
|
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); |
||||
|
//还可以添加i他的拦截器 |
||||
|
return interceptor; |
||||
|
} |
||||
|
|
||||
|
@Bean |
||||
|
public ConfigurationCustomizer configurationCustomizer() { |
||||
|
return configuration -> configuration.setUseGeneratedShortKey(false); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,310 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
<parent> |
||||
|
<groupId>{{ groupId }}</groupId> |
||||
|
<artifactId>{{ mainModule }}</artifactId> |
||||
|
<version>1.0.0</version> |
||||
|
</parent> |
||||
|
<artifactId>{{ moduleName }}</artifactId> |
||||
|
<name>{{ moduleName }}</name> |
||||
|
<properties> |
||||
|
<java.version>1.8</java.version> |
||||
|
</properties> |
||||
|
<dependencies> |
||||
|
|
||||
|
<!-- netty tcp 客户端和服务端 --> |
||||
|
<dependency> |
||||
|
<groupId>io.netty</groupId> |
||||
|
<artifactId>netty-all</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- mysql 8.0.27--> |
||||
|
<dependency> |
||||
|
<groupId>mysql</groupId> |
||||
|
<artifactId>mysql-connector-java</artifactId> |
||||
|
<version>8.0.27</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!--web 模块 --> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-web</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<!--tomcat容器 --> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-tomcat</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-jdbc</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- mybatis-plus --> |
||||
|
<dependency> |
||||
|
<groupId>com.github.yulichang</groupId> |
||||
|
<artifactId>mybatis-plus-join-boot-starter</artifactId> |
||||
|
<version>1.4.11</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.github.yulichang</groupId> |
||||
|
<artifactId>mybatis-plus-join-core</artifactId> |
||||
|
<version>1.4.11</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>io.minio</groupId> |
||||
|
<artifactId>minio</artifactId> |
||||
|
<version>7.1.0</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- Others --> |
||||
|
<dependency> |
||||
|
<groupId>com.jcraft</groupId> |
||||
|
<artifactId>jsch</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<!--freemarker-2.3.19.jar --> |
||||
|
<dependency> |
||||
|
<groupId>org.freemarker</groupId> |
||||
|
<artifactId>freemarker</artifactId> |
||||
|
<version>2.3.28</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-data-redis</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<!--spring2.X集成redis所需common-pool2--> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.commons</groupId> |
||||
|
<artifactId>commons-pool2</artifactId> |
||||
|
<version>2.10.0</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.alibaba</groupId> |
||||
|
<artifactId>fastjson</artifactId> |
||||
|
<version>1.2.78</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.apache.axis</groupId> |
||||
|
<artifactId>axis</artifactId> |
||||
|
<version>1.4</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.apache.axis</groupId> |
||||
|
<artifactId>axis-jaxrpc</artifactId> |
||||
|
<version>1.4</version> |
||||
|
<scope>compile</scope> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.sap.cloud.db.jdbc</groupId> |
||||
|
<artifactId>ngdbc</artifactId> |
||||
|
<version>2.5.49</version> |
||||
|
<type>pom</type> |
||||
|
<scope>test</scope> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>commons-discovery</groupId> |
||||
|
<artifactId>commons-discovery</artifactId> |
||||
|
<version>0.2</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>wsdl4j</groupId> |
||||
|
<artifactId>wsdl4j</artifactId> |
||||
|
<version>1.6.3</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.junit.jupiter</groupId> |
||||
|
<artifactId>junit-jupiter-api</artifactId> |
||||
|
<version>5.5.0</version> |
||||
|
<scope>test</scope> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>cn.hutool</groupId> |
||||
|
<artifactId>hutool-all</artifactId> |
||||
|
<version>5.3.8</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.alibaba</groupId> |
||||
|
<artifactId>transmittable-thread-local</artifactId> |
||||
|
<version>2.12.2</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.jeecgframework</groupId> |
||||
|
<artifactId>autopoi</artifactId> |
||||
|
<version>1.3.6</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>io.springfox</groupId> |
||||
|
<artifactId>springfox-swagger2</artifactId> |
||||
|
<version>2.9.2</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>io.springfox</groupId> |
||||
|
<artifactId>springfox-swagger-ui</artifactId> |
||||
|
<version>2.9.2</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.github.xiaoymin</groupId> |
||||
|
<artifactId>swagger-bootstrap-ui</artifactId> |
||||
|
<version>1.8.7</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.cloud</groupId> |
||||
|
<artifactId>spring-cloud-starter-openfeign</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- 热部署模块 --> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-devtools</artifactId> |
||||
|
<version>2.0.4.RELEASE</version> |
||||
|
<optional>true</optional> <!-- 这个需要为 true 热部署才有效 --> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>commons-net</groupId> |
||||
|
<artifactId>commons-net</artifactId> |
||||
|
<version>3.6</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- 新增poi 3.9版本 --> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.poi</groupId> |
||||
|
<artifactId>poi</artifactId> |
||||
|
<version>3.9</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.apache.poi</groupId> |
||||
|
<artifactId>poi-ooxml</artifactId> |
||||
|
<version>3.9</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-websocket</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.github.penggle</groupId> |
||||
|
<artifactId>kaptcha</artifactId> |
||||
|
<version>2.3.2</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- aliyun下达指令的两个依赖 --> |
||||
|
<dependency> |
||||
|
<groupId>com.aliyun</groupId> |
||||
|
<artifactId>aliyun-java-sdk-core</artifactId> |
||||
|
<version>4.5.17</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.aliyun</groupId> |
||||
|
<artifactId>aliyun-java-sdk-iot</artifactId> |
||||
|
<version>7.1.0</version> |
||||
|
</dependency> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.baomidou</groupId> |
||||
|
<artifactId>mybatis-plus-generator</artifactId> |
||||
|
<version>3.5.3.2</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.baomidou</groupId> |
||||
|
<artifactId>mybatis-plus-boot-starter</artifactId> |
||||
|
<version>3.5.3.2</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- 对象映射的库 --> |
||||
|
<dependency> |
||||
|
<groupId>org.modelmapper</groupId> |
||||
|
<artifactId>modelmapper</artifactId> |
||||
|
<version>2.3.9</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- swagger --> |
||||
|
<dependency> |
||||
|
<groupId>com.github.xiaoymin</groupId> |
||||
|
<artifactId>swagger-bootstrap-ui</artifactId> |
||||
|
<version>1.8.7</version> |
||||
|
<scope>compile</scope> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) --> |
||||
|
<dependency> |
||||
|
<groupId>cn.dev33</groupId> |
||||
|
<artifactId>sa-token-redis-jackson</artifactId> |
||||
|
<version>1.38.0</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>cn.dev33</groupId> |
||||
|
<artifactId>sa-token-spring-boot-starter</artifactId> |
||||
|
<version>1.38.0</version> |
||||
|
<scope>compile</scope> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- xxl-job --> |
||||
|
<dependency> |
||||
|
<groupId>com.xuxueli</groupId> |
||||
|
<artifactId>xxl-job-core</artifactId> |
||||
|
<version>2.4.0</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- 验证码 --> |
||||
|
<dependency> |
||||
|
<groupId>com.github.whvcse</groupId> |
||||
|
<artifactId>easy-captcha</artifactId> |
||||
|
<version>1.6.2</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<!-- websocket --> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-websocket</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
</dependencies> |
||||
|
|
||||
|
<build> |
||||
|
<plugins> |
||||
|
<plugin> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
|
<executions> |
||||
|
<execution> |
||||
|
<goals> |
||||
|
<goal>repackage</goal> |
||||
|
</goals> |
||||
|
</execution> |
||||
|
</executions> |
||||
|
</plugin> |
||||
|
</plugins> |
||||
|
</build> |
||||
|
|
||||
|
</project> |
||||
@ -0,0 +1,172 @@ |
|||||
|
package {{ package.Common }}.vo; |
||||
|
|
||||
|
//---固定引入---// |
||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||
|
import io.swagger.annotations.ApiModel; |
||||
|
import io.swagger.annotations.ApiModelProperty; |
||||
|
import lombok.Data; |
||||
|
import java.io.Serializable; |
||||
|
//---固定引入---// |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 接口返回数据格式 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
|
||||
|
@Data |
||||
|
@ApiModel(value="接口返回对象", description="接口返回对象") |
||||
|
public class Result<T> implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
/** |
||||
|
* 成功标志 |
||||
|
*/ |
||||
|
@ApiModelProperty(value = "成功标志") |
||||
|
private boolean success = true; |
||||
|
|
||||
|
/** |
||||
|
* 返回处理消息 |
||||
|
*/ |
||||
|
@ApiModelProperty(value = "返回处理消息") |
||||
|
private String message = ""; |
||||
|
|
||||
|
/** |
||||
|
* 返回代码 |
||||
|
*/ |
||||
|
@ApiModelProperty(value = "返回代码") |
||||
|
private Integer code = 0; |
||||
|
|
||||
|
/** |
||||
|
* 返回数据对象 data |
||||
|
*/ |
||||
|
@ApiModelProperty(value = "返回数据对象") |
||||
|
private T result; |
||||
|
|
||||
|
/** |
||||
|
* 时间戳 |
||||
|
*/ |
||||
|
@ApiModelProperty(value = "时间戳") |
||||
|
private long timestamp = System.currentTimeMillis(); |
||||
|
|
||||
|
public Result() { |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 兼容VUE3版token失效不跳转登录页面 |
||||
|
* @param code |
||||
|
* @param message |
||||
|
*/ |
||||
|
public Result(Integer code, String message) { |
||||
|
this.code = code; |
||||
|
this.message = message; |
||||
|
} |
||||
|
|
||||
|
public Result<T> success(String message) { |
||||
|
this.message = message; |
||||
|
this.code = 200; |
||||
|
this.success = true; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
@Deprecated |
||||
|
public static Result<Object> ok() { |
||||
|
Result<Object> r = new Result<Object>(); |
||||
|
r.setSuccess(true); |
||||
|
r.setCode(200); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
@Deprecated |
||||
|
public static Result<Object> ok(String msg) { |
||||
|
Result<Object> r = new Result<Object>(); |
||||
|
r.setSuccess(true); |
||||
|
r.setCode(200); |
||||
|
r.setMessage(msg); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
@Deprecated |
||||
|
public static Result<Object> ok(Object data) { |
||||
|
Result<Object> r = new Result<Object>(); |
||||
|
r.setSuccess(true); |
||||
|
r.setCode(200); |
||||
|
r.setResult(data); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
public static<T> Result<T> OK() { |
||||
|
Result<T> r = new Result<T>(); |
||||
|
r.setSuccess(true); |
||||
|
r.setCode(200); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
public static<T> Result<T> OK(String msg) { |
||||
|
Result<T> r = new Result<T>(); |
||||
|
r.setSuccess(true); |
||||
|
r.setCode(200); |
||||
|
r.setMessage(msg); |
||||
|
//Result OK(String msg)方法会造成兼容性问题 issues/I4IP3D |
||||
|
r.setResult((T) msg); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
public static<T> Result<T> OK(T data) { |
||||
|
Result<T> r = new Result<T>(); |
||||
|
r.setSuccess(true); |
||||
|
r.setCode(200); |
||||
|
r.setResult(data); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
public static<T> Result<T> OK(String msg, T data) { |
||||
|
Result<T> r = new Result<T>(); |
||||
|
r.setSuccess(true); |
||||
|
r.setCode(200); |
||||
|
r.setMessage(msg); |
||||
|
r.setResult(data); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
public static<T> Result<T> error(String msg, T data) { |
||||
|
Result<T> r = new Result<T>(); |
||||
|
r.setSuccess(false); |
||||
|
r.setCode(500); |
||||
|
r.setMessage(msg); |
||||
|
r.setResult(data); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
public static Result<Object> error(String msg) { |
||||
|
return error(500, msg); |
||||
|
} |
||||
|
|
||||
|
public static Result<Object> error(int code, String msg) { |
||||
|
Result<Object> r = new Result<Object>(); |
||||
|
r.setCode(code); |
||||
|
r.setMessage(msg); |
||||
|
r.setSuccess(false); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
public Result<T> error500(String message) { |
||||
|
this.message = message; |
||||
|
this.code = 500; |
||||
|
this.success = false; |
||||
|
return this; |
||||
|
} |
||||
|
/** |
||||
|
* 无权限访问返回结果 |
||||
|
*/ |
||||
|
public static Result<Object> noauth(String msg) { |
||||
|
return error(210, msg); |
||||
|
} |
||||
|
|
||||
|
@JsonIgnore |
||||
|
private String onlTable; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
package {{ package.Common }}.config; |
||||
|
|
||||
|
import cn.dev33.satoken.interceptor.SaInterceptor; |
||||
|
import cn.dev33.satoken.router.SaRouter; |
||||
|
import cn.dev33.satoken.stp.StpUtil; |
||||
|
import com.alibaba.fastjson.JSONArray; |
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* SaToken配置 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
* 解决@RequestAttribute、@RequestParam和@RequestBody三种类型的时间类型参数接收与转换问题 |
||||
|
*/ |
||||
|
@Configuration |
||||
|
public class SaTokenConfig implements WebMvcConfigurer { |
||||
|
|
||||
|
@Override |
||||
|
public void addInterceptors(InterceptorRegistry registry) { |
||||
|
|
||||
|
// 注册 Sa-Token 拦截器,定义详细认证规则 |
||||
|
registry.addInterceptor(new SaInterceptor(handler -> { |
||||
|
// 指定一条 match 规则 |
||||
|
SaRouter |
||||
|
.match("/models/**") // 拦截的 path 列表,可以写多个 */ |
||||
|
// .notMatch("/models/health-user/login") // 排除掉的 path 列表,可以写多个 |
||||
|
.check(r -> StpUtil.checkLogin()); // 要执行的校验动作,可以写完整的 lambda 表达式 |
||||
|
|
||||
|
//拦截并写操作日志 |
||||
|
// SaRouter.match(r).check(t->{ |
||||
|
// SaLog.info("操作日志:{}", SaLog.getParamJson()); |
||||
|
// SaLog.info("操作日志:{}", SaLog.getRequestBody()); |
||||
|
// ); |
||||
|
|
||||
|
})).addPathPatterns("/**"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,85 @@ |
|||||
|
package {{ package.Service }}; |
||||
|
import {{ package.Entity }}.{{ table.entity }}; |
||||
|
|
||||
|
//--- import 固定引入 ---// |
||||
|
import com.baomidou.mybatisplus.extension.service.IService; |
||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
import java.util.List; |
||||
|
//--- import 固定引入 ---// |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}服务接口 |
||||
|
* |
||||
|
* @author {{ author }} |
||||
|
* @date {{ date }} |
||||
|
*/ |
||||
|
|
||||
|
public interface {{ table.entity }}Service extends IService<{{ table.entity }}> { |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}分页列表 |
||||
|
* |
||||
|
* @param param 根据需要进行传值 |
||||
|
* @return |
||||
|
*/ |
||||
|
Page<{{ table.entity }}> page({{ table.entity }} param); |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}详情 |
||||
|
* |
||||
|
* @param param |
||||
|
* @return |
||||
|
*/ |
||||
|
{{ table.entity }} info({{ table.entity }} param); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}详情 |
||||
|
* |
||||
|
* @param id |
||||
|
* @return |
||||
|
*/ |
||||
|
{{ table.entity }} info(Integer id); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}列表 |
||||
|
* |
||||
|
* @param param |
||||
|
* @return |
||||
|
*/ |
||||
|
List<{{ table.entity }}> list({{ table.entity }} param); |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}新增 |
||||
|
* |
||||
|
* @param param 根据需要进行传值 |
||||
|
* @return |
||||
|
*/ |
||||
|
void add({{ table.entity }} param); |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}修改 |
||||
|
* |
||||
|
* @param param 根据需要进行传值 |
||||
|
* @return |
||||
|
*/ |
||||
|
void modify({{ table.entity }} param); |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}删除(单个条目) |
||||
|
* |
||||
|
* @param id |
||||
|
* @return |
||||
|
*/ |
||||
|
void remove(Integer id); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}删除(多个条目) |
||||
|
* |
||||
|
* @param ids |
||||
|
* @return |
||||
|
*/ |
||||
|
void removes(List<Integer> ids); |
||||
|
} |
||||
@ -0,0 +1,154 @@ |
|||||
|
package {{ package.ServiceImpl }}; |
||||
|
|
||||
|
import {{ package.Entity }}.{{ table.entity }}; |
||||
|
import {{ package.Mapper }}.{{ table.entity }}Mapper; |
||||
|
import {{ package.Service }}.{{ table.entity }}Service; |
||||
|
|
||||
|
//--- import 固定引入 ---// |
||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||
|
import com.github.yulichang.base.MPJBaseServiceImpl; |
||||
|
import com.github.yulichang.wrapper.MPJLambdaWrapper; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
//--- import 固定引入 ---// |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* {{ table.comment }} 服务实现类 |
||||
|
* </p> |
||||
|
* |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
@Service |
||||
|
public class {{ table.entity }}MPJBaseServiceImpl extends MPJBaseServiceImpl<{{ table.entity }}Mapper, {{ table.entity }}> implements {{ table.entity }}Service { |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}分页列表 |
||||
|
* @param param 根据需要进行传值 |
||||
|
* @return |
||||
|
*/ |
||||
|
@Override |
||||
|
public Page<{{ table.entity }}> page({{ table.entity }} param) { |
||||
|
MPJLambdaWrapper<{{ table.entity }}> queryWrapper = new MPJLambdaWrapper<>(); |
||||
|
queryWrapper.selectAll({{ table.entity }}.class) |
||||
|
{% for field in fields %}{% if not entityLombokModel %}{% if field.java_type == "Boolean" %}{% set get_pre_fix = "is" %}{% else %}{% set get_pre_fix = "get" %}{% endif %}{% if field.java_type == "String" %} |
||||
|
.eq(StringUtils.isNotBlank(param.{{ get_pre_fix }}{{ field.java_get_name }}()), {{ table.entity }}::{{ get_pre_fix }}{{ field.capital_name }}, param.{{ get_pre_fix }}{{ field.java_get_name }}()) |
||||
|
{% else %} |
||||
|
.eq(param.{{ get_pre_fix }}{{ field.java_get_name }}() != null, {{ table.entity }}::{{ get_pre_fix }}{{ field.capital_name }}, param.{{ get_pre_fix }}{{ field.java_get_name }}()) |
||||
|
{% endif %}{% else %}{% if field.java_type == "String" %} |
||||
|
.eq(StringUtils.isNotBlank(param.get{{ field.java_get_name }}()), {{ table.entity }}::get{{ field.java_get_name }}, param.get{{ field.java_get_name }}()) |
||||
|
{% else %} |
||||
|
.eq(param.get{{ field.java_get_name }}() != null, {{ table.entity }}::get{{ field.java_get_name }}, param.get{{ field.java_get_name }}()) |
||||
|
{% endif %}{% endif %}{% endfor %}; |
||||
|
return selectJoinListPage( new Page<>(param.getPageNum(), param.getPageSize()), {{ table.entity }}.class, queryWrapper); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}详情 |
||||
|
* @param param |
||||
|
* @return |
||||
|
*/ |
||||
|
@Override |
||||
|
public {{ table.entity }} info({{ table.entity }} param) { |
||||
|
MPJLambdaWrapper<{{ table.entity }}> queryWrapper = new MPJLambdaWrapper<>(); |
||||
|
queryWrapper.selectAll({{ table.entity }}.class) |
||||
|
{% for field in fields %}{% if not entityLombokModel %}{% if field.java_type == "Boolean" %}{% set get_pre_fix = "is" %}{% else %}{% set get_pre_fix = "get" %}{% endif %}{% if field.java_type == "String" %} |
||||
|
.eq(StringUtils.isNotBlank(param.{{ get_pre_fix }}{{ field.java_get_name }}()), {{ table.entity }}::{{ get_pre_fix }}{{ field.capital_name }}, param.{{ get_pre_fix }}{{ field.java_get_name }}()) |
||||
|
{% else %} |
||||
|
.eq(param.{{ get_pre_fix }}{{ field.java_get_name }}() != null, {{ table.entity }}::{{ get_pre_fix }}{{ field.capital_name }}, param.{{ get_pre_fix }}{{ field.java_get_name }}()) |
||||
|
{% endif %}{% else %}{% if field.java_type == "String" %} |
||||
|
.eq(StringUtils.isNotBlank(param.get{{ field.java_get_name }}()), {{ table.entity }}::get{{ field.java_get_name }}, param.get{{ field.java_get_name }}()) |
||||
|
{% else %} |
||||
|
.eq(param.get{{ field.java_get_name }}() != null, {{ table.entity }}::get{{ field.java_get_name }}, param.get{{ field.java_get_name }}()) |
||||
|
{% endif %}{% endif %}{% endfor %}; |
||||
|
return selectJoinOne( {{ table.entity }}.class, queryWrapper ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}详情 |
||||
|
* @param id |
||||
|
* @return |
||||
|
*/ |
||||
|
@Override |
||||
|
public {{ table.entity }} info(Integer id) { |
||||
|
return getById(id); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}列表 |
||||
|
* @param param |
||||
|
*/ |
||||
|
@Override |
||||
|
public List<{{ table.entity }}> list({{ table.entity }} param) { |
||||
|
MPJLambdaWrapper<{{ table.entity }}> queryWrapper = new MPJLambdaWrapper<>(); |
||||
|
queryWrapper.selectAll({{ table.entity }}.class) |
||||
|
{% for field in fields %}{% if not entityLombokModel %}{% if field.java_type == "Boolean" %}{% set get_pre_fix = "is" %}{% else %}{% set get_pre_fix = "get" %}{% endif %}{% if field.java_type == "String" %} |
||||
|
.eq(StringUtils.isNotBlank(param.{{ get_pre_fix }}{{ field.java_get_name }}()), {{ table.entity }}::{{ get_pre_fix }}{{ field.capital_name }}, param.{{ get_pre_fix }}{{ field.java_get_name }}()) |
||||
|
{% else %} |
||||
|
.eq(param.{{ get_pre_fix }}{{ field.java_get_name }}() != null, {{ table.entity }}::{{ get_pre_fix }}{{ field.capital_name }}, param.{{ get_pre_fix }}{{ field.java_get_name }}()) |
||||
|
{% endif %}{% else %}{% if field.java_type == "String" %} |
||||
|
.eq(StringUtils.isNotBlank(param.get{{ field.java_get_name }}()), {{ table.entity }}::get{{ field.java_get_name }}, param.get{{ field.java_get_name }}()) |
||||
|
{% else %} |
||||
|
.eq(param.get{{ field.java_get_name }}() != null, {{ table.entity }}::get{{ field.java_get_name }}, param.get{{ field.java_get_name }}()) |
||||
|
{% endif %}{% endif %}{% endfor %}; |
||||
|
return selectJoinList( {{ table.entity }}.class, queryWrapper); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}新增 |
||||
|
* |
||||
|
* @param param 根据需要进行传值 |
||||
|
* @return |
||||
|
*/ |
||||
|
@Override |
||||
|
public void add({{ table.entity }} param) { |
||||
|
param.setCreatedAt(new Date()); |
||||
|
param.setCreatedBy(param.getUserId()); |
||||
|
save(param); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}修改 |
||||
|
* |
||||
|
* @param param 根据需要进行传值 |
||||
|
* @return |
||||
|
*/ |
||||
|
@Override |
||||
|
public void modify({{ table.entity }} param) { |
||||
|
param.setUpdatedAt(new Date()); |
||||
|
param.setUpdatedBy(param.getUserId()); |
||||
|
updateById(param); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}删除(单个条目) |
||||
|
* |
||||
|
* @param id |
||||
|
* @return |
||||
|
*/ |
||||
|
@Override |
||||
|
public void remove(Integer id) { |
||||
|
removeById(id); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {{ table.comment }}删除(多个条目) |
||||
|
* |
||||
|
* @param ids |
||||
|
* @return |
||||
|
*/ |
||||
|
@Override |
||||
|
public void removes(List<Integer> ids) { |
||||
|
removeByIds(ids); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,66 @@ |
|||||
|
package {{ package.Common }}.config; |
||||
|
|
||||
|
//--- 固定引入 ---// |
||||
|
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI; |
||||
|
import com.google.common.base.Predicates; |
||||
|
import org.springframework.beans.factory.annotation.Value; |
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import springfox.documentation.builders.ApiInfoBuilder; |
||||
|
import springfox.documentation.builders.PathSelectors; |
||||
|
import springfox.documentation.builders.RequestHandlerSelectors; |
||||
|
import springfox.documentation.service.ApiInfo; |
||||
|
import springfox.documentation.service.Contact; |
||||
|
import springfox.documentation.spi.DocumentationType; |
||||
|
import springfox.documentation.spring.web.plugins.Docket; |
||||
|
import springfox.documentation.swagger2.annotations.EnableSwagger2; |
||||
|
//--- 固定引入 ---// |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Swagger2配置类 |
||||
|
* 在与spring boot集成时,放在与Application.java同级的目录下。 |
||||
|
* 通过@Configuration注解,让Spring来加载该类配置。 |
||||
|
* 再通过@EnableSwagger2注解来启用Swagger2。 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
* 访问地址:http://localhost:port/api/doc.html |
||||
|
*/ |
||||
|
@Configuration |
||||
|
@EnableSwagger2 |
||||
|
@EnableSwaggerBootstrapUI |
||||
|
public class Swagger2 { |
||||
|
|
||||
|
@Value("${swagger.show}") |
||||
|
private boolean swaggerShow; |
||||
|
|
||||
|
@Bean |
||||
|
public Docket createRestApi() { |
||||
|
|
||||
|
return new Docket(DocumentationType.SWAGGER_2) |
||||
|
.apiInfo(apiInfo()) |
||||
|
.enable(swaggerShow)// 设置正式环境不显示Swagger2 |
||||
|
.select() |
||||
|
// 配置多个扫描路径 |
||||
|
.apis( |
||||
|
Predicates.or( |
||||
|
RequestHandlerSelectors.basePackage("{{package.Controller}}") |
||||
|
) |
||||
|
) |
||||
|
.paths(PathSelectors.any()) |
||||
|
.build(); |
||||
|
} |
||||
|
|
||||
|
private ApiInfo apiInfo() { |
||||
|
// name:作者,url:通常项目地址,email:邮箱 |
||||
|
Contact contact=new Contact("{{author}}","https://blog.csdn.net/Extraordinarylife"," "); |
||||
|
return new ApiInfoBuilder() |
||||
|
.title("数据中心接口文档")//标题 |
||||
|
.description("数据中心相关接口文档")// 描述 |
||||
|
.contact(contact) |
||||
|
.version("1.0")//版本 |
||||
|
.build(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,26 @@ |
|||||
|
package {{ package.Common }}.job; |
||||
|
|
||||
|
import com.xxl.job.core.handler.annotation.XxlJob; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* @Description: |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
@Component |
||||
|
public class TestJob { |
||||
|
private static Logger logger = LoggerFactory.getLogger(TestJob.class); |
||||
|
|
||||
|
@XxlJob("testJobHand") |
||||
|
public void testJobHand() { |
||||
|
logger.info(">>>>>>>>>>> testJobHand"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
@ -0,0 +1,85 @@ |
|||||
|
package {{ package.Common }}.config; |
||||
|
|
||||
|
//--- 固定引入 ---// |
||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.aspectj.lang.ProceedingJoinPoint; |
||||
|
import org.aspectj.lang.annotation.Around; |
||||
|
import org.aspectj.lang.annotation.Aspect; |
||||
|
import org.aspectj.lang.reflect.MethodSignature; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import org.springframework.web.context.request.RequestContextHolder; |
||||
|
import org.springframework.web.context.request.ServletRequestAttributes; |
||||
|
//--- 固定引入 ---// |
||||
|
|
||||
|
|
||||
|
/*** |
||||
|
* @Description: 日志切面 |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Aspect |
||||
|
@Component |
||||
|
public class WebLogAspect { |
||||
|
|
||||
|
private final ObjectMapper objectMapper = new ObjectMapper(); |
||||
|
|
||||
|
/** 拦截所有 Controller 方法 */ |
||||
|
@Around("within(@org.springframework.web.bind.annotation.RestController *)") |
||||
|
public Object logWebRequest(ProceedingJoinPoint joinPoint) throws Throwable { |
||||
|
long start = System.currentTimeMillis(); |
||||
|
|
||||
|
ServletRequestAttributes attributes = |
||||
|
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
||||
|
HttpServletRequest request = attributes != null ? attributes.getRequest() : null; |
||||
|
|
||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); |
||||
|
String methodName = signature.toShortString(); |
||||
|
|
||||
|
// ========== 读取请求入参 ========== |
||||
|
String paramsJson = ""; |
||||
|
try { |
||||
|
paramsJson = objectMapper.writeValueAsString(joinPoint.getArgs()); |
||||
|
} catch (Exception ignored) {} |
||||
|
|
||||
|
// ----------- 打印入参 ------- |
||||
|
if (request != null) { |
||||
|
log.info("\n================= 请求开始 =================\n" + |
||||
|
"URL : {}\n" + |
||||
|
"Method : {}\n" + |
||||
|
"Controller : {}\n" + |
||||
|
"IP : {}\n" + |
||||
|
"Request : {}\n" + |
||||
|
"============================================", |
||||
|
request.getRequestURI(), |
||||
|
request.getMethod(), |
||||
|
methodName, |
||||
|
request.getRemoteAddr(), |
||||
|
paramsJson); |
||||
|
} |
||||
|
|
||||
|
// ========== 执行方法 ========== |
||||
|
Object result = joinPoint.proceed(); |
||||
|
|
||||
|
// ========== 打印返回结果 ========== |
||||
|
String resultJson = ""; |
||||
|
try { |
||||
|
resultJson = objectMapper.writeValueAsString(result); |
||||
|
} catch (Exception ignored) {} |
||||
|
|
||||
|
log.info("\n================= 请求结束 =================\n" + |
||||
|
"URL : {}\n" + |
||||
|
"耗时 : {} ms\n" + |
||||
|
"返回值 : {}\n" + |
||||
|
"============================================", |
||||
|
request != null ? request.getRequestURI() : methodName, |
||||
|
(System.currentTimeMillis() - start), |
||||
|
resultJson); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,51 @@ |
|||||
|
package {{ package.Common }}.config; |
||||
|
|
||||
|
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; |
||||
|
import org.springframework.beans.factory.annotation.Value; |
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
||||
|
|
||||
|
/**** |
||||
|
* xxl-job config |
||||
|
* @Author: {{author}} |
||||
|
* @Date: {{date}} |
||||
|
* @Wechat: {{ wechat }} |
||||
|
*/ |
||||
|
@Configuration |
||||
|
public class XxlJobConfig implements WebMvcConfigurer { |
||||
|
|
||||
|
@Value("${xxl.job.admin.addresses}") |
||||
|
private String adminAddresses; |
||||
|
|
||||
|
@Value("${xxl.job.executor.appname}") |
||||
|
private String appName; |
||||
|
|
||||
|
@Value("${xxl.job.executor.ip}") |
||||
|
private String ip; |
||||
|
|
||||
|
@Value("${xxl.job.executor.port}") |
||||
|
private int port; |
||||
|
|
||||
|
@Value("${xxl.job.accessToken}") |
||||
|
private String accessToken; |
||||
|
|
||||
|
@Value("${xxl.job.executor.logpath}") |
||||
|
private String logPath; |
||||
|
|
||||
|
@Value("${xxl.job.executor.logretentiondays}") |
||||
|
private int logRetentionDays; |
||||
|
|
||||
|
@Bean |
||||
|
public XxlJobSpringExecutor xxlJobExecutor() { |
||||
|
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); |
||||
|
xxlJobSpringExecutor.setAdminAddresses(adminAddresses); |
||||
|
xxlJobSpringExecutor.setAppname(appName); |
||||
|
xxlJobSpringExecutor.setIp(ip); |
||||
|
xxlJobSpringExecutor.setPort(port); |
||||
|
xxlJobSpringExecutor.setAccessToken(accessToken); |
||||
|
xxlJobSpringExecutor.setLogPath(logPath); |
||||
|
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); |
||||
|
return xxlJobSpringExecutor; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,131 @@ |
|||||
|
import argparse |
||||
|
import re |
||||
|
from copy import deepcopy |
||||
|
|
||||
|
def to_camel(name): |
||||
|
parts = name.split("_") |
||||
|
return parts[0] + "".join(p.capitalize() for p in parts[1:]) |
||||
|
|
||||
|
def to_m_camel(name): |
||||
|
return "".join(p.capitalize() for p in name.split("_")) |
||||
|
|
||||
|
def to_class(name): |
||||
|
return "".join(p.capitalize() for p in name.split("_")) |
||||
|
|
||||
|
def lower_first(s: str) -> str: |
||||
|
if not s: |
||||
|
return s |
||||
|
return s[0].lower() + s[1:] |
||||
|
|
||||
|
def to_path(name): |
||||
|
parts = name.split(".") |
||||
|
if len(parts) < 2: # 如果没有".",parts长度就是1 |
||||
|
return "" |
||||
|
return parts[0] + "/" + "/".join(p for p in parts[1:]) |
||||
|
|
||||
|
|
||||
|
def get_first_part(name, default=""): |
||||
|
delimiter="_" |
||||
|
if delimiter not in name: |
||||
|
return default |
||||
|
|
||||
|
parts = name.split(delimiter) |
||||
|
if not parts or not parts[0]: |
||||
|
return default |
||||
|
|
||||
|
return parts[0].capitalize() |
||||
|
|
||||
|
def parse_args(): |
||||
|
parser = argparse.ArgumentParser(description="Java Code Generator") |
||||
|
|
||||
|
parser.add_argument( |
||||
|
"--tab", |
||||
|
default="", |
||||
|
help="表名,多个用逗号分隔,例如: tab,tab2" |
||||
|
) |
||||
|
|
||||
|
parser.add_argument( |
||||
|
"--model", |
||||
|
default="", |
||||
|
help="可选模块 xxlJob,minio,saToken,swagger" |
||||
|
) |
||||
|
|
||||
|
parser.add_argument( |
||||
|
"--re", |
||||
|
action="store_true", |
||||
|
help="是否覆盖已存在文件(默认不覆盖)" |
||||
|
) |
||||
|
|
||||
|
parser.add_argument( |
||||
|
"--conf", |
||||
|
required=True, |
||||
|
default="", |
||||
|
help="配置文件路径" |
||||
|
) |
||||
|
|
||||
|
return parser.parse_args() |
||||
|
|
||||
|
|
||||
|
VAR_PATTERN = re.compile(r"\$\{([^}]+)\}") |
||||
|
def get_by_path(data: dict, path: str): |
||||
|
""" |
||||
|
从 dict 中通过 a.b.c 取值 |
||||
|
""" |
||||
|
cur = data |
||||
|
for key in path.split("."): |
||||
|
if not isinstance(cur, dict) or key not in cur: |
||||
|
return None |
||||
|
cur = cur[key] |
||||
|
return cur |
||||
|
|
||||
|
def resolve_string(value: str, data: dict) -> str: |
||||
|
def replacer(match): |
||||
|
expr = match.group(1) |
||||
|
v = get_by_path(data, expr) |
||||
|
return str(v) if v is not None else match.group(0) |
||||
|
|
||||
|
return VAR_PATTERN.sub(replacer, value) |
||||
|
|
||||
|
def resolve_config(config: dict, max_rounds=5) -> dict: |
||||
|
""" |
||||
|
递归解析配置中的 ${xxx} |
||||
|
""" |
||||
|
result = deepcopy(config) |
||||
|
|
||||
|
for _ in range(max_rounds): |
||||
|
changed = False |
||||
|
|
||||
|
def walk(obj): |
||||
|
nonlocal changed |
||||
|
if isinstance(obj, dict): |
||||
|
for k, v in obj.items(): |
||||
|
obj[k] = walk(v) |
||||
|
elif isinstance(obj, list): |
||||
|
return [walk(i) for i in obj] |
||||
|
elif isinstance(obj, str): |
||||
|
new = resolve_string(obj, result) |
||||
|
if new != obj: |
||||
|
changed = True |
||||
|
return new |
||||
|
return obj |
||||
|
|
||||
|
walk(result) |
||||
|
|
||||
|
if not changed: |
||||
|
break |
||||
|
|
||||
|
return result |
||||
|
|
||||
|
|
||||
|
def mysql_to_java(mysql_type): |
||||
|
mapping = { |
||||
|
"bigint": "Long", |
||||
|
"int": "Integer", |
||||
|
"tinyint": "Integer", |
||||
|
"varchar": "String", |
||||
|
"mediumtext": "String", |
||||
|
"datetime": "Date", |
||||
|
"date": "Date", |
||||
|
"decimal": "BigDecimal" |
||||
|
} |
||||
|
return mapping.get(mysql_type, "String") |
||||
Loading…
Reference in new issue