项目初次提交
This commit is contained in:
148
.gitignore
vendored
Normal file
148
.gitignore
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
### @author <a href="https://github.com/liyupi">程序员鱼皮</a> ###
|
||||
### @from <a href="https://yupi.icu">编程导航知识星球</a> ###
|
||||
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
### Java template
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
### Maven template
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
!/.xcodemap/
|
||||
23
.xcodemap/config/xcodemap-class-filter.yaml
Normal file
23
.xcodemap/config/xcodemap-class-filter.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
autoDetectedPackages:
|
||||
- com.yupi.springbootinit
|
||||
enableAutoDetect: true
|
||||
entryDisplayConfig:
|
||||
excludedPathPatterns: []
|
||||
skipJsCss: true
|
||||
funcDisplayConfig:
|
||||
skipConstructors: false
|
||||
skipFieldAccess: true
|
||||
skipFieldChange: true
|
||||
skipGetters: false
|
||||
skipNonProjectPackages: false
|
||||
skipPrivateMethods: false
|
||||
skipSetters: false
|
||||
ignoreSameClassCall: null
|
||||
ignoreSamePackageCall: null
|
||||
includedPackagePrefixes: null
|
||||
includedParentClasses: null
|
||||
name: xcodemap-filter
|
||||
recordMode: all
|
||||
sourceDisplayConfig:
|
||||
color: blue
|
||||
startOnDebug: false
|
||||
15
Dockerfile
Normal file
15
Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
# Docker 镜像构建
|
||||
# @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
# @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
FROM maven:3.8.1-jdk-8-slim as builder
|
||||
|
||||
# Copy local code to the container image.
|
||||
WORKDIR /app
|
||||
COPY pom.xml .
|
||||
COPY src ./src
|
||||
|
||||
# Build a release artifact.
|
||||
RUN mvn package -DskipTests
|
||||
|
||||
# Run the web service on container startup.
|
||||
CMD ["java","-jar","/app/target/springboot-init-0.0.1-SNAPSHOT.jar","--spring.profiles.active=prod"]
|
||||
181
README.md
Normal file
181
README.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# SpringBoot 项目初始模板
|
||||
|
||||
> 作者:[程序员鱼皮](https://github.com/liyupi)
|
||||
> 仅分享于 [编程导航知识星球](https://yupi.icu)
|
||||
|
||||
基于 Java SpringBoot 的项目初始模板,整合了常用框架和主流业务的示例代码。
|
||||
|
||||
只需 1 分钟即可完成内容网站的后端!!!大家还可以在此基础上快速开发自己的项目。
|
||||
|
||||
[toc]
|
||||
|
||||
## 模板特点
|
||||
|
||||
### 主流框架 & 特性
|
||||
|
||||
- Spring Boot 2.7.x(贼新)
|
||||
- Spring MVC
|
||||
- MyBatis + MyBatis Plus 数据访问(开启分页)
|
||||
- Spring Boot 调试工具和项目处理器
|
||||
- Spring AOP 切面编程
|
||||
- Spring Scheduler 定时任务
|
||||
- Spring 事务注解
|
||||
|
||||
### 数据存储
|
||||
|
||||
- MySQL 数据库
|
||||
- Redis 内存数据库
|
||||
- Elasticsearch 搜索引擎
|
||||
- 腾讯云 COS 对象存储
|
||||
|
||||
### 工具类
|
||||
|
||||
- Easy Excel 表格处理
|
||||
- Hutool 工具库
|
||||
- Apache Commons Lang3 工具类
|
||||
- Lombok 注解
|
||||
|
||||
### 业务特性
|
||||
|
||||
- 业务代码生成器(支持自动生成 Service、Controller、数据模型代码)
|
||||
- Spring Session Redis 分布式登录
|
||||
- 全局请求响应拦截器(记录日志)
|
||||
- 全局异常处理器
|
||||
- 自定义错误码
|
||||
- 封装通用响应类
|
||||
- Swagger + Knife4j 接口文档
|
||||
- 自定义权限注解 + 全局校验
|
||||
- 全局跨域处理
|
||||
- 长整数丢失精度解决
|
||||
- 多环境配置
|
||||
|
||||
|
||||
## 业务功能
|
||||
|
||||
- 提供示例 SQL(用户、帖子、帖子点赞、帖子收藏表)
|
||||
- 用户登录、注册、注销、更新、检索、权限管理
|
||||
- 帖子创建、删除、编辑、更新、数据库检索、ES 灵活检索
|
||||
- 帖子点赞、取消点赞
|
||||
- 帖子收藏、取消收藏、检索已收藏帖子
|
||||
- 帖子全量同步 ES、增量同步 ES 定时任务
|
||||
- 支持微信开放平台登录
|
||||
- 支持微信公众号订阅、收发消息、设置菜单
|
||||
- 支持分业务的文件上传
|
||||
|
||||
### 单元测试
|
||||
|
||||
- JUnit5 单元测试
|
||||
- 示例单元测试类
|
||||
|
||||
### 架构设计
|
||||
|
||||
- 合理分层
|
||||
|
||||
|
||||
## 快速上手
|
||||
|
||||
> 所有需要修改的地方鱼皮都标记了 `todo`,便于大家找到修改的位置~
|
||||
|
||||
### MySQL 数据库
|
||||
|
||||
1)修改 `application.yml` 的数据库配置为你自己的:
|
||||
|
||||
```yml
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/my_db
|
||||
username: root
|
||||
password: 123456
|
||||
```
|
||||
|
||||
2)执行 `sql/create_table.sql` 中的数据库语句,自动创建库表
|
||||
|
||||
3)启动项目,访问 `http://localhost:8101/api/doc.html` 即可打开接口文档,不需要写前端就能在线调试接口了~
|
||||
|
||||

|
||||
|
||||
### Redis 分布式登录
|
||||
|
||||
1)修改 `application.yml` 的 Redis 配置为你自己的:
|
||||
|
||||
```yml
|
||||
spring:
|
||||
redis:
|
||||
database: 1
|
||||
host: localhost
|
||||
port: 6379
|
||||
timeout: 5000
|
||||
password: 123456
|
||||
```
|
||||
|
||||
2)修改 `application.yml` 中的 session 存储方式:
|
||||
|
||||
```yml
|
||||
spring:
|
||||
session:
|
||||
store-type: redis
|
||||
```
|
||||
|
||||
3)移除 `MainApplication` 类开头 `@SpringBootApplication` 注解内的 exclude 参数:
|
||||
|
||||
修改前:
|
||||
|
||||
```java
|
||||
@SpringBootApplication(exclude = {RedisAutoConfiguration.class})
|
||||
```
|
||||
|
||||
修改后:
|
||||
|
||||
|
||||
```java
|
||||
@SpringBootApplication
|
||||
```
|
||||
|
||||
### Elasticsearch 搜索引擎
|
||||
|
||||
1)修改 `application.yml` 的 Elasticsearch 配置为你自己的:
|
||||
|
||||
```yml
|
||||
spring:
|
||||
elasticsearch:
|
||||
uris: http://localhost:9200
|
||||
username: root
|
||||
password: 123456
|
||||
```
|
||||
|
||||
2)复制 `sql/post_es_mapping.json` 文件中的内容,通过调用 Elasticsearch 的接口或者 Kibana Dev Tools 来创建索引(相当于数据库建表)
|
||||
|
||||
```
|
||||
PUT post_v1
|
||||
{
|
||||
参数见 sql/post_es_mapping.json 文件
|
||||
}
|
||||
```
|
||||
|
||||
这步不会操作的话需要补充下 Elasticsearch 的知识,或者自行百度一下~
|
||||
|
||||
3)开启同步任务,将数据库的帖子同步到 Elasticsearch
|
||||
|
||||
找到 job 目录下的 `FullSyncPostToEs` 和 `IncSyncPostToEs` 文件,取消掉 `@Component` 注解的注释,再次执行程序即可触发同步:
|
||||
|
||||
```java
|
||||
// todo 取消注释开启任务
|
||||
//@Component
|
||||
```
|
||||
|
||||
### 业务代码生成器
|
||||
|
||||
支持自动生成 Service、Controller、数据模型代码,配合 MyBatisX 插件,可以快速开发增删改查等实用基础功能。
|
||||
|
||||
找到 `generate.CodeGenerator` 类,修改生成参数和生成路径,并且支持注释掉不需要的生成逻辑,然后运行即可。
|
||||
|
||||
```
|
||||
// 指定生成参数
|
||||
String packageName = "com.yupi.springbootinit";
|
||||
String dataName = "用户评论";
|
||||
String dataKey = "userComment";
|
||||
String upperDataKey = "UserComment";
|
||||
```
|
||||
|
||||
生成代码后,可以移动到实际项目中,并且按照 `// todo` 注释的提示来针对自己的业务需求进行修改。
|
||||
316
mvnw
vendored
Executable file
316
mvnw
vendored
Executable file
@@ -0,0 +1,316 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /usr/local/etc/mavenrc ] ; then
|
||||
. /usr/local/etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`\\unset -f command; \\command -v java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=`cd "$wdir/.."; pwd`
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||
fi
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
fi
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=`cygpath --path --windows "$javaClass"`
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
# Compiling the Java class
|
||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||
fi
|
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
# Running the downloader
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Running MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
fi
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
188
mvnw.cmd
vendored
Normal file
188
mvnw.cmd
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% ^
|
||||
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||
%MAVEN_OPTS% ^
|
||||
%MAVEN_DEBUG_OPTS% ^
|
||||
-classpath %WRAPPER_JAR% ^
|
||||
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||
|
||||
cmd /C exit /B %ERROR_CODE%
|
||||
134
pom.xml
Normal file
134
pom.xml
Normal file
@@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- @author <a href="https://github.com/liyupi">程序员鱼皮</a> -->
|
||||
<!-- @from <a href="https://yupi.icu">编程导航知识星球</a> -->
|
||||
<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>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.7.2</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.yupi</groupId>
|
||||
<artifactId>springboot-init</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>springboot-init</name>
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.5.2</version>
|
||||
</dependency>
|
||||
<!-- rabbit-mq -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
<!-- redis -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-data-redis</artifactId>
|
||||
</dependency>
|
||||
<!-- https://doc.xiaominfo.com/docs/quick-start#openapi2 -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
|
||||
<version>4.4.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<!-- https://hutool.cn/docs/index.html#/-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>r07</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>9</source>
|
||||
<target>9</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
27
src/main/java/com/yupi/springbootinit/MainApplication.java
Normal file
27
src/main/java/com/yupi/springbootinit/MainApplication.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.yupi.springbootinit;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* 主类(项目启动入口)
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
// todo 如需开启 Redis,须移除 exclude 中的内容
|
||||
@SpringBootApplication(exclude = {RedisAutoConfiguration.class})
|
||||
@MapperScan("com.yupi.springbootinit.mapper")
|
||||
@EnableScheduling
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
|
||||
public class MainApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MainApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.yupi.springbootinit.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 权限校验
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface AuthCheck {
|
||||
|
||||
/**
|
||||
* 必须有某个角色
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String mustRole() default "";
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.yupi.springbootinit.aop;
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
/**
|
||||
* 请求响应日志 AOP
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
**/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class LogInterceptor {
|
||||
|
||||
/**
|
||||
* 执行拦截
|
||||
*/
|
||||
@Around("execution(* com.yupi.springbootinit.controller.*.*(..))")
|
||||
public Object doInterceptor(ProceedingJoinPoint point) throws Throwable {
|
||||
// 计时
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
// 获取请求路径
|
||||
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
|
||||
HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||
// 生成请求唯一 id
|
||||
String requestId = UUID.randomUUID().toString();
|
||||
String url = httpServletRequest.getRequestURI();
|
||||
// 获取请求参数
|
||||
Object[] args = point.getArgs();
|
||||
String reqParam = "[" + StringUtils.join(args, ", ") + "]";
|
||||
// 输出请求日志
|
||||
log.info("request start,id: {}, path: {}, ip: {}, params: {}", requestId, url,
|
||||
httpServletRequest.getRemoteHost(), reqParam);
|
||||
// 执行原方法
|
||||
Object result = point.proceed();
|
||||
// 输出响应日志
|
||||
stopWatch.stop();
|
||||
long totalTimeMillis = stopWatch.getTotalTimeMillis();
|
||||
log.info("request end, id: {}, cost: {}ms", requestId, totalTimeMillis);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.yupi.springbootinit.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 通用返回类
|
||||
*
|
||||
* @param <T>
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
@Data
|
||||
public class BaseResponse<T> implements Serializable {
|
||||
|
||||
private int code;
|
||||
|
||||
private T data;
|
||||
|
||||
private String message;
|
||||
|
||||
public BaseResponse(int code, T data, String message) {
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public BaseResponse(int code, T data) {
|
||||
this(code, data, "");
|
||||
}
|
||||
|
||||
public BaseResponse(ErrorCode errorCode) {
|
||||
this(errorCode.getCode(), null, errorCode.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.yupi.springbootinit.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 删除请求
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
@Data
|
||||
public class DeleteRequest implements Serializable {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
47
src/main/java/com/yupi/springbootinit/common/ErrorCode.java
Normal file
47
src/main/java/com/yupi/springbootinit/common/ErrorCode.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package com.yupi.springbootinit.common;
|
||||
|
||||
/**
|
||||
* 自定义错误码
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public enum ErrorCode {
|
||||
|
||||
SUCCESS(0, "ok"),
|
||||
PARAMS_ERROR(40000, "请求参数错误"),
|
||||
NOT_LOGIN_ERROR(40100, "未登录"),
|
||||
USERNAME_OR_PASSWORD_ERROR(40200, "账号或密码错误"),
|
||||
USER_DISABLE(40300, "用户被禁用"),
|
||||
NO_AUTH_ERROR(40101, "无权限"),
|
||||
NOT_FOUND_ERROR(40400, "请求数据不存在"),
|
||||
FORBIDDEN_ERROR(40300, "禁止访问"),
|
||||
SYSTEM_ERROR(50000, "系统内部异常"),
|
||||
OPERATION_ERROR(50001, "操作失败"),
|
||||
QUEUE_ERROR(60001, "队列消息添加失败"),
|
||||
QUEUE_CONSUMPTION_FAILURE(60001, "队列消息消费失败");
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
private final int code;
|
||||
|
||||
/**
|
||||
* 信息
|
||||
*/
|
||||
private final String message;
|
||||
|
||||
ErrorCode(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.yupi.springbootinit.common;
|
||||
|
||||
import com.yupi.springbootinit.constant.CommonConstant;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 分页请求
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
@Data
|
||||
public class PageRequest {
|
||||
|
||||
/**
|
||||
* 当前页号
|
||||
*/
|
||||
private int current = 1;
|
||||
|
||||
/**
|
||||
* 页面大小
|
||||
*/
|
||||
private int pageSize = 10;
|
||||
|
||||
/**
|
||||
* 排序字段
|
||||
*/
|
||||
private String sortField;
|
||||
|
||||
/**
|
||||
* 排序顺序(默认升序)
|
||||
*/
|
||||
private String sortOrder = CommonConstant.SORT_ORDER_ASC;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.yupi.springbootinit.common;
|
||||
|
||||
/**
|
||||
* 返回工具类
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public class ResultUtils {
|
||||
|
||||
/**
|
||||
* 成功
|
||||
*
|
||||
* @param data
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> BaseResponse<T> success(T data) {
|
||||
return new BaseResponse<>(0, data, "ok");
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*
|
||||
* @param errorCode
|
||||
* @return
|
||||
*/
|
||||
public static BaseResponse error(ErrorCode errorCode) {
|
||||
return new BaseResponse<>(errorCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*
|
||||
* @param code
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
public static BaseResponse error(int code, String message) {
|
||||
return new BaseResponse(code, null, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*
|
||||
* @param errorCode
|
||||
* @return
|
||||
*/
|
||||
public static BaseResponse error(ErrorCode errorCode, String message) {
|
||||
return new BaseResponse(errorCode.getCode(), null, message);
|
||||
}
|
||||
}
|
||||
28
src/main/java/com/yupi/springbootinit/config/CorsConfig.java
Normal file
28
src/main/java/com/yupi/springbootinit/config/CorsConfig.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.yupi.springbootinit.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* 全局跨域配置
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
@Configuration
|
||||
public class CorsConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
// 覆盖所有请求
|
||||
registry.addMapping("/**")
|
||||
// 允许发送 Cookie
|
||||
.allowCredentials(true)
|
||||
// 放行哪些域名(必须用 patterns,否则 * 会和 allowCredentials 冲突)
|
||||
.allowedOriginPatterns("*")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||
.allowedHeaders("*")
|
||||
.exposedHeaders("*");
|
||||
}
|
||||
}
|
||||
31
src/main/java/com/yupi/springbootinit/config/JsonConfig.java
Normal file
31
src/main/java/com/yupi/springbootinit/config/JsonConfig.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.yupi.springbootinit.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import org.springframework.boot.jackson.JsonComponent;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
|
||||
/**
|
||||
* Spring MVC Json 配置
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
@JsonComponent
|
||||
public class JsonConfig {
|
||||
|
||||
/**
|
||||
* 添加 Long 转 json 精度丢失的配置
|
||||
*/
|
||||
@Bean
|
||||
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
|
||||
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
|
||||
SimpleModule module = new SimpleModule();
|
||||
module.addSerializer(Long.class, ToStringSerializer.instance);
|
||||
module.addSerializer(Long.TYPE, ToStringSerializer.instance);
|
||||
objectMapper.registerModule(module);
|
||||
return objectMapper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.yupi.springbootinit.config;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
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;
|
||||
|
||||
/**
|
||||
* MyBatis Plus 配置
|
||||
*
|
||||
* @author https://github.com/liyupi
|
||||
*/
|
||||
@Configuration
|
||||
@MapperScan("com.yupi.springbootinit.mapper")
|
||||
public class MyBatisPlusConfig {
|
||||
|
||||
/**
|
||||
* 拦截器配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
// 分页插件
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
|
||||
return interceptor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.yupi.springbootinit.config;
|
||||
|
||||
import org.springframework.amqp.core.Queue;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class RabbitMQConfig {
|
||||
private static final String QUEUE = "HOST_INFO_QUEUE";
|
||||
|
||||
//创建队列
|
||||
//true:表示持久化
|
||||
//队列在默认情况下放到内存,rabbitmq重启后就丢失了,如果希望重启后,队列
|
||||
//数据还能使用,就需要持久化
|
||||
@Bean
|
||||
public Queue hostInfoQueue(){
|
||||
return new Queue(QUEUE,true);
|
||||
}
|
||||
@Bean
|
||||
public MessageConverter messageConverter(){
|
||||
return new Jackson2JsonMessageConverter();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.yupi.springbootinit.constant;
|
||||
|
||||
/**
|
||||
* 通用常量
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public interface CommonConstant {
|
||||
|
||||
/**
|
||||
* 升序
|
||||
*/
|
||||
String SORT_ORDER_ASC = "ascend";
|
||||
|
||||
/**
|
||||
* 降序
|
||||
*/
|
||||
String SORT_ORDER_DESC = " descend";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.yupi.springbootinit.constant;
|
||||
|
||||
/**
|
||||
* 文件常量
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public interface FileConstant {
|
||||
|
||||
/**
|
||||
* COS 访问地址
|
||||
* todo 需替换配置
|
||||
*/
|
||||
String COS_HOST = "https://yupi.icu";
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.yupi.springbootinit.constant;
|
||||
|
||||
/**
|
||||
* 用户常量
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public interface UserConstant {
|
||||
|
||||
/**
|
||||
* 用户登录态键
|
||||
*/
|
||||
String USER_LOGIN_STATE = "user_login";
|
||||
|
||||
// region 权限
|
||||
|
||||
/**
|
||||
* 默认角色
|
||||
*/
|
||||
String DEFAULT_ROLE = "user";
|
||||
|
||||
/**
|
||||
* 管理员角色
|
||||
*/
|
||||
String ADMIN_ROLE = "admin";
|
||||
|
||||
/**
|
||||
* 被封号
|
||||
*/
|
||||
String BAN_ROLE = "ban";
|
||||
|
||||
// endregion
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.yupi.springbootinit.controller;
|
||||
|
||||
import com.yupi.springbootinit.common.BaseResponse;
|
||||
import com.yupi.springbootinit.common.ResultUtils;
|
||||
import com.yupi.springbootinit.model.dto.host.HostInfoDTO;
|
||||
import com.yupi.springbootinit.model.entity.NewHosts;
|
||||
import com.yupi.springbootinit.model.vo.hosts.NewHostsVO;
|
||||
import com.yupi.springbootinit.rabbitMQ.MQSender;
|
||||
import com.yupi.springbootinit.service.HostInfoService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/10 17:09
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/save_data")
|
||||
@Slf4j
|
||||
@CrossOrigin
|
||||
public class HostInfoController {
|
||||
|
||||
@Resource
|
||||
private MQSender mqSender;
|
||||
|
||||
@PostMapping("add_host")
|
||||
public BaseResponse<Boolean> addHost(@RequestBody List<NewHosts> newHosts){
|
||||
mqSender.send(newHosts);
|
||||
return ResultUtils.success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.yupi.springbootinit.exception;
|
||||
|
||||
import com.yupi.springbootinit.common.ErrorCode;
|
||||
|
||||
/**
|
||||
* 自定义异常类
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public class BusinessException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private final int code;
|
||||
|
||||
public BusinessException(int code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public BusinessException(ErrorCode errorCode) {
|
||||
super(errorCode.getMessage());
|
||||
this.code = errorCode.getCode();
|
||||
}
|
||||
|
||||
public BusinessException(ErrorCode errorCode, String message) {
|
||||
super(message);
|
||||
this.code = errorCode.getCode();
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.yupi.springbootinit.exception;
|
||||
|
||||
import com.yupi.springbootinit.common.BaseResponse;
|
||||
import com.yupi.springbootinit.common.ErrorCode;
|
||||
import com.yupi.springbootinit.common.ResultUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
@Slf4j
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
public BaseResponse<?> businessExceptionHandler(BusinessException e) {
|
||||
log.error("BusinessException", e);
|
||||
return ResultUtils.error(e.getCode(), e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public BaseResponse<?> runtimeExceptionHandler(RuntimeException e) {
|
||||
log.error("RuntimeException", e);
|
||||
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.yupi.springbootinit.exception;
|
||||
|
||||
import com.yupi.springbootinit.common.ErrorCode;
|
||||
|
||||
/**
|
||||
* 抛异常工具类
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public class ThrowUtils {
|
||||
|
||||
/**
|
||||
* 条件成立则抛异常
|
||||
*
|
||||
* @param condition
|
||||
* @param runtimeException
|
||||
*/
|
||||
public static void throwIf(boolean condition, RuntimeException runtimeException) {
|
||||
if (condition) {
|
||||
throw runtimeException;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件成立则抛异常
|
||||
*
|
||||
* @param condition
|
||||
* @param errorCode
|
||||
*/
|
||||
public static void throwIf(boolean condition, ErrorCode errorCode) {
|
||||
throwIf(condition, new BusinessException(errorCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件成立则抛异常
|
||||
*
|
||||
* @param condition
|
||||
* @param errorCode
|
||||
* @param message
|
||||
*/
|
||||
public static void throwIf(boolean condition, ErrorCode errorCode, String message) {
|
||||
throwIf(condition, new BusinessException(errorCode, message));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.yupi.springbootinit.generate;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.io.FileWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* 代码生成器
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
|
||||
*/
|
||||
public class CodeGenerator {
|
||||
|
||||
/**
|
||||
* 用法:修改生成参数和生成路径,注释掉不需要的生成逻辑,然后运行即可
|
||||
*
|
||||
* @param args
|
||||
* @throws TemplateException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void main(String[] args) throws TemplateException, IOException {
|
||||
// 指定生成参数
|
||||
String packageName = "com.yupi.springbootinit";
|
||||
String dataName = "用户评论";
|
||||
String dataKey = "userComment";
|
||||
String upperDataKey = "UserComment";
|
||||
|
||||
// 封装生成参数
|
||||
Map<String, Object> dataModel = new HashMap<>();
|
||||
dataModel.put("packageName", packageName);
|
||||
dataModel.put("dataName", dataName);
|
||||
dataModel.put("dataKey", dataKey);
|
||||
dataModel.put("upperDataKey", upperDataKey);
|
||||
|
||||
// 生成路径默认值
|
||||
String projectPath = System.getProperty("user.dir");
|
||||
// 参考路径,可以自己调整下面的 outputPath
|
||||
String inputPath = projectPath + File.separator + "src/main/resources/templates/模板名称.java.ftl";
|
||||
String outputPath = String.format("%s/generator/包名/%s类后缀.java", projectPath, upperDataKey);
|
||||
|
||||
// 1、生成 Controller
|
||||
// 指定生成路径
|
||||
inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateController.java.ftl";
|
||||
outputPath = String.format("%s/generator/controller/%sController.java", projectPath, upperDataKey);
|
||||
// 生成
|
||||
doGenerate(inputPath, outputPath, dataModel);
|
||||
System.out.println("生成 Controller 成功,文件路径:" + outputPath);
|
||||
|
||||
// 2、生成 Service 接口和实现类
|
||||
// 生成 Service 接口
|
||||
inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateService.java.ftl";
|
||||
outputPath = String.format("%s/generator/service/%sService.java", projectPath, upperDataKey);
|
||||
doGenerate(inputPath, outputPath, dataModel);
|
||||
System.out.println("生成 Service 接口成功,文件路径:" + outputPath);
|
||||
// 生成 Service 实现类
|
||||
inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateServiceImpl.java.ftl";
|
||||
outputPath = String.format("%s/generator/service/impl/%sServiceImpl.java", projectPath, upperDataKey);
|
||||
doGenerate(inputPath, outputPath, dataModel);
|
||||
System.out.println("生成 Service 实现类成功,文件路径:" + outputPath);
|
||||
|
||||
// 3、生成数据模型封装类(包括 DTO 和 VO)
|
||||
// 生成 DTO
|
||||
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateAddRequest.java.ftl";
|
||||
outputPath = String.format("%s/generator/model/dto/%sAddRequest.java", projectPath, upperDataKey);
|
||||
doGenerate(inputPath, outputPath, dataModel);
|
||||
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateQueryRequest.java.ftl";
|
||||
outputPath = String.format("%s/generator/model/dto/%sQueryRequest.java", projectPath, upperDataKey);
|
||||
doGenerate(inputPath, outputPath, dataModel);
|
||||
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateEditRequest.java.ftl";
|
||||
outputPath = String.format("%s/generator/model/dto/%sEditRequest.java", projectPath, upperDataKey);
|
||||
doGenerate(inputPath, outputPath, dataModel);
|
||||
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateUpdateRequest.java.ftl";
|
||||
outputPath = String.format("%s/generator/model/dto/%sUpdateRequest.java", projectPath, upperDataKey);
|
||||
doGenerate(inputPath, outputPath, dataModel);
|
||||
System.out.println("生成 DTO 成功,文件路径:" + outputPath);
|
||||
// 生成 VO
|
||||
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateVO.java.ftl";
|
||||
outputPath = String.format("%s/generator/model/vo/%sVO.java", projectPath, upperDataKey);
|
||||
doGenerate(inputPath, outputPath, dataModel);
|
||||
System.out.println("生成 VO 成功,文件路径:" + outputPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件
|
||||
*
|
||||
* @param inputPath 模板文件输入路径
|
||||
* @param outputPath 输出路径
|
||||
* @param model 数据模型
|
||||
* @throws IOException
|
||||
* @throws TemplateException
|
||||
*/
|
||||
public static void doGenerate(String inputPath, String outputPath, Object model) throws IOException, TemplateException {
|
||||
// new 出 Configuration 对象,参数为 FreeMarker 版本号
|
||||
Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
|
||||
|
||||
// 指定模板文件所在的路径
|
||||
File templateDir = new File(inputPath).getParentFile();
|
||||
configuration.setDirectoryForTemplateLoading(templateDir);
|
||||
|
||||
// 设置模板文件使用的字符集
|
||||
configuration.setDefaultEncoding("utf-8");
|
||||
|
||||
// 创建模板对象,加载指定模板
|
||||
String templateName = new File(inputPath).getName();
|
||||
Template template = configuration.getTemplate(templateName);
|
||||
|
||||
// 文件不存在则创建文件和父目录
|
||||
if (!FileUtil.exist(outputPath)) {
|
||||
FileUtil.touch(outputPath);
|
||||
}
|
||||
|
||||
// 生成
|
||||
Writer out = new FileWriter(outputPath);
|
||||
template.process(model, out);
|
||||
|
||||
// 生成文件后别忘了关闭哦
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.yupi.springbootinit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yupi.springbootinit.model.entity.NewHosts;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/10 18:54
|
||||
*/
|
||||
public interface NewHostsMapper extends BaseMapper<NewHosts> {
|
||||
int deleteByPrimaryKey(Long id);
|
||||
|
||||
int insert(NewHosts record);
|
||||
|
||||
int insertSelective(NewHosts record);
|
||||
|
||||
NewHosts selectByPrimaryKey(Long id);
|
||||
|
||||
int updateByPrimaryKeySelective(NewHosts record);
|
||||
|
||||
int updateByPrimaryKey(NewHosts record);
|
||||
|
||||
int batchInsert(@Param("list") List<NewHosts> list);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.yupi.springbootinit.model.dto.host;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/10 18:58
|
||||
*/
|
||||
@Data
|
||||
public class HostInfoDTO {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 主播id
|
||||
*/
|
||||
private String hostsId;
|
||||
|
||||
/**
|
||||
* 主播等级
|
||||
*/
|
||||
private String hostsLevel;
|
||||
|
||||
/**
|
||||
* 主播金币
|
||||
*/
|
||||
private Integer hostsCoins;
|
||||
|
||||
/**
|
||||
* 邀请类型
|
||||
*/
|
||||
private Integer invitationType;
|
||||
|
||||
/**
|
||||
* 粉丝数量
|
||||
*/
|
||||
private Integer fans;
|
||||
|
||||
/**
|
||||
* 关注数量
|
||||
*/
|
||||
private Integer fllowernum;
|
||||
|
||||
/**
|
||||
* 昨日金币
|
||||
*/
|
||||
private Integer yesterdayCoins;
|
||||
|
||||
/**
|
||||
* 主播国家
|
||||
*/
|
||||
private String country;
|
||||
|
||||
/**
|
||||
* 直播类型 娱乐,游戏
|
||||
*/
|
||||
private String hostsKind;
|
||||
|
||||
/**
|
||||
* 租户 Id
|
||||
*/
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 入库人
|
||||
*/
|
||||
private Integer creator;
|
||||
|
||||
/**
|
||||
* 数据插入时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updater;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.yupi.springbootinit.model.dto.user;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/11 20:13
|
||||
*/
|
||||
|
||||
/**
|
||||
* 用户信息表
|
||||
*/
|
||||
@Data
|
||||
public class SystemUsersDTO {
|
||||
|
||||
/**
|
||||
* 用户账号
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private Long tenantId;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.yupi.springbootinit.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/10 18:54
|
||||
*/
|
||||
@Data
|
||||
public class NewHosts {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 主播id
|
||||
*/
|
||||
private String hostsId;
|
||||
|
||||
/**
|
||||
* 主播等级
|
||||
*/
|
||||
private String hostsLevel;
|
||||
|
||||
/**
|
||||
* 主播金币
|
||||
*/
|
||||
private Integer hostsCoins;
|
||||
|
||||
/**
|
||||
* 邀请类型
|
||||
*/
|
||||
private Integer invitationType;
|
||||
|
||||
/**
|
||||
* 粉丝数量
|
||||
*/
|
||||
private Integer fans;
|
||||
|
||||
/**
|
||||
* 关注数量
|
||||
*/
|
||||
private Integer fllowernum;
|
||||
|
||||
/**
|
||||
* 昨日金币
|
||||
*/
|
||||
private Integer yesterdayCoins;
|
||||
|
||||
/**
|
||||
* 主播国家
|
||||
*/
|
||||
private String country;
|
||||
|
||||
/**
|
||||
* 直播类型 娱乐,游戏
|
||||
*/
|
||||
private String hostsKind;
|
||||
|
||||
/**
|
||||
* 租户 Id
|
||||
*/
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 入库人
|
||||
*/
|
||||
private Long creator;
|
||||
|
||||
/**
|
||||
* 数据插入时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updater;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.yupi.springbootinit.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/11 20:13
|
||||
*/
|
||||
|
||||
/**
|
||||
* 用户信息表
|
||||
*/
|
||||
@Data
|
||||
public class SystemUsers {
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户账号
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
@TableField("dept_id")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 岗位编号数组
|
||||
*/
|
||||
@TableField("post_ids")
|
||||
private String postIds;
|
||||
|
||||
/**
|
||||
* 用户邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 用户性别
|
||||
*/
|
||||
private Byte sex;
|
||||
|
||||
/**
|
||||
* 头像地址
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 帐号状态(0正常 1停用)
|
||||
*/
|
||||
private Byte status;
|
||||
|
||||
/**
|
||||
* 最后登录IP
|
||||
*/
|
||||
@TableField("login_ip")
|
||||
private String loginIp;
|
||||
|
||||
/**
|
||||
* 最后登录时间
|
||||
*/
|
||||
@TableField("login_date")
|
||||
private Date loginDate;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
private String creator;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
private String updater;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 是否删除
|
||||
*/
|
||||
private Boolean deleted;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
@TableField("tenant_id")
|
||||
private Long tenantId;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.yupi.springbootinit.model.enums;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 文件上传业务类型枚举
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public enum FileUploadBizEnum {
|
||||
|
||||
USER_AVATAR("用户头像", "user_avatar");
|
||||
|
||||
private final String text;
|
||||
|
||||
private final String value;
|
||||
|
||||
FileUploadBizEnum(String text, String value) {
|
||||
this.text = text;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static List<String> getValues() {
|
||||
return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 value 获取枚举
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static FileUploadBizEnum getEnumByValue(String value) {
|
||||
if (ObjectUtils.isEmpty(value)) {
|
||||
return null;
|
||||
}
|
||||
for (FileUploadBizEnum anEnum : FileUploadBizEnum.values()) {
|
||||
if (anEnum.value.equals(value)) {
|
||||
return anEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.yupi.springbootinit.model.enums;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 用户角色枚举
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public enum UserRoleEnum {
|
||||
|
||||
USER("用户", "user"),
|
||||
ADMIN("管理员", "admin"),
|
||||
BAN("被封号", "ban");
|
||||
|
||||
private final String text;
|
||||
|
||||
private final String value;
|
||||
|
||||
UserRoleEnum(String text, String value) {
|
||||
this.text = text;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static List<String> getValues() {
|
||||
return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 value 获取枚举
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static UserRoleEnum getEnumByValue(String value) {
|
||||
if (ObjectUtils.isEmpty(value)) {
|
||||
return null;
|
||||
}
|
||||
for (UserRoleEnum anEnum : UserRoleEnum.values()) {
|
||||
if (anEnum.value.equals(value)) {
|
||||
return anEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.yupi.springbootinit.model.vo.hosts;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/10 18:54
|
||||
*/
|
||||
@Data
|
||||
public class NewHostsVO {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 主播id
|
||||
*/
|
||||
private String hostsId;
|
||||
|
||||
/**
|
||||
* 主播等级
|
||||
*/
|
||||
private String hostsLevel;
|
||||
|
||||
/**
|
||||
* 主播金币
|
||||
*/
|
||||
private Integer hostsCoins;
|
||||
|
||||
/**
|
||||
* 邀请类型
|
||||
*/
|
||||
private Integer invitationType;
|
||||
|
||||
/**
|
||||
* 粉丝数量
|
||||
*/
|
||||
private Integer fans;
|
||||
|
||||
/**
|
||||
* 关注数量
|
||||
*/
|
||||
private Integer fllowernum;
|
||||
|
||||
/**
|
||||
* 昨日金币
|
||||
*/
|
||||
private Integer yesterdayCoins;
|
||||
|
||||
/**
|
||||
* 主播国家
|
||||
*/
|
||||
private String country;
|
||||
|
||||
/**
|
||||
* 直播类型 娱乐,游戏
|
||||
*/
|
||||
private String hostsKind;
|
||||
|
||||
/**
|
||||
* 租户 Id
|
||||
*/
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 入库人
|
||||
*/
|
||||
private Long creator;
|
||||
|
||||
/**
|
||||
* 数据插入时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.yupi.springbootinit.model.vo.user;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/11 20:13
|
||||
*/
|
||||
|
||||
/**
|
||||
* 用户信息表
|
||||
*/
|
||||
@Data
|
||||
public class SystemUsersVO {
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private Long tenantId;
|
||||
|
||||
private String username;
|
||||
|
||||
private String tokenName;
|
||||
|
||||
private String tokenValue;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.yupi.springbootinit.rabbitMQ;
|
||||
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.yupi.springbootinit.common.ErrorCode;
|
||||
import com.yupi.springbootinit.exception.BusinessException;
|
||||
import com.yupi.springbootinit.model.entity.NewHosts;
|
||||
import com.yupi.springbootinit.service.HostInfoService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class MQReceiver {
|
||||
@Resource
|
||||
private HostInfoService hostInfoService;
|
||||
|
||||
|
||||
// //方法:接收消息
|
||||
// @RabbitListener(queues = "HOST_INFO_QUEUE")
|
||||
// public void receive(List<NewHosts> hosts, Channel channel, Message message) throws IOException {
|
||||
// long deliveryTag = message.getMessageProperties().getDeliveryTag();
|
||||
// try {
|
||||
// hostInfoService.processHosts(hosts);
|
||||
// channel.basicAck(deliveryTag,false);
|
||||
// log.info("deliveryTag:{}",deliveryTag);
|
||||
// log.info("接收到的消息------->" + hosts.size());
|
||||
// }catch (Exception e){
|
||||
// channel.basicNack(deliveryTag,false,true);
|
||||
// log.error("消息消费失败------->消息内容大小{}",hosts.size() );
|
||||
// }
|
||||
// }
|
||||
|
||||
@RabbitListener(queues = "HOST_INFO_QUEUE")
|
||||
public void receive(List<NewHosts> hosts, Channel channel, Message message) throws IOException {
|
||||
long deliveryTag = message.getMessageProperties().getDeliveryTag();
|
||||
try {
|
||||
// 等待所有异步任务完成
|
||||
hostInfoService.processHosts(hosts).join(); // 这里会抛出异常
|
||||
channel.basicAck(deliveryTag, false);
|
||||
log.info("deliveryTag:{}", deliveryTag);
|
||||
log.info("{} 消息消费内容大小-------> {}",DateTime.now(),hosts.size());
|
||||
} catch (Exception e) {
|
||||
channel.basicNack(deliveryTag, false, false);
|
||||
log.error("消息消费失败------->消息内容大小{}", hosts.size(), e);
|
||||
throw new BusinessException(ErrorCode.QUEUE_CONSUMPTION_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/main/java/com/yupi/springbootinit/rabbitMQ/MQSender.java
Normal file
35
src/main/java/com/yupi/springbootinit/rabbitMQ/MQSender.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.yupi.springbootinit.rabbitMQ;
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import com.yupi.springbootinit.common.ErrorCode;
|
||||
import com.yupi.springbootinit.exception.BusinessException;
|
||||
import com.yupi.springbootinit.model.entity.NewHosts;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MQSender {
|
||||
|
||||
@Resource
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
|
||||
//方法:发送消息
|
||||
public void send(List<NewHosts> list){
|
||||
try {
|
||||
log.info("{} 接收到的消息数量----------->{}", DateTime.now(),list.size());
|
||||
this.rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
|
||||
//指定你队列的名字
|
||||
rabbitTemplate.convertAndSend("HOST_INFO_QUEUE",list);
|
||||
}catch (Exception e){
|
||||
throw new BusinessException(ErrorCode.QUEUE_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.yupi.springbootinit.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yupi.springbootinit.model.dto.host.HostInfoDTO;
|
||||
import com.yupi.springbootinit.model.entity.NewHosts;
|
||||
import com.yupi.springbootinit.model.vo.hosts.NewHostsVO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/10 19:04
|
||||
*/
|
||||
public interface HostInfoService extends IService<NewHosts> {
|
||||
|
||||
public CompletableFuture<Void> saveHostInfo(List<NewHosts> newHosts);
|
||||
|
||||
public CompletableFuture<Void> processHosts(List<NewHosts> hosts);
|
||||
|
||||
List<NewHostsVO> getConditionHosts(HostInfoDTO hostInfoDTO);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.yupi.springbootinit.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.yupi.springbootinit.mapper.NewHostsMapper;
|
||||
import com.yupi.springbootinit.model.dto.host.HostInfoDTO;
|
||||
import com.yupi.springbootinit.model.entity.NewHosts;
|
||||
import com.yupi.springbootinit.model.vo.hosts.NewHostsVO;
|
||||
import com.yupi.springbootinit.service.HostInfoService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2025/6/10 19:04
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class HostInfoServiceImpl extends ServiceImpl<NewHostsMapper, NewHosts> implements HostInfoService {
|
||||
|
||||
|
||||
@Override
|
||||
@Async("taskExecutor")
|
||||
public CompletableFuture<Void> saveHostInfo(List<NewHosts> newHosts) {
|
||||
try {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
saveBatch(newHosts);
|
||||
stopWatch.stop();
|
||||
long totalTimeMillis = stopWatch.getTotalTimeMillis();
|
||||
log.info("存储花费: {}ms", totalTimeMillis);
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} catch (Exception e) {
|
||||
// 将异常包装到Future,使调用方能处理
|
||||
return CompletableFuture.failedFuture(e);
|
||||
}
|
||||
}
|
||||
|
||||
// public void processHosts(List<NewHosts> hosts) {
|
||||
// List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
// // 分片提交(避免单批次过大)
|
||||
// Lists.partition(hosts, 1500).forEach(batch -> {
|
||||
// CompletableFuture<Void> future = this.saveHostInfo(batch);
|
||||
// futures.add(future);
|
||||
// });
|
||||
// CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||
// .whenComplete((result, ex) -> {
|
||||
// if (ex != null) {
|
||||
// log.error("部分批次处理失败", ex);
|
||||
// } else {
|
||||
// log.info("所有批次处理完成");
|
||||
// }
|
||||
// // 这里可以触发其他业务逻辑(如发送通知)
|
||||
// });
|
||||
// }
|
||||
public CompletableFuture<Void> processHosts(List<NewHosts> hosts) {
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
// 分片提交(避免单批次过大)
|
||||
Lists.partition(hosts, 1500).forEach(batch -> {
|
||||
log.info("当前存储数据量大小 {}", batch.size());
|
||||
CompletableFuture<Void> future = this.saveHostInfo(batch);
|
||||
futures.add(future);
|
||||
});
|
||||
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||
.whenComplete((result, ex) -> {
|
||||
if (ex != null) {
|
||||
log.error("部分批次处理失败", ex);
|
||||
} else {
|
||||
log.info("所有批次处理完成");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NewHostsVO> getConditionHosts(HostInfoDTO hostInfoDTO) {
|
||||
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
55
src/main/java/com/yupi/springbootinit/utils/NetUtils.java
Normal file
55
src/main/java/com/yupi/springbootinit/utils/NetUtils.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package com.yupi.springbootinit.utils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 网络工具类
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public class NetUtils {
|
||||
|
||||
/**
|
||||
* 获取客户端 IP 地址
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static String getIpAddress(HttpServletRequest request) {
|
||||
String ip = request.getHeader("x-forwarded-for");
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
if (ip.equals("127.0.0.1")) {
|
||||
// 根据网卡取本机配置的 IP
|
||||
InetAddress inet = null;
|
||||
try {
|
||||
inet = InetAddress.getLocalHost();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (inet != null) {
|
||||
ip = inet.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
|
||||
if (ip != null && ip.length() > 15) {
|
||||
if (ip.indexOf(",") > 0) {
|
||||
ip = ip.substring(0, ip.indexOf(","));
|
||||
}
|
||||
}
|
||||
if (ip == null) {
|
||||
return "127.0.0.1";
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.yupi.springbootinit.utils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Spring 上下文获取工具
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
@Component
|
||||
public class SpringContextUtils implements ApplicationContextAware {
|
||||
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
|
||||
SpringContextUtils.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过名称获取 Bean
|
||||
*
|
||||
* @param beanName
|
||||
* @return
|
||||
*/
|
||||
public static Object getBean(String beanName) {
|
||||
return applicationContext.getBean(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 class 获取 Bean
|
||||
*
|
||||
* @param beanClass
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> T getBean(Class<T> beanClass) {
|
||||
return applicationContext.getBean(beanClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过名称和类型获取 Bean
|
||||
*
|
||||
* @param beanName
|
||||
* @param beanClass
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> T getBean(String beanName, Class<T> beanClass) {
|
||||
return applicationContext.getBean(beanName, beanClass);
|
||||
}
|
||||
}
|
||||
25
src/main/java/com/yupi/springbootinit/utils/SqlUtils.java
Normal file
25
src/main/java/com/yupi/springbootinit/utils/SqlUtils.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.yupi.springbootinit.utils;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* SQL 工具
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
public class SqlUtils {
|
||||
|
||||
/**
|
||||
* 校验排序字段是否合法(防止 SQL 注入)
|
||||
*
|
||||
* @param sortField
|
||||
* @return
|
||||
*/
|
||||
public static boolean validSortField(String sortField) {
|
||||
if (StringUtils.isBlank(sortField)) {
|
||||
return false;
|
||||
}
|
||||
return !StringUtils.containsAny(sortField, "=", "(", ")", " ");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "cos.client.accessKey",
|
||||
"type": "java.lang.String",
|
||||
"description": "Description for cos.client.accessKey."
|
||||
},
|
||||
{
|
||||
"name": "cos.client.secretKey",
|
||||
"type": "java.lang.String",
|
||||
"description": "Description for cos.client.secretKey."
|
||||
},
|
||||
{
|
||||
"name": "cos.client.region",
|
||||
"type": "java.lang.String",
|
||||
"description": "Description for cos.client.region."
|
||||
},
|
||||
{
|
||||
"name": "cos.client.bucket",
|
||||
"type": "java.lang.String",
|
||||
"description": "Description for cos.client.bucket."
|
||||
},
|
||||
{
|
||||
"name": "wx.open.appId",
|
||||
"type": "java.lang.String",
|
||||
"description": "Description for wx.open.appId."
|
||||
},
|
||||
{
|
||||
"name": "wx.open.appSecret",
|
||||
"type": "java.lang.String",
|
||||
"description": "Description for wx.open.appSecret."
|
||||
}
|
||||
]
|
||||
}
|
||||
30
src/main/resources/application-dev.yml
Normal file
30
src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
# 测试配置文件
|
||||
# @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
# @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
server:
|
||||
port: 19665
|
||||
spring:
|
||||
# 数据库配置
|
||||
# todo 需替换配置
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/ruoyi-vue-pro?rewriteBatchedStatements=true
|
||||
username: root
|
||||
password: 123asd
|
||||
# Redis 配置
|
||||
# todo 需替换配置
|
||||
redis:
|
||||
database: 1
|
||||
host: localhost
|
||||
port: 6379
|
||||
timeout: 5000
|
||||
password: 123456
|
||||
rabbitmq:
|
||||
host: localhost
|
||||
port: 5672
|
||||
username: guest
|
||||
password: guest
|
||||
listener:
|
||||
simple:
|
||||
acknowledge-mode: manual
|
||||
|
||||
40
src/main/resources/application-prod.yml
Normal file
40
src/main/resources/application-prod.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
# 线上配置文件
|
||||
# @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
# @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
server:
|
||||
port: 19665
|
||||
spring:
|
||||
# 数据库配置
|
||||
# todo 需替换配置
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/ruoyi-vue-pro?rewriteBatchedStatements=true
|
||||
username: root
|
||||
password: 123asd
|
||||
# Redis 配置
|
||||
# todo 需替换配置
|
||||
redis:
|
||||
database: 1
|
||||
host: localhost
|
||||
port: 6379
|
||||
timeout: 5000
|
||||
password: 123456
|
||||
rabbitmq:
|
||||
host: localhost
|
||||
port: 5672
|
||||
username: guest
|
||||
password: guest
|
||||
listener:
|
||||
simple:
|
||||
acknowledge-mode: manual
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
# 生产环境关闭日志
|
||||
log-impl: ''
|
||||
# 接口文档配置
|
||||
knife4j:
|
||||
basic:
|
||||
enable: false
|
||||
username: root
|
||||
password: 123456
|
||||
|
||||
109
src/main/resources/application.yml
Normal file
109
src/main/resources/application.yml
Normal file
@@ -0,0 +1,109 @@
|
||||
# 公共配置文件
|
||||
# @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
# @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
spring:
|
||||
application:
|
||||
name: springboot-init
|
||||
# 默认 dev 环境
|
||||
profiles:
|
||||
active: dev
|
||||
# 支持 swagger3
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
# session 配置
|
||||
session:
|
||||
# todo 取消注释开启分布式 session(须先配置 Redis)
|
||||
# store-type: redis
|
||||
# 30 天过期
|
||||
timeout: 2592000
|
||||
# 数据库配置
|
||||
# todo 需替换配置
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/my_db
|
||||
username: root
|
||||
password: 123asd
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
servlet:
|
||||
multipart:
|
||||
# 大小限制
|
||||
max-file-size: 10MB
|
||||
server:
|
||||
address: 0.0.0.0
|
||||
port: 8101
|
||||
servlet:
|
||||
context-path: /api
|
||||
# cookie 30 天过期
|
||||
session:
|
||||
cookie:
|
||||
max-age: 2592000
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: false
|
||||
log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
|
||||
log-sql:
|
||||
default-executor-type: batch
|
||||
global-config:
|
||||
db-config:
|
||||
logic-delete-field: isDelete # 全局逻辑删除的实体字段名
|
||||
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
|
||||
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
|
||||
# 微信相关
|
||||
wx:
|
||||
# 微信公众平台
|
||||
# todo 需替换配置
|
||||
mp:
|
||||
token: xxx
|
||||
aesKey: xxx
|
||||
appId: xxx
|
||||
secret: xxx
|
||||
config-storage:
|
||||
http-client-type: HttpClient
|
||||
key-prefix: wx
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
type: Memory
|
||||
# 微信开放平台
|
||||
# todo 需替换配置
|
||||
open:
|
||||
appId: xxx
|
||||
appSecret: xxx
|
||||
# 对象存储
|
||||
# todo 需替换配置
|
||||
cos:
|
||||
client:
|
||||
accessKey: xxx
|
||||
secretKey: xxx
|
||||
region: xxx
|
||||
bucket: xxx
|
||||
# 接口文档配置
|
||||
knife4j:
|
||||
enable: true
|
||||
openapi:
|
||||
title: "接口文档"
|
||||
version: 1.0
|
||||
group:
|
||||
default:
|
||||
api-rule: package
|
||||
api-rule-resources:
|
||||
- com.yupi.springbootinit.controller
|
||||
|
||||
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
||||
sa-token:
|
||||
# token 名称(同时也是 cookie 名称)
|
||||
token-name: vvtoken
|
||||
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||
timeout: 2592000
|
||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||
active-timeout: -1
|
||||
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||
is-concurrent: false
|
||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||
is-share: false
|
||||
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||
token-style: random-128
|
||||
# 是否输出操作日志
|
||||
is-log: true
|
||||
225
src/main/resources/mapper/NewHostsMapper.xml
Normal file
225
src/main/resources/mapper/NewHostsMapper.xml
Normal file
@@ -0,0 +1,225 @@
|
||||
<?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="com.yupi.springbootinit.mapper.NewHostsMapper">
|
||||
<resultMap id="BaseResultMap" type="com.yupi.springbootinit.model.entity.NewHosts">
|
||||
<!--@mbg.generated-->
|
||||
<!--@Table new_hosts-->
|
||||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="hosts_id" jdbcType="VARCHAR" property="hostsId" />
|
||||
<result column="hosts_level" jdbcType="VARCHAR" property="hostsLevel" />
|
||||
<result column="hosts_coins" jdbcType="INTEGER" property="hostsCoins" />
|
||||
<result column="Invitation_type" jdbcType="INTEGER" property="invitationType" />
|
||||
<result column="fans" jdbcType="INTEGER" property="fans" />
|
||||
<result column="fllowernum" jdbcType="INTEGER" property="fllowernum" />
|
||||
<result column="yesterday_coins" jdbcType="INTEGER" property="yesterdayCoins" />
|
||||
<result column="country" jdbcType="VARCHAR" property="country" />
|
||||
<result column="hosts_kind" jdbcType="VARCHAR" property="hostsKind" />
|
||||
<result column="tenant_id" jdbcType="BIGINT" property="tenantId" />
|
||||
<result column="creator" jdbcType="BIGINT" property="creator" />
|
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
|
||||
<result column="updater" jdbcType="VARCHAR" property="updater" />
|
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
|
||||
</resultMap>
|
||||
<sql id="Base_Column_List">
|
||||
<!--@mbg.generated-->
|
||||
id, hosts_id, hosts_level, hosts_coins, Invitation_type, fans, fllowernum, yesterday_coins,
|
||||
country, hosts_kind, tenant_id, creator, create_time, updater, update_time
|
||||
</sql>
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
|
||||
<!--@mbg.generated-->
|
||||
select
|
||||
<include refid="Base_Column_List" />
|
||||
from new_hosts
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</select>
|
||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
|
||||
<!--@mbg.generated-->
|
||||
delete from new_hosts
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</delete>
|
||||
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.yupi.springbootinit.model.entity.NewHosts" useGeneratedKeys="true">
|
||||
<!--@mbg.generated-->
|
||||
insert into new_hosts (hosts_id, hosts_level, hosts_coins,
|
||||
Invitation_type, fans, fllowernum,
|
||||
yesterday_coins, country, hosts_kind,
|
||||
tenant_id, creator
|
||||
)
|
||||
values (#{hostsId,jdbcType=VARCHAR}, #{hostsLevel,jdbcType=VARCHAR}, #{hostsCoins,jdbcType=INTEGER},
|
||||
#{invitationType,jdbcType=INTEGER}, #{fans,jdbcType=INTEGER}, #{fllowernum,jdbcType=INTEGER},
|
||||
#{yesterdayCoins,jdbcType=INTEGER}, #{country,jdbcType=VARCHAR}, #{hostsKind,jdbcType=VARCHAR},
|
||||
#{tenantId,jdbcType=BIGINT}, #{creator,jdbcType=BIGINT})
|
||||
</insert>
|
||||
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.yupi.springbootinit.model.entity.NewHosts" useGeneratedKeys="true">
|
||||
<!--@mbg.generated-->
|
||||
insert into new_hosts
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="hostsId != null">
|
||||
hosts_id,
|
||||
</if>
|
||||
<if test="hostsLevel != null">
|
||||
hosts_level,
|
||||
</if>
|
||||
<if test="hostsCoins != null">
|
||||
hosts_coins,
|
||||
</if>
|
||||
<if test="invitationType != null">
|
||||
Invitation_type,
|
||||
</if>
|
||||
<if test="fans != null">
|
||||
fans,
|
||||
</if>
|
||||
<if test="fllowernum != null">
|
||||
fllowernum,
|
||||
</if>
|
||||
<if test="yesterdayCoins != null">
|
||||
yesterday_coins,
|
||||
</if>
|
||||
<if test="country != null">
|
||||
country,
|
||||
</if>
|
||||
<if test="hostsKind != null">
|
||||
hosts_kind,
|
||||
</if>
|
||||
<if test="tenantId != null">
|
||||
tenant_id,
|
||||
</if>
|
||||
<if test="creator != null">
|
||||
creator,
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time,
|
||||
</if>
|
||||
<if test="updater != null">
|
||||
updater,
|
||||
</if>
|
||||
<if test="updateTime != null">
|
||||
update_time,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="hostsId != null">
|
||||
#{hostsId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="hostsLevel != null">
|
||||
#{hostsLevel,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="hostsCoins != null">
|
||||
#{hostsCoins,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="invitationType != null">
|
||||
#{invitationType,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="fans != null">
|
||||
#{fans,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="fllowernum != null">
|
||||
#{fllowernum,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="yesterdayCoins != null">
|
||||
#{yesterdayCoins,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="country != null">
|
||||
#{country,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="hostsKind != null">
|
||||
#{hostsKind,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="tenantId != null">
|
||||
#{tenantId,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="creator != null">
|
||||
#{creator,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
#{createTime,jdbcType=TIMESTAMP},
|
||||
</if>
|
||||
<if test="updater != null">
|
||||
#{updater,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="updateTime != null">
|
||||
#{updateTime,jdbcType=TIMESTAMP},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<update id="updateByPrimaryKeySelective" parameterType="com.yupi.springbootinit.model.entity.NewHosts">
|
||||
<!--@mbg.generated-->
|
||||
update new_hosts
|
||||
<set>
|
||||
<if test="hostsId != null">
|
||||
hosts_id = #{hostsId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="hostsLevel != null">
|
||||
hosts_level = #{hostsLevel,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="hostsCoins != null">
|
||||
hosts_coins = #{hostsCoins,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="invitationType != null">
|
||||
Invitation_type = #{invitationType,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="fans != null">
|
||||
fans = #{fans,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="fllowernum != null">
|
||||
fllowernum = #{fllowernum,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="yesterdayCoins != null">
|
||||
yesterday_coins = #{yesterdayCoins,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="country != null">
|
||||
country = #{country,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="hostsKind != null">
|
||||
hosts_kind = #{hostsKind,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="tenantId != null">
|
||||
tenant_id = #{tenantId,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="creator != null">
|
||||
creator = #{creator,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time = #{createTime,jdbcType=TIMESTAMP},
|
||||
</if>
|
||||
<if test="updater != null">
|
||||
updater = #{updater,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="updateTime != null">
|
||||
update_time = #{updateTime,jdbcType=TIMESTAMP},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="com.yupi.springbootinit.model.entity.NewHosts">
|
||||
<!--@mbg.generated-->
|
||||
update new_hosts
|
||||
set hosts_id = #{hostsId,jdbcType=VARCHAR},
|
||||
hosts_level = #{hostsLevel,jdbcType=VARCHAR},
|
||||
hosts_coins = #{hostsCoins,jdbcType=INTEGER},
|
||||
Invitation_type = #{invitationType,jdbcType=INTEGER},
|
||||
fans = #{fans,jdbcType=INTEGER},
|
||||
fllowernum = #{fllowernum,jdbcType=INTEGER},
|
||||
yesterday_coins = #{yesterdayCoins,jdbcType=INTEGER},
|
||||
country = #{country,jdbcType=VARCHAR},
|
||||
hosts_kind = #{hostsKind,jdbcType=VARCHAR},
|
||||
tenant_id = #{tenantId,jdbcType=BIGINT},
|
||||
creator = #{creator,jdbcType=INTEGER},
|
||||
create_time = #{createTime,jdbcType=TIMESTAMP},
|
||||
updater = #{updater,jdbcType=VARCHAR},
|
||||
update_time = #{updateTime,jdbcType=TIMESTAMP}
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
<insert id="batchInsert" keyColumn="id" keyProperty="id" parameterType="map">
|
||||
<!--@mbg.generated-->
|
||||
insert into new_hosts
|
||||
(hosts_id, hosts_level, hosts_coins, Invitation_type, fans, fllowernum, yesterday_coins,
|
||||
country, hosts_kind, tenant_id, creator)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.hostsId,jdbcType=VARCHAR}, #{item.hostsLevel,jdbcType=VARCHAR}, #{item.hostsCoins,jdbcType=INTEGER},
|
||||
#{item.invitationType,jdbcType=INTEGER}, #{item.fans,jdbcType=INTEGER}, #{item.fllowernum,jdbcType=INTEGER},
|
||||
#{item.yesterdayCoins,jdbcType=INTEGER}, #{item.country,jdbcType=VARCHAR}, #{item.hostsKind,jdbcType=VARCHAR},
|
||||
#{item.tenantId,jdbcType=BIGINT}, #{item.creator,jdbcType=INTEGER})
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
||||
239
src/main/resources/templates/TemplateController.java.ftl
Normal file
239
src/main/resources/templates/TemplateController.java.ftl
Normal file
@@ -0,0 +1,239 @@
|
||||
package ${packageName}.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import ${packageName}.annotation.AuthCheck;
|
||||
import ${packageName}.common.BaseResponse;
|
||||
import ${packageName}.common.DeleteRequest;
|
||||
import ${packageName}.common.ErrorCode;
|
||||
import ${packageName}.common.ResultUtils;
|
||||
import ${packageName}.constant.UserConstant;
|
||||
import ${packageName}.exception.BusinessException;
|
||||
import ${packageName}.exception.ThrowUtils;
|
||||
import ${packageName}.model.dto.${dataKey}.${upperDataKey}AddRequest;
|
||||
import ${packageName}.model.dto.${dataKey}.${upperDataKey}EditRequest;
|
||||
import ${packageName}.model.dto.${dataKey}.${upperDataKey}QueryRequest;
|
||||
import ${packageName}.model.dto.${dataKey}.${upperDataKey}UpdateRequest;
|
||||
import ${packageName}.model.entity.${upperDataKey};
|
||||
import ${packageName}.model.entity.User;
|
||||
import ${packageName}.model.vo.${upperDataKey}VO;
|
||||
import ${packageName}.service.${upperDataKey}Service;
|
||||
import ${packageName}.service.UserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* ${dataName}接口
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/${dataKey}")
|
||||
@Slf4j
|
||||
public class ${upperDataKey}Controller {
|
||||
|
||||
@Resource
|
||||
private ${upperDataKey}Service ${dataKey}Service;
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
// region 增删改查
|
||||
|
||||
/**
|
||||
* 创建${dataName}
|
||||
*
|
||||
* @param ${dataKey}AddRequest
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public BaseResponse<Long> add${upperDataKey}(@RequestBody ${upperDataKey}AddRequest ${dataKey}AddRequest, HttpServletRequest request) {
|
||||
ThrowUtils.throwIf(${dataKey}AddRequest == null, ErrorCode.PARAMS_ERROR);
|
||||
// todo 在此处将实体类和 DTO 进行转换
|
||||
${upperDataKey} ${dataKey} = new ${upperDataKey}();
|
||||
BeanUtils.copyProperties(${dataKey}AddRequest, ${dataKey});
|
||||
// 数据校验
|
||||
${dataKey}Service.valid${upperDataKey}(${dataKey}, true);
|
||||
// todo 填充默认值
|
||||
User loginUser = userService.getLoginUser(request);
|
||||
${dataKey}.setUserId(loginUser.getId());
|
||||
// 写入数据库
|
||||
boolean result = ${dataKey}Service.save(${dataKey});
|
||||
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
|
||||
// 返回新写入的数据 id
|
||||
long new${upperDataKey}Id = ${dataKey}.getId();
|
||||
return ResultUtils.success(new${upperDataKey}Id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除${dataName}
|
||||
*
|
||||
* @param deleteRequest
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
public BaseResponse<Boolean> delete${upperDataKey}(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
|
||||
if (deleteRequest == null || deleteRequest.getId() <= 0) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
User user = userService.getLoginUser(request);
|
||||
long id = deleteRequest.getId();
|
||||
// 判断是否存在
|
||||
${upperDataKey} old${upperDataKey} = ${dataKey}Service.getById(id);
|
||||
ThrowUtils.throwIf(old${upperDataKey} == null, ErrorCode.NOT_FOUND_ERROR);
|
||||
// 仅本人或管理员可删除
|
||||
if (!old${upperDataKey}.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
|
||||
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
|
||||
}
|
||||
// 操作数据库
|
||||
boolean result = ${dataKey}Service.removeById(id);
|
||||
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
|
||||
return ResultUtils.success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新${dataName}(仅管理员可用)
|
||||
*
|
||||
* @param ${dataKey}UpdateRequest
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
|
||||
public BaseResponse<Boolean> update${upperDataKey}(@RequestBody ${upperDataKey}UpdateRequest ${dataKey}UpdateRequest) {
|
||||
if (${dataKey}UpdateRequest == null || ${dataKey}UpdateRequest.getId() <= 0) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
// todo 在此处将实体类和 DTO 进行转换
|
||||
${upperDataKey} ${dataKey} = new ${upperDataKey}();
|
||||
BeanUtils.copyProperties(${dataKey}UpdateRequest, ${dataKey});
|
||||
// 数据校验
|
||||
${dataKey}Service.valid${upperDataKey}(${dataKey}, false);
|
||||
// 判断是否存在
|
||||
long id = ${dataKey}UpdateRequest.getId();
|
||||
${upperDataKey} old${upperDataKey} = ${dataKey}Service.getById(id);
|
||||
ThrowUtils.throwIf(old${upperDataKey} == null, ErrorCode.NOT_FOUND_ERROR);
|
||||
// 操作数据库
|
||||
boolean result = ${dataKey}Service.updateById(${dataKey});
|
||||
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
|
||||
return ResultUtils.success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 id 获取${dataName}(封装类)
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/get/vo")
|
||||
public BaseResponse<${upperDataKey}VO> get${upperDataKey}VOById(long id, HttpServletRequest request) {
|
||||
ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
|
||||
// 查询数据库
|
||||
${upperDataKey} ${dataKey} = ${dataKey}Service.getById(id);
|
||||
ThrowUtils.throwIf(${dataKey} == null, ErrorCode.NOT_FOUND_ERROR);
|
||||
// 获取封装类
|
||||
return ResultUtils.success(${dataKey}Service.get${upperDataKey}VO(${dataKey}, request));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页获取${dataName}列表(仅管理员可用)
|
||||
*
|
||||
* @param ${dataKey}QueryRequest
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/list/page")
|
||||
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
|
||||
public BaseResponse<Page<${upperDataKey}>> list${upperDataKey}ByPage(@RequestBody ${upperDataKey}QueryRequest ${dataKey}QueryRequest) {
|
||||
long current = ${dataKey}QueryRequest.getCurrent();
|
||||
long size = ${dataKey}QueryRequest.getPageSize();
|
||||
// 查询数据库
|
||||
Page<${upperDataKey}> ${dataKey}Page = ${dataKey}Service.page(new Page<>(current, size),
|
||||
${dataKey}Service.getQueryWrapper(${dataKey}QueryRequest));
|
||||
return ResultUtils.success(${dataKey}Page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页获取${dataName}列表(封装类)
|
||||
*
|
||||
* @param ${dataKey}QueryRequest
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/list/page/vo")
|
||||
public BaseResponse<Page<${upperDataKey}VO>> list${upperDataKey}VOByPage(@RequestBody ${upperDataKey}QueryRequest ${dataKey}QueryRequest,
|
||||
HttpServletRequest request) {
|
||||
long current = ${dataKey}QueryRequest.getCurrent();
|
||||
long size = ${dataKey}QueryRequest.getPageSize();
|
||||
// 限制爬虫
|
||||
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
|
||||
// 查询数据库
|
||||
Page<${upperDataKey}> ${dataKey}Page = ${dataKey}Service.page(new Page<>(current, size),
|
||||
${dataKey}Service.getQueryWrapper(${dataKey}QueryRequest));
|
||||
// 获取封装类
|
||||
return ResultUtils.success(${dataKey}Service.get${upperDataKey}VOPage(${dataKey}Page, request));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页获取当前登录用户创建的${dataName}列表
|
||||
*
|
||||
* @param ${dataKey}QueryRequest
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/my/list/page/vo")
|
||||
public BaseResponse<Page<${upperDataKey}VO>> listMy${upperDataKey}VOByPage(@RequestBody ${upperDataKey}QueryRequest ${dataKey}QueryRequest,
|
||||
HttpServletRequest request) {
|
||||
ThrowUtils.throwIf(${dataKey}QueryRequest == null, ErrorCode.PARAMS_ERROR);
|
||||
// 补充查询条件,只查询当前登录用户的数据
|
||||
User loginUser = userService.getLoginUser(request);
|
||||
${dataKey}QueryRequest.setUserId(loginUser.getId());
|
||||
long current = ${dataKey}QueryRequest.getCurrent();
|
||||
long size = ${dataKey}QueryRequest.getPageSize();
|
||||
// 限制爬虫
|
||||
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
|
||||
// 查询数据库
|
||||
Page<${upperDataKey}> ${dataKey}Page = ${dataKey}Service.page(new Page<>(current, size),
|
||||
${dataKey}Service.getQueryWrapper(${dataKey}QueryRequest));
|
||||
// 获取封装类
|
||||
return ResultUtils.success(${dataKey}Service.get${upperDataKey}VOPage(${dataKey}Page, request));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑${dataName}(给用户使用)
|
||||
*
|
||||
* @param ${dataKey}EditRequest
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/edit")
|
||||
public BaseResponse<Boolean> edit${upperDataKey}(@RequestBody ${upperDataKey}EditRequest ${dataKey}EditRequest, HttpServletRequest request) {
|
||||
if (${dataKey}EditRequest == null || ${dataKey}EditRequest.getId() <= 0) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
// todo 在此处将实体类和 DTO 进行转换
|
||||
${upperDataKey} ${dataKey} = new ${upperDataKey}();
|
||||
BeanUtils.copyProperties(${dataKey}EditRequest, ${dataKey});
|
||||
// 数据校验
|
||||
${dataKey}Service.valid${upperDataKey}(${dataKey}, false);
|
||||
User loginUser = userService.getLoginUser(request);
|
||||
// 判断是否存在
|
||||
long id = ${dataKey}EditRequest.getId();
|
||||
${upperDataKey} old${upperDataKey} = ${dataKey}Service.getById(id);
|
||||
ThrowUtils.throwIf(old${upperDataKey} == null, ErrorCode.NOT_FOUND_ERROR);
|
||||
// 仅本人或管理员可编辑
|
||||
if (!old${upperDataKey}.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
|
||||
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
|
||||
}
|
||||
// 操作数据库
|
||||
boolean result = ${dataKey}Service.updateById(${dataKey});
|
||||
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
|
||||
return ResultUtils.success(true);
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
53
src/main/resources/templates/TemplateService.java.ftl
Normal file
53
src/main/resources/templates/TemplateService.java.ftl
Normal file
@@ -0,0 +1,53 @@
|
||||
package ${packageName}.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import ${packageName}.model.dto.${dataKey}.${upperDataKey}QueryRequest;
|
||||
import ${packageName}.model.entity.${upperDataKey};
|
||||
import ${packageName}.model.vo.${upperDataKey}VO;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* ${dataName}服务
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
|
||||
*/
|
||||
public interface ${upperDataKey}Service extends IService<${upperDataKey}> {
|
||||
|
||||
/**
|
||||
* 校验数据
|
||||
*
|
||||
* @param ${dataKey}
|
||||
* @param add 对创建的数据进行校验
|
||||
*/
|
||||
void valid${upperDataKey}(${upperDataKey} ${dataKey}, boolean add);
|
||||
|
||||
/**
|
||||
* 获取查询条件
|
||||
*
|
||||
* @param ${dataKey}QueryRequest
|
||||
* @return
|
||||
*/
|
||||
QueryWrapper<${upperDataKey}> getQueryWrapper(${upperDataKey}QueryRequest ${dataKey}QueryRequest);
|
||||
|
||||
/**
|
||||
* 获取${dataName}封装
|
||||
*
|
||||
* @param ${dataKey}
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
${upperDataKey}VO get${upperDataKey}VO(${upperDataKey} ${dataKey}, HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 分页获取${dataName}封装
|
||||
*
|
||||
* @param ${dataKey}Page
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
Page<${upperDataKey}VO> get${upperDataKey}VOPage(Page<${upperDataKey}> ${dataKey}Page, HttpServletRequest request);
|
||||
}
|
||||
224
src/main/resources/templates/TemplateServiceImpl.java.ftl
Normal file
224
src/main/resources/templates/TemplateServiceImpl.java.ftl
Normal file
@@ -0,0 +1,224 @@
|
||||
package ${packageName}.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import ${packageName}.common.ErrorCode;
|
||||
import ${packageName}.constant.CommonConstant;
|
||||
import ${packageName}.exception.ThrowUtils;
|
||||
import ${packageName}.mapper.${upperDataKey}Mapper;
|
||||
import ${packageName}.model.dto.${dataKey}.${upperDataKey}QueryRequest;
|
||||
import ${packageName}.model.entity.${upperDataKey};
|
||||
import ${packageName}.model.entity.${upperDataKey}Favour;
|
||||
import ${packageName}.model.entity.${upperDataKey}Thumb;
|
||||
import ${packageName}.model.entity.User;
|
||||
import ${packageName}.model.vo.${upperDataKey}VO;
|
||||
import ${packageName}.model.vo.UserVO;
|
||||
import ${packageName}.service.${upperDataKey}Service;
|
||||
import ${packageName}.service.UserService;
|
||||
import ${packageName}.utils.SqlUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* ${dataName}服务实现
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ${upperDataKey}ServiceImpl extends ServiceImpl<${upperDataKey}Mapper, ${upperDataKey}> implements ${upperDataKey}Service {
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
/**
|
||||
* 校验数据
|
||||
*
|
||||
* @param ${dataKey}
|
||||
* @param add 对创建的数据进行校验
|
||||
*/
|
||||
@Override
|
||||
public void valid${upperDataKey}(${upperDataKey} ${dataKey}, boolean add) {
|
||||
ThrowUtils.throwIf(${dataKey} == null, ErrorCode.PARAMS_ERROR);
|
||||
// todo 从对象中取值
|
||||
String title = ${dataKey}.getTitle();
|
||||
// 创建数据时,参数不能为空
|
||||
if (add) {
|
||||
// todo 补充校验规则
|
||||
ThrowUtils.throwIf(StringUtils.isBlank(title), ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
// 修改数据时,有参数则校验
|
||||
// todo 补充校验规则
|
||||
if (StringUtils.isNotBlank(title)) {
|
||||
ThrowUtils.throwIf(title.length() > 80, ErrorCode.PARAMS_ERROR, "标题过长");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取查询条件
|
||||
*
|
||||
* @param ${dataKey}QueryRequest
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public QueryWrapper<${upperDataKey}> getQueryWrapper(${upperDataKey}QueryRequest ${dataKey}QueryRequest) {
|
||||
QueryWrapper<${upperDataKey}> queryWrapper = new QueryWrapper<>();
|
||||
if (${dataKey}QueryRequest == null) {
|
||||
return queryWrapper;
|
||||
}
|
||||
// todo 从对象中取值
|
||||
Long id = ${dataKey}QueryRequest.getId();
|
||||
Long notId = ${dataKey}QueryRequest.getNotId();
|
||||
String title = ${dataKey}QueryRequest.getTitle();
|
||||
String content = ${dataKey}QueryRequest.getContent();
|
||||
String searchText = ${dataKey}QueryRequest.getSearchText();
|
||||
String sortField = ${dataKey}QueryRequest.getSortField();
|
||||
String sortOrder = ${dataKey}QueryRequest.getSortOrder();
|
||||
List<String> tagList = ${dataKey}QueryRequest.getTags();
|
||||
Long userId = ${dataKey}QueryRequest.getUserId();
|
||||
// todo 补充需要的查询条件
|
||||
// 从多字段中搜索
|
||||
if (StringUtils.isNotBlank(searchText)) {
|
||||
// 需要拼接查询条件
|
||||
queryWrapper.and(qw -> qw.like("title", searchText).or().like("content", searchText));
|
||||
}
|
||||
// 模糊查询
|
||||
queryWrapper.like(StringUtils.isNotBlank(title), "title", title);
|
||||
queryWrapper.like(StringUtils.isNotBlank(content), "content", content);
|
||||
// JSON 数组查询
|
||||
if (CollUtil.isNotEmpty(tagList)) {
|
||||
for (String tag : tagList) {
|
||||
queryWrapper.like("tags", "\"" + tag + "\"");
|
||||
}
|
||||
}
|
||||
// 精确查询
|
||||
queryWrapper.ne(ObjectUtils.isNotEmpty(notId), "id", notId);
|
||||
queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
|
||||
queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
|
||||
// 排序规则
|
||||
queryWrapper.orderBy(SqlUtils.validSortField(sortField),
|
||||
sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
|
||||
sortField);
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取${dataName}封装
|
||||
*
|
||||
* @param ${dataKey}
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ${upperDataKey}VO get${upperDataKey}VO(${upperDataKey} ${dataKey}, HttpServletRequest request) {
|
||||
// 对象转封装类
|
||||
${upperDataKey}VO ${dataKey}VO = ${upperDataKey}VO.objToVo(${dataKey});
|
||||
|
||||
// todo 可以根据需要为封装对象补充值,不需要的内容可以删除
|
||||
// region 可选
|
||||
// 1. 关联查询用户信息
|
||||
Long userId = ${dataKey}.getUserId();
|
||||
User user = null;
|
||||
if (userId != null && userId > 0) {
|
||||
user = userService.getById(userId);
|
||||
}
|
||||
UserVO userVO = userService.getUserVO(user);
|
||||
${dataKey}VO.setUser(userVO);
|
||||
// 2. 已登录,获取用户点赞、收藏状态
|
||||
long ${dataKey}Id = ${dataKey}.getId();
|
||||
User loginUser = userService.getLoginUserPermitNull(request);
|
||||
if (loginUser != null) {
|
||||
// 获取点赞
|
||||
QueryWrapper<${upperDataKey}Thumb> ${dataKey}ThumbQueryWrapper = new QueryWrapper<>();
|
||||
${dataKey}ThumbQueryWrapper.in("${dataKey}Id", ${dataKey}Id);
|
||||
${dataKey}ThumbQueryWrapper.eq("userId", loginUser.getId());
|
||||
${upperDataKey}Thumb ${dataKey}Thumb = ${dataKey}ThumbMapper.selectOne(${dataKey}ThumbQueryWrapper);
|
||||
${dataKey}VO.setHasThumb(${dataKey}Thumb != null);
|
||||
// 获取收藏
|
||||
QueryWrapper<${upperDataKey}Favour> ${dataKey}FavourQueryWrapper = new QueryWrapper<>();
|
||||
${dataKey}FavourQueryWrapper.in("${dataKey}Id", ${dataKey}Id);
|
||||
${dataKey}FavourQueryWrapper.eq("userId", loginUser.getId());
|
||||
${upperDataKey}Favour ${dataKey}Favour = ${dataKey}FavourMapper.selectOne(${dataKey}FavourQueryWrapper);
|
||||
${dataKey}VO.setHasFavour(${dataKey}Favour != null);
|
||||
}
|
||||
// endregion
|
||||
|
||||
return ${dataKey}VO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页获取${dataName}封装
|
||||
*
|
||||
* @param ${dataKey}Page
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Page<${upperDataKey}VO> get${upperDataKey}VOPage(Page<${upperDataKey}> ${dataKey}Page, HttpServletRequest request) {
|
||||
List<${upperDataKey}> ${dataKey}List = ${dataKey}Page.getRecords();
|
||||
Page<${upperDataKey}VO> ${dataKey}VOPage = new Page<>(${dataKey}Page.getCurrent(), ${dataKey}Page.getSize(), ${dataKey}Page.getTotal());
|
||||
if (CollUtil.isEmpty(${dataKey}List)) {
|
||||
return ${dataKey}VOPage;
|
||||
}
|
||||
// 对象列表 => 封装对象列表
|
||||
List<${upperDataKey}VO> ${dataKey}VOList = ${dataKey}List.stream().map(${dataKey} -> {
|
||||
return ${upperDataKey}VO.objToVo(${dataKey});
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
// todo 可以根据需要为封装对象补充值,不需要的内容可以删除
|
||||
// region 可选
|
||||
// 1. 关联查询用户信息
|
||||
Set<Long> userIdSet = ${dataKey}List.stream().map(${upperDataKey}::getUserId).collect(Collectors.toSet());
|
||||
Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
|
||||
.collect(Collectors.groupingBy(User::getId));
|
||||
// 2. 已登录,获取用户点赞、收藏状态
|
||||
Map<Long, Boolean> ${dataKey}IdHasThumbMap = new HashMap<>();
|
||||
Map<Long, Boolean> ${dataKey}IdHasFavourMap = new HashMap<>();
|
||||
User loginUser = userService.getLoginUserPermitNull(request);
|
||||
if (loginUser != null) {
|
||||
Set<Long> ${dataKey}IdSet = ${dataKey}List.stream().map(${upperDataKey}::getId).collect(Collectors.toSet());
|
||||
loginUser = userService.getLoginUser(request);
|
||||
// 获取点赞
|
||||
QueryWrapper<${upperDataKey}Thumb> ${dataKey}ThumbQueryWrapper = new QueryWrapper<>();
|
||||
${dataKey}ThumbQueryWrapper.in("${dataKey}Id", ${dataKey}IdSet);
|
||||
${dataKey}ThumbQueryWrapper.eq("userId", loginUser.getId());
|
||||
List<${upperDataKey}Thumb> ${dataKey}${upperDataKey}ThumbList = ${dataKey}ThumbMapper.selectList(${dataKey}ThumbQueryWrapper);
|
||||
${dataKey}${upperDataKey}ThumbList.forEach(${dataKey}${upperDataKey}Thumb -> ${dataKey}IdHasThumbMap.put(${dataKey}${upperDataKey}Thumb.get${upperDataKey}Id(), true));
|
||||
// 获取收藏
|
||||
QueryWrapper<${upperDataKey}Favour> ${dataKey}FavourQueryWrapper = new QueryWrapper<>();
|
||||
${dataKey}FavourQueryWrapper.in("${dataKey}Id", ${dataKey}IdSet);
|
||||
${dataKey}FavourQueryWrapper.eq("userId", loginUser.getId());
|
||||
List<${upperDataKey}Favour> ${dataKey}FavourList = ${dataKey}FavourMapper.selectList(${dataKey}FavourQueryWrapper);
|
||||
${dataKey}FavourList.forEach(${dataKey}Favour -> ${dataKey}IdHasFavourMap.put(${dataKey}Favour.get${upperDataKey}Id(), true));
|
||||
}
|
||||
// 填充信息
|
||||
${dataKey}VOList.forEach(${dataKey}VO -> {
|
||||
Long userId = ${dataKey}VO.getUserId();
|
||||
User user = null;
|
||||
if (userIdUserListMap.containsKey(userId)) {
|
||||
user = userIdUserListMap.get(userId).get(0);
|
||||
}
|
||||
${dataKey}VO.setUser(userService.getUserVO(user));
|
||||
${dataKey}VO.setHasThumb(${dataKey}IdHasThumbMap.getOrDefault(${dataKey}VO.getId(), false));
|
||||
${dataKey}VO.setHasFavour(${dataKey}IdHasFavourMap.getOrDefault(${dataKey}VO.getId(), false));
|
||||
});
|
||||
// endregion
|
||||
|
||||
${dataKey}VOPage.setRecords(${dataKey}VOList);
|
||||
return ${dataKey}VOPage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package ${packageName}.model.dto.${dataKey};
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 创建${dataName}请求
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
|
||||
*/
|
||||
@Data
|
||||
public class ${upperDataKey}AddRequest implements Serializable {
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 标签列表
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package ${packageName}.model.dto.${dataKey};
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 编辑${dataName}请求
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
|
||||
*/
|
||||
@Data
|
||||
public class ${upperDataKey}EditRequest implements Serializable {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 标签列表
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package ${packageName}.model.dto.${dataKey};
|
||||
|
||||
import ${packageName}.common.PageRequest;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 查询${dataName}请求
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class ${upperDataKey}QueryRequest extends PageRequest implements Serializable {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long notId;
|
||||
|
||||
/**
|
||||
* 搜索词
|
||||
*/
|
||||
private String searchText;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 标签列表
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
/**
|
||||
* 创建用户 id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package ${packageName}.model.dto.${dataKey};
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 更新${dataName}请求
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
|
||||
*/
|
||||
@Data
|
||||
public class ${upperDataKey}UpdateRequest implements Serializable {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 标签列表
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
93
src/main/resources/templates/model/TemplateVO.java.ftl
Normal file
93
src/main/resources/templates/model/TemplateVO.java.ftl
Normal file
@@ -0,0 +1,93 @@
|
||||
package ${packageName}.model.vo;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import ${packageName}.model.entity.${upperDataKey};
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ${dataName}视图
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
|
||||
*/
|
||||
@Data
|
||||
public class ${upperDataKey}VO implements Serializable {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 创建用户 id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 标签列表
|
||||
*/
|
||||
private List<String> tagList;
|
||||
|
||||
/**
|
||||
* 创建用户信息
|
||||
*/
|
||||
private UserVO user;
|
||||
|
||||
/**
|
||||
* 封装类转对象
|
||||
*
|
||||
* @param ${dataKey}VO
|
||||
* @return
|
||||
*/
|
||||
public static ${upperDataKey} voToObj(${upperDataKey}VO ${dataKey}VO) {
|
||||
if (${dataKey}VO == null) {
|
||||
return null;
|
||||
}
|
||||
${upperDataKey} ${dataKey} = new ${upperDataKey}();
|
||||
BeanUtils.copyProperties(${dataKey}VO, ${dataKey});
|
||||
List<String> tagList = ${dataKey}VO.getTagList();
|
||||
${dataKey}.setTags(JSONUtil.toJsonStr(tagList));
|
||||
return ${dataKey};
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象转封装类
|
||||
*
|
||||
* @param ${dataKey}
|
||||
* @return
|
||||
*/
|
||||
public static ${upperDataKey}VO objToVo(${upperDataKey} ${dataKey}) {
|
||||
if (${dataKey} == null) {
|
||||
return null;
|
||||
}
|
||||
${upperDataKey}VO ${dataKey}VO = new ${upperDataKey}VO();
|
||||
BeanUtils.copyProperties(${dataKey}, ${dataKey}VO);
|
||||
${dataKey}VO.setTagList(JSONUtil.toList(${dataKey}.getTags(), String.class));
|
||||
return ${dataKey}VO;
|
||||
}
|
||||
}
|
||||
BIN
src/main/resources/test_excel.xlsx
Normal file
BIN
src/main/resources/test_excel.xlsx
Normal file
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
package com.yupi.springbootinit;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* 主类测试
|
||||
*
|
||||
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
|
||||
* @from <a href="https://yupi.icu">编程导航知识星球</a>
|
||||
*/
|
||||
@SpringBootTest
|
||||
class MainApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user