init
This commit is contained in:
commit
cf399b316e
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
||||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
73
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
73
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="TOP_LEVEL_CLASS_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="INNER_CLASS_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="METHOD_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="FIELD_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="IGNORE_DEPRECATED" value="false" />
|
||||||
|
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
|
||||||
|
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
|
||||||
|
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
|
||||||
|
<option name="myAdditionalJavadocTags" value="description:,author:,date:,date" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="JavadocDeclaration" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="ADDITIONAL_TAGS" value="description:,author:,date:,date" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="MissingJavadoc" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="PACKAGE_SETTINGS">
|
||||||
|
<Options>
|
||||||
|
<option name="ENABLED" value="false" />
|
||||||
|
</Options>
|
||||||
|
</option>
|
||||||
|
<option name="MODULE_SETTINGS">
|
||||||
|
<Options>
|
||||||
|
<option name="ENABLED" value="false" />
|
||||||
|
</Options>
|
||||||
|
</option>
|
||||||
|
<option name="TOP_LEVEL_CLASS_SETTINGS">
|
||||||
|
<Options>
|
||||||
|
<option name="ENABLED" value="false" />
|
||||||
|
</Options>
|
||||||
|
</option>
|
||||||
|
<option name="INNER_CLASS_SETTINGS">
|
||||||
|
<Options>
|
||||||
|
<option name="ENABLED" value="false" />
|
||||||
|
</Options>
|
||||||
|
</option>
|
||||||
|
<option name="METHOD_SETTINGS">
|
||||||
|
<Options>
|
||||||
|
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
|
||||||
|
<option name="ENABLED" value="false" />
|
||||||
|
</Options>
|
||||||
|
</option>
|
||||||
|
<option name="FIELD_SETTINGS">
|
||||||
|
<Options>
|
||||||
|
<option name="ENABLED" value="false" />
|
||||||
|
</Options>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="SerializableHasSerialVersionUIDField" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
20
.idea/misc.xml
generated
Normal file
20
.idea/misc.xml
generated
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ComposerSettings">
|
||||||
|
<execution />
|
||||||
|
</component>
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="JavaScriptSettings">
|
||||||
|
<option name="languageLevel" value="ES6" />
|
||||||
|
</component>
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="zulu-11" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
124
.idea/uiDesigner.xml
generated
Normal file
124
.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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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.svg" 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>
|
||||||
130
pom.xml
Normal file
130
pom.xml
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.baogutang.demo</groupId>
|
||||||
|
<artifactId>baogutang-demo</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.3.2.RELEASE</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>3.5.3.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.9.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
<version>1.9.6</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>32.1.1-jre</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
<excludes>
|
||||||
|
<exclude>templates/fonts/**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>false</filtering>
|
||||||
|
<includes>
|
||||||
|
<include>templates/fonts/**</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.19</version>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package top.baogutang.demo;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 14:48
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootApplication(scanBasePackages = {"top.baogutang.demo.*"})
|
||||||
|
@EnableAsync
|
||||||
|
public class BaoGuTangDemoApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(BaoGuTangDemoApplication.class, args);
|
||||||
|
log.info("==============DEMO服务启动成功!!=================");
|
||||||
|
}
|
||||||
|
}
|
||||||
70
src/main/java/top/baogutang/demo/config/RedisConfig.java
Normal file
70
src/main/java/top/baogutang/demo/config/RedisConfig.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package top.baogutang.demo.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||||
|
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
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.Jackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 10:56
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class RedisConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编写自定义的 redisTemplate
|
||||||
|
* 这是一个比较固定的模板
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
|
||||||
|
// 为了开发方便,直接使用<String, Object>
|
||||||
|
RedisTemplate<String, Object> template = new RedisTemplate();
|
||||||
|
template.setConnectionFactory(redisConnectionFactory);
|
||||||
|
|
||||||
|
// Json 配置序列化
|
||||||
|
// 使用 jackson 解析任意的对象
|
||||||
|
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||||
|
// 使用 objectMapper 进行转义
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||||
|
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
|
||||||
|
objectMapper.registerModule(new JavaTimeModule());
|
||||||
|
objectMapper.setTimeZone(TimeZone.getDefault());
|
||||||
|
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
|
||||||
|
// String 的序列化
|
||||||
|
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||||
|
|
||||||
|
// key 采用 String 的序列化方式
|
||||||
|
template.setKeySerializer(stringRedisSerializer);
|
||||||
|
// Hash 的 key 采用 String 的序列化方式
|
||||||
|
template.setHashKeySerializer(stringRedisSerializer);
|
||||||
|
// value 采用 jackson 的序列化方式
|
||||||
|
template.setValueSerializer(jackson2JsonRedisSerializer);
|
||||||
|
// Hash 的 value 采用 String 的序列化方式
|
||||||
|
template.setHashValueSerializer(jackson2JsonRedisSerializer);
|
||||||
|
// 把所有的配置 set 进 template
|
||||||
|
template.afterPropertiesSet();
|
||||||
|
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
21
src/main/java/top/baogutang/demo/constants/MsgConstant.java
Normal file
21
src/main/java/top/baogutang/demo/constants/MsgConstant.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package top.baogutang.demo.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 13:38
|
||||||
|
*/
|
||||||
|
public class MsgConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消费端策略:异常时再次消费
|
||||||
|
*/
|
||||||
|
public static final String CONSUMER_STRATEGY_RECONSUME = "RECONSUME";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整支持多topic订阅时,兼容旧的项目,未设置handler的topic时,使用默认值
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_TOPIC_NAME = "DEFAULT_TOPIC_NAME";
|
||||||
|
}
|
||||||
36
src/main/java/top/baogutang/demo/constants/RedisKey.java
Normal file
36
src/main/java/top/baogutang/demo/constants/RedisKey.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package top.baogutang.demo.constants;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import top.baogutang.demo.constants.enums.QueueType;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 13:44
|
||||||
|
*/
|
||||||
|
public class RedisKey {
|
||||||
|
|
||||||
|
private RedisKey() {
|
||||||
|
// empty private constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String MODULE = "baogutang-demo";
|
||||||
|
|
||||||
|
private static final String SEPARATOR = ":";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 影像推送key
|
||||||
|
*
|
||||||
|
* @param queueType queueType
|
||||||
|
* @param userId userId
|
||||||
|
* @param messageKey messageKey
|
||||||
|
* @return key
|
||||||
|
*/
|
||||||
|
public static String getImagePushMsgLockKey(QueueType queueType, Long userId, String messageKey) {
|
||||||
|
return Joiner.on(SEPARATOR).join(Arrays.asList(MODULE, queueType.getTopicName(), userId, messageKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package top.baogutang.demo.constants.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 11:42
|
||||||
|
*/
|
||||||
|
public enum QueuePlatform {
|
||||||
|
|
||||||
|
REDIS,
|
||||||
|
|
||||||
|
KAFKA,
|
||||||
|
|
||||||
|
;
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package top.baogutang.demo.constants.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 10:56
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum QueueType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 影像推送
|
||||||
|
*/
|
||||||
|
IMAGE_PUSH("IMAGE_PUSH", "影像推送"),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private final String topicName;
|
||||||
|
|
||||||
|
private final String topicDesc;
|
||||||
|
|
||||||
|
QueueType(String topicName, String topicDesc) {
|
||||||
|
this.topicName = topicName;
|
||||||
|
this.topicDesc = topicDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QueueType[] allTypes() {
|
||||||
|
|
||||||
|
return values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QueueType get(String topicName) {
|
||||||
|
for (QueueType value : values()) {
|
||||||
|
if (value.getTopicName().equals(topicName)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
66
src/main/java/top/baogutang/demo/message/IQueueMsg.java
Normal file
66
src/main/java/top/baogutang/demo/message/IQueueMsg.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package top.baogutang.demo.message;
|
||||||
|
|
||||||
|
import top.baogutang.demo.constants.enums.QueueType;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 10:56
|
||||||
|
*/
|
||||||
|
public interface IQueueMsg<T> extends Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getMsgType
|
||||||
|
*
|
||||||
|
* @return QueueType
|
||||||
|
*/
|
||||||
|
QueueType getMsgType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* body
|
||||||
|
*
|
||||||
|
* @return body
|
||||||
|
*/
|
||||||
|
T getMsgBody();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getMsgBizKey
|
||||||
|
*
|
||||||
|
* @return getMsgBizKey
|
||||||
|
*/
|
||||||
|
String getMsgBizKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getDelayTime
|
||||||
|
*
|
||||||
|
* @return getDelayTime
|
||||||
|
*/
|
||||||
|
long getDelayTime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setDelayTime
|
||||||
|
*
|
||||||
|
* @param delayTime delayTime
|
||||||
|
*/
|
||||||
|
void setDelayTime(long delayTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getTimeUnit
|
||||||
|
*
|
||||||
|
* @return getTimeUnit
|
||||||
|
*/
|
||||||
|
TimeUnit getTimeUnit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setTimeUnit
|
||||||
|
*
|
||||||
|
* @param timeUnit timeUnit
|
||||||
|
*/
|
||||||
|
void setTimeUnit(TimeUnit timeUnit);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package top.baogutang.demo.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 13:48
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ImagePushMessage implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -870177103586251908L;
|
||||||
|
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
// 这个类就是具体的消息类,需要什么字段就加什么字段
|
||||||
|
}
|
||||||
101
src/main/java/top/baogutang/demo/message/QueueMsg.java
Normal file
101
src/main/java/top/baogutang/demo/message/QueueMsg.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package top.baogutang.demo.message;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import top.baogutang.demo.constants.enums.QueueType;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 10:56
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class QueueMsg<T> implements IQueueMsg<T> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 8969365246492490122L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*/
|
||||||
|
private QueueType msgType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息内容
|
||||||
|
*/
|
||||||
|
private T msgBody;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息业务key
|
||||||
|
*/
|
||||||
|
private String msgBizKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延迟时间
|
||||||
|
*/
|
||||||
|
private long delayTime = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延迟时间单位
|
||||||
|
*/
|
||||||
|
private TimeUnit timeUnit = TimeUnit.SECONDS;
|
||||||
|
|
||||||
|
public QueueMsg() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public QueueMsg(QueueType msgType, T msgBody, String msgBizKey) {
|
||||||
|
this.msgType = msgType;
|
||||||
|
this.msgBody = msgBody;
|
||||||
|
this.msgBizKey = msgBizKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public QueueMsg(QueueType msgType, T msgBody) {
|
||||||
|
this.msgType = msgType;
|
||||||
|
this.msgBody = msgBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueueType getMsgType() {
|
||||||
|
return msgType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getMsgBody() {
|
||||||
|
|
||||||
|
return msgBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMsgBizKey() {
|
||||||
|
return msgBizKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDelayTime() {
|
||||||
|
return delayTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDelayTime(long delayTime) {
|
||||||
|
this.delayTime = delayTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeUnit getTimeUnit() {
|
||||||
|
return timeUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTimeUnit(TimeUnit timeUnit) {
|
||||||
|
this.timeUnit = timeUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
36
src/main/java/top/baogutang/demo/message/SendResult.java
Normal file
36
src/main/java/top/baogutang/demo/message/SendResult.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package top.baogutang.demo.message;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 10:56
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class SendResult implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -3562968976733007349L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送结果
|
||||||
|
*/
|
||||||
|
private boolean success;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已发送消息的ID(如果有)
|
||||||
|
*/
|
||||||
|
private String messageId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已发送消息的主题
|
||||||
|
*/
|
||||||
|
private String topic;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package top.baogutang.demo.message.consumer;
|
||||||
|
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 13:41
|
||||||
|
*/
|
||||||
|
public abstract class AbstractQueueMessageConsumer implements IQueueMessageConsumer {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重复消息处理
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @return res
|
||||||
|
*/
|
||||||
|
protected boolean duplicateMsg(String key) {
|
||||||
|
Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, 1, 300, TimeUnit.SECONDS);
|
||||||
|
return Boolean.FALSE.equals(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除lock
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
*/
|
||||||
|
protected void removeLock(String key) {
|
||||||
|
redisTemplate.delete(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package top.baogutang.demo.message.consumer;
|
||||||
|
|
||||||
|
|
||||||
|
import top.baogutang.demo.constants.MsgConstant;
|
||||||
|
import top.baogutang.demo.message.IQueueMsg;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 11:04
|
||||||
|
*/
|
||||||
|
public interface IQueueMessageConsumer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消费消息
|
||||||
|
* @param queueMsg 消息体
|
||||||
|
*/
|
||||||
|
<T> void consume(IQueueMsg<T> queueMsg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getTopicName
|
||||||
|
*
|
||||||
|
* @return topic
|
||||||
|
*/
|
||||||
|
default String getTopicName() {
|
||||||
|
return MsgConstant.DEFAULT_TOPIC_NAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package top.baogutang.demo.message.consumer;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 14:37
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class MessageConsumerFactory implements ApplicationListener<ApplicationReadyEvent> {
|
||||||
|
|
||||||
|
public final Map<String, IQueueMessageConsumer> consumerMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||||
|
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
|
||||||
|
Map<String, IQueueMessageConsumer> beansOfType = applicationContext.getBeansOfType(IQueueMessageConsumer.class);
|
||||||
|
beansOfType.forEach((key, value) -> consumerMap.put(value.getTopicName(), value));
|
||||||
|
log.info(">>>>>>>>>>queue message consumer inject complete<<<<<<<<<<");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQueueMessageConsumer getConsumer(String topicName) {
|
||||||
|
return consumerMap.get(topicName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package top.baogutang.demo.message.consumer;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import top.baogutang.demo.constants.RedisKey;
|
||||||
|
import top.baogutang.demo.constants.enums.QueueType;
|
||||||
|
import top.baogutang.demo.message.IQueueMsg;
|
||||||
|
import top.baogutang.demo.message.ImagePushMessage;
|
||||||
|
import top.baogutang.demo.utils.JacksonUtil;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 13:47
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class RedisImagePushQueueMessageConsumer extends AbstractQueueMessageConsumer {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void consume(IQueueMsg<T> queueMsg) {
|
||||||
|
log.info("RedisImagePushQueueMessageConsumer received message:{}", JacksonUtil.toJson(queueMsg));
|
||||||
|
ImagePushMessage imagePushMessage = (ImagePushMessage) queueMsg.getMsgBody();
|
||||||
|
String lockKey = RedisKey.getImagePushMsgLockKey(queueMsg.getMsgType(), imagePushMessage.getUserId(), queueMsg.getMsgBizKey());
|
||||||
|
if (duplicateMsg(lockKey)) {
|
||||||
|
log.info("RedisImagePushQueueMessageConsumer received duplicate message:{}", lockKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// TODO: process message
|
||||||
|
// ...
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("RedisImagePushQueueMessageConsumer process message:{} error:{}", JacksonUtil.toJson(queueMsg), e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
removeLock(lockKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTopicName() {
|
||||||
|
return QueueType.IMAGE_PUSH.getTopicName();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package top.baogutang.demo.message.producer;
|
||||||
|
|
||||||
|
import top.baogutang.demo.constants.enums.QueuePlatform;
|
||||||
|
import top.baogutang.demo.message.IQueueMsg;
|
||||||
|
import top.baogutang.demo.message.SendResult;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 10:56
|
||||||
|
*/
|
||||||
|
public interface IQueueMessageProducer {
|
||||||
|
|
||||||
|
QueuePlatform getPlatform();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送延迟消息
|
||||||
|
* @param topic 队列
|
||||||
|
* @param queueMsg 消息
|
||||||
|
* @return 发送结果
|
||||||
|
*/
|
||||||
|
<T> SendResult sendDelayMessage(String topic, IQueueMsg<T> queueMsg);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package top.baogutang.demo.message.producer;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import top.baogutang.demo.constants.enums.QueuePlatform;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 14:27
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class MessageProducerFactory implements ApplicationListener<ApplicationReadyEvent> {
|
||||||
|
|
||||||
|
public final Map<QueuePlatform, IQueueMessageProducer> producerMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||||
|
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
|
||||||
|
Map<String, IQueueMessageProducer> beansOfType = applicationContext.getBeansOfType(IQueueMessageProducer.class);
|
||||||
|
beansOfType.forEach((key, value) -> producerMap.put(value.getPlatform(), value));
|
||||||
|
log.info(">>>>>>>>>>queue message producer inject complete<<<<<<<<<<");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQueueMessageProducer getProducer(QueuePlatform platform) {
|
||||||
|
return producerMap.get(platform);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package top.baogutang.demo.message.producer;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import top.baogutang.demo.constants.enums.QueuePlatform;
|
||||||
|
import top.baogutang.demo.message.IQueueMsg;
|
||||||
|
import top.baogutang.demo.message.SendResult;
|
||||||
|
import top.baogutang.demo.utils.JacksonUtil;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 11:43
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class RedisQueueMessageProducer implements IQueueMessageProducer {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueuePlatform getPlatform() {
|
||||||
|
return QueuePlatform.REDIS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> SendResult sendDelayMessage(String topic, IQueueMsg<T> queueMsg) {
|
||||||
|
long delayTime = System.currentTimeMillis() + queueMsg.getTimeUnit().toMillis(queueMsg.getDelayTime());
|
||||||
|
Boolean addResult = null;
|
||||||
|
try {
|
||||||
|
addResult = redisTemplate.opsForZSet().add(topic, queueMsg, delayTime);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(">>>>>>>>>>send delay message error:{} topic:{},message:{}<<<<<<<<<<", e.getMessage(), topic, JacksonUtil.toJson(queueMsg), e);
|
||||||
|
return SendResult.builder()
|
||||||
|
.success(Boolean.FALSE)
|
||||||
|
.topic(topic)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
return SendResult.builder()
|
||||||
|
.success(Boolean.TRUE.equals(addResult))
|
||||||
|
.topic(topic)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package top.baogutang.demo.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 15:00
|
||||||
|
*/
|
||||||
|
public interface IConsumeMessageService {
|
||||||
|
|
||||||
|
<T> void consumeRedisMessage(String messageTopic);
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package top.baogutang.demo.service;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 14:40
|
||||||
|
*/
|
||||||
|
public interface ISendMessageService {
|
||||||
|
|
||||||
|
<T> void sendMessage(T msgBody, Long delayTime, TimeUnit timeUnit, String messageTopic);
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package top.baogutang.demo.service.impl;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import top.baogutang.demo.message.IQueueMsg;
|
||||||
|
import top.baogutang.demo.message.consumer.MessageConsumerFactory;
|
||||||
|
import top.baogutang.demo.service.IConsumeMessageService;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 15:00
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ConsumeMessageServiceImpl implements IConsumeMessageService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MessageConsumerFactory messageConsumerFactory;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> void consumeRedisMessage(String messageTopic) {
|
||||||
|
while (true) {
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
// 拉取到期消息
|
||||||
|
Set<Object> queueMsgSet = redisTemplate.opsForZSet().rangeByScore(messageTopic, 0, currentTime);
|
||||||
|
if (CollectionUtils.isEmpty(queueMsgSet)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
queueMsgSet.forEach(queueMsgObj -> {
|
||||||
|
IQueueMsg<T> queueMsg = (IQueueMsg<T>) queueMsgObj;
|
||||||
|
messageConsumerFactory.getConsumer(queueMsg.getMsgType().getTopicName())
|
||||||
|
.consume(queueMsg);
|
||||||
|
// 删除已处理消息
|
||||||
|
redisTemplate.opsForZSet().remove(messageTopic, queueMsgObj);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
package top.baogutang.demo.service.impl;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import top.baogutang.demo.constants.enums.QueuePlatform;
|
||||||
|
import top.baogutang.demo.constants.enums.QueueType;
|
||||||
|
import top.baogutang.demo.message.IQueueMsg;
|
||||||
|
import top.baogutang.demo.message.QueueMsg;
|
||||||
|
import top.baogutang.demo.message.SendResult;
|
||||||
|
import top.baogutang.demo.message.producer.IQueueMessageProducer;
|
||||||
|
import top.baogutang.demo.message.producer.MessageProducerFactory;
|
||||||
|
import top.baogutang.demo.service.ISendMessageService;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 14:40
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class SendMessageServiceImpl implements ISendMessageService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MessageProducerFactory messageProducerFactory;
|
||||||
|
|
||||||
|
public <T> void sendMessage(T msgBody, Long delayTime, TimeUnit timeUnit,String messageTopic) {
|
||||||
|
// TODO 业务消息key,可自定义
|
||||||
|
String msgKey = UUID.randomUUID().toString();
|
||||||
|
IQueueMsg<T> queueMsg = new QueueMsg<>(QueueType.IMAGE_PUSH, msgBody, msgKey);
|
||||||
|
queueMsg.setDelayTime(delayTime);
|
||||||
|
queueMsg.setTimeUnit(timeUnit);
|
||||||
|
IQueueMessageProducer producer = messageProducerFactory.getProducer(QueuePlatform.REDIS);
|
||||||
|
SendResult sendResult = producer.sendDelayMessage(messageTopic, queueMsg);
|
||||||
|
if (Objects.isNull(sendResult) || !Boolean.TRUE.equals(sendResult.isSuccess())) {
|
||||||
|
// TODO 消息发送不成功,逻辑处理
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
191
src/main/java/top/baogutang/demo/utils/JacksonUtil.java
Normal file
191
src/main/java/top/baogutang/demo/utils/JacksonUtil.java
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
package top.baogutang.demo.utils;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 11:50
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class JacksonUtil {
|
||||||
|
|
||||||
|
private JacksonUtil() {
|
||||||
|
// empty private constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
|
|
||||||
|
static {
|
||||||
|
|
||||||
|
// yyyy-MM-dd HH:mm:ss
|
||||||
|
OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_FORMAT));
|
||||||
|
// JavaTimeModule Java 8
|
||||||
|
OBJECT_MAPPER.registerModule(new JavaTimeModule());
|
||||||
|
//
|
||||||
|
OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||||
|
// ObjectMapper null
|
||||||
|
OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||||
|
// ObjectMapper Bean ()
|
||||||
|
OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||||
|
// ObjectMapper JSON Java
|
||||||
|
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* json
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @return json
|
||||||
|
*/
|
||||||
|
public static String toJson(Object content) {
|
||||||
|
String result = StringUtils.EMPTY;
|
||||||
|
if (Objects.isNull(content)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
result = OBJECT_MAPPER.writeValueAsString(content);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(">>>>>>>>>>parse object to json fail:{}<<<<<<<<<<", e.getMessage());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @param clazz
|
||||||
|
* @param <T>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> T fromJson(String content, Class<T> clazz) {
|
||||||
|
T result = null;
|
||||||
|
if (StringUtils.isBlank(content)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
result = OBJECT_MAPPER.readValue(content, clazz);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(">>>>>>>>>>parse json to object fail:{}<<<<<<<<<<", e.getMessage());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @param type
|
||||||
|
* @param <T>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> T fromJson(String content, TypeReference<T> type) {
|
||||||
|
T result = null;
|
||||||
|
if (StringUtils.isBlank(content)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
result = OBJECT_MAPPER.readValue(content, type);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(">>>>>>>>>>parse json to object fail:{}<<<<<<<<<<", e.getMessage());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jsonList
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @param clazz
|
||||||
|
* @param <T>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> List<T> jsonToList(String content, Class<T> clazz) {
|
||||||
|
List<T> list = new ArrayList<>();
|
||||||
|
if (StringUtils.isBlank(content) || clazz == null) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
list = OBJECT_MAPPER.readValue(content, new TypeReference<List<T>>() {
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(">>>>>>>>>>parse json to list fail:{}<<<<<<<<<<", e.getMessage());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jsonMap
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @param keyType key
|
||||||
|
* @param valueType value
|
||||||
|
* @param <K> Class<K>
|
||||||
|
* @param <V> Class<V>
|
||||||
|
* @return Map
|
||||||
|
*/
|
||||||
|
public static <K, V> Map<K, V> jsonToMap(String content, Class<K> keyType, Class<V> valueType) {
|
||||||
|
Map<K, V> result = new HashMap<>();
|
||||||
|
if (StringUtils.isBlank(content) || Objects.isNull(keyType) || Objects.isNull(valueType)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
result = OBJECT_MAPPER.readValue(content, new TypeReference<>() {
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(">>>>>>>>>>parse json to map fail:{}<<<<<<<<<<", e.getMessage());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> Map<K, V> beanToMap(Object content, Class<K> keyType, Class<V> valueType) {
|
||||||
|
Map<K, V> result = new HashMap<>();
|
||||||
|
if (Objects.isNull(content) || Objects.isNull(keyType) || Objects.isNull(valueType)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
result = OBJECT_MAPPER.convertValue(content, new TypeReference<>() {
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(">>>>>>>>>>parse json to map fail:{}<<<<<<<<<<", e.getMessage());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jsonJsonNode
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @return JsonNode
|
||||||
|
*/
|
||||||
|
public static JsonNode jsonToNode(String content) {
|
||||||
|
JsonNode jsonNode = null;
|
||||||
|
if (StringUtils.isBlank(content)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
jsonNode = OBJECT_MAPPER.readTree(content);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(">>>>>>>>>>parse json to node fail:{}<<<<<<<<<<", e.getMessage());
|
||||||
|
}
|
||||||
|
return jsonNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/main/resources/application.yml
Normal file
36
src/main/resources/application.yml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
server:
|
||||||
|
port: 8106
|
||||||
|
|
||||||
|
spring:
|
||||||
|
profiles:
|
||||||
|
active: ${SPRING_ACTIVE_PROFILE:local}
|
||||||
|
application:
|
||||||
|
name: baogutang-demo
|
||||||
|
datasource:
|
||||||
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
|
url: jdbc:mysql://117.72.78.133:3306/baogutang-music?characterEncoding=UTF-8
|
||||||
|
username: baogutang-music
|
||||||
|
password: xCcFfY3zXh8sC28e
|
||||||
|
hikari:
|
||||||
|
max-lifetime: 60000
|
||||||
|
redis:
|
||||||
|
host: 117.72.78.133
|
||||||
|
port: 6379
|
||||||
|
password: admin@pwdpwd
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
max-file-size: 2048MB
|
||||||
|
max-request-size: 32MB
|
||||||
|
resources:
|
||||||
|
static-locations: classpath:/templates/
|
||||||
|
|
||||||
|
thread:
|
||||||
|
pool:
|
||||||
|
core: 10
|
||||||
|
max: 10
|
||||||
|
alive: 10
|
||||||
|
capacity: 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package top.baogutang.demo.service;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 15:26
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootTest
|
||||||
|
class ConsumerServiceTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IConsumeMessageService consumeMessageService;
|
||||||
|
|
||||||
|
private static final String MESSAGE_TOPIC = "baogutang.demo.message";
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_consume_message() throws InterruptedException {
|
||||||
|
consumeMessageService.consumeRedisMessage(MESSAGE_TOPIC);
|
||||||
|
|
||||||
|
Thread.sleep(10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package top.baogutang.demo.service;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import top.baogutang.demo.message.ImagePushMessage;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
*
|
||||||
|
* @author: N1KO
|
||||||
|
* @date: 2024/12/13 : 15:28
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootTest
|
||||||
|
class SendMessageServiceTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ISendMessageService sendMessageService;
|
||||||
|
|
||||||
|
private static final String MESSAGE_TOPIC = "baogutang.demo.message";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_send_message() {
|
||||||
|
ImagePushMessage imagePushMessage = new ImagePushMessage();
|
||||||
|
imagePushMessage.setUserId(1L);
|
||||||
|
sendMessageService.sendMessage(imagePushMessage, 2L, TimeUnit.SECONDS, MESSAGE_TOPIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user