后端代码上传
38
jjj_erp/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
20
jjj_erp/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
8
jjj_erp/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
36
jjj_erp/.idea/compiler.xml
generated
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="true" />
|
||||
<profile name="Annotation profile for jjj-erp" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="false">
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/org/mapstruct/mapstruct-processor/1.3.1.Final/mapstruct-processor-1.3.1.Final.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/com/jolira/hickory/1.0.0/hickory-1.0.0.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/org/mapstruct/mapstruct/1.3.1.Final/mapstruct-1.3.1.Final.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/junit/junit/4.12/junit-4.12.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/org/assertj/assertj-core/3.11.1/assertj-core-3.11.1.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/com/google/guava/guava/19.0/guava-19.0.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/com/puppycrawl/tools/checkstyle/8.14/checkstyle-8.14.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/javax/inject/javax.inject/1/javax.inject-1.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/org/codehaus/plexus/plexus-container-default/1.6/plexus-container-default-1.6.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/org/springframework/spring-test/4.0.3.RELEASE/spring-test-4.0.3.RELEASE.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/org/springframework/spring-beans/4.0.3.RELEASE/spring-beans-4.0.3.RELEASE.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/org/springframework/spring-context/4.0.3.RELEASE/spring-context-4.0.3.RELEASE.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/joda-time/joda-time/2.9/joda-time-2.9.jar" />
|
||||
<entry name="$PROJECT_DIR$/../../../../../Maven/maven-repository/org/projectlombok/lombok/1.18.12/lombok-1.18.12.jar" />
|
||||
</processorPath>
|
||||
<module name="jjj-saas" />
|
||||
<module name="jjj-job" />
|
||||
<module name="generator" />
|
||||
<module name="jjj-admin" />
|
||||
<module name="bootstrap" />
|
||||
<module name="jjj-common" />
|
||||
<module name="config" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
13
jjj_erp/.idea/encodings.xml
generated
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/bootstrap/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/config/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/generator/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/jjj-admin/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/jjj-common/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/jjj-job/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/jjj-saas/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
30
jjj_erp/.idea/jarRepositories.xml
generated
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="maven-central" />
|
||||
<option name="url" value="http://maven.aliyun.com/nexus/content/repositories/central/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="aliyun" />
|
||||
<option name="name" value="aliyun-maven" />
|
||||
<option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="spring-milestones" />
|
||||
<option name="name" value="Spring Milestones" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/spring" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
26
jjj_erp/.idea/misc.xml
generated
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
<option value="$PROJECT_DIR$/jjj-saas/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
|
||||
<component name="SvnBranchConfigurationManager">
|
||||
<option name="myConfigurationMap">
|
||||
<map>
|
||||
<entry key="$PROJECT_DIR$">
|
||||
<value>
|
||||
<SvnBranchConfiguration>
|
||||
<option name="trunkUrl" value="svn://120.78.205.187/product_java/jjj_erp_java/jjj_erp" />
|
||||
</SvnBranchConfiguration>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
124
jjj_erp/.idea/uiDesigner.xml
generated
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
6
jjj_erp/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="svn" />
|
||||
</component>
|
||||
</project>
|
||||
53
jjj_erp/.workflow/BranchPipeline.yml
Normal file
@ -0,0 +1,53 @@
|
||||
version: '1.0'
|
||||
name: branch-pipeline
|
||||
displayName: BranchPipeline
|
||||
stages:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
- step: build@maven
|
||||
name: build_maven
|
||||
displayName: Maven 构建
|
||||
# 支持6、7、8、9、10、11六个版本
|
||||
jdkVersion: 8
|
||||
# 支持2.2.1、3.2.5、3.3.9、3.5.2、3.5.3、3.5.4、3.6.1、3.6.3八个版本
|
||||
mavenVersion: 3.3.9
|
||||
# 构建命令
|
||||
commands:
|
||||
- mvn -B clean package -Dmaven.test.skip=true
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径,如通常jar包在target目录下。当前目录为代码库根目录
|
||||
path:
|
||||
- ./target
|
||||
- step: publish@general_artifacts
|
||||
name: publish_general_artifacts
|
||||
displayName: 上传制品
|
||||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
|
||||
dependArtifact: BUILD_ARTIFACT
|
||||
# 上传到制品库时的制品命名,默认output
|
||||
artifactName: output
|
||||
dependsOn: build_maven
|
||||
- stage:
|
||||
name: release
|
||||
displayName: 发布
|
||||
steps:
|
||||
- step: publish@release_artifacts
|
||||
name: publish_release_artifacts
|
||||
displayName: '发布'
|
||||
# 上游上传制品任务的产出
|
||||
dependArtifact: output
|
||||
# 发布制品版本号
|
||||
version: '1.0.0.0'
|
||||
# 是否开启版本号自增,默认开启
|
||||
autoIncrement: true
|
||||
triggers:
|
||||
push:
|
||||
branches:
|
||||
exclude:
|
||||
- master
|
||||
include:
|
||||
- .*
|
||||
51
jjj_erp/.workflow/MasterPipeline.yml
Normal file
@ -0,0 +1,51 @@
|
||||
version: '1.0'
|
||||
name: master-pipeline
|
||||
displayName: MasterPipeline
|
||||
stages:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
- step: build@maven
|
||||
name: build_maven
|
||||
displayName: Maven 构建
|
||||
# 支持6、7、8、9、10、11六个版本
|
||||
jdkVersion: 8
|
||||
# 支持2.2.1、3.2.5、3.3.9、3.5.2、3.5.3、3.5.4、3.6.1、3.6.3八个版本
|
||||
mavenVersion: 3.3.9
|
||||
# 构建命令
|
||||
commands:
|
||||
- mvn -B clean package -Dmaven.test.skip=true
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径,如通常jar包在target目录下。当前目录为代码库根目录
|
||||
path:
|
||||
- ./target
|
||||
- step: publish@general_artifacts
|
||||
name: publish_general_artifacts
|
||||
displayName: 上传制品
|
||||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
|
||||
dependArtifact: BUILD_ARTIFACT
|
||||
# 上传到制品库时的制品命名,默认output
|
||||
artifactName: output
|
||||
dependsOn: build_maven
|
||||
- stage:
|
||||
name: release
|
||||
displayName: 发布
|
||||
steps:
|
||||
- step: publish@release_artifacts
|
||||
name: publish_release_artifacts
|
||||
displayName: '发布'
|
||||
# 上游上传制品任务的产出
|
||||
dependArtifact: output
|
||||
# 发布制品版本号
|
||||
version: '1.0.0.0'
|
||||
# 是否开启版本号自增,默认开启
|
||||
autoIncrement: true
|
||||
triggers:
|
||||
push:
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
40
jjj_erp/.workflow/PRPipeline.yml
Normal file
@ -0,0 +1,40 @@
|
||||
version: '1.0'
|
||||
name: pr-pipeline
|
||||
displayName: PRPipeline
|
||||
stages:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
- step: build@maven
|
||||
name: build_maven
|
||||
displayName: Maven 构建
|
||||
# 支持6、7、8、9、10、11六个版本
|
||||
jdkVersion: 8
|
||||
# 支持2.2.1、3.2.5、3.3.9、3.5.2、3.5.3、3.5.4、3.6.1、3.6.3八个版本
|
||||
mavenVersion: 3.3.9
|
||||
# 构建命令
|
||||
commands:
|
||||
- mvn -B clean package -Dmaven.test.skip=true
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径,如通常jar包在target目录下。当前目录为代码库根目录
|
||||
path:
|
||||
- ./target
|
||||
- step: publish@general_artifacts
|
||||
name: publish_general_artifacts
|
||||
displayName: 上传制品
|
||||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
|
||||
dependArtifact: BUILD_ARTIFACT
|
||||
# 构建产物制品库,默认default,系统默认创建
|
||||
artifactRepository: default
|
||||
# 上传到制品库时的制品命名,默认output
|
||||
artifactName: output
|
||||
dependsOn: build_maven
|
||||
triggers:
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
1
jjj_erp/bootstrap/README.md
Normal file
@ -0,0 +1 @@
|
||||
# bootstrap 项目启动模块
|
||||
54
jjj_erp/bootstrap/pom.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.jjjerp</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>bootstrap</artifactId>
|
||||
<name>bootstrap</name>
|
||||
<description>项目启动模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.jjjerp</groupId>
|
||||
<artifactId>jjj-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.jjjerp</groupId>
|
||||
<artifactId>jjj-saas</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.jjjerp</groupId>
|
||||
<artifactId>jjj-admin</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.jjjerp</groupId>
|
||||
<artifactId>jjj-job</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
package net.jjjerp;
|
||||
|
||||
import net.jjjerp.config.JjjNameGenerator;
|
||||
import net.jjjerp.framework.util.PrintApplicationInfo;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* spring-boot-jjj 项目启动入口
|
||||
*/
|
||||
@EnableAsync
|
||||
@EnableScheduling
|
||||
@EnableTransactionManagement
|
||||
@EnableConfigurationProperties
|
||||
@ComponentScan(nameGenerator = JjjNameGenerator.class)
|
||||
@ServletComponentScan
|
||||
@MapperScan(basePackages = {"net.jjjerp.**.mapper"}, nameGenerator = JjjNameGenerator.class)
|
||||
@SpringBootApplication(scanBasePackages = {"net.jjjerp"})
|
||||
public class SpringBootJjjApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 启动spring-boot-jjj
|
||||
ConfigurableApplicationContext context = SpringApplication.run(SpringBootJjjApplication.class, args);
|
||||
// 打印项目信息
|
||||
PrintApplicationInfo.print(context);
|
||||
// 打印项目提示
|
||||
PrintApplicationInfo.printTip(context);
|
||||
}
|
||||
|
||||
}
|
||||
72
jjj_erp/bootstrap/src/main/java/net/jjjerp/aop/LogAop.java
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
|
||||
package net.jjjerp.aop;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.jjjerp.framework.log.aop.BaseLogAop;
|
||||
import net.jjjerp.framework.log.bean.OperationLogInfo;
|
||||
import net.jjjerp.framework.log.bean.RequestInfo;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Controller Aop
|
||||
* 获取响应结果信息
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
@ConditionalOnProperty(value = {"spring-boot-jjj.aop.log.enable"}, matchIfMissing = true)
|
||||
public class LogAop extends BaseLogAop {
|
||||
/**
|
||||
* 切点
|
||||
*/
|
||||
private static final String POINTCUT =
|
||||
"execution(public * net.jjjerp..*.controller..*.*(..))";
|
||||
|
||||
@Around(POINTCUT)
|
||||
@Override
|
||||
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
return super.handle(joinPoint);
|
||||
}
|
||||
|
||||
@AfterThrowing(pointcut = POINTCUT, throwing = "exception")
|
||||
@Override
|
||||
public void afterThrowing(JoinPoint joinPoint, Exception exception) {
|
||||
super.handleAfterThrowing(exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setRequestId(RequestInfo requestInfo) {
|
||||
super.handleRequestId(requestInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getRequestInfo(RequestInfo requestInfo) {
|
||||
// 处理请求参数日志
|
||||
super.handleRequestInfo(requestInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getResponseResult(Object result) {
|
||||
// 处理响应结果日志
|
||||
super.handleResponseResult(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finish(RequestInfo requestInfo, OperationLogInfo operationLogInfo, Object result, Exception exception) {
|
||||
// 只记录shop端日志
|
||||
if(requestInfo.getPath().startsWith("/api/admin/")){
|
||||
// 异步保存操作日志
|
||||
super.saveShopOperationLog(requestInfo, operationLogInfo, result, exception);
|
||||
// 异步保存登录日志
|
||||
super.saveShopLoginLog(requestInfo, operationLogInfo, result, exception);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
|
||||
import net.jjjerp.config.constant.DatePattern;
|
||||
import net.jjjerp.framework.config.jackson.serializer.JacksonBigDecimalSerializer;
|
||||
import net.jjjerp.framework.config.jackson.deserializer.JacksonDateDeserializer;
|
||||
import net.jjjerp.framework.config.jackson.deserializer.JacksonDoubleDeserializer;
|
||||
import net.jjjerp.framework.config.jackson.serializer.JacksonDateSerializer;
|
||||
import net.jjjerp.framework.config.jackson.serializer.JacksonIntegerDeserializer;
|
||||
import net.jjjerp.framework.core.xss.XssJacksonDeserializer;
|
||||
import net.jjjerp.framework.core.xss.XssJacksonSerializer;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
public class JacksonConfig implements WebMvcConfigurer {
|
||||
|
||||
@Value("${spring-boot-jjj.filter.xss.enable}")
|
||||
private boolean enableXss;
|
||||
|
||||
@Override
|
||||
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
|
||||
|
||||
ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
|
||||
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
|
||||
|
||||
SimpleModule simpleModule = new SimpleModule();
|
||||
|
||||
// XSS序列化
|
||||
if (enableXss){
|
||||
simpleModule.addSerializer(String.class, new XssJacksonSerializer());
|
||||
simpleModule.addDeserializer(String.class, new XssJacksonDeserializer());
|
||||
}
|
||||
|
||||
// Date
|
||||
simpleModule.addSerializer(Date.class, new JacksonDateSerializer());
|
||||
simpleModule.addDeserializer(Date.class, new JacksonDateDeserializer());
|
||||
|
||||
simpleModule.addSerializer(BigDecimal.class, new JacksonBigDecimalSerializer());
|
||||
|
||||
simpleModule.addDeserializer(Integer.class, new JacksonIntegerDeserializer());
|
||||
simpleModule.addDeserializer(Double.class, new JacksonDoubleDeserializer());
|
||||
|
||||
// jdk8日期序列化和反序列化设置
|
||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD_HH_MM_SS)));
|
||||
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD_HH_MM_SS)));
|
||||
|
||||
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD)));
|
||||
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD)));
|
||||
|
||||
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.HH_MM_SS)));
|
||||
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.HH_MM_SS)));
|
||||
|
||||
objectMapper.registerModule(simpleModule).registerModule(javaTimeModule).registerModule(new ParameterNamesModule());
|
||||
|
||||
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
|
||||
|
||||
//放到第一个
|
||||
converters.add(0, jackson2HttpMessageConverter);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package net.jjjerp.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
|
||||
|
||||
/**
|
||||
* @className: JjjNameGenerator
|
||||
* @description: 解决不同包下相同类名冲突
|
||||
*/
|
||||
public class JjjNameGenerator extends AnnotationBeanNameGenerator {
|
||||
@Override
|
||||
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
|
||||
//全限定类名
|
||||
String beanName = definition.getBeanClassName();
|
||||
return beanName;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.jjjerp.common.interceptor.JjjTenantLineInnerInterceptor;
|
||||
import net.jjjerp.config.properties.SpringBootJjjProperties;
|
||||
import net.jjjerp.framework.core.bean.RequestDetail;
|
||||
import net.jjjerp.framework.core.util.RequestDetailThreadLocal;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.LongValue;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MybatisPlus配置
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class MybatisPlusConfig {
|
||||
@Value("${spring.profiles.active}")
|
||||
private String env;
|
||||
/**
|
||||
* spring-boot-jjj配置属性
|
||||
*/
|
||||
@Autowired
|
||||
private SpringBootJjjProperties springBootJjjProperties;
|
||||
@Autowired
|
||||
private RedisTemplate redisTemplate;
|
||||
/**
|
||||
* 新多租户插件配置,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存万一出现问题
|
||||
*/
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
interceptor.addInnerInterceptor(new JjjTenantLineInnerInterceptor(new TenantLineHandler() {
|
||||
@Override
|
||||
public Expression getTenantId() {
|
||||
RequestDetail requestDetail = RequestDetailThreadLocal.getRequestDetail();
|
||||
// 0为不带租户id
|
||||
if(requestDetail == null){
|
||||
return new LongValue(0);
|
||||
}
|
||||
return new LongValue(requestDetail.getAppId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTenantIdColumn() {
|
||||
// 对应数据库租户标识的列名
|
||||
return "app_id";
|
||||
}
|
||||
|
||||
// 这是 default 方法,默认返回 false 表示所有表都需要拼多租户条件
|
||||
@Override
|
||||
public boolean ignoreTable(String tableName) {
|
||||
List<String> tables = springBootJjjProperties.getIgnoreTables();
|
||||
return tables.contains(tableName);
|
||||
}
|
||||
},env,redisTemplate));
|
||||
// 如果用了分页插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
|
||||
// 用了分页插件必须设置 MybatisConfiguration#useDeprecatedExecutor = false
|
||||
// 分页插件
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
|
||||
return interceptor;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.KeyGenerator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Redis Cache配置
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class RedisCacheConfig extends CachingConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public KeyGenerator keyGenerator() {
|
||||
return (target, method, params) -> {
|
||||
StringBuffer redisKey = new StringBuffer();
|
||||
redisKey.append(target.getClass().getName()).append("-");
|
||||
redisKey.append(method.getName());
|
||||
if (params.length > 0) {
|
||||
redisKey.append("-").append(Arrays.deepToString(params));
|
||||
}
|
||||
return redisKey.toString();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public CacheManager cacheManager(RedisConnectionFactory factory) {
|
||||
// 生成一个默认配置,通过config对象即可对缓存进行自定义配置
|
||||
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
|
||||
// 设置缓存的默认过期时间,也是使用Duration设置
|
||||
// 过期时间5分钟
|
||||
config = config.entryTtl(Duration.ofMinutes(5));
|
||||
|
||||
// 设置一个初始化的缓存空间set集合
|
||||
Set<String> cacheNames = new HashSet<>();
|
||||
cacheNames.add("my-redis-cache1");
|
||||
cacheNames.add("my-redis-cache2");
|
||||
|
||||
// 对每个缓存空间应用不同的配置
|
||||
Map<String, RedisCacheConfiguration> configMap = new HashMap<>(10);
|
||||
configMap.put("my-redis-cache1", config);
|
||||
configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));
|
||||
|
||||
// 使用自定义的缓存配置初始化一个cacheManager
|
||||
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
|
||||
// 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
|
||||
.initialCacheNames(cacheNames)
|
||||
.withInitialCacheConfigurations(configMap)
|
||||
.build();
|
||||
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* Redis Template 配置
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
|
||||
// 自定义的string序列化器和fastjson序列化器
|
||||
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||
|
||||
// jackson 序列化器
|
||||
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
|
||||
|
||||
// kv 序列化
|
||||
redisTemplate.setKeySerializer(stringRedisSerializer);
|
||||
redisTemplate.setValueSerializer(jsonRedisSerializer);
|
||||
|
||||
// hash 序列化
|
||||
redisTemplate.setHashKeySerializer(stringRedisSerializer);
|
||||
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
|
||||
|
||||
redisTemplate.afterPropertiesSet();
|
||||
|
||||
return redisTemplate;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
|
||||
return new RestTemplate(factory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
|
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||
//单位为ms
|
||||
factory.setReadTimeout(5000);
|
||||
//单位为ms
|
||||
factory.setConnectTimeout(5000);
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,300 @@
|
||||
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.jjjerp.config.properties.JwtProperties;
|
||||
import net.jjjerp.config.properties.ShiroPermissionProperties;
|
||||
import net.jjjerp.config.properties.ShiroProperties;
|
||||
import net.jjjerp.framework.shiro.cache.AdminLoginRedisService;
|
||||
import net.jjjerp.framework.shiro.cache.ShopLoginRedisService;
|
||||
import net.jjjerp.framework.shiro.exception.ShiroConfigException;
|
||||
import net.jjjerp.framework.shiro.jwt.JwtCredentialsMatcher;
|
||||
import net.jjjerp.framework.shiro.jwt.JwtFilter;
|
||||
import net.jjjerp.framework.shiro.jwt.JwtRealm;
|
||||
import net.jjjerp.framework.shiro.service.ShiroLoginService;
|
||||
import net.jjjerp.framework.util.IniUtil;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.Authenticator;
|
||||
import org.apache.shiro.authc.credential.CredentialsMatcher;
|
||||
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
|
||||
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
|
||||
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
|
||||
import org.apache.shiro.mgt.DefaultSubjectDAO;
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.mgt.SessionStorageEvaluator;
|
||||
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Shiro配置
|
||||
* https://shiro.apache.org/spring.html
|
||||
* https://shiro.apache.org/spring-boot.html
|
||||
**/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({ShiroProperties.class})
|
||||
@ConditionalOnProperty(value = {"spring-boot-jjj.shiro.enable"}, matchIfMissing = true)
|
||||
public class ShiroConfig {
|
||||
|
||||
/**
|
||||
* JWT过滤器名称
|
||||
*/
|
||||
private static final String JWT_FILTER_NAME = "jwtFilter";
|
||||
|
||||
/**
|
||||
* Shiro过滤器名称
|
||||
*/
|
||||
private static final String SHIRO_FILTER_NAME = "shiroFilter";
|
||||
|
||||
/**
|
||||
* anon
|
||||
*/
|
||||
private static final String ANON = "anon";
|
||||
|
||||
|
||||
@Bean
|
||||
public CredentialsMatcher credentialsMatcher() {
|
||||
return new JwtCredentialsMatcher();
|
||||
}
|
||||
|
||||
/**
|
||||
* JWT数据源验证
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public JwtRealm jwtRealm(AdminLoginRedisService adminLoginRedisService, ShopLoginRedisService shopLoginRedisService) {
|
||||
JwtRealm jwtRealm = new JwtRealm(adminLoginRedisService, shopLoginRedisService);
|
||||
jwtRealm.setCachingEnabled(false);
|
||||
jwtRealm.setCredentialsMatcher(credentialsMatcher());
|
||||
return jwtRealm;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public SessionStorageEvaluator sessionStorageEvaluator() {
|
||||
DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
|
||||
sessionStorageEvaluator.setSessionStorageEnabled(false);
|
||||
return sessionStorageEvaluator;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultSubjectDAO subjectDAO() {
|
||||
DefaultSubjectDAO defaultSubjectDAO = new DefaultSubjectDAO();
|
||||
defaultSubjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator());
|
||||
return defaultSubjectDAO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全管理器配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public SecurityManager securityManager(AdminLoginRedisService adminLoginRedisService, ShopLoginRedisService shopLoginRedisService) {
|
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||
securityManager.setRealm(jwtRealm(adminLoginRedisService, shopLoginRedisService));
|
||||
securityManager.setSubjectDAO(subjectDAO());
|
||||
SecurityUtils.setSecurityManager(securityManager);
|
||||
return securityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* ShiroFilterFactoryBean配置
|
||||
*
|
||||
* @param securityManager
|
||||
* @param adminLoginRedisService
|
||||
* @param shiroProperties
|
||||
* @param jwtProperties
|
||||
* @return
|
||||
*/
|
||||
@Bean(SHIRO_FILTER_NAME)
|
||||
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager,
|
||||
ShiroLoginService shiroLoginService,
|
||||
AdminLoginRedisService adminLoginRedisService,
|
||||
ShopLoginRedisService shopLoginRedisService,
|
||||
ShiroProperties shiroProperties,
|
||||
JwtProperties jwtProperties) {
|
||||
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
|
||||
shiroFilterFactoryBean.setSecurityManager(securityManager);
|
||||
Map<String, Filter> filterMap = getFilterMap(shiroLoginService, adminLoginRedisService, shopLoginRedisService, jwtProperties);
|
||||
shiroFilterFactoryBean.setFilters(filterMap);
|
||||
Map<String, String> filterChainMap = getFilterChainDefinitionMap(shiroProperties);
|
||||
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取filter map
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Filter> getFilterMap(ShiroLoginService shiroLoginService,
|
||||
AdminLoginRedisService adminLoginRedisService,
|
||||
ShopLoginRedisService shopLoginRedisService,
|
||||
JwtProperties jwtProperties) {
|
||||
Map<String, Filter> filterMap = new LinkedHashMap<>();
|
||||
filterMap.put(JWT_FILTER_NAME, new JwtFilter(shiroLoginService, adminLoginRedisService, shopLoginRedisService, jwtProperties));
|
||||
return filterMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shiro路径权限配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Map<String, String> getFilterChainDefinitionMap(ShiroProperties shiroProperties) {
|
||||
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
|
||||
// 获取排除的路径
|
||||
List<String[]> anonList = shiroProperties.getAnon();
|
||||
log.debug("anonList:{}", JSON.toJSONString(anonList));
|
||||
if (CollectionUtils.isNotEmpty(anonList)) {
|
||||
anonList.forEach(anonArray -> {
|
||||
if (ArrayUtils.isNotEmpty(anonArray)) {
|
||||
for (String anonPath : anonArray) {
|
||||
filterChainDefinitionMap.put(anonPath, ANON);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 获取ini格式配置
|
||||
String definitions = shiroProperties.getFilterChainDefinitions();
|
||||
if (StringUtils.isNotBlank(definitions)) {
|
||||
Map<String, String> section = IniUtil.parseIni(definitions);
|
||||
log.debug("definitions:{}", JSON.toJSONString(section));
|
||||
for (Map.Entry<String, String> entry : section.entrySet()) {
|
||||
filterChainDefinitionMap.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// 获取自定义权限路径配置集合
|
||||
List<ShiroPermissionProperties> permissionConfigs = shiroProperties.getPermission();
|
||||
log.debug("permissionConfigs:{}", JSON.toJSONString(permissionConfigs));
|
||||
if (CollectionUtils.isNotEmpty(permissionConfigs)) {
|
||||
for (ShiroPermissionProperties permissionConfig : permissionConfigs) {
|
||||
String url = permissionConfig.getUrl();
|
||||
String[] urls = permissionConfig.getUrls();
|
||||
String permission = permissionConfig.getPermission();
|
||||
if (StringUtils.isBlank(url) && ArrayUtils.isEmpty(urls)) {
|
||||
throw new ShiroConfigException("shiro permission config 路径配置不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(permission)) {
|
||||
throw new ShiroConfigException("shiro permission config permission不能为空");
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(url)) {
|
||||
filterChainDefinitionMap.put(url, permission);
|
||||
}
|
||||
if (ArrayUtils.isNotEmpty(urls)) {
|
||||
for (String string : urls) {
|
||||
filterChainDefinitionMap.put(string, permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果启用shiro,则设置最后一个设置为JWTFilter,否则全部路径放行
|
||||
if (shiroProperties.isEnable()) {
|
||||
filterChainDefinitionMap.put("/**", JWT_FILTER_NAME);
|
||||
} else {
|
||||
filterChainDefinitionMap.put("/**", ANON);
|
||||
}
|
||||
|
||||
log.debug("filterChainMap:{}", JSON.toJSONString(filterChainDefinitionMap));
|
||||
|
||||
// 添加默认的filter
|
||||
Map<String, String> newFilterChainDefinitionMap = addDefaultFilterDefinition(filterChainDefinitionMap);
|
||||
return newFilterChainDefinitionMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加默认的filter权限过滤
|
||||
*
|
||||
* @param filterChainDefinitionMap
|
||||
* @return
|
||||
*/
|
||||
private Map<String, String> addDefaultFilterDefinition(Map<String, String> filterChainDefinitionMap) {
|
||||
if (MapUtils.isEmpty(filterChainDefinitionMap)) {
|
||||
return filterChainDefinitionMap;
|
||||
}
|
||||
final Map<String, String> map = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, String> entry : filterChainDefinitionMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
String definition;
|
||||
String[] strings = value.split(",");
|
||||
List<String> list = new ArrayList<>();
|
||||
list.addAll(Arrays.asList(strings));
|
||||
definition = String.join(",", list);
|
||||
map.put(key, definition);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* ShiroFilter配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean delegatingFilterProxy() {
|
||||
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
|
||||
DelegatingFilterProxy proxy = new DelegatingFilterProxy();
|
||||
proxy.setTargetFilterLifecycle(true);
|
||||
proxy.setTargetBeanName(SHIRO_FILTER_NAME);
|
||||
filterRegistrationBean.setFilter(proxy);
|
||||
filterRegistrationBean.setAsyncSupported(true);
|
||||
filterRegistrationBean.setEnabled(true);
|
||||
filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
|
||||
return filterRegistrationBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Authenticator authenticator(AdminLoginRedisService adminLoginRedisService, ShopLoginRedisService shopLoginRedisService) {
|
||||
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
|
||||
authenticator.setRealms(Arrays.asList(jwtRealm(adminLoginRedisService, shopLoginRedisService)));
|
||||
authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
|
||||
return authenticator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enabling Shiro Annotations
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
|
||||
return new LifecycleBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
|
||||
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
|
||||
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
|
||||
return authorizationAttributeSourceAdvisor;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* spring-boot-jjj配置
|
||||
*/
|
||||
@Slf4j
|
||||
public class SpringBootJjjConfig {
|
||||
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
|
||||
import net.jjjerp.config.properties.SpringBootJjjCorsProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
* 跨域配置
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = {"spring-boot-jjj.cors.enable"}, matchIfMissing = true)
|
||||
public class SpringBootJjjCorsConfig {
|
||||
|
||||
/**
|
||||
* CORS跨域设置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean corsFilter(SpringBootJjjCorsProperties corsProperties) {
|
||||
log.debug("corsProperties:{}", corsProperties);
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
// 跨域配置
|
||||
corsConfiguration.setAllowedOrigins(corsProperties.getAllowedOrigins());
|
||||
corsConfiguration.setAllowedHeaders(corsProperties.getAllowedHeaders());
|
||||
corsConfiguration.setAllowedMethods(corsProperties.getAllowedMethods());
|
||||
corsConfiguration.setAllowCredentials(corsProperties.isAllowCredentials());
|
||||
corsConfiguration.setExposedHeaders(corsProperties.getExposedHeaders());
|
||||
corsConfiguration.setMaxAge(corsConfiguration.getMaxAge());
|
||||
|
||||
source.registerCorsConfiguration(corsProperties.getPath(), corsConfiguration);
|
||||
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
|
||||
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||
bean.setEnabled(corsProperties.isEnable());
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,145 @@
|
||||
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import net.jjjerp.config.properties.SpringBootJjjFilterProperties;
|
||||
import net.jjjerp.config.properties.SpringBootJjjInterceptorProperties;
|
||||
import net.jjjerp.config.properties.SpringBootJjjProperties;
|
||||
import net.jjjerp.framework.core.filter.RequestDetailFilter;
|
||||
import net.jjjerp.framework.core.interceptor.FrontInterceptor;
|
||||
import net.jjjerp.framework.core.interceptor.PermissionInterceptor;
|
||||
import net.jjjerp.framework.core.xss.XssFilter;
|
||||
import net.jjjerp.framework.util.IniUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* WebMvc配置
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class SpringBootJjjWebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
/**
|
||||
* spring-boot-jjj配置属性
|
||||
*/
|
||||
@Autowired
|
||||
private SpringBootJjjProperties springBootJjjProperties;
|
||||
|
||||
/**
|
||||
* Filter配置
|
||||
*/
|
||||
private SpringBootJjjFilterProperties filterConfig;
|
||||
|
||||
/**
|
||||
* 拦截器配置
|
||||
*/
|
||||
private SpringBootJjjInterceptorProperties interceptorConfig;
|
||||
|
||||
/**
|
||||
* RequestDetailFilter配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean requestDetailFilter() {
|
||||
SpringBootJjjFilterProperties.FilterConfig requestFilterConfig = filterConfig.getRequest();
|
||||
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
|
||||
filterRegistrationBean.setFilter(new RequestDetailFilter());
|
||||
filterRegistrationBean.setEnabled(requestFilterConfig.isEnable());
|
||||
filterRegistrationBean.addUrlPatterns(requestFilterConfig.getUrlPatterns());
|
||||
filterRegistrationBean.setOrder(requestFilterConfig.getOrder());
|
||||
filterRegistrationBean.setAsyncSupported(requestFilterConfig.isAsync());
|
||||
return filterRegistrationBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* XssFilter配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean xssFilter() {
|
||||
SpringBootJjjFilterProperties.FilterConfig xssFilterConfig = filterConfig.getXss();
|
||||
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
|
||||
filterRegistrationBean.setFilter(new XssFilter());
|
||||
filterRegistrationBean.setEnabled(xssFilterConfig.isEnable());
|
||||
filterRegistrationBean.addUrlPatterns(xssFilterConfig.getUrlPatterns());
|
||||
filterRegistrationBean.setOrder(xssFilterConfig.getOrder());
|
||||
filterRegistrationBean.setAsyncSupported(xssFilterConfig.isAsync());
|
||||
return filterRegistrationBean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 自定义权限拦截器
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public PermissionInterceptor permissionInterceptor() {
|
||||
return new PermissionInterceptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* 前端拦截器
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public FrontInterceptor frontInterceptor() {
|
||||
return new FrontInterceptor();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
filterConfig = springBootJjjProperties.getFilter();
|
||||
interceptorConfig = springBootJjjProperties.getInterceptor();
|
||||
// 打印SpringBootJjjProperties配置信息
|
||||
log.debug("SpringBootJjjProperties:{}", JSON.toJSONString(springBootJjjProperties));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
|
||||
// 自定义权限拦截器注册
|
||||
if (interceptorConfig.getPermission().isEnable()) {
|
||||
registry.addInterceptor(permissionInterceptor())
|
||||
.addPathPatterns(interceptorConfig.getPermission().getIncludePaths())
|
||||
.excludePathPatterns(interceptorConfig.getPermission().getExcludePaths());
|
||||
}
|
||||
registry.addInterceptor(frontInterceptor())
|
||||
.addPathPatterns("/front/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
// 设置项目静态资源访问
|
||||
String resourceHandlers = springBootJjjProperties.getResourceHandlers();
|
||||
if (StringUtils.isNotBlank(resourceHandlers)) {
|
||||
Map<String, String> map = IniUtil.parseIni(resourceHandlers);
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
String pathPatterns = entry.getKey();
|
||||
String resourceLocations = entry.getValue();
|
||||
registry.addResourceHandler(pathPatterns)
|
||||
.addResourceLocations(resourceLocations);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置上传文件访问路径
|
||||
registry.addResourceHandler(springBootJjjProperties.getResourceAccessPatterns())
|
||||
.addResourceLocations("file:" + springBootJjjProperties.getUploadPath() + "/");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,255 @@
|
||||
|
||||
|
||||
package net.jjjerp.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
|
||||
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
|
||||
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import net.jjjerp.config.properties.SwaggerProperties;
|
||||
import net.jjjerp.framework.common.exception.SpringBootJjjConfigException;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.stereotype.Component;
|
||||
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
|
||||
import springfox.documentation.RequestHandler;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.ParameterBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.schema.ModelRef;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.Contact;
|
||||
import springfox.documentation.service.Parameter;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
|
||||
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
|
||||
import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger.common.SwaggerPluginSupport;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static springfox.documentation.schema.Annotations.findPropertyAnnotation;
|
||||
import static springfox.documentation.swagger.schema.ApiModelProperties.findApiModePropertyAnnotation;
|
||||
|
||||
/**
|
||||
* Swagger2全局配置
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
@EnableKnife4j
|
||||
@Import(BeanValidatorPluginsConfiguration.class)
|
||||
@ConditionalOnProperty(value = {"knife4j.enable"}, matchIfMissing = true)
|
||||
public class Swagger2Config {
|
||||
|
||||
@Autowired
|
||||
private SwaggerProperties swaggerProperties;
|
||||
|
||||
/**
|
||||
* 扫描多包时,包路径的拆分符,分号
|
||||
*/
|
||||
private static final String SPLIT_COMMA = ",";
|
||||
|
||||
/**
|
||||
* 扫描多包时,包路径的拆分符,逗号
|
||||
*/
|
||||
private static final String SPLIT_SEMICOLON = ";";
|
||||
|
||||
/**
|
||||
* Swagger忽略的参数类型
|
||||
*/
|
||||
private Class<?>[] ignoredParameterTypes = new Class[]{
|
||||
ServletRequest.class,
|
||||
ServletResponse.class,
|
||||
HttpServletRequest.class,
|
||||
HttpServletResponse.class,
|
||||
HttpSession.class,
|
||||
ApiIgnore.class
|
||||
};
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
// 获取需要扫描的包
|
||||
String[] basePackages = getBasePackages();
|
||||
ApiSelectorBuilder apiSelectorBuilder = new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(apiInfo())
|
||||
.select();
|
||||
// 如果扫描的包为空,则默认扫描类上有@Api注解的类
|
||||
if (ArrayUtils.isEmpty(basePackages)) {
|
||||
apiSelectorBuilder.apis(RequestHandlerSelectors.withClassAnnotation(Api.class));
|
||||
} else {
|
||||
// 扫描指定的包
|
||||
apiSelectorBuilder.apis(basePackage(basePackages));
|
||||
}
|
||||
Docket docket = apiSelectorBuilder.paths(PathSelectors.any())
|
||||
.build()
|
||||
.enable(swaggerProperties.isEnable())
|
||||
.ignoredParameterTypes(ignoredParameterTypes)
|
||||
.globalOperationParameters(getParameters());
|
||||
return docket;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取apiInfo
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title(swaggerProperties.getTitle())
|
||||
.description(swaggerProperties.getDescription())
|
||||
.termsOfServiceUrl(swaggerProperties.getUrl())
|
||||
.contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail()))
|
||||
.version(swaggerProperties.getVersion())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取扫描的包
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String[] getBasePackages() {
|
||||
log.debug("swaggerProperties = " + swaggerProperties);
|
||||
String basePackage = swaggerProperties.getBasePackage();
|
||||
if (StringUtils.isBlank(basePackage)) {
|
||||
throw new SpringBootJjjConfigException("Swagger basePackage不能为空");
|
||||
}
|
||||
String[] basePackages = null;
|
||||
if (basePackage.contains(SPLIT_COMMA)) {
|
||||
basePackages = basePackage.split(SPLIT_COMMA);
|
||||
} else if (basePackage.contains(SPLIT_SEMICOLON)) {
|
||||
basePackages = basePackage.split(SPLIT_SEMICOLON);
|
||||
}
|
||||
log.info("swagger scan basePackages:" + Arrays.toString(basePackages));
|
||||
return basePackages;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加额外参数
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<Parameter> getParameters() {
|
||||
// 获取自定义参数配置
|
||||
List<SwaggerProperties.ParameterConfig> parameterConfig = swaggerProperties.getParameterConfig();
|
||||
if (CollectionUtils.isEmpty(parameterConfig)) {
|
||||
return null;
|
||||
}
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameterConfig.forEach(parameter -> {
|
||||
// 设置自定义参数
|
||||
parameters.add(new ParameterBuilder()
|
||||
.name(parameter.getName())
|
||||
.description(parameter.getDescription())
|
||||
.modelRef(new ModelRef(parameter.getDataType()))
|
||||
.parameterType(parameter.getType())
|
||||
.required(parameter.isRequired())
|
||||
.defaultValue(parameter.getDefaultValue())
|
||||
.build());
|
||||
});
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
||||
public static Predicate<RequestHandler> basePackage(final String[] basePackages) {
|
||||
return input -> declaringClass(input).transform(handlerPackage(basePackages)).or(true);
|
||||
}
|
||||
|
||||
private static Function<Class<?>, Boolean> handlerPackage(final String[] basePackages) {
|
||||
return input -> {
|
||||
// 循环判断匹配
|
||||
for (String strPackage : basePackages) {
|
||||
boolean isMatch = input.getPackage().getName().startsWith(strPackage);
|
||||
if (isMatch) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static Optional<? extends Class<?>> declaringClass(RequestHandler input) {
|
||||
return Optional.fromNullable(input.declaringClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按照类中字段顺序显示
|
||||
*/
|
||||
@Component
|
||||
public static class ApiModelPropertyBuilderPlugin implements ModelPropertyBuilderPlugin {
|
||||
|
||||
@Override
|
||||
public void apply(ModelPropertyContext context) {
|
||||
try {
|
||||
Optional<BeanPropertyDefinition> beanPropertyDefinitionOptional = context.getBeanPropertyDefinition();
|
||||
Optional<ApiModelProperty> annotation = Optional.absent();
|
||||
if (context.getAnnotatedElement().isPresent()) {
|
||||
annotation = annotation.or(findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
|
||||
}
|
||||
if (context.getBeanPropertyDefinition().isPresent()) {
|
||||
annotation = annotation.or(findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelProperty.class));
|
||||
}
|
||||
if (beanPropertyDefinitionOptional.isPresent()) {
|
||||
BeanPropertyDefinition beanPropertyDefinition = beanPropertyDefinitionOptional.get();
|
||||
if (annotation.isPresent() && annotation.get().position() != 0) {
|
||||
return;
|
||||
}
|
||||
AnnotatedField annotatedField = beanPropertyDefinition.getField();
|
||||
if (annotatedField == null) {
|
||||
return;
|
||||
}
|
||||
Class<?> clazz = annotatedField.getDeclaringClass();
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
// 获取当前字段对象
|
||||
Field field = clazz.getDeclaredField(annotatedField.getName());
|
||||
boolean required = false;
|
||||
// 获取字段注解
|
||||
NotNull notNull = field.getDeclaredAnnotation(NotNull.class);
|
||||
NotBlank notBlank = field.getDeclaredAnnotation(NotBlank.class);
|
||||
if (notNull != null || notBlank != null) {
|
||||
required = true;
|
||||
}
|
||||
int position = ArrayUtils.indexOf(fields, field);
|
||||
if (position != -1) {
|
||||
context.getBuilder().position(position).required(required);
|
||||
}
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
log.error("Swagger ApiModelProperty预处理异常", exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(DocumentationType delimiter) {
|
||||
return SwaggerPluginSupport.pluginDoesApply(delimiter);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,260 @@
|
||||
|
||||
|
||||
package net.jjjerp.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.auth0.jwt.exceptions.JWTDecodeException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.jjjerp.framework.common.api.ApiCode;
|
||||
import net.jjjerp.framework.common.api.ApiResult;
|
||||
import net.jjjerp.framework.common.exception.BusinessException;
|
||||
import net.jjjerp.framework.common.exception.DaoException;
|
||||
import net.jjjerp.framework.common.exception.SpringBootJjjException;
|
||||
import net.jjjerp.framework.core.bean.RequestDetail;
|
||||
import net.jjjerp.framework.core.util.RequestDetailThreadLocal;
|
||||
import net.jjjerp.admin.exception.SysLoginException;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authz.UnauthenticatedException;
|
||||
import org.apache.shiro.authz.UnauthorizedException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.HttpMediaTypeException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@ControllerAdvice
|
||||
@RestController
|
||||
@Slf4j
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
/**
|
||||
* 非法参数验证异常
|
||||
*
|
||||
* @param ex
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
public ApiResult<List<String>> handleMethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
|
||||
printRequestDetail();
|
||||
BindingResult bindingResult = ex.getBindingResult();
|
||||
List<String> list = new ArrayList<>();
|
||||
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
|
||||
for (FieldError fieldError : fieldErrors) {
|
||||
list.add(fieldError.getDefaultMessage());
|
||||
}
|
||||
Collections.sort(list);
|
||||
log.error(getApiCodeString(ApiCode.PARAMETER_EXCEPTION) + ":" + JSON.toJSONString(list));
|
||||
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统登录异常处理
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = SysLoginException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<Boolean> sysLoginExceptionHandler(SysLoginException exception) {
|
||||
printRequestDetail();
|
||||
printApiCodeException(ApiCode.LOGIN_EXCEPTION, exception);
|
||||
return ApiResult.fail(ApiCode.LOGIN_EXCEPTION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* HTTP解析请求参数异常
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = HttpMessageNotReadableException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<Boolean> httpMessageNotReadableException(HttpMessageNotReadableException exception) {
|
||||
printRequestDetail();
|
||||
printApiCodeException(ApiCode.PARAMETER_EXCEPTION, exception);
|
||||
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = HttpMediaTypeException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<Boolean> httpMediaTypeException(HttpMediaTypeException exception) {
|
||||
printRequestDetail();
|
||||
printApiCodeException(ApiCode.HTTP_MEDIA_TYPE_EXCEPTION, exception);
|
||||
return ApiResult.fail(ApiCode.HTTP_MEDIA_TYPE_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义业务/数据异常处理
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = {SpringBootJjjException.class})
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<String> springBootJjjExceptionHandler(SpringBootJjjException exception) {
|
||||
int errorCode;
|
||||
boolean isLog = true;
|
||||
if (exception instanceof BusinessException) {
|
||||
if(exception.getErrorCode() != null){
|
||||
errorCode = exception.getErrorCode();
|
||||
}else{
|
||||
errorCode = ApiCode.BUSINESS_EXCEPTION.getCode();
|
||||
}
|
||||
isLog = false;
|
||||
} else if (exception instanceof DaoException) {
|
||||
errorCode = ApiCode.DAO_EXCEPTION.getCode();
|
||||
} else {
|
||||
errorCode = ApiCode.SPRING_BOOT_JJJ_EXCEPTION.getCode();
|
||||
}
|
||||
// BusinessException不记录
|
||||
if(isLog){
|
||||
printRequestDetail();
|
||||
log.error("springBootJjjException:", exception);
|
||||
}
|
||||
return ApiResult.fail(errorCode, exception.getMessage());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 登录授权异常处理
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = AuthenticationException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<String> authenticationExceptionHandler(AuthenticationException exception) {
|
||||
printRequestDetail();
|
||||
printApiCodeException(ApiCode.AUTHENTICATION_EXCEPTION, exception);
|
||||
return ApiResult.fail(exception.getMessage());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 未认证异常处理
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = UnauthenticatedException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<Boolean> unauthenticatedExceptionHandler(UnauthenticatedException exception) {
|
||||
printRequestDetail();
|
||||
printApiCodeException(ApiCode.UNAUTHENTICATED_EXCEPTION, exception);
|
||||
return ApiResult.fail(ApiCode.UNAUTHENTICATED_EXCEPTION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 未授权异常处理
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = UnauthorizedException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<Boolean> unauthorizedExceptionHandler(UnauthorizedException exception) {
|
||||
printRequestDetail();
|
||||
printApiCodeException(ApiCode.UNAUTHORIZED_EXCEPTION, exception);
|
||||
return ApiResult.fail(ApiCode.UNAUTHORIZED_EXCEPTION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* JWT Token解析异常
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = JWTDecodeException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<Boolean> jWTDecodeExceptionHandler(JWTDecodeException exception) {
|
||||
printRequestDetail();
|
||||
printApiCodeException(ApiCode.JWTDECODE_EXCEPTION, exception);
|
||||
return ApiResult.fail(ApiCode.JWTDECODE_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认的异常处理
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<String> httpRequestMethodNotSupportedExceptionHandler(Exception exception) {
|
||||
printRequestDetail();
|
||||
printApiCodeException(ApiCode.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION, exception);
|
||||
return ApiResult.fail(ApiCode.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION.getCode(), exception.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认的异常处理
|
||||
*
|
||||
* @param exception
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public ApiResult<String> exceptionHandler(Exception exception) {
|
||||
printRequestDetail();
|
||||
printApiCodeException(ApiCode.SYSTEM_EXCEPTION, exception);
|
||||
if(exception.getCause() != null && exception.getCause().getCause() != null){
|
||||
return ApiResult.fail(0, exception.getCause().getCause().getMessage());
|
||||
}else{
|
||||
return ApiResult.fail(0, exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打印请求详情
|
||||
*/
|
||||
private void printRequestDetail() {
|
||||
RequestDetail requestDetail = RequestDetailThreadLocal.getRequestDetail();
|
||||
if (requestDetail != null) {
|
||||
log.error("异常来源:ip: {}, path: {}", requestDetail.getIp(), requestDetail.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取ApiCode格式化字符串
|
||||
*
|
||||
* @param apiCode
|
||||
* @return
|
||||
*/
|
||||
private String getApiCodeString(ApiCode apiCode) {
|
||||
if (apiCode != null) {
|
||||
return String.format("errorCode: %s, errorMessage: %s", apiCode.getCode(), apiCode.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印错误码及异常
|
||||
*
|
||||
* @param apiCode
|
||||
* @param exception
|
||||
*/
|
||||
private void printApiCodeException(ApiCode apiCode, Exception exception) {
|
||||
log.error(getApiCodeString(apiCode), exception);
|
||||
}
|
||||
|
||||
}
|
||||
BIN
jjj_erp/bootstrap/target/classes/net/jjjerp/aop/LogAop.class
Normal file
BIN
jjj_erp/bootstrap/target/jjj-erp-1.0.jar
Normal file
BIN
jjj_erp/bootstrap/target/jjj-erp-1.0.jar.original
Normal file
5
jjj_erp/bootstrap/target/maven-archiver/pom.properties
Normal file
@ -0,0 +1,5 @@
|
||||
#Generated by Maven
|
||||
#Sat Jun 29 14:55:11 CST 2024
|
||||
version=1.0
|
||||
groupId=net.jjjerp
|
||||
artifactId=bootstrap
|
||||
@ -0,0 +1,16 @@
|
||||
net\jjjerp\SpringBootJjjApplication.class
|
||||
net\jjjerp\config\RestTemplateConfig.class
|
||||
net\jjjerp\config\Swagger2Config$ApiModelPropertyBuilderPlugin.class
|
||||
net\jjjerp\config\MybatisPlusConfig.class
|
||||
net\jjjerp\config\JjjNameGenerator.class
|
||||
net\jjjerp\aop\LogAop.class
|
||||
net\jjjerp\config\Swagger2Config.class
|
||||
net\jjjerp\config\SpringBootJjjWebMvcConfig.class
|
||||
net\jjjerp\config\MybatisPlusConfig$1.class
|
||||
net\jjjerp\config\RedisTemplateConfig.class
|
||||
net\jjjerp\config\ShiroConfig.class
|
||||
net\jjjerp\config\SpringBootJjjConfig.class
|
||||
net\jjjerp\handler\GlobalExceptionHandler.class
|
||||
net\jjjerp\config\JacksonConfig.class
|
||||
net\jjjerp\config\RedisCacheConfig.class
|
||||
net\jjjerp\config\SpringBootJjjCorsConfig.class
|
||||
@ -0,0 +1,14 @@
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\MybatisPlusConfig.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\SpringBootJjjConfig.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\SpringBootJjjWebMvcConfig.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\JjjNameGenerator.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\handler\GlobalExceptionHandler.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\ShiroConfig.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\SpringBootJjjCorsConfig.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\aop\LogAop.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\RestTemplateConfig.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\Swagger2Config.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\JacksonConfig.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\RedisCacheConfig.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\SpringBootJjjApplication.java
|
||||
D:\IdeaProjects\jiujiujia\svn\jjj_erp_java\jjj_erp\bootstrap\src\main\java\net\jjjerp\config\RedisTemplateConfig.java
|
||||
1
jjj_erp/config/README.md
Normal file
@ -0,0 +1 @@
|
||||
# config 项目配置模块
|
||||
49
jjj_erp/config/pom.xml
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>${hikari.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<parent>
|
||||
<groupId>net.jjjerp</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>config</artifactId>
|
||||
<name>config</name>
|
||||
<description>项目配置模块</description>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<excludes>
|
||||
<exclude>config/application-*.yml</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources/config</directory>
|
||||
<filtering>true</filtering>
|
||||
<targetPath>config</targetPath>
|
||||
<includes>
|
||||
<include>application-${profileActive}.yml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.constant;
|
||||
|
||||
/**
|
||||
* 可排序查询参数对象
|
||||
*/
|
||||
public interface CacheKey {
|
||||
|
||||
}
|
||||
@ -0,0 +1,153 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.constant;
|
||||
|
||||
/**
|
||||
* 公共常量
|
||||
*/
|
||||
public interface CommonConstant {
|
||||
|
||||
/**
|
||||
* 默认页码为1
|
||||
*/
|
||||
Long DEFAULT_PAGE_INDEX = 1L;
|
||||
|
||||
/**
|
||||
* 默认页大小为10
|
||||
*/
|
||||
Long DEFAULT_PAGE_SIZE = 10L;
|
||||
|
||||
/**
|
||||
* 分页总行数名称
|
||||
*/
|
||||
String PAGE_TOTAL_NAME = "total";
|
||||
|
||||
/**
|
||||
* 分页数据列表名称
|
||||
*/
|
||||
String PAGE_RECORDS_NAME = "records";
|
||||
|
||||
/**
|
||||
* 分页当前页码名称
|
||||
*/
|
||||
String PAGE_INDEX_NAME = "pageIndex";
|
||||
|
||||
/**
|
||||
* 分页当前页大小名称
|
||||
*/
|
||||
String PAGE_SIZE_NAME = "pageSize";
|
||||
|
||||
/**
|
||||
* 分页最后一页
|
||||
*/
|
||||
String PAGE_LAST_NAME = "lastPage";
|
||||
|
||||
/**
|
||||
* 登录用户
|
||||
*/
|
||||
String LOGIN_SYS_USER = "loginSysUser";
|
||||
|
||||
/**
|
||||
* 登录token
|
||||
*/
|
||||
String JWT_DEFAULT_TOKEN_NAME = "token";
|
||||
|
||||
/**
|
||||
* JWT用户名
|
||||
*/
|
||||
String JWT_USERNAME = "username";
|
||||
|
||||
/**
|
||||
* JWT刷新新token响应状态码
|
||||
*/
|
||||
int JWT_REFRESH_TOKEN_CODE = 460;
|
||||
|
||||
/**
|
||||
* JWT刷新新token响应状态码,
|
||||
* Redis中不存在,但jwt未过期,不生成新的token,返回361状态码
|
||||
*/
|
||||
int JWT_INVALID_TOKEN_CODE = 461;
|
||||
|
||||
/**
|
||||
* JWT Token默认密钥
|
||||
*/
|
||||
String JWT_DEFAULT_SECRET = "888888";
|
||||
|
||||
/**
|
||||
* JWT 默认过期时间,3600L,单位秒
|
||||
*/
|
||||
Long JWT_DEFAULT_EXPIRE_SECOND = 3600L;
|
||||
|
||||
/**
|
||||
* 默认头像
|
||||
*/
|
||||
String DEFAULT_HEAD_URL = "";
|
||||
|
||||
/**
|
||||
* 管理员角色名称
|
||||
*/
|
||||
String ADMIN_ROLE_NAME = "管理员";
|
||||
|
||||
String ADMIN_LOGIN = "adminLogin";
|
||||
|
||||
/**
|
||||
* 验证码token
|
||||
*/
|
||||
String VERIFY_TOKEN = "verifyToken";
|
||||
|
||||
/**
|
||||
* 图片
|
||||
*/
|
||||
String IMAGE = "image";
|
||||
|
||||
/**
|
||||
* JPEG
|
||||
*/
|
||||
String JPEG = "JPEG";
|
||||
|
||||
/**
|
||||
* base64前缀
|
||||
*/
|
||||
String BASE64_PREFIX = "data:image/png;base64,";
|
||||
|
||||
/**
|
||||
* ..
|
||||
*/
|
||||
String SPOT_SPOT = "..";
|
||||
|
||||
/**
|
||||
* ../
|
||||
*/
|
||||
String SPOT_SPOT_BACKSLASH = "../";
|
||||
|
||||
/**
|
||||
* SpringBootAdmin登录信息
|
||||
*/
|
||||
String ADMIN_LOGIN_SESSION = "adminLoginSession";
|
||||
|
||||
/**
|
||||
* 用户浏览器代理
|
||||
*/
|
||||
String USER_AGENT = "User-Agent";
|
||||
|
||||
/**
|
||||
* 本机地址IP
|
||||
*/
|
||||
String LOCALHOST_IP = "127.0.0.1";
|
||||
/**
|
||||
* 本机地址名称
|
||||
*/
|
||||
String LOCALHOST_IP_NAME = "本机地址";
|
||||
/**
|
||||
* 局域网IP
|
||||
*/
|
||||
String LAN_IP = "192.168";
|
||||
/**
|
||||
* 局域网名称
|
||||
*/
|
||||
String LAN_IP_NAME = "局域网";
|
||||
/**
|
||||
* 忽略appId
|
||||
*/
|
||||
String NOT_WITH_App_Id = "notWithAppId";
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.constant;
|
||||
|
||||
/**
|
||||
* redis key 常量
|
||||
**/
|
||||
public interface CommonRedisKey {
|
||||
|
||||
// --------------------admin端登录信息开始----------------------
|
||||
/**
|
||||
* 登录用户token信息key
|
||||
* login:token:tokenMd5
|
||||
*/
|
||||
String ADMIN_LOGIN_TOKEN = "erp.admin:login:token:%s";
|
||||
|
||||
/**
|
||||
* 登录用户信息key
|
||||
* login:user:username
|
||||
*/
|
||||
String ADMIN_LOGIN_USER = "erp.admin:login:user:%s";
|
||||
|
||||
/**
|
||||
* 登录用户盐值信息key
|
||||
* login:salt:username
|
||||
*/
|
||||
String ADMIN_LOGIN_SALT = "erp.admin:login:salt:%s";
|
||||
|
||||
/**
|
||||
* 登录用户username token
|
||||
* login:user:token:username:token
|
||||
*/
|
||||
String ADMIN_LOGIN_USER_TOKEN = "erp.admin:login:user:token:%s:%s";
|
||||
|
||||
|
||||
/**
|
||||
* 登录用户下的所有token
|
||||
* login:user:token:username:*
|
||||
*/
|
||||
String ADMIN_LOGIN_USER_ALL_TOKEN = "erp.admin:login:user:token:%s:*";
|
||||
|
||||
// --------------------admin端登录信息结束----------------------
|
||||
|
||||
// --------------------shop端登录信息开始----------------------
|
||||
/**
|
||||
* 登录用户token信息key
|
||||
* login:token:tokenMd5
|
||||
*/
|
||||
String SHOP_LOGIN_TOKEN = "erp.shop:login:token:%s";
|
||||
|
||||
/**
|
||||
* 登录用户信息key
|
||||
* login:user:username
|
||||
*/
|
||||
String SHOP_LOGIN_USER = "erp.shop:login:user:%s";
|
||||
|
||||
/**
|
||||
* 登录用户盐值信息key
|
||||
* login:salt:username
|
||||
*/
|
||||
String SHOP_LOGIN_SALT = "erp.shop:login:salt:%s";
|
||||
|
||||
/**
|
||||
* 登录用户username token
|
||||
* login:user:token:username:token
|
||||
*/
|
||||
String SHOP_LOGIN_USER_TOKEN = "erp.shop:login:user:token:%s:%s";
|
||||
|
||||
|
||||
/**
|
||||
* 登录用户下的所有token
|
||||
* login:user:token:username:*
|
||||
*/
|
||||
String SHOP_LOGIN_USER_ALL_TOKEN = "erp.shop:login:user:token:%s:*";
|
||||
|
||||
// --------------------shop端登录信息结束----------------------
|
||||
|
||||
/**
|
||||
* 地区缓存
|
||||
*/
|
||||
String REGION_DATA = "erp.region.data";
|
||||
/**
|
||||
* 设置缓存
|
||||
*/
|
||||
String SETTING_DATA = "erp.setting.data:%s:%s";
|
||||
/**
|
||||
* 所有设置缓存
|
||||
*/
|
||||
String SETTING_DATA_ALL = "erp.setting.data:%s:*";
|
||||
/**
|
||||
* 商品分类缓存
|
||||
*/
|
||||
String PRODUCT_CATEGORY_DATA = "erp.product.category.data:%s";
|
||||
|
||||
/**
|
||||
* uat测试安全ip
|
||||
*/
|
||||
String UAT_IP = "uat.ip";
|
||||
/**
|
||||
* 所有设置缓存
|
||||
*/
|
||||
String TASK_DATA= "erp.task.data.%s:%s:%s:%s";
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.constant;
|
||||
|
||||
/**
|
||||
* 日期格式常量
|
||||
*/
|
||||
public interface DatePattern {
|
||||
|
||||
/**
|
||||
* 年-月-日
|
||||
*/
|
||||
String YYYY_MM_DD = "yyyy-MM-dd";
|
||||
/**
|
||||
* 年-月-日 时:分
|
||||
*/
|
||||
String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
|
||||
/**
|
||||
* 年-月-日 时:分:秒
|
||||
*/
|
||||
String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
|
||||
/**
|
||||
* 年-月-日 时:分:秒:毫秒
|
||||
*/
|
||||
String YYYY_MM_DD_HH_MM_SS_S = "yyyy-MM-dd HH:mm:ss.S";
|
||||
|
||||
/**
|
||||
* 时:分
|
||||
*/
|
||||
String HH_MM = "HH:mm";
|
||||
/**
|
||||
* 时:分:秒
|
||||
*/
|
||||
String HH_MM_SS = "HH:mm:ss";
|
||||
/**
|
||||
* 时:分:秒:毫秒
|
||||
*/
|
||||
String HH_MM_SS_S = "HH:mm:ss:S";
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
import net.jjjerp.config.constant.CommonConstant;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* JWT属性配置
|
||||
**/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "spring-boot-jjj.jwt")
|
||||
public class JwtProperties {
|
||||
|
||||
/**
|
||||
* token名称,默认名称为:token,可自定义
|
||||
*/
|
||||
private String tokenName = CommonConstant.JWT_DEFAULT_TOKEN_NAME;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String secret = CommonConstant.JWT_DEFAULT_SECRET;
|
||||
|
||||
/**
|
||||
* 签发人
|
||||
*/
|
||||
private String issuer;
|
||||
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
private String subject;
|
||||
|
||||
/**
|
||||
* 签发的目标
|
||||
*/
|
||||
private String audience;
|
||||
|
||||
/**
|
||||
* token失效时间,默认1小时,60*60=3600
|
||||
*/
|
||||
private Long expireSecond = CommonConstant.JWT_DEFAULT_EXPIRE_SECOND;
|
||||
|
||||
/**
|
||||
* 是否刷新token,默认为true
|
||||
*/
|
||||
private boolean refreshToken = true;
|
||||
|
||||
/**
|
||||
* 刷新token倒计时,默认10分钟,10*60=600
|
||||
*/
|
||||
private Integer refreshTokenCountdown;
|
||||
|
||||
/**
|
||||
* redis校验jwt token是否存在
|
||||
*/
|
||||
private boolean redisCheck;
|
||||
|
||||
/**
|
||||
* 单用户登录,一个用户只能又一个有效的token
|
||||
*/
|
||||
private boolean singleLogin;
|
||||
|
||||
/**
|
||||
* 是否进行盐值校验
|
||||
*/
|
||||
private boolean saltCheck;
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Shiro权限配置映射类
|
||||
**/
|
||||
@Data
|
||||
public class ShiroPermissionProperties {
|
||||
|
||||
/**
|
||||
* 路径
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 路径数组
|
||||
*/
|
||||
private String[] urls;
|
||||
|
||||
/**
|
||||
* 权限
|
||||
*/
|
||||
private String permission;
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Shiro配置映射类
|
||||
**/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "spring-boot-jjj.shiro")
|
||||
public class ShiroProperties {
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private boolean enable;
|
||||
|
||||
/**
|
||||
* 路径权限配置
|
||||
*/
|
||||
private String filterChainDefinitions;
|
||||
|
||||
/**
|
||||
* 设置无需权限路径集合
|
||||
*/
|
||||
private List<String[]> anon;
|
||||
|
||||
/**
|
||||
* 权限配置集合
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private List<ShiroPermissionProperties> permission;
|
||||
|
||||
}
|
||||
@ -0,0 +1,162 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* AOP配置属性
|
||||
**/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "spring-boot-jjj.aop")
|
||||
public class SpringBootJjjAopProperties {
|
||||
|
||||
/**
|
||||
* 请求路径Filter配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private LogAopConfig log = new LogAopConfig();
|
||||
|
||||
/**
|
||||
* 操作日志配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private OperationLogConfig operationLog;
|
||||
|
||||
/**
|
||||
* 登录日志配置
|
||||
*/
|
||||
private LoginLogConfig loginLog;
|
||||
|
||||
@Data
|
||||
public static class AopConfig {
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private boolean enable;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public static class LogAopConfig extends AopConfig {
|
||||
|
||||
/**
|
||||
* 是否启用requestId
|
||||
*/
|
||||
private boolean enableRequestId = true;
|
||||
|
||||
/**
|
||||
* 日志输出类型:print-type
|
||||
*/
|
||||
private LogPrintType logPrintType = LogPrintType.ORDER;
|
||||
|
||||
/**
|
||||
* 请求ID生成类型
|
||||
*/
|
||||
private RequestIdType requestIdType = RequestIdType.IDWORK;
|
||||
|
||||
/**
|
||||
* 请求日志在控制台是否格式化输出,local环境建议开启,服务器环境设置为false
|
||||
*/
|
||||
private boolean requestLogFormat = true;
|
||||
|
||||
/**
|
||||
* 响应日志在控制台是否格式化输出,local环境建议开启,服务器环境设置为false
|
||||
*/
|
||||
private boolean responseLogFormat = true;
|
||||
|
||||
/**
|
||||
* 排除路径
|
||||
*/
|
||||
private Set<String> excludePaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作日志配置
|
||||
*/
|
||||
@Data
|
||||
public static class OperationLogConfig {
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private boolean enable = true;
|
||||
|
||||
/**
|
||||
* 排除路径
|
||||
*/
|
||||
private Set<String> excludePaths;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录日志配置
|
||||
*/
|
||||
@Data
|
||||
public static class LoginLogConfig {
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private boolean enable = true;
|
||||
|
||||
/**
|
||||
* 登录路径
|
||||
*/
|
||||
private String loginPath = "/login";
|
||||
|
||||
/**
|
||||
* 登出路径
|
||||
*/
|
||||
private String logoutPath = "/logout";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志打印类型
|
||||
**/
|
||||
public enum LogPrintType {
|
||||
|
||||
/**
|
||||
* 不打印日志
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
* 请求和响应日志,按照执行顺序分开打印
|
||||
*/
|
||||
ORDER,
|
||||
/**
|
||||
* 方法执行结束时,连续分开打印请求和响应日志
|
||||
*/
|
||||
LINE,
|
||||
/**
|
||||
* 方法执行结束时,合并请求和响应日志,同时打印
|
||||
*/
|
||||
MERGE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求ID生成类型
|
||||
**/
|
||||
public enum RequestIdType {
|
||||
/**
|
||||
* 生成UUID无中横线
|
||||
*/
|
||||
UUID,
|
||||
/**
|
||||
* 生成数字
|
||||
*/
|
||||
IDWORK
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 跨域属性配置
|
||||
**/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "spring-boot-jjj.cors")
|
||||
public class SpringBootJjjCorsProperties {
|
||||
|
||||
/**
|
||||
* 是否启用跨域,默认启用
|
||||
*/
|
||||
private boolean enable = true;
|
||||
|
||||
/**
|
||||
* CORS过滤的路径,默认:/**
|
||||
*/
|
||||
private String path = "/**";
|
||||
|
||||
/**
|
||||
* 允许访问的源
|
||||
*/
|
||||
private List<String> allowedOrigins = Collections.singletonList(CorsConfiguration.ALL);
|
||||
|
||||
/**
|
||||
* 允许访问的请求头
|
||||
*/
|
||||
private List<String> allowedHeaders = Collections.singletonList(CorsConfiguration.ALL);
|
||||
|
||||
/**
|
||||
* 是否允许发送cookie
|
||||
*/
|
||||
private boolean allowCredentials = true;
|
||||
|
||||
/**
|
||||
* 允许访问的请求方式
|
||||
*/
|
||||
private List<String> allowedMethods = Collections.singletonList(CorsConfiguration.ALL);
|
||||
|
||||
/**
|
||||
* 允许响应的头
|
||||
*/
|
||||
private List<String> exposedHeaders = Arrays.asList("token");
|
||||
|
||||
/**
|
||||
* 该响应的有效时间默认为30分钟,在有效时间内,浏览器无须为同一请求再次发起预检请求
|
||||
*/
|
||||
private Long maxAge = 1800L;
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Filter配置属性
|
||||
**/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "spring-boot-jjj.filter")
|
||||
public class SpringBootJjjFilterProperties {
|
||||
|
||||
/**
|
||||
* RequestDetail Filter配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private FilterConfig request = new FilterConfig();
|
||||
|
||||
/**
|
||||
* XSS Filter配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private FilterConfig xss = new FilterConfig();
|
||||
|
||||
@Data
|
||||
public static class FilterConfig {
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private boolean enable;
|
||||
|
||||
/**
|
||||
* 过滤的路径
|
||||
*/
|
||||
private String[] urlPatterns;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private int order;
|
||||
|
||||
/**
|
||||
* 是否支持异步
|
||||
*/
|
||||
private boolean async;
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* spring-boot-jjj拦截器配置属性
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "spring-boot-jjj.interceptor")
|
||||
public class SpringBootJjjInterceptorProperties {
|
||||
|
||||
/**
|
||||
* SpringBootAdmin权限拦截器
|
||||
*/
|
||||
private InterceptorConfig springbootadmin = new InterceptorConfig();
|
||||
|
||||
/**
|
||||
* 自定义权限拦截器
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private InterceptorConfig permission = new InterceptorConfig();
|
||||
|
||||
/**
|
||||
* 资源拦截器
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private InterceptorConfig resource = new InterceptorConfig();
|
||||
|
||||
/**
|
||||
* 上传拦截器
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private InterceptorConfig upload = new InterceptorConfig();
|
||||
|
||||
/**
|
||||
* 下载拦截器
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private InterceptorConfig download = new InterceptorConfig();
|
||||
|
||||
@Data
|
||||
public static class InterceptorConfig {
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private boolean enable;
|
||||
|
||||
/**
|
||||
* 包含的路径
|
||||
*/
|
||||
private String[] includePaths = new String[]{};
|
||||
|
||||
/**
|
||||
* 排除路径
|
||||
*/
|
||||
private String[] excludePaths = new String[]{};
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,149 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* spring-boot-jjj属性配置信息
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "spring-boot-jjj")
|
||||
public class SpringBootJjjProperties {
|
||||
/**
|
||||
* 当前版本号
|
||||
*/
|
||||
private String projectVersion;
|
||||
|
||||
/**
|
||||
* 是否启用ansi控制台输出有颜色的字体,local环境建议开启,服务器环境设置为false
|
||||
*/
|
||||
private boolean enableAnsi;
|
||||
|
||||
/**
|
||||
* 项目IP或域名地址
|
||||
*/
|
||||
private String serverIp;
|
||||
|
||||
/**
|
||||
* 是否启用验证码
|
||||
*/
|
||||
private boolean enableVerifyCode;
|
||||
|
||||
/**
|
||||
* 新建登录用户初始化盐值
|
||||
*/
|
||||
private String loginInitSalt;
|
||||
|
||||
/**
|
||||
* 新建登录用户初始化密码
|
||||
*/
|
||||
private String loginInitPassword;
|
||||
|
||||
/**
|
||||
* 新建用户初始化头像
|
||||
*/
|
||||
private String loginInitHead;
|
||||
|
||||
/**
|
||||
* 实现BaseEnum接口的枚举包
|
||||
*/
|
||||
private String[] enumPackages;
|
||||
|
||||
/**
|
||||
* 拦截器配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private SpringBootJjjInterceptorProperties interceptor;
|
||||
|
||||
/**
|
||||
* 过滤器配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private SpringBootJjjFilterProperties filter;
|
||||
|
||||
/**
|
||||
* 上传目录
|
||||
*/
|
||||
private String uploadPath;
|
||||
/**
|
||||
* 资源访问路径,前端访问
|
||||
*/
|
||||
private String resourceAccessPath;
|
||||
/**
|
||||
* 资源访问路径,后段配置,资源映射/拦截器使用
|
||||
*/
|
||||
private String resourceAccessPatterns;
|
||||
/**
|
||||
* 资源访问全路径
|
||||
*/
|
||||
private String resourceAccessUrl;
|
||||
|
||||
/**
|
||||
* 允许上传的文件后缀集合
|
||||
*/
|
||||
private List<String> allowUploadFileExtensions;
|
||||
/**
|
||||
* 允许下载的文件后缀集合
|
||||
*/
|
||||
private List<String> allowDownloadFileExtensions;
|
||||
/**
|
||||
* 租户忽略表
|
||||
*/
|
||||
private List<String> ignoreTables;
|
||||
|
||||
/**
|
||||
* JWT配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private JwtProperties jwt;
|
||||
|
||||
/**
|
||||
* Shiro配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private ShiroProperties shiro = new ShiroProperties();
|
||||
|
||||
/**
|
||||
* 项目静态资源访问配置
|
||||
*
|
||||
* @see SpringBootJjjWebMvcConfig addResourceHandlers
|
||||
*/
|
||||
private String resourceHandlers;
|
||||
|
||||
/**
|
||||
* 跨域配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private SpringBootJjjCorsProperties cors = new SpringBootJjjCorsProperties();
|
||||
|
||||
/**
|
||||
* Swagger路径
|
||||
*/
|
||||
private List<String> swaggerPaths;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 静态资源访问全路径
|
||||
*/
|
||||
//private String staticAccessUrl;
|
||||
|
||||
private static String staticAccessUrl;
|
||||
|
||||
|
||||
public static String getStaticAccessUrl() {
|
||||
return staticAccessUrl;
|
||||
}
|
||||
|
||||
public void setStaticAccessUrl(String staticAccessUrl) {
|
||||
SpringBootJjjProperties.staticAccessUrl = staticAccessUrl;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* 配置文件属性映射为静态属性
|
||||
**/
|
||||
@Slf4j
|
||||
@Data
|
||||
@Component
|
||||
public class SpringBootJjjStaticProperties {
|
||||
|
||||
public static String INFO_PROJECT_VERSION = "";
|
||||
|
||||
@Value("${info.project-version}")
|
||||
private String infoProjectVersion;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
INFO_PROJECT_VERSION = this.infoProjectVersion;
|
||||
log.debug("INFO_PROJECT_VERSION:" + INFO_PROJECT_VERSION);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
|
||||
|
||||
package net.jjjerp.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Swagger配置属性
|
||||
**/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "spring-boot-jjj.swagger")
|
||||
public class SwaggerProperties {
|
||||
|
||||
/**
|
||||
* 是否启用Swagger
|
||||
*/
|
||||
private boolean enable;
|
||||
|
||||
/**
|
||||
* 扫描的基本包
|
||||
*/
|
||||
@Value("${spring-boot-jjj.swagger.base.package}")
|
||||
private String basePackage;
|
||||
|
||||
/**
|
||||
* 联系人邮箱
|
||||
*/
|
||||
@Value("${spring-boot-jjj.swagger.contact.email}")
|
||||
private String contactEmail;
|
||||
|
||||
/**
|
||||
* 联系人名称
|
||||
*/
|
||||
@Value("${spring-boot-jjj.swagger.contact.name}")
|
||||
private String contactName;
|
||||
|
||||
/**
|
||||
* 联系人网址
|
||||
*/
|
||||
@Value("${spring-boot-jjj.swagger.contact.url}")
|
||||
private String contactUrl;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 网址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 自定义参数配置
|
||||
*/
|
||||
@NestedConfigurationProperty
|
||||
private List<ParameterConfig> parameterConfig;
|
||||
|
||||
/**
|
||||
* 自定义参数配置
|
||||
*/
|
||||
@Data
|
||||
public static class ParameterConfig {
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 参数类型
|
||||
* header, cookie, body, query
|
||||
*/
|
||||
private String type = "head";
|
||||
|
||||
/**
|
||||
* 数据类型
|
||||
*/
|
||||
private String dataType = "String";
|
||||
|
||||
/**
|
||||
* 是否必填
|
||||
*/
|
||||
private boolean required;
|
||||
|
||||
/**
|
||||
* 默认值
|
||||
*/
|
||||
private String defaultValue;
|
||||
|
||||
}
|
||||
}
|
||||
28
jjj_erp/config/src/main/resources/config/application-dev.yml
Normal file
@ -0,0 +1,28 @@
|
||||
spring-boot-jjj:
|
||||
# 是否启用ansi控制台输出有颜色的字体,dev环境建议开启,服务器环境设置为false
|
||||
enable-ansi: true
|
||||
# 文件上传下载配置
|
||||
upload-path: D:/product_java/jjj_erp_java/uploads
|
||||
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/jjj_erp_java?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: root
|
||||
|
||||
# Redis配置
|
||||
redis:
|
||||
database: 0
|
||||
host: 127.0.0.1
|
||||
password: 123456
|
||||
port: 6379
|
||||
|
||||
# logback.xml中有详细的日志配置
|
||||
# 打印SQL语句和结果集,本地开发环境可开启,线上注释掉
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
logging:
|
||||
file:
|
||||
path: D:/java/logs/erp
|
||||
@ -0,0 +1,40 @@
|
||||
server:
|
||||
port: 8892
|
||||
|
||||
spring-boot-jjj:
|
||||
# 是否启用ansi控制台输出有颜色的字体,dev环境建议开启,服务器环境设置为false
|
||||
enable-ansi: false
|
||||
# 当前环境服务IP地址/域名
|
||||
server-ip: https://erp.jjjshop.net
|
||||
# 文件上传下载配置
|
||||
upload-path: /www/wwwroot/java/uploads
|
||||
# AOP配置
|
||||
aop:
|
||||
# Aop日志配置
|
||||
log:
|
||||
# NONE:不打印日志
|
||||
# ORDER:请求和响应日志,按照执行顺序分开打印
|
||||
# LINE:方法执行结束时,连续分开打印请求和响应日志
|
||||
# MERGE:方法执行结束时,合并请求和响应日志,同时打印
|
||||
log-print-type: NONE
|
||||
# logback.xml中有详细的日志配置
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/jjj_erp_java?autoReconnect=true&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: cLGfTNk3sBRmRBnw
|
||||
|
||||
# Redis配置
|
||||
redis:
|
||||
database: 0
|
||||
host: localhost
|
||||
password: 123456
|
||||
port: 6379
|
||||
|
||||
# 打印SQL语句和结果集,本地开发环境可开启,线上注释掉
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
logging:
|
||||
file:
|
||||
path: /www/wwwroot/erp.jjjerp.net/logs
|
||||
@ -0,0 +1,42 @@
|
||||
server:
|
||||
port: 8892
|
||||
|
||||
spring-boot-jjj:
|
||||
# 是否启用ansi控制台输出有颜色的字体,dev环境建议开启,服务器环境设置为false
|
||||
enable-ansi: false
|
||||
# 当前环境服务IP地址/域名
|
||||
server-ip: http://150.158.154.41
|
||||
# 文件上传下载配置
|
||||
upload-path: /www/wwwroot/jjj_erp.com/uploads
|
||||
# AOP配置
|
||||
aop:
|
||||
# Aop日志配置
|
||||
log:
|
||||
# NONE:不打印日志
|
||||
# ORDER:请求和响应日志,按照执行顺序分开打印
|
||||
# LINE:方法执行结束时,连续分开打印请求和响应日志
|
||||
# MERGE:方法执行结束时,合并请求和响应日志,同时打印
|
||||
log-print-type: NONE
|
||||
|
||||
# logback.xml中有详细的日志配置
|
||||
logging:
|
||||
path: /www/wwwroot/jjj_erp.com/logs
|
||||
################################ spring config end #################################
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/jjj_erp?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
|
||||
username: jjj_erp
|
||||
password: 2STCfnf2WRSGfRn3
|
||||
|
||||
# Redis配置
|
||||
redis:
|
||||
database: 0
|
||||
host: localhost
|
||||
password: 123456
|
||||
port: 6379
|
||||
|
||||
# 打印SQL语句和结果集,本地开发环境可开启,线上注释掉
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
42
jjj_erp/config/src/main/resources/config/application-uat.yml
Normal file
@ -0,0 +1,42 @@
|
||||
server:
|
||||
port: 8892
|
||||
|
||||
spring-boot-jjj:
|
||||
# 是否启用ansi控制台输出有颜色的字体,dev环境建议开启,服务器环境设置为false
|
||||
enable-ansi: false
|
||||
# 当前环境服务IP地址/域名
|
||||
server-ip: http://demo-erp.jjjerp.net
|
||||
# 文件上传下载配置
|
||||
upload-path: /www/wwwroot/demo-erp.jjjerp.net/uploads
|
||||
# AOP配置
|
||||
aop:
|
||||
# Aop日志配置
|
||||
log:
|
||||
# NONE:不打印日志
|
||||
# ORDER:请求和响应日志,按照执行顺序分开打印
|
||||
# LINE:方法执行结束时,连续分开打印请求和响应日志
|
||||
# MERGE:方法执行结束时,合并请求和响应日志,同时打印
|
||||
log-print-type: NONE
|
||||
|
||||
# logback.xml中有详细的日志配置
|
||||
logging:
|
||||
path: /www/wwwroot/demo-erp.jjjerp.net/logs
|
||||
################################ spring config end #################################
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mysql://127.0.0.1:3306/demo_erp?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
|
||||
username: demo_erp
|
||||
password: znJ5J3j7nzwA45cx
|
||||
|
||||
# Redis配置
|
||||
redis:
|
||||
database: 0
|
||||
host: localhost
|
||||
password: 123456
|
||||
port: 6379
|
||||
|
||||
# 打印SQL语句和结果集,本地开发环境可开启,线上注释掉
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
381
jjj_erp/config/src/main/resources/config/application.yml
Normal file
@ -0,0 +1,381 @@
|
||||
# spring-boot-jjj Common Config
|
||||
|
||||
############################# 访问路径、端口tomcat start #############################
|
||||
server:
|
||||
port: 8892
|
||||
servlet:
|
||||
context-path: /api
|
||||
encoding:
|
||||
charset: UTF-8
|
||||
enabled: true
|
||||
force: true
|
||||
tomcat:
|
||||
threads:
|
||||
max: 1000
|
||||
min-spare: 30
|
||||
uri-encoding: UTF-8
|
||||
############################# 访问路径、端口tomcat end ###############################
|
||||
|
||||
################################ spring config start ###############################
|
||||
spring:
|
||||
application:
|
||||
name: spring-boot-jjj
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
banner:
|
||||
charset: UTF-8
|
||||
location: classpath:config/banner.txt
|
||||
servlet:
|
||||
# 文件上传配置
|
||||
multipart:
|
||||
# 指定上传文件的临时目录
|
||||
location: /opt/upload/tmp
|
||||
# 单个文件最大值
|
||||
max-file-size: 10MB
|
||||
# 单个请求文件总计最大值
|
||||
max-request-size: 100MB
|
||||
mvc:
|
||||
async:
|
||||
request-timeout: 20000
|
||||
|
||||
# 当前项目maven激活环境,例如:dev/test/uat/prod,对应pom.xml中profile设置值
|
||||
---
|
||||
spring:
|
||||
profiles:
|
||||
active: @profileActive@
|
||||
|
||||
# logback.xml中有详细的日志配置
|
||||
logging:
|
||||
config: classpath:config/logback.xml
|
||||
# 方便Spring Boot Admin页面上实时查看日志
|
||||
file:
|
||||
name: logs/${spring.application.name}.log
|
||||
path: ./logs
|
||||
################################ spring config end #################################
|
||||
|
||||
|
||||
############################## spring-boot-jjj start ##############################
|
||||
spring-boot-jjj:
|
||||
# 当前版本号
|
||||
project-version: '@project.version@'
|
||||
# 是否启用ansi控制台输出有颜色的字体
|
||||
enable-ansi: true
|
||||
# 服务器IP地址或域名
|
||||
server-ip: http://127.0.0.1:${server.port}
|
||||
# 是否启用验证码
|
||||
enable-verify-code: false
|
||||
# 实现BaseEnum接口的枚举包
|
||||
enum-packages: net.jjjerp.framework.common.enums
|
||||
# Swagger路径
|
||||
swagger-paths: /swagger-ui.html,/docs,/doc.html,/swagger-resources/**,/webjars/**,/v2/api-docs,/csrf,/v2/api-docs-ext,/null/swagger-resources/**
|
||||
# Filter配置
|
||||
filter:
|
||||
request:
|
||||
enable: true
|
||||
url-patterns: /*
|
||||
order: 1
|
||||
async: true
|
||||
xss:
|
||||
enable: true
|
||||
url-patterns: /*
|
||||
order: 2
|
||||
async: true
|
||||
|
||||
# 拦截器配置
|
||||
interceptor:
|
||||
permission:
|
||||
enable: false
|
||||
include-paths: /**
|
||||
resource:
|
||||
enable: false
|
||||
include-paths: ${spring-boot-jjj.resource-access-patterns}
|
||||
upload:
|
||||
enable: false
|
||||
include-paths: /uploads/**
|
||||
download:
|
||||
enable: false
|
||||
include-paths: /download/**
|
||||
|
||||
# AOP配置
|
||||
aop:
|
||||
# Aop日志配置
|
||||
log:
|
||||
# 是否启用
|
||||
enable: true
|
||||
# 是否启用requestId
|
||||
enable-request-id: true
|
||||
# requestId生成规则: UUID/IDWORK
|
||||
request-id-type: IDWORK
|
||||
# NONE:不打印日志
|
||||
# ORDER:请求和响应日志,按照执行顺序分开打印
|
||||
# LINE:方法执行结束时,连续分开打印请求和响应日志
|
||||
# MERGE:方法执行结束时,合并请求和响应日志,同时打印
|
||||
log-print-type: ORDER
|
||||
# 请求日志在控制台是否格式化输出,local环境建议开启,服务器环境设置为false
|
||||
request-log-format: true
|
||||
# 响应日志在控制台是否格式化输出,local环境建议开启,服务器环境设置为false
|
||||
response-log-format: true
|
||||
# 排除的路径
|
||||
exclude-paths: /,/csrf
|
||||
# 操作日志配置
|
||||
operation-log:
|
||||
# 是否启用
|
||||
enable: true
|
||||
# 排除的路径
|
||||
exclude-paths:
|
||||
# 登录日志配置
|
||||
login-log:
|
||||
# 是否启用
|
||||
enable: true
|
||||
# 登录地址
|
||||
login-path: /admin/passport/login
|
||||
# 登出地址
|
||||
logout-path: /admin/passport/logout
|
||||
|
||||
# 文件上传下载配置
|
||||
# 上传路径配置
|
||||
upload-path: /opt/resource/uploads/
|
||||
# 资源访问路径
|
||||
resource-access-path: /resource/
|
||||
# 资源访问路径匹配:/resource/**
|
||||
resource-access-patterns: ${spring-boot-jjj.resource-access-path}**
|
||||
# 资源访问全路径前缀:http://127.0.0.1:8888/resource/
|
||||
resource-access-url: ${spring-boot-jjj.server-ip}${server.servlet.context-path}${spring-boot-jjj.resource-access-path}
|
||||
# 静态资源访问目录
|
||||
static-access-url: ${spring-boot-jjj.server-ip}${server.servlet.context-path}/static/
|
||||
# 全局允许上传的类型
|
||||
allow-upload-file-extensions: jpg,png,docx,xlsx,pptx,pdf
|
||||
# 全局允许下载的类型
|
||||
allow-download-file-extensions: jpg,png,docx,xlsx,pptx,pdf
|
||||
# 租户忽略表
|
||||
ignore_tables: jjjerp_region,jjjerp_message,jjjerp_message_field,jjjerp_material_property
|
||||
|
||||
############################ CORS start ############################
|
||||
# CORS跨域配置,默认允许跨域
|
||||
cors:
|
||||
# 是否启用跨域,默认启用
|
||||
enable: true
|
||||
# CORS过滤的路径,默认:/**
|
||||
path: /**
|
||||
# 允许访问的源
|
||||
allowed-origins: '*'
|
||||
# 允许访问的请求头
|
||||
allowed-headers: '*'
|
||||
# 是否允许发送cookie
|
||||
allow-credentials: true
|
||||
# 允许访问的请求方式
|
||||
allowed-methods: OPTION,GET,POST
|
||||
# 允许响应的头
|
||||
exposed-headers: token
|
||||
# 该响应的有效时间默认为30分钟,在有效时间内,浏览器无须为同一请求再次发起预检请求
|
||||
max-age: 1800
|
||||
|
||||
############################ CORS end ##############################
|
||||
|
||||
########################## Resource start ##########################
|
||||
# 静态资源访问配置
|
||||
resource-handlers: |
|
||||
/static/**=classpath:/static/
|
||||
swagger-ui.html=classpath:/META-INF/resources/
|
||||
/webjars/**=classpath:/META-INF/resources/webjars/
|
||||
doc.html=classpath:/META-INF/resources/
|
||||
########################## Resource end ############################
|
||||
|
||||
######################## Spring Shiro start ########################
|
||||
shiro:
|
||||
# 是否启用
|
||||
enable: true
|
||||
# 权限配置
|
||||
anon:
|
||||
# 排除静态资源
|
||||
- /static/**,/templates/**
|
||||
# 排除Swagger
|
||||
- ${spring-boot-jjj.swagger-paths}
|
||||
# 排除actuator
|
||||
- /actuator/**
|
||||
- # 排除首页
|
||||
- /,/index.html
|
||||
# front模块
|
||||
- /front/**
|
||||
# admin模块
|
||||
- /saas/passport/login
|
||||
# shop模块
|
||||
- /admin/index/base,/admin/passport/login
|
||||
# job模块
|
||||
- /job/**
|
||||
# 多行字符串权限配置
|
||||
filter-chain-definitions: |
|
||||
/resource/**=anon
|
||||
/uploads/**=anon
|
||||
/verificationCode/**=anon
|
||||
/enum=anon
|
||||
/getSysUserInfo=anon
|
||||
|
||||
######################## Spring Shiro end ##########################
|
||||
|
||||
############################ JWT start #############################
|
||||
jwt:
|
||||
# token请求头名称
|
||||
token-name: token
|
||||
# jwt密钥
|
||||
secret: 888888
|
||||
# 发行人
|
||||
issuer: ${spring.application.name}
|
||||
# 观众
|
||||
audience: web
|
||||
# 默认过期时间1小时,单位:秒
|
||||
expire-second: 36000
|
||||
# 是否刷新token
|
||||
refresh-token: true
|
||||
# 刷新token的时间间隔,默认10分钟,单位:秒
|
||||
refresh-token-countdown: 600
|
||||
# redis校验jwt token是否存在,可选
|
||||
redis-check: true
|
||||
# true: 同一个账号只能是最后一次登录token有效,false:同一个账号可多次登录
|
||||
single-login: false
|
||||
# 盐值校验,如果不加自定义盐值,则使用secret校验
|
||||
salt-check: true
|
||||
############################ JWT end ###############################
|
||||
|
||||
############################### spring-boot-jjj end ###############################
|
||||
|
||||
|
||||
############################### mybatis-plus start #################################
|
||||
mybatis-plus:
|
||||
# 启动时是否检查MyBatis XML文件是否存在
|
||||
check-config-location: true
|
||||
# 支持统配符 * 或者 ; 分割
|
||||
typeEnumsPackage: net.jjjerp.*.enums
|
||||
# MyBatis原生配置
|
||||
configuration:
|
||||
# 字段名称下划线转驼峰命名
|
||||
map-underscore-to-camel-case: true
|
||||
global-config:
|
||||
db-config:
|
||||
# 全局默认主键类型
|
||||
id-type: auto
|
||||
# 逻辑已删除值(默认为 1)
|
||||
logic-delete-value: 1
|
||||
# 逻辑未删除值(默认为 0)
|
||||
logic-not-delete-value: 0
|
||||
# 表前缀
|
||||
table-prefix: jjjerp_
|
||||
configuration-properties:
|
||||
# 自定义sql中表名带前缀
|
||||
prefix: jjjerp_
|
||||
# mapper xml映射路径
|
||||
mapper-locations: classpath*:mapper/**/*Mapper.xml
|
||||
################################ mybatis-plus end ##################################
|
||||
|
||||
|
||||
############################### HikariCP 数据源配置 start ################################
|
||||
---
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
cachePrepStmts: true
|
||||
prepStmtCacheSize: 300
|
||||
prepStmtCacheSqlLimit: 2048
|
||||
useServerPrepStmts: true
|
||||
useLocalSessionState: true
|
||||
rewriteBatchedStatements: true
|
||||
cacheResultSetMetadata: true
|
||||
cacheServerConfiguration: true
|
||||
elideSetAutoCommits: true
|
||||
maintainTimeStats: false
|
||||
hikari:
|
||||
minimum-idle: 10
|
||||
maximum-pool-size: 20
|
||||
idle-timeout: 10000
|
||||
max-lifetime: 1800000
|
||||
connection-timeout: 30000
|
||||
############################### HikariCP 数据源配置 end ################################
|
||||
|
||||
|
||||
############################### Redis 公共配置 start ###############################
|
||||
---
|
||||
spring:
|
||||
redis:
|
||||
timeout: 10s
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 200
|
||||
max-idle: 8
|
||||
max-wait: 10s
|
||||
min-idle: 2
|
||||
shutdown-timeout: 3s
|
||||
############################### Redis 公共配置 end ##################################
|
||||
|
||||
|
||||
#################################### Swagger start #################################
|
||||
---
|
||||
spring-boot-jjj:
|
||||
swagger:
|
||||
# 是否启用
|
||||
enable: true
|
||||
base:
|
||||
# 扫描的包,多个包使用逗号隔开
|
||||
package: net.jjjerp
|
||||
contact:
|
||||
email: 279517889@qq.com
|
||||
name: jjjerp
|
||||
url: https://www.jjjshop.net
|
||||
description:
|
||||
title: ${spring.application.name} API Documents
|
||||
version: ${project.version}
|
||||
# 自定义参数配置,可配置N个
|
||||
parameter-config:
|
||||
- name: ${spring-boot-jjj.jwt.token-name}
|
||||
description: Token Request Header
|
||||
# header, cookie, body, query
|
||||
type: header
|
||||
data-type: String
|
||||
required: false
|
||||
# 测试接口时,自动填充token的值
|
||||
default-value:
|
||||
|
||||
# knife4j配置
|
||||
knife4j:
|
||||
enable: ${spring-boot-jjj.swagger.enable}
|
||||
basic:
|
||||
enable: false
|
||||
username: admin
|
||||
password: admin
|
||||
|
||||
#################################### Swagger end ###################################
|
||||
|
||||
|
||||
############################## Spring boot admin start ##############################
|
||||
|
||||
# 开启和暴露端点
|
||||
management:
|
||||
endpoint:
|
||||
health:
|
||||
show-details: ALWAYS
|
||||
logfile:
|
||||
#可在线查看日志
|
||||
enabled: true
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: '*'
|
||||
|
||||
# 自定义项目信息,Spring Boot Admin展示使用
|
||||
info:
|
||||
project-groupId: '@project.parent.groupId@'
|
||||
project-name: ${spring.application.name}
|
||||
project-finalName: '@boot.artifact.name@'
|
||||
project-author: jjjerp
|
||||
project-description: ${spring.application.name} project
|
||||
project-sourceEncoding: '@project.build.sourceEncoding@'
|
||||
project-spring-boot-version: '@spring-boot.version@'
|
||||
project-mybatis-plus-version: '@mybatis-plus-boot-starter.version@'
|
||||
project-version: '@project.version@'
|
||||
project-website: 'https://www.jjjshop.net'
|
||||
project-home: ${spring-boot-jjj.server-ip}${server.servlet.context-path}
|
||||
project-swagger: ${spring-boot-jjj.server-ip}${server.servlet.context-path}/swagger-ui.html
|
||||
project-knife4j: ${spring-boot-jjj.server-ip}${server.servlet.context-path}/doc.html
|
||||
############################## Spring boot admin end ###############################
|
||||
|
||||
13
jjj_erp/config/src/main/resources/config/banner.txt
Normal file
@ -0,0 +1,13 @@
|
||||
${AnsiColor.BLUE}
|
||||
_ _ _ _
|
||||
(_) | | | | | |
|
||||
___ _ __ _ __ _ _ __ __ _ ______| |__ ___ ___ | |_ ______ _ __ | |_ _ ___
|
||||
/ __| '_ \| '__| | '_ \ / _` |______| '_ \ / _ \ / _ \| __|______| '_ \| | | | / __|
|
||||
\__ \ |_) | | | | | | | (_| | | |_) | (_) | (_) | |_ | |_) | | |_| \__ \
|
||||
|___/ .__/|_| |_|_| |_|\__, | |_.__/ \___/ \___/ \__| | .__/|_|\__,_|___/
|
||||
| | __/ | | |
|
||||
|_| |___/ |_|
|
||||
|
||||
${AnsiColor.YELLOW} :: Spring Boot :: ${AnsiColor.WHITE}(v${spring-boot.version})
|
||||
${AnsiColor.YELLOW} :: jjj-erp :: ${AnsiColor.WHITE}(v${project.version})
|
||||
https://www.jjjshop.net
|
||||
89
jjj_erp/config/src/main/resources/config/logback.xml
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<property name="CONTEXT_NAME" value="spring-boot-jjj"/>
|
||||
<springProperty name="LOG_PATH" source="logging.path" defaultValue="./logs" />
|
||||
<property name="log.path" value="${LOG_PATH:-.}"/>
|
||||
<property name="MAX_FILE_SIZE" value="10MB"/>
|
||||
<property name="MAX_HISTORY" value="30"/>
|
||||
|
||||
<contextName>${CONTEXT_NAME}</contextName>
|
||||
|
||||
<!-- 彩色日志 -->
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
|
||||
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
|
||||
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
|
||||
|
||||
<!-- 控制台日志样式 -->
|
||||
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%15.15t]){faint} [%X{requestId}] %clr(%-40.40logger{39}){cyan} [%L] %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
<!-- 文件日志样式 -->
|
||||
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} [%t] [%X{requestId}] %-40.40logger{39} %L : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
|
||||
<!-- 禁用logback自身日志输出 -->
|
||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
|
||||
|
||||
<!-- 控制台 -->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 运行日志文件 -->
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
<file>${log.path}/spring-boot-jjj.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${log.path}/spring-boot-jjj-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
|
||||
<maxHistory>${MAX_HISTORY}</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- 错误日志文件 -->
|
||||
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
<file>${log.path}/spring-boot-jjj-error.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${log.path}/spring-boot-jjj-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
|
||||
<maxHistory>${MAX_HISTORY}</maxHistory>
|
||||
</rollingPolicy>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 异步写日志 -->
|
||||
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<discardingThreshold>0</discardingThreshold>
|
||||
<queueSize>1024</queueSize>
|
||||
<appender-ref ref ="FILE"/>
|
||||
</appender>
|
||||
<appender name="ASYNC_ERROR_FILE" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<discardingThreshold>0</discardingThreshold>
|
||||
<queueSize>1024</queueSize>
|
||||
<appender-ref ref ="ERROR_FILE"/>
|
||||
</appender>
|
||||
|
||||
<!-- 不同环境的日志级别配置 -->
|
||||
<springProfile name="dev">
|
||||
<logger name="net.jjjerp" level="DEBUG"/>
|
||||
</springProfile>
|
||||
|
||||
<!-- 解决SpringBootAdmin错误日志问题 -->
|
||||
<logger name="org.apache.catalina.connector.CoyoteAdapter" level="OFF"/>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="ASYNC_FILE" />
|
||||
<appender-ref ref="ASYNC_ERROR_FILE" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@ -0,0 +1,4 @@
|
||||
#
|
||||
# 扩展mime-type
|
||||
# 参考:https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?revision=1752884&view=co
|
||||
md=text/markdown
|
||||
10
jjj_erp/config/src/main/resources/static/404.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>404</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Not Found</h1>
|
||||
</body>
|
||||
</html>
|
||||
10
jjj_erp/config/src/main/resources/static/500.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>500</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>500</h1>
|
||||
</body>
|
||||
</html>
|
||||
10
jjj_erp/config/src/main/resources/static/error.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>404</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Error</h1>
|
||||
</body>
|
||||
</html>
|
||||
BIN
jjj_erp/config/src/main/resources/static/express.xlsx
Normal file
BIN
jjj_erp/config/src/main/resources/static/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 9.5 KiB |