This commit is contained in:
yovinchen 2023-06-14 20:12:48 +08:00
commit 8c936791c3
169 changed files with 4079 additions and 0 deletions

10
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Zeppelin 忽略的文件
/ZeppelinRemoteNotebooks/

25
.idea/compiler.xml Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="forum" />
<module name="doubao_community_backend-master" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
<module name="doubao" target="1.8" />
</bytecodeTargetLevel>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="doubao" options="-parameters" />
<module name="doubao_community_backend-master" options="-parameters" />
<module name="forum" options="-parameters" />
</option>
</component>
</project>

12
.idea/dataSources.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="@localhost" uuid="3d4f9a7b-fcfe-49a3-b4f2-5d8d850af172">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://localhost:3306/</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

View File

@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="yovinchen">
<words>
<w>doubao</w>
</words>
</dictionary>
</component>

7
.idea/encodings.xml Normal file
View 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>

View File

@ -0,0 +1,204 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaDocConfiguration">
<GENERAL>
<MODE>UPDATE</MODE>
<OVERRIDDEN_METHODS>false</OVERRIDDEN_METHODS>
<SPLITTED_CLASS_NAME>true</SPLITTED_CLASS_NAME>
<LEVELS>
<LEVEL>TYPE</LEVEL>
<LEVEL>METHOD</LEVEL>
<LEVEL>FIELD</LEVEL>
</LEVELS>
<VISIBILITIES>
<VISIBILITY>PUBLIC</VISIBILITY>
<VISIBILITY>DEFAULT</VISIBILITY>
<VISIBILITY>PROTECTED</VISIBILITY>
</VISIBILITIES>
</GENERAL>
<TEMPLATES>
<CLASSES>
<CLASS>
<KEY>^.*(public|protected|private)*.+interface\s+\w+.*</KEY>
<VALUE>/**\n
* The interface ${name}.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;
&lt;#list element.typeParameters as typeParameter&gt;
* @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt;
*/</VALUE>
</CLASS>
<CLASS>
<KEY>^.*(public|protected|private)*.+enum\s+\w+.*</KEY>
<VALUE>/**\n
* The enum ${name}.\n
*/</VALUE>
</CLASS>
<CLASS>
<KEY>^.*(public|protected|private)*.+class\s+\w+.*</KEY>
<VALUE>/**\n
* The type ${name}.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;
&lt;#list element.typeParameters as typeParameter&gt;
* @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt;
*/</VALUE>
</CLASS>
<CLASS>
<KEY>.+</KEY>
<VALUE>/**\n
* The type ${name}.\n
*/</VALUE>
</CLASS>
</CLASSES>
<CONSTRUCTORS>
<CONSTRUCTOR>
<KEY>.+</KEY>
<VALUE>/**\n
* Instantiates a new ${name}.\n
&lt;#if element.parameterList.parameters?has_content&gt;
*\n
&lt;/#if&gt;
&lt;#list element.parameterList.parameters as parameter&gt;
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
&lt;/#list&gt;
&lt;#if element.throwsList.referenceElements?has_content&gt;
*\n
&lt;/#if&gt;
&lt;#list element.throwsList.referenceElements as exception&gt;
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt;
*/</VALUE>
</CONSTRUCTOR>
</CONSTRUCTORS>
<METHODS>
<METHOD>
<KEY>^.*(public|protected|private)*\s*.*(\w(\s*&lt;.+&gt;)*)+\s+get\w+\s*\(.*\).+</KEY>
<VALUE>/**\n
* Gets ${partName}.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;
&lt;#list element.typeParameters as typeParameter&gt;
* @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt;
&lt;#if element.parameterList.parameters?has_content&gt;
*\n
&lt;/#if&gt;
&lt;#list element.parameterList.parameters as parameter&gt;
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
&lt;/#list&gt;
&lt;#if isNotVoid&gt;
*\n
* @return the ${partName}\n
&lt;/#if&gt;
&lt;#if element.throwsList.referenceElements?has_content&gt;
*\n
&lt;/#if&gt;
&lt;#list element.throwsList.referenceElements as exception&gt;
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt;
*/</VALUE>
</METHOD>
<METHOD>
<KEY>^.*(public|protected|private)*\s*.*(void|\w(\s*&lt;.+&gt;)*)+\s+set\w+\s*\(.*\).+</KEY>
<VALUE>/**\n
* Sets ${partName}.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;
&lt;#list element.typeParameters as typeParameter&gt;
* @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt;
&lt;#if element.parameterList.parameters?has_content&gt;
*\n
&lt;/#if&gt;
&lt;#list element.parameterList.parameters as parameter&gt;
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
&lt;/#list&gt;
&lt;#if isNotVoid&gt;
*\n
* @return the ${partName}\n
&lt;/#if&gt;
&lt;#if element.throwsList.referenceElements?has_content&gt;
*\n
&lt;/#if&gt;
&lt;#list element.throwsList.referenceElements as exception&gt;
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt;
*/</VALUE>
</METHOD>
<METHOD>
<KEY>^.*((public\s+static)|(static\s+public))\s+void\s+main\s*\(\s*String\s*(\[\s*\]|\.\.\.)\s+\w+\s*\).+</KEY>
<VALUE>/**\n
* The entry point of application.\n
&lt;#if element.parameterList.parameters?has_content&gt;
*\n
&lt;/#if&gt;
* @param ${element.parameterList.parameters[0].name} the input arguments\n
&lt;#if element.throwsList.referenceElements?has_content&gt;
*\n
&lt;/#if&gt;
&lt;#list element.throwsList.referenceElements as exception&gt;
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt;
*/</VALUE>
</METHOD>
<METHOD>
<KEY>.+</KEY>
<VALUE>/**\n
* ${name}&lt;#if isNotVoid&gt; ${return}&lt;/#if&gt;.\n
&lt;#if element.typeParameters?has_content&gt; * \n
&lt;/#if&gt;
&lt;#list element.typeParameters as typeParameter&gt;
* @param &lt;${typeParameter.name}&gt; the type parameter\n
&lt;/#list&gt;
&lt;#if element.parameterList.parameters?has_content&gt;
*\n
&lt;/#if&gt;
&lt;#list element.parameterList.parameters as parameter&gt;
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
&lt;/#list&gt;
&lt;#if isNotVoid&gt;
*\n
* @return the ${return}\n
&lt;/#if&gt;
&lt;#if element.throwsList.referenceElements?has_content&gt;
*\n
&lt;/#if&gt;
&lt;#list element.throwsList.referenceElements as exception&gt;
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
&lt;/#list&gt;
*/</VALUE>
</METHOD>
</METHODS>
<FIELDS>
<FIELD>
<KEY>^.*(public|protected|private)*.+static.*(\w\s\w)+.+</KEY>
<VALUE>/**\n
* The constant ${element.getName()}.\n
*/</VALUE>
</FIELD>
<FIELD>
<KEY>^.*(public|protected|private)*.*(\w\s\w)+.+</KEY>
<VALUE>/**\n
&lt;#if element.parent.isInterface()&gt;
* The constant ${element.getName()}.\n
&lt;#else&gt;
* The ${name}.\n
&lt;/#if&gt; */</VALUE>
</FIELD>
<FIELD>
<KEY>.+</KEY>
<VALUE>/**\n
&lt;#if element.parent.isEnum()&gt;
*${name} ${typeName}.\n
&lt;#else&gt;
* The ${name}.\n
&lt;/#if&gt;*/</VALUE>
</FIELD>
</FIELDS>
</TEMPLATES>
</component>
</project>

25
.idea/jarRepositories.xml Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<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>
</component>
</project>

6
.idea/jpa-buddy.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JpaBuddyIdeaProjectConfig">
<option name="renamerInitialized" value="true" />
</component>
</project>

24
.idea/misc.xml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FindBugsConfigurable">
<option name="make" value="true" />
<option name="effort" value="default" />
<option name="priority" value="Medium" />
<option name="excludeFilter" value="" />
</component>
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="9" project-jdk-type="JavaSDK" />
<component name="ProjectType">
<option name="id" value="jpab" />
</component>
<component name="SuppressionsComponent">
<option name="suppComments" value="[]" />
</component>
</project>

465
.idea/qaplug_profiles.xml Normal file
View File

@ -0,0 +1,465 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AnalysisProjectProfileManager">
<option name="PROJECT_PROFILE" value="Project Default" />
<option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
<scopes />
<profiles>
<profile profile_name="Project Default" version="1.0" is_locked="false">
<coding_rule class="AM_CREATES_EMPTY_JAR_FILE_ENTRY" level="MAJOR" enabled="true" />
<coding_rule class="AM_CREATES_EMPTY_ZIP_FILE_ENTRY" level="MAJOR" enabled="true" />
<coding_rule class="AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTRACTION" level="CRITICAL" enabled="false" />
<coding_rule class="BAC_BAD_APPLET_CONSTRUCTOR" level="MAJOR" enabled="false" />
<coding_rule class="BC_BAD_CAST_TO_ABSTRACT_COLLECTION" level="MAJOR" enabled="true" />
<coding_rule class="BC_BAD_CAST_TO_CONCRETE_COLLECTION" level="CRITICAL" enabled="true" />
<coding_rule class="BC_EQUALS_METHOD_SHOULD_WORK_FOR_ALL_OBJECTS" level="CRITICAL" enabled="true" />
<coding_rule class="BC_IMPOSSIBLE_CAST" level="BLOCKER" enabled="true" />
<coding_rule class="BC_IMPOSSIBLE_DOWNCAST" level="MAJOR" enabled="false" />
<coding_rule class="BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY" level="MAJOR" enabled="false" />
<coding_rule class="BC_IMPOSSIBLE_INSTANCEOF" level="CRITICAL" enabled="true" />
<coding_rule class="BC_UNCONFIRMED_CAST" level="CRITICAL" enabled="true" />
<coding_rule class="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE" level="CRITICAL" enabled="false" />
<coding_rule class="BC_VACUOUS_INSTANCEOF" level="CRITICAL" enabled="true" />
<coding_rule class="BIT_ADD_OF_SIGNED_BYTE" level="CRITICAL" enabled="true" />
<coding_rule class="BIT_AND" level="CRITICAL" enabled="true" />
<coding_rule class="BIT_AND_ZZ" level="CRITICAL" enabled="true" />
<coding_rule class="BIT_IOR" level="CRITICAL" enabled="true" />
<coding_rule class="BIT_IOR_OF_SIGNED_BYTE" level="CRITICAL" enabled="true" />
<coding_rule class="BIT_SIGNED_CHECK" level="CRITICAL" enabled="true" />
<coding_rule class="BIT_SIGNED_CHECK_HIGH_BIT" level="CRITICAL" enabled="true" />
<coding_rule class="BOA_BADLY_OVERRIDDEN_ADAPTER" level="CRITICAL" enabled="true" />
<coding_rule class="BSHIFT_WRONG_ADD_PRIORITY" level="MAJOR" enabled="false" />
<coding_rule class="BX_BOXING_IMMEDIATELY_UNBOXED" level="MAJOR" enabled="true" />
<coding_rule class="BX_BOXING_IMMEDIATELY_UNBOXED_TO_PERFORM_COERCION" level="MAJOR" enabled="true" />
<coding_rule class="BX_UNBOXED_AND_COERCED_FOR_TERNARY_OPERATOR" level="MAJOR" enabled="true" />
<coding_rule class="BX_UNBOXING_IMMEDIATELY_REBOXED" level="CRITICAL" enabled="false" />
<coding_rule class="CAA_COVARIANT_ARRAY_ELEMENT_STORE" level="MAJOR" enabled="false" />
<coding_rule class="CAA_COVARIANT_ARRAY_FIELD" level="MAJOR" enabled="false" />
<coding_rule class="CAA_COVARIANT_ARRAY_LOCAL" level="MAJOR" enabled="false" />
<coding_rule class="CAA_COVARIANT_ARRAY_RETURN" level="MAJOR" enabled="false" />
<coding_rule class="CD_CIRCULAR_DEPENDENCY" level="MAJOR" enabled="false" />
<coding_rule class="CI_CONFUSED_INHERITANCE" level="MINOR" enabled="true" />
<coding_rule class="CNT_ROUGH_CONSTANT_VALUE" level="MAJOR" enabled="false" />
<coding_rule class="CN_IDIOM" level="MAJOR" enabled="true" />
<coding_rule class="CN_IDIOM_NO_SUPER_CALL" level="MAJOR" enabled="true" />
<coding_rule class="CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE" level="MAJOR" enabled="true" />
<coding_rule class="CO_ABSTRACT_SELF" level="MAJOR" enabled="true" />
<coding_rule class="CO_COMPARETO_INCORRECT_FLOATING" level="MAJOR" enabled="false" />
<coding_rule class="CO_COMPARETO_RESULTS_MIN_VALUE" level="CRITICAL" enabled="false" />
<coding_rule class="CO_SELF_NO_OBJECT" level="MAJOR" enabled="true" />
<coding_rule class="DB_DUPLICATE_BRANCHES" level="CRITICAL" enabled="true" />
<coding_rule class="DB_DUPLICATE_SWITCH_CLAUSES" level="CRITICAL" enabled="true" />
<coding_rule class="DC_DOUBLECHECK" level="MAJOR" enabled="true" />
<coding_rule class="DC_PARTIALLY_CONSTRUCTED" level="MAJOR" enabled="false" />
<coding_rule class="DE_MIGHT_DROP" level="MAJOR" enabled="true" />
<coding_rule class="DE_MIGHT_IGNORE" level="MAJOR" enabled="true" />
<coding_rule class="DLS_DEAD_LOCAL_INCREMENT_IN_RETURN" level="MAJOR" enabled="false" />
<coding_rule class="DLS_DEAD_LOCAL_STORE" level="CRITICAL" enabled="true" />
<coding_rule class="DLS_DEAD_LOCAL_STORE_IN_RETURN" level="CRITICAL" enabled="true" />
<coding_rule class="DLS_DEAD_LOCAL_STORE_OF_NULL" level="CRITICAL" enabled="true" />
<coding_rule class="DLS_DEAD_LOCAL_STORE_SHADOWS_FIELD" level="CRITICAL" enabled="false" />
<coding_rule class="DLS_DEAD_STORE_OF_CLASS_LITERAL" level="CRITICAL" enabled="true" />
<coding_rule class="DLS_OVERWRITTEN_INCREMENT" level="CRITICAL" enabled="true" />
<coding_rule class="DL_SYNCHRONIZATION_ON_BOOLEAN" level="CRITICAL" enabled="true" />
<coding_rule class="DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE" level="CRITICAL" enabled="true" />
<coding_rule class="DL_SYNCHRONIZATION_ON_SHARED_CONSTANT" level="CRITICAL" enabled="true" />
<coding_rule class="DL_SYNCHRONIZATION_ON_UNSHARED_BOXED_PRIMITIVE" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_ANNOTATION_IS_NOT_VISIBLE_TO_REFLECTION" level="MAJOR" enabled="true" />
<coding_rule class="DMI_ARGUMENTS_WRONG_ORDER" level="CRITICAL" enabled="false" />
<coding_rule class="DMI_BAD_MONTH" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_BIGDECIMAL_CONSTRUCTED_FROM_DOUBLE" level="CRITICAL" enabled="false" />
<coding_rule class="DMI_BLOCKING_METHODS_ON_URL" level="BLOCKER" enabled="true" />
<coding_rule class="DMI_CALLING_NEXT_FROM_HASNEXT" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_COLLECTIONS_SHOULD_NOT_CONTAIN_THEMSELVES" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_COLLECTION_OF_URLS" level="BLOCKER" enabled="true" />
<coding_rule class="DMI_CONSTANT_DB_PASSWORD" level="BLOCKER" enabled="true" />
<coding_rule class="DMI_DOH" level="CRITICAL" enabled="false" />
<coding_rule class="DMI_EMPTY_DB_PASSWORD" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_ENTRY_SETS_MAY_REUSE_ENTRY_OBJECTS" level="CRITICAL" enabled="false" />
<coding_rule class="DMI_FUTILE_ATTEMPT_TO_CHANGE_MAXPOOL_SIZE_OF_SCHEDULED_THREAD_POOL_EXECUTOR" level="MINOR" enabled="true" />
<coding_rule class="DMI_HARDCODED_ABSOLUTE_FILENAME" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_INVOKING_HASHCODE_ON_ARRAY" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_INVOKING_TOSTRING_ON_ANONYMOUS_ARRAY" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_INVOKING_TOSTRING_ON_ARRAY" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_LONG_BITS_TO_DOUBLE_INVOKED_ON_INT" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_NONSERIALIZABLE_OBJECT_WRITTEN" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_RANDOM_USED_ONLY_ONCE" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_SCHEDULED_THREAD_POOL_EXECUTOR_WITH_ZERO_CORE_THREADS" level="MINOR" enabled="true" />
<coding_rule class="DMI_THREAD_PASSED_WHERE_RUNNABLE_EXPECTED" level="MAJOR" enabled="true" />
<coding_rule class="DMI_UNSUPPORTED_METHOD" level="MAJOR" enabled="true" />
<coding_rule class="DMI_USELESS_SUBSTRING" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_USING_REMOVEALL_TO_CLEAR_COLLECTION" level="CRITICAL" enabled="true" />
<coding_rule class="DMI_VACUOUS_CALL_TO_EASYMOCK_METHOD" level="MINOR" enabled="true" />
<coding_rule class="DMI_VACUOUS_SELF_COLLECTION_CALL" level="CRITICAL" enabled="true" />
<coding_rule class="DM_BOOLEAN_CTOR" level="MAJOR" enabled="true" />
<coding_rule class="DM_BOXED_PRIMITIVE_FOR_COMPARE" level="MAJOR" enabled="false" />
<coding_rule class="DM_BOXED_PRIMITIVE_FOR_PARSING" level="MAJOR" enabled="false" />
<coding_rule class="DM_BOXED_PRIMITIVE_TOSTRING" level="MAJOR" enabled="true" />
<coding_rule class="DM_CONVERT_CASE" level="INFO" enabled="true" />
<coding_rule class="DM_DEFAULT_ENCODING" level="CRITICAL" enabled="false" />
<coding_rule class="DM_EXIT" level="MAJOR" enabled="true" />
<coding_rule class="DM_FP_NUMBER_CTOR" level="MAJOR" enabled="true" />
<coding_rule class="DM_GC" level="MAJOR" enabled="true" />
<coding_rule class="DM_INVALID_MIN_MAX" level="MAJOR" enabled="false" />
<coding_rule class="DM_MONITOR_WAIT_ON_CONDITION" level="MAJOR" enabled="true" />
<coding_rule class="DM_NEW_FOR_GETCLASS" level="MAJOR" enabled="true" />
<coding_rule class="DM_NEXTINT_VIA_NEXTDOUBLE" level="MAJOR" enabled="true" />
<coding_rule class="DM_NUMBER_CTOR" level="CRITICAL" enabled="true" />
<coding_rule class="DM_RUN_FINALIZERS_ON_EXIT" level="MAJOR" enabled="true" />
<coding_rule class="DM_STRING_CTOR" level="MAJOR" enabled="true" />
<coding_rule class="DM_STRING_TOSTRING" level="INFO" enabled="true" />
<coding_rule class="DM_STRING_VOID_CTOR" level="MAJOR" enabled="true" />
<coding_rule class="DM_USELESS_THREAD" level="MAJOR" enabled="true" />
<coding_rule class="DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED" level="MAJOR" enabled="true" />
<coding_rule class="DP_DO_INSIDE_DO_PRIVILEGED" level="MAJOR" enabled="true" />
<coding_rule class="EC_ARRAY_AND_NONARRAY" level="CRITICAL" enabled="true" />
<coding_rule class="EC_BAD_ARRAY_COMPARE" level="CRITICAL" enabled="true" />
<coding_rule class="EC_INCOMPATIBLE_ARRAY_COMPARE" level="MAJOR" enabled="false" />
<coding_rule class="EC_NULL_ARG" level="CRITICAL" enabled="true" />
<coding_rule class="EC_UNRELATED_CLASS_AND_INTERFACE" level="CRITICAL" enabled="true" />
<coding_rule class="EC_UNRELATED_INTERFACES" level="CRITICAL" enabled="true" />
<coding_rule class="EC_UNRELATED_TYPES" level="CRITICAL" enabled="true" />
<coding_rule class="EC_UNRELATED_TYPES_USING_POINTER_EQUALITY" level="CRITICAL" enabled="true" />
<coding_rule class="EI_EXPOSE_REP" level="MAJOR" enabled="true" />
<coding_rule class="EI_EXPOSE_REP2" level="MAJOR" enabled="true" />
<coding_rule class="EI_EXPOSE_STATIC_REP2" level="MAJOR" enabled="true" />
<coding_rule class="EQ_ABSTRACT_SELF" level="MAJOR" enabled="true" />
<coding_rule class="EQ_ALWAYS_FALSE" level="BLOCKER" enabled="true" />
<coding_rule class="EQ_ALWAYS_TRUE" level="BLOCKER" enabled="true" />
<coding_rule class="EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS" level="MAJOR" enabled="true" />
<coding_rule class="EQ_COMPARETO_USE_OBJECT_EQUALS" level="CRITICAL" enabled="true" />
<coding_rule class="EQ_COMPARING_CLASS_NAMES" level="MAJOR" enabled="true" />
<coding_rule class="EQ_DOESNT_OVERRIDE_EQUALS" level="MAJOR" enabled="false" />
<coding_rule class="EQ_DONT_DEFINE_EQUALS_FOR_ENUM" level="MAJOR" enabled="true" />
<coding_rule class="EQ_GETCLASS_AND_CLASS_CONSTANT" level="CRITICAL" enabled="true" />
<coding_rule class="EQ_OTHER_NO_OBJECT" level="MAJOR" enabled="true" />
<coding_rule class="EQ_OTHER_USE_OBJECT" level="MAJOR" enabled="true" />
<coding_rule class="EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC" level="MAJOR" enabled="true" />
<coding_rule class="EQ_SELF_NO_OBJECT" level="MAJOR" enabled="true" />
<coding_rule class="EQ_SELF_USE_OBJECT" level="MAJOR" enabled="true" />
<coding_rule class="EQ_UNUSUAL" level="MINOR" enabled="true" />
<coding_rule class="ES_COMPARING_PARAMETER_STRING_WITH_EQ" level="MAJOR" enabled="true" />
<coding_rule class="ES_COMPARING_STRINGS_WITH_EQ" level="MAJOR" enabled="true" />
<coding_rule class="ESync_EMPTY_SYNC" level="MAJOR" enabled="true" />
<coding_rule class="FB_MISSING_EXPECTED_WARNING" level="CRITICAL" enabled="false" />
<coding_rule class="FB_UNEXPECTED_WARNING" level="CRITICAL" enabled="false" />
<coding_rule class="FE_FLOATING_POINT_EQUALITY" level="CRITICAL" enabled="true" />
<coding_rule class="FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER" level="CRITICAL" enabled="true" />
<coding_rule class="FI_EMPTY" level="MAJOR" enabled="true" />
<coding_rule class="FI_EXPLICIT_INVOCATION" level="MAJOR" enabled="true" />
<coding_rule class="FI_FINALIZER_NULLS_FIELDS" level="MAJOR" enabled="true" />
<coding_rule class="FI_FINALIZER_ONLY_NULLS_FIELDS" level="MAJOR" enabled="true" />
<coding_rule class="FI_MISSING_SUPER_CALL" level="MAJOR" enabled="true" />
<coding_rule class="FI_NULLIFY_SUPER" level="CRITICAL" enabled="true" />
<coding_rule class="FI_PUBLIC_SHOULD_BE_PROTECTED" level="MAJOR" enabled="true" />
<coding_rule class="FI_USELESS" level="MINOR" enabled="true" />
<coding_rule class="FL_MATH_USING_FLOAT_PRECISION" level="CRITICAL" enabled="true" />
<coding_rule class="GC_UNCHECKED_TYPE_IN_GENERIC_CALL" level="CRITICAL" enabled="true" />
<coding_rule class="GC_UNRELATED_TYPES" level="CRITICAL" enabled="true" />
<coding_rule class="HE_EQUALS_NO_HASHCODE" level="MAJOR" enabled="true" />
<coding_rule class="HE_EQUALS_USE_HASHCODE" level="CRITICAL" enabled="true" />
<coding_rule class="HE_HASHCODE_NO_EQUALS" level="CRITICAL" enabled="true" />
<coding_rule class="HE_HASHCODE_USE_OBJECT_EQUALS" level="CRITICAL" enabled="true" />
<coding_rule class="HE_INHERITS_EQUALS_USE_HASHCODE" level="CRITICAL" enabled="true" />
<coding_rule class="HE_SIGNATURE_DECLARES_HASHING_OF_UNHASHABLE_CLASS" level="CRITICAL" enabled="true" />
<coding_rule class="HE_USE_OF_UNHASHABLE_CLASS" level="CRITICAL" enabled="true" />
<coding_rule class="HRS_REQUEST_PARAMETER_TO_COOKIE" level="MAJOR" enabled="true" />
<coding_rule class="HRS_REQUEST_PARAMETER_TO_HTTP_HEADER" level="MAJOR" enabled="true" />
<coding_rule class="HSC_HUGE_SHARED_STRING_CONSTANT" level="CRITICAL" enabled="true" />
<coding_rule class="IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD" level="MAJOR" enabled="true" />
<coding_rule class="ICAST_BAD_SHIFT_AMOUNT" level="CRITICAL" enabled="true" />
<coding_rule class="ICAST_IDIV_CAST_TO_DOUBLE" level="CRITICAL" enabled="true" />
<coding_rule class="ICAST_INTEGER_MULTIPLY_CAST_TO_LONG" level="CRITICAL" enabled="true" />
<coding_rule class="ICAST_INT_2_LONG_AS_INSTANT" level="CRITICAL" enabled="false" />
<coding_rule class="ICAST_INT_CAST_TO_DOUBLE_PASSED_TO_CEIL" level="CRITICAL" enabled="true" />
<coding_rule class="ICAST_INT_CAST_TO_FLOAT_PASSED_TO_ROUND" level="CRITICAL" enabled="true" />
<coding_rule class="ICAST_QUESTIONABLE_UNSIGNED_RIGHT_SHIFT" level="CRITICAL" enabled="true" />
<coding_rule class="IC_INIT_CIRCULARITY" level="CRITICAL" enabled="true" />
<coding_rule class="IC_SUPERCLASS_USES_SUBCLASS_DURING_INITIALIZATION" level="MAJOR" enabled="true" />
<coding_rule class="IIL_ELEMENTS_GET_LENGTH_IN_LOOP" level="MAJOR" enabled="false" />
<coding_rule class="IIL_PATTERN_COMPILE_IN_LOOP" level="MAJOR" enabled="false" />
<coding_rule class="IIL_PATTERN_COMPILE_IN_LOOP_INDIRECT" level="MAJOR" enabled="false" />
<coding_rule class="IIL_PREPARE_STATEMENT_IN_LOOP" level="MAJOR" enabled="false" />
<coding_rule class="IIO_INEFFICIENT_INDEX_OF" level="MAJOR" enabled="false" />
<coding_rule class="IIO_INEFFICIENT_LAST_INDEX_OF" level="MAJOR" enabled="false" />
<coding_rule class="IJU_ASSERT_METHOD_INVOKED_FROM_RUN_METHOD" level="CRITICAL" enabled="true" />
<coding_rule class="IJU_BAD_SUITE_METHOD" level="CRITICAL" enabled="true" />
<coding_rule class="IJU_NO_TESTS" level="CRITICAL" enabled="true" />
<coding_rule class="IJU_SETUP_NO_SUPER" level="CRITICAL" enabled="true" />
<coding_rule class="IJU_SUITE_NOT_STATIC" level="CRITICAL" enabled="true" />
<coding_rule class="IJU_TEARDOWN_NO_SUPER" level="CRITICAL" enabled="true" />
<coding_rule class="IL_CONTAINER_ADDED_TO_ITSELF" level="CRITICAL" enabled="true" />
<coding_rule class="IL_INFINITE_LOOP" level="CRITICAL" enabled="true" />
<coding_rule class="IL_INFINITE_RECURSIVE_LOOP" level="CRITICAL" enabled="true" />
<coding_rule class="IMA_INEFFICIENT_MEMBER_ACCESS" level="MAJOR" enabled="false" />
<coding_rule class="IMSE_DONT_CATCH_IMSE" level="MAJOR" enabled="true" />
<coding_rule class="IM_AVERAGE_COMPUTATION_COULD_OVERFLOW" level="CRITICAL" enabled="true" />
<coding_rule class="IM_BAD_CHECK_FOR_ODD" level="CRITICAL" enabled="true" />
<coding_rule class="IM_MULTIPLYING_RESULT_OF_IREM" level="CRITICAL" enabled="true" />
<coding_rule class="INT_BAD_COMPARISON_WITH_INT_VALUE" level="CRITICAL" enabled="false" />
<coding_rule class="INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE" level="CRITICAL" enabled="true" />
<coding_rule class="INT_BAD_COMPARISON_WITH_SIGNED_BYTE" level="CRITICAL" enabled="true" />
<coding_rule class="INT_BAD_REM_BY_1" level="CRITICAL" enabled="true" />
<coding_rule class="INT_VACUOUS_BIT_OPERATION" level="CRITICAL" enabled="true" />
<coding_rule class="INT_VACUOUS_COMPARISON" level="CRITICAL" enabled="true" />
<coding_rule class="IO_APPENDING_TO_OBJECT_OUTPUT_STREAM" level="CRITICAL" enabled="true" />
<coding_rule class="IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN" level="CRITICAL" enabled="true" />
<coding_rule class="IS2_INCONSISTENT_SYNC" level="CRITICAL" enabled="true" />
<coding_rule class="ISC_INSTANTIATE_STATIC_CLASS" level="MAJOR" enabled="true" />
<coding_rule class="IS_FIELD_NOT_GUARDED" level="CRITICAL" enabled="true" />
<coding_rule class="ITA_INEFFICIENT_TO_ARRAY" level="CRITICAL" enabled="true" />
<coding_rule class="IT_NO_SUCH_ELEMENT" level="MINOR" enabled="true" />
<coding_rule class="J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION" level="CRITICAL" enabled="true" />
<coding_rule class="JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS" level="MINOR" enabled="true" />
<coding_rule class="JLM_JSR166_LOCK_MONITORENTER" level="CRITICAL" enabled="true" />
<coding_rule class="JLM_JSR166_UTILCONCURRENT_MONITORENTER" level="CRITICAL" enabled="false" />
<coding_rule class="JML_JSR166_CALLING_WAIT_RATHER_THAN_AWAIT" level="CRITICAL" enabled="false" />
<coding_rule class="LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE" level="MAJOR" enabled="false" />
<coding_rule class="LI_LAZY_INIT_STATIC" level="CRITICAL" enabled="true" />
<coding_rule class="LI_LAZY_INIT_UPDATE_STATIC" level="CRITICAL" enabled="true" />
<coding_rule class="ME_ENUM_FIELD_SETTER" level="MAJOR" enabled="false" />
<coding_rule class="ME_MUTABLE_ENUM_FIELD" level="MAJOR" enabled="false" />
<coding_rule class="MF_CLASS_MASKS_FIELD" level="MAJOR" enabled="true" />
<coding_rule class="MF_METHOD_MASKS_FIELD" level="MAJOR" enabled="true" />
<coding_rule class="ML_SYNC_ON_FIELD_TO_GUARD_CHANGING_THAT_FIELD" level="MAJOR" enabled="true" />
<coding_rule class="ML_SYNC_ON_UPDATED_FIELD" level="MAJOR" enabled="true" />
<coding_rule class="MSF_MUTABLE_SERVLET_FIELD" level="MAJOR" enabled="true" />
<coding_rule class="MS_CANNOT_BE_FINAL" level="MAJOR" enabled="true" />
<coding_rule class="MS_EXPOSE_REP" level="CRITICAL" enabled="true" />
<coding_rule class="MS_FINAL_PKGPROTECT" level="MAJOR" enabled="true" />
<coding_rule class="MS_MUTABLE_ARRAY" level="MAJOR" enabled="true" />
<coding_rule class="MS_MUTABLE_COLLECTION" level="MAJOR" enabled="false" />
<coding_rule class="MS_MUTABLE_COLLECTION_PKGPROTECT" level="MAJOR" enabled="false" />
<coding_rule class="MS_MUTABLE_HASHTABLE" level="MAJOR" enabled="true" />
<coding_rule class="MS_OOI_PKGPROTECT" level="MAJOR" enabled="true" />
<coding_rule class="MS_PKGPROTECT" level="MAJOR" enabled="true" />
<coding_rule class="MS_SHOULD_BE_FINAL" level="MAJOR" enabled="true" />
<coding_rule class="MS_SHOULD_BE_REFACTORED_TO_BE_FINAL" level="CRITICAL" enabled="false" />
<coding_rule class="MTIA_SUSPECT_SERVLET_INSTANCE_FIELD" level="CRITICAL" enabled="true" />
<coding_rule class="MTIA_SUSPECT_STRUTS_INSTANCE_FIELD" level="CRITICAL" enabled="true" />
<coding_rule class="MWN_MISMATCHED_NOTIFY" level="CRITICAL" enabled="true" />
<coding_rule class="MWN_MISMATCHED_WAIT" level="CRITICAL" enabled="true" />
<coding_rule class="NM_BAD_EQUAL" level="MAJOR" enabled="false" />
<coding_rule class="NM_CLASS_NAMING_CONVENTION" level="MAJOR" enabled="false" />
<coding_rule class="NM_CLASS_NOT_EXCEPTION" level="MAJOR" enabled="true" />
<coding_rule class="NM_CONFUSING" level="MAJOR" enabled="true" />
<coding_rule class="NM_FIELD_NAMING_CONVENTION" level="MAJOR" enabled="false" />
<coding_rule class="NM_FUTURE_KEYWORD_USED_AS_IDENTIFIER" level="MAJOR" enabled="true" />
<coding_rule class="NM_FUTURE_KEYWORD_USED_AS_MEMBER_IDENTIFIER" level="MAJOR" enabled="true" />
<coding_rule class="NM_LCASE_HASHCODE" level="MAJOR" enabled="false" />
<coding_rule class="NM_LCASE_TOSTRING" level="MAJOR" enabled="false" />
<coding_rule class="NM_METHOD_CONSTRUCTOR_CONFUSION" level="MAJOR" enabled="true" />
<coding_rule class="NM_METHOD_NAMING_CONVENTION" level="MAJOR" enabled="false" />
<coding_rule class="NM_SAME_SIMPLE_NAME_AS_INTERFACE" level="MAJOR" enabled="true" />
<coding_rule class="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS" level="MAJOR" enabled="true" />
<coding_rule class="NM_VERY_CONFUSING" level="MAJOR" enabled="true" />
<coding_rule class="NM_VERY_CONFUSING_INTENTIONAL" level="MAJOR" enabled="true" />
<coding_rule class="NM_WRONG_PACKAGE" level="MAJOR" enabled="true" />
<coding_rule class="NM_WRONG_PACKAGE_INTENTIONAL" level="MAJOR" enabled="true" />
<coding_rule class="NN_NAKED_NOTIFY" level="CRITICAL" enabled="true" />
<coding_rule class="NOISE_FIELD_REFERENCE" level="MAJOR" enabled="false" />
<coding_rule class="NOISE_METHOD_CALL" level="MAJOR" enabled="false" />
<coding_rule class="NOISE_NULL_DEREFERENCE" level="MAJOR" enabled="false" />
<coding_rule class="NOISE_OPERATION" level="MAJOR" enabled="false" />
<coding_rule class="NO_NOTIFY_NOT_NOTIFYALL" level="CRITICAL" enabled="true" />
<coding_rule class="NP_ALWAYS_NULL" level="CRITICAL" enabled="true" />
<coding_rule class="NP_ALWAYS_NULL_EXCEPTION" level="CRITICAL" enabled="true" />
<coding_rule class="NP_ARGUMENT_MIGHT_BE_NULL" level="MAJOR" enabled="true" />
<coding_rule class="NP_BOOLEAN_RETURN_NULL" level="MAJOR" enabled="true" />
<coding_rule class="NP_CLONE_COULD_RETURN_NULL" level="CRITICAL" enabled="true" />
<coding_rule class="NP_CLOSING_NULL" level="MAJOR" enabled="false" />
<coding_rule class="NP_DEREFERENCE_OF_READLINE_VALUE" level="CRITICAL" enabled="true" />
<coding_rule class="NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT" level="CRITICAL" enabled="true" />
<coding_rule class="NP_GUARANTEED_DEREF" level="BLOCKER" enabled="true" />
<coding_rule class="NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH" level="CRITICAL" enabled="true" />
<coding_rule class="NP_IMMEDIATE_DEREFERENCE_OF_READLINE" level="CRITICAL" enabled="true" />
<coding_rule class="NP_LOAD_OF_KNOWN_NULL_VALUE" level="CRITICAL" enabled="true" />
<coding_rule class="NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION" level="MAJOR" enabled="false" />
<coding_rule class="NP_METHOD_RETURN_RELAXING_ANNOTATION" level="MAJOR" enabled="false" />
<coding_rule class="NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" level="CRITICAL" enabled="false" />
<coding_rule class="NP_NONNULL_PARAM_VIOLATION" level="CRITICAL" enabled="true" />
<coding_rule class="NP_NONNULL_RETURN_VIOLATION" level="CRITICAL" enabled="true" />
<coding_rule class="NP_NULL_INSTANCEOF" level="BLOCKER" enabled="true" />
<coding_rule class="NP_NULL_ON_SOME_PATH" level="CRITICAL" enabled="true" />
<coding_rule class="NP_NULL_ON_SOME_PATH_EXCEPTION" level="CRITICAL" enabled="true" />
<coding_rule class="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" level="CRITICAL" enabled="true" />
<coding_rule class="NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE" level="CRITICAL" enabled="true" />
<coding_rule class="NP_NULL_PARAM_DEREF" level="CRITICAL" enabled="true" />
<coding_rule class="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS" level="CRITICAL" enabled="true" />
<coding_rule class="NP_NULL_PARAM_DEREF_NONVIRTUAL" level="CRITICAL" enabled="true" />
<coding_rule class="NP_OPTIONAL_RETURN_NULL" level="MAJOR" enabled="false" />
<coding_rule class="NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE" level="CRITICAL" enabled="true" />
<coding_rule class="NP_STORE_INTO_NONNULL_FIELD" level="CRITICAL" enabled="true" />
<coding_rule class="NP_SYNC_AND_NULL_CHECK_FIELD" level="MAJOR" enabled="true" />
<coding_rule class="NP_TOSTRING_COULD_RETURN_NULL" level="CRITICAL" enabled="true" />
<coding_rule class="NP_UNWRITTEN_FIELD" level="MAJOR" enabled="false" />
<coding_rule class="NP_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD" level="CRITICAL" enabled="false" />
<coding_rule class="NS_DANGEROUS_NON_SHORT_CIRCUIT" level="CRITICAL" enabled="true" />
<coding_rule class="NS_NON_SHORT_CIRCUIT" level="MAJOR" enabled="true" />
<coding_rule class="OBL_UNSATISFIED_OBLIGATION" level="CRITICAL" enabled="false" />
<coding_rule class="OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE" level="CRITICAL" enabled="false" />
<coding_rule class="ODR_OPEN_DATABASE_RESOURCE" level="CRITICAL" enabled="true" />
<coding_rule class="ODR_OPEN_DATABASE_RESOURCE_EXCEPTION_PATH" level="CRITICAL" enabled="true" />
<coding_rule class="OS_OPEN_STREAM" level="CRITICAL" enabled="true" />
<coding_rule class="OS_OPEN_STREAM_EXCEPTION_PATH" level="CRITICAL" enabled="true" />
<coding_rule class="PS_PUBLIC_SEMAPHORES" level="CRITICAL" enabled="true" />
<coding_rule class="PT_ABSOLUTE_PATH_TRAVERSAL" level="CRITICAL" enabled="false" />
<coding_rule class="PT_RELATIVE_PATH_TRAVERSAL" level="CRITICAL" enabled="false" />
<coding_rule class="PZLA_PREFER_ZERO_LENGTH_ARRAYS" level="MAJOR" enabled="true" />
<coding_rule class="PZ_DONT_REUSE_ENTRY_OBJECTS_IN_ITERATORS" level="CRITICAL" enabled="false" />
<coding_rule class="QBA_QUESTIONABLE_BOOLEAN_ASSIGNMENT" level="CRITICAL" enabled="true" />
<coding_rule class="QF_QUESTIONABLE_FOR_LOOP" level="CRITICAL" enabled="true" />
<coding_rule class="RANGE_ARRAY_INDEX" level="MAJOR" enabled="false" />
<coding_rule class="RANGE_ARRAY_LENGTH" level="MAJOR" enabled="false" />
<coding_rule class="RANGE_ARRAY_OFFSET" level="MAJOR" enabled="false" />
<coding_rule class="RANGE_STRING_INDEX" level="MAJOR" enabled="false" />
<coding_rule class="RCN_REDUNDANT_COMPARISON_OF_NULL_AND_NONNULL_VALUE" level="CRITICAL" enabled="true" />
<coding_rule class="RCN_REDUNDANT_COMPARISON_TWO_NULL_VALUES" level="CRITICAL" enabled="true" />
<coding_rule class="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" level="CRITICAL" enabled="true" />
<coding_rule class="RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE" level="CRITICAL" enabled="true" />
<coding_rule class="RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE" level="CRITICAL" enabled="true" />
<coding_rule class="RC_REF_COMPARISON" level="CRITICAL" enabled="true" />
<coding_rule class="RC_REF_COMPARISON_BAD_PRACTICE" level="MAJOR" enabled="false" />
<coding_rule class="RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN" level="MAJOR" enabled="false" />
<coding_rule class="REC_CATCH_EXCEPTION" level="MAJOR" enabled="true" />
<coding_rule class="RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION" level="CRITICAL" enabled="true" />
<coding_rule class="RE_CANT_USE_FILE_SEPARATOR_AS_REGULAR_EXPRESSION" level="CRITICAL" enabled="true" />
<coding_rule class="RE_POSSIBLE_UNINTENDED_PATTERN" level="CRITICAL" enabled="true" />
<coding_rule class="RI_REDUNDANT_INTERFACES" level="MAJOR" enabled="true" />
<coding_rule class="RR_NOT_CHECKED" level="MAJOR" enabled="true" />
<coding_rule class="RS_READOBJECT_SYNC" level="CRITICAL" enabled="true" />
<coding_rule class="RU_INVOKE_RUN" level="MAJOR" enabled="true" />
<coding_rule class="RV_01_TO_INT" level="MAJOR" enabled="true" />
<coding_rule class="RV_ABSOLUTE_VALUE_OF_HASHCODE" level="CRITICAL" enabled="true" />
<coding_rule class="RV_ABSOLUTE_VALUE_OF_RANDOM_INT" level="CRITICAL" enabled="true" />
<coding_rule class="RV_CHECK_COMPARETO_FOR_SPECIFIC_RETURN_VALUE" level="CRITICAL" enabled="false" />
<coding_rule class="RV_CHECK_FOR_POSITIVE_INDEXOF" level="MINOR" enabled="true" />
<coding_rule class="RV_DONT_JUST_NULL_CHECK_READLINE" level="MAJOR" enabled="true" />
<coding_rule class="RV_EXCEPTION_NOT_THROWN" level="CRITICAL" enabled="true" />
<coding_rule class="RV_NEGATING_RESULT_OF_COMPARETO" level="CRITICAL" enabled="false" />
<coding_rule class="RV_REM_OF_HASHCODE" level="CRITICAL" enabled="true" />
<coding_rule class="RV_REM_OF_RANDOM_INT" level="CRITICAL" enabled="true" />
<coding_rule class="RV_RETURN_VALUE_IGNORED" level="MINOR" enabled="true" />
<coding_rule class="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE" level="MAJOR" enabled="true" />
<coding_rule class="RV_RETURN_VALUE_IGNORED_INFERRED" level="CRITICAL" enabled="false" />
<coding_rule class="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT" level="MAJOR" enabled="false" />
<coding_rule class="RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED" level="MAJOR" enabled="false" />
<coding_rule class="RpC_REPEATED_CONDITIONAL_TEST" level="MAJOR" enabled="true" />
<coding_rule class="SA_FIELD_DOUBLE_ASSIGNMENT" level="CRITICAL" enabled="true" />
<coding_rule class="SA_FIELD_SELF_ASSIGNMENT" level="CRITICAL" enabled="true" />
<coding_rule class="SA_FIELD_SELF_COMPARISON" level="CRITICAL" enabled="true" />
<coding_rule class="SA_FIELD_SELF_COMPUTATION" level="CRITICAL" enabled="true" />
<coding_rule class="SA_LOCAL_DOUBLE_ASSIGNMENT" level="CRITICAL" enabled="true" />
<coding_rule class="SA_LOCAL_SELF_ASSIGNMENT" level="CRITICAL" enabled="true" />
<coding_rule class="SA_LOCAL_SELF_ASSIGNMENT_INSTEAD_OF_FIELD" level="CRITICAL" enabled="false" />
<coding_rule class="SA_LOCAL_SELF_COMPARISON" level="CRITICAL" enabled="true" />
<coding_rule class="SA_LOCAL_SELF_COMPUTATION" level="CRITICAL" enabled="true" />
<coding_rule class="SBSC_USE_STRINGBUFFER_CONCATENATION" level="CRITICAL" enabled="true" />
<coding_rule class="SC_START_IN_CTOR" level="CRITICAL" enabled="true" />
<coding_rule class="SE_BAD_FIELD" level="MINOR" enabled="false" />
<coding_rule class="SE_BAD_FIELD_INNER_CLASS" level="MINOR" enabled="true" />
<coding_rule class="SE_BAD_FIELD_STORE" level="CRITICAL" enabled="true" />
<coding_rule class="SE_COMPARATOR_SHOULD_BE_SERIALIZABLE" level="MAJOR" enabled="true" />
<coding_rule class="SE_INNER_CLASS" level="MAJOR" enabled="true" />
<coding_rule class="SE_METHOD_MUST_BE_PRIVATE" level="MAJOR" enabled="true" />
<coding_rule class="SE_NONFINAL_SERIALVERSIONID" level="CRITICAL" enabled="true" />
<coding_rule class="SE_NONLONG_SERIALVERSIONID" level="MAJOR" enabled="true" />
<coding_rule class="SE_NONSTATIC_SERIALVERSIONID" level="MAJOR" enabled="true" />
<coding_rule class="SE_NO_SERIALVERSIONID" level="MAJOR" enabled="true" />
<coding_rule class="SE_NO_SUITABLE_CONSTRUCTOR" level="MAJOR" enabled="true" />
<coding_rule class="SE_NO_SUITABLE_CONSTRUCTOR_FOR_EXTERNALIZATION" level="MAJOR" enabled="true" />
<coding_rule class="SE_PRIVATE_READ_RESOLVE_NOT_INHERITED" level="MAJOR" enabled="true" />
<coding_rule class="SE_READ_RESOLVE_IS_STATIC" level="MAJOR" enabled="true" />
<coding_rule class="SE_READ_RESOLVE_MUST_RETURN_OBJECT" level="MAJOR" enabled="true" />
<coding_rule class="SE_TRANSIENT_FIELD_NOT_RESTORED" level="MAJOR" enabled="true" />
<coding_rule class="SE_TRANSIENT_FIELD_OF_NONSERIALIZABLE_CLASS" level="MAJOR" enabled="true" />
<coding_rule class="SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH" level="MAJOR" enabled="false" />
<coding_rule class="SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH_TO_THROW" level="MAJOR" enabled="false" />
<coding_rule class="SF_SWITCH_FALLTHROUGH" level="MAJOR" enabled="false" />
<coding_rule class="SF_SWITCH_NO_DEFAULT" level="MAJOR" enabled="false" />
<coding_rule class="SIC_INNER_SHOULD_BE_STATIC" level="MAJOR" enabled="true" />
<coding_rule class="SIC_INNER_SHOULD_BE_STATIC_ANON" level="MAJOR" enabled="true" />
<coding_rule class="SIC_INNER_SHOULD_BE_STATIC_NEEDS_THIS" level="MAJOR" enabled="true" />
<coding_rule class="SIC_THREADLOCAL_DEADLY_EMBRACE" level="MAJOR" enabled="false" />
<coding_rule class="SIO_SUPERFLUOUS_INSTANCEOF" level="CRITICAL" enabled="true" />
<coding_rule class="SI_INSTANCE_BEFORE_FINALS_ASSIGNED" level="CRITICAL" enabled="true" />
<coding_rule class="SP_SPIN_ON_FIELD" level="MAJOR" enabled="true" />
<coding_rule class="SQL_BAD_PREPARED_STATEMENT_ACCESS" level="CRITICAL" enabled="true" />
<coding_rule class="SQL_BAD_RESULTSET_ACCESS" level="CRITICAL" enabled="true" />
<coding_rule class="SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE" level="CRITICAL" enabled="true" />
<coding_rule class="SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING" level="CRITICAL" enabled="true" />
<coding_rule class="SR_NOT_CHECKED" level="MAJOR" enabled="true" />
<coding_rule class="SS_SHOULD_BE_STATIC" level="MAJOR" enabled="true" />
<coding_rule class="STCAL_INVOKE_ON_STATIC_CALENDAR_INSTANCE" level="CRITICAL" enabled="true" />
<coding_rule class="STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE" level="CRITICAL" enabled="true" />
<coding_rule class="STCAL_STATIC_CALENDAR_INSTANCE" level="CRITICAL" enabled="true" />
<coding_rule class="STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE" level="CRITICAL" enabled="true" />
<coding_rule class="STI_INTERRUPTED_ON_CURRENTTHREAD" level="CRITICAL" enabled="true" />
<coding_rule class="STI_INTERRUPTED_ON_UNKNOWNTHREAD" level="CRITICAL" enabled="true" />
<coding_rule class="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD" level="CRITICAL" enabled="true" />
<coding_rule class="SWL_SLEEP_WITH_LOCK_HELD" level="CRITICAL" enabled="true" />
<coding_rule class="SW_SWING_METHODS_INVOKED_IN_SWING_THREAD" level="MAJOR" enabled="true" />
<coding_rule class="TLW_TWO_LOCK_WAIT" level="MAJOR" enabled="true" />
<coding_rule class="TQ_ALWAYS_VALUE_USED_WHERE_NEVER_REQUIRED" level="CRITICAL" enabled="true" />
<coding_rule class="TQ_COMPARING_VALUES_WITH_INCOMPATIBLE_TYPE_QUALIFIERS" level="CRITICAL" enabled="false" />
<coding_rule class="TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_ALWAYS_SINK" level="CRITICAL" enabled="true" />
<coding_rule class="TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_NEVER_SINK" level="CRITICAL" enabled="true" />
<coding_rule class="TQ_MAYBE_SOURCE_VALUE_REACHES_ALWAYS_SINK" level="CRITICAL" enabled="true" />
<coding_rule class="TQ_MAYBE_SOURCE_VALUE_REACHES_NEVER_SINK" level="CRITICAL" enabled="true" />
<coding_rule class="TQ_NEVER_VALUE_USED_WHERE_ALWAYS_REQUIRED" level="CRITICAL" enabled="true" />
<coding_rule class="TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED" level="CRITICAL" enabled="false" />
<coding_rule class="UCF_USELESS_CONTROL_FLOW" level="CRITICAL" enabled="true" />
<coding_rule class="UCF_USELESS_CONTROL_FLOW_NEXT_LINE" level="CRITICAL" enabled="true" />
<coding_rule class="UC_USELESS_CONDITION" level="MAJOR" enabled="false" />
<coding_rule class="UC_USELESS_CONDITION_TYPE" level="MAJOR" enabled="false" />
<coding_rule class="UC_USELESS_OBJECT" level="MAJOR" enabled="false" />
<coding_rule class="UC_USELESS_OBJECT_STACK" level="MAJOR" enabled="false" />
<coding_rule class="UC_USELESS_VOID_METHOD" level="MAJOR" enabled="false" />
<coding_rule class="UG_SYNC_SET_UNSYNC_GET" level="MAJOR" enabled="true" />
<coding_rule class="UI_INHERITANCE_UNSAFE_GETRESOURCE" level="MAJOR" enabled="true" />
<coding_rule class="UL_UNRELEASED_LOCK" level="CRITICAL" enabled="true" />
<coding_rule class="UL_UNRELEASED_LOCK_EXCEPTION_PATH" level="CRITICAL" enabled="true" />
<coding_rule class="UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS" level="CRITICAL" enabled="true" />
<coding_rule class="UM_UNNECESSARY_MATH" level="CRITICAL" enabled="true" />
<coding_rule class="UPM_UNCALLED_PRIVATE_METHOD" level="CRITICAL" enabled="true" />
<coding_rule class="URF_UNREAD_FIELD" level="MAJOR" enabled="true" />
<coding_rule class="URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD" level="CRITICAL" enabled="false" />
<coding_rule class="UR_UNINIT_READ" level="MAJOR" enabled="true" />
<coding_rule class="UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR" level="MAJOR" enabled="false" />
<coding_rule class="USM_USELESS_ABSTRACT_METHOD" level="MAJOR" enabled="false" />
<coding_rule class="USM_USELESS_SUBCLASS_METHOD" level="MAJOR" enabled="false" />
<coding_rule class="UUF_UNUSED_FIELD" level="MAJOR" enabled="true" />
<coding_rule class="UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD" level="CRITICAL" enabled="false" />
<coding_rule class="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" level="MAJOR" enabled="false" />
<coding_rule class="UWF_NULL_FIELD" level="CRITICAL" enabled="true" />
<coding_rule class="UWF_UNWRITTEN_FIELD" level="MAJOR" enabled="false" />
<coding_rule class="UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD" level="CRITICAL" enabled="false" />
<coding_rule class="UW_UNCOND_WAIT" level="MAJOR" enabled="true" />
<coding_rule class="VA_FORMAT_STRING_BAD_ARGUMENT" level="CRITICAL" enabled="true" />
<coding_rule class="VA_FORMAT_STRING_BAD_CONVERSION" level="CRITICAL" enabled="true" />
<coding_rule class="VA_FORMAT_STRING_BAD_CONVERSION_FROM_ARRAY" level="MAJOR" enabled="true" />
<coding_rule class="VA_FORMAT_STRING_BAD_CONVERSION_TO_BOOLEAN" level="MAJOR" enabled="true" />
<coding_rule class="VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED" level="MAJOR" enabled="false" />
<coding_rule class="VA_FORMAT_STRING_EXTRA_ARGUMENTS_PASSED" level="MAJOR" enabled="true" />
<coding_rule class="VA_FORMAT_STRING_ILLEGAL" level="CRITICAL" enabled="true" />
<coding_rule class="VA_FORMAT_STRING_MISSING_ARGUMENT" level="CRITICAL" enabled="true" />
<coding_rule class="VA_FORMAT_STRING_NO_PREVIOUS_ARGUMENT" level="CRITICAL" enabled="true" />
<coding_rule class="VA_FORMAT_STRING_USES_NEWLINE" level="CRITICAL" enabled="false" />
<coding_rule class="VA_PRIMITIVE_ARRAY_PASSED_TO_OBJECT_VARARG" level="CRITICAL" enabled="true" />
<coding_rule class="VO_VOLATILE_INCREMENT" level="CRITICAL" enabled="false" />
<coding_rule class="VO_VOLATILE_REFERENCE_TO_ARRAY" level="MAJOR" enabled="true" />
<coding_rule class="VR_UNRESOLVABLE_REFERENCE" level="MAJOR" enabled="false" />
<coding_rule class="WA_AWAIT_NOT_IN_LOOP" level="CRITICAL" enabled="true" />
<coding_rule class="WA_NOT_IN_LOOP" level="CRITICAL" enabled="true" />
<coding_rule class="WL_USING_GETCLASS_RATHER_THAN_CLASS_LITERAL" level="CRITICAL" enabled="true" />
<coding_rule class="WMI_WRONG_MAP_ITERATOR" level="CRITICAL" enabled="true" />
<coding_rule class="WS_WRITEOBJECT_SYNC" level="CRITICAL" enabled="true" />
<coding_rule class="XFB_XML_FACTORY_BYPASS" level="CRITICAL" enabled="true" />
<coding_rule class="XSS_REQUEST_PARAMETER_TO_JSP_WRITER" level="CRITICAL" enabled="true" />
<coding_rule class="XSS_REQUEST_PARAMETER_TO_SEND_ERROR" level="CRITICAL" enabled="true" />
<coding_rule class="XSS_REQUEST_PARAMETER_TO_SERVLET_WRITER" level="CRITICAL" enabled="true" />
</profile>
</profiles>
<list size="0" />
</component>
</project>

6
.idea/sqldialects.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="PROJECT" dialect="MySQL" />
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

133
pom.xml Normal file
View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yovinchen</groupId>
<artifactId>forum</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>doubao</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<mybatis-plus.version>3.4.2</mybatis-plus.version>
<fastjson.version>1.2.75</fastjson.version>
<hutool.version>5.5.7</hutool.version>
<jwt.version>0.9.1</jwt.version>
<emoji-java.version>5.1.1</emoji-java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--jjwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!--emoji-java-->
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>${emoji-java.version}</version>
</dependency>
<!-- lettuce pool 缓存连接池-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--HuTool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--yaml-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--bean validator-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<!--knife4j-整合Swagger-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,31 @@
package com.yovinchen.forum;
import com.yovinchen.forum.jwt.JwtAuthenticationFilter;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
@MapperScan("com.yovinchen.forum.mapper")
@SpringBootApplication
public class DoubaoApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(DoubaoApplication.class);
}
@Bean
public FilterRegistrationBean<JwtAuthenticationFilter> jwtFilter() {
final FilterRegistrationBean<JwtAuthenticationFilter> registrationBean = new FilterRegistrationBean<>();
JwtAuthenticationFilter filter = new JwtAuthenticationFilter();
registrationBean.setFilter(filter);
return registrationBean;
}
public static void main(String[] args) {
SpringApplication.run(DoubaoApplication.class, args);
}
}

View File

@ -0,0 +1,52 @@
package com.yovinchen.forum.common.api;
public enum ApiErrorCode implements IErrorCode {
/**
* 成功
*/
SUCCESS(200, "操作成功"),
/**
* 失败
*/
FAILED(-1, "操作失败"),
/**
* 未登录Token过期
*/
UNAUTHORIZED(401, "暂未登录或token已经过期"),
/**
* 权限不足
*/
FORBIDDEN(403, "权限不足"),
/**
* 参数校验错误
*/
VALIDATE_FAILED(404, "参数检验失败");
private final Integer code;
private final String message;
ApiErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
@Override
public String toString() {
return "ApiErrorCode{" +
"code=" + code +
", message='" + message + '\'' +
'}';
}
}

View File

@ -0,0 +1,152 @@
package com.yovinchen.forum.common.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Optional;
@Data
@NoArgsConstructor
@ApiModel(value = "API 接口返回结果", description = "用于封装 API 接口返回的结果")
public class ApiResult<T> implements Serializable {
private static final long serialVersionUID = -4153430394359594346L;
/**
* 业务状态码
*/
@ApiModelProperty(value = "业务状态码")
private long code;
/**
* 结果集
*/
@ApiModelProperty(value = "结果集")
private T data;
/**
* 接口描述
*/
@ApiModelProperty(value = "接口描述")
private String message;
/**
* 全参
*
* @param code 业务状态码
* @param message 描述
* @param data 结果集
*/
public ApiResult(long code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
public ApiResult(IErrorCode errorCode) {
errorCode = Optional.ofNullable(errorCode).orElse(ApiErrorCode.FAILED);
this.code = errorCode.getCode();
this.message = errorCode.getMessage();
}
/**
* 成功
*
* @param data 结果集
* @return {code:200,message:操作成功,data:自定义}
*/
public static <T> ApiResult<T> success() {
return new ApiResult<T>(ApiErrorCode.SUCCESS.getCode(), ApiErrorCode.SUCCESS.getMessage(), null);
}
/**
* 成功
*
* @param data 结果集
* @return {code:200,message:操作成功,data:自定义}
*/
public static <T> ApiResult<T> success(T data) {
return new ApiResult<T>(ApiErrorCode.SUCCESS.getCode(), ApiErrorCode.SUCCESS.getMessage(), data);
}
/**
* 成功
*
* @param data 结果集
* @param message 自定义提示信息
* @return {code:200,message:自定义,data:自定义}
*/
public static <T> ApiResult<T> success(T data, String message) {
return new ApiResult<T>(ApiErrorCode.SUCCESS.getCode(), message, data);
}
/**
* 失败返回结果
*/
public static <T> ApiResult<T> failed() {
return failed(ApiErrorCode.FAILED);
}
/**
* 失败返回结果
*
* @param message 提示信息
* @return {code:枚举ApiErrorCode取,message:自定义,data:null}
*/
public static <T> ApiResult<T> failed(String message) {
return new ApiResult<T>(ApiErrorCode.FAILED.getCode(), message, null);
}
/**
* 失败
*
* @param errorCode 错误码
* @return {code:封装接口取,message:封装接口取,data:null}
*/
public static <T> ApiResult<T> failed(IErrorCode errorCode) {
return new ApiResult<T>(errorCode.getCode(), errorCode.getMessage(), null);
}
/**
* 失败返回结果
*
* @param errorCode 错误码
* @param message 错误信息
* @return {code:枚举ApiErrorCode取,message:自定义,data:null}
*/
public static <T> ApiResult<T> failed(IErrorCode errorCode, String message) {
return new ApiResult<T>(errorCode.getCode(), message, null);
}
/**
* 参数验证失败返回结果
*/
public static <T> ApiResult<T> validateFailed() {
return failed(ApiErrorCode.VALIDATE_FAILED);
}
/**
* 参数验证失败返回结果
*
* @param message 提示信息
*/
public static <T> ApiResult<T> validateFailed(String message) {
return new ApiResult<T>(ApiErrorCode.VALIDATE_FAILED.getCode(), message, null);
}
/**
* 未登录返回结果
*/
public static <T> ApiResult<T> unauthorized(T data) {
return new ApiResult<T>(ApiErrorCode.UNAUTHORIZED.getCode(), ApiErrorCode.UNAUTHORIZED.getMessage(), data);
}
/**
* 未授权返回结果
*/
public static <T> ApiResult<T> forbidden(T data) {
return new ApiResult<T>(ApiErrorCode.FORBIDDEN.getCode(), ApiErrorCode.FORBIDDEN.getMessage(), data);
}
}

View File

@ -0,0 +1,18 @@
package com.yovinchen.forum.common.api;
public interface IErrorCode {
/**
* 错误编码: -1失败;200成功
*
* @return 错误编码
*/
Integer getCode();
/**
* 错误描述
*
* @return 错误描述
*/
String getMessage();
}

View File

@ -0,0 +1,24 @@
package com.yovinchen.forum.common.exception;
import com.yovinchen.forum.common.api.IErrorCode;
public class ApiAsserts {
/**
* 抛失败异常
*
* @param message 说明
*/
public static void fail(String message) {
throw new ApiException(message);
}
/**
* 抛失败异常
*
* @param errorCode 状态码
*/
public static void fail(IErrorCode errorCode) {
throw new ApiException(errorCode);
}
}

View File

@ -0,0 +1,21 @@
package com.yovinchen.forum.common.exception;
import com.yovinchen.forum.common.api.IErrorCode;
public class ApiException extends RuntimeException {
private IErrorCode errorCode;
public ApiException(IErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
public ApiException(String message) {
super(message);
}
public IErrorCode getErrorCode() {
return errorCode;
}
}

View File

@ -0,0 +1,23 @@
package com.yovinchen.forum.common.exception;//package com.knox.aurora.common.exception;
import com.yovinchen.forum.common.api.ApiResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 捕获自定义异常
*/
@ResponseBody
@ExceptionHandler(value = ApiException.class)
public ApiResult<Map<String, Object>> handle(ApiException e) {
if (e.getErrorCode() != null) {
return ApiResult.failed(e.getErrorCode());
}
return ApiResult.failed(e.getMessage());
}
}

View File

@ -0,0 +1,31 @@
package com.yovinchen.forum.common.mybatisplus;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.yovinchen.forum.mapper")
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,
* 需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
}

View File

@ -0,0 +1,43 @@
package com.yovinchen.forum.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class GlobalWebMvcConfigurer implements WebMvcConfigurer {
/**
* 跨域
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOrigin("*");
//允许跨越发送cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

View File

@ -0,0 +1,49 @@
package com.yovinchen.forum.config;
/**
* ClassName: config
* Package: com.yovinchen.forum.config
*
* @author yovinchen
* @Create 2023/6/14 16:51
*/
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
@EnableKnife4j
public class Knife4jConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.yovinchen.forum.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.description("论坛接口测试文档")
.contact(new Contact("测试", "https://github.com", "123@qq.com"))
.version("v1.0.1")
.title("API测试文档")
.build();
}
}

View File

@ -0,0 +1,4 @@
package com.yovinchen.forum.controller;
public class BaseController {
}

View File

@ -0,0 +1,32 @@
package com.yovinchen.forum.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yovinchen.forum.common.api.ApiResult;
import com.yovinchen.forum.model.entity.BmsBillboard;
import com.yovinchen.forum.service.IBmsBillboardService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "公告牌管理接口")
@RestController
@RequestMapping("/billboard")
public class BmsBillboardController extends BaseController {
@Resource
private IBmsBillboardService bmsBillboardService;
@ApiOperation(value = "展示公告牌", notes = "获取最近一条展示中的公告牌信息")
@GetMapping("/show")
public ApiResult<BmsBillboard> getNotices(){
List<BmsBillboard> list = bmsBillboardService.list(new
LambdaQueryWrapper<BmsBillboard>().eq(BmsBillboard::isShow,true));
return ApiResult.success(list.get(list.size()- 1));
}
}

View File

@ -0,0 +1,44 @@
package com.yovinchen.forum.controller;
import com.yovinchen.forum.common.api.ApiResult;
import com.yovinchen.forum.jwt.JwtUtil;
import com.yovinchen.forum.model.dto.CommentDTO;
import com.yovinchen.forum.model.entity.BmsComment;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.model.vo.CommentVO;
import com.yovinchen.forum.service.IBmsCommentService;
import com.yovinchen.forum.service.IUmsUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "评论管理接口")
@RestController
@RequestMapping("/comment")
public class BmsCommentController extends BaseController {
@Resource
private IBmsCommentService bmsCommentService;
@Resource
private IUmsUserService umsUserService;
@ApiOperation(value = "根据话题ID获取评论列表", notes = "根据话题ID获取评论列表")
@GetMapping("/get_comments")
public ApiResult<List<CommentVO>> getCommentsByTopicID(@ApiParam(value = "话题ID", required = true) @RequestParam(value = "topicid", defaultValue = "1") String topicid) {
List<CommentVO> lstBmsComment = bmsCommentService.getCommentsByTopicID(topicid);
return ApiResult.success(lstBmsComment);
}
@ApiOperation(value = "添加评论", notes = "添加评论")
@PostMapping("/add_comment")
public ApiResult<BmsComment> create(@ApiParam(value = "当前用户名称", required = true) @RequestHeader(value = JwtUtil.USER_NAME) String userName, @ApiParam(value = "评论内容相关信息", required = true) @RequestBody CommentDTO dto) {
UmsUser user = umsUserService.getUserByUsername(userName);
BmsComment comment = bmsCommentService.create(dto, user);
return ApiResult.success(comment);
}
}

View File

@ -0,0 +1,91 @@
package com.yovinchen.forum.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vdurmont.emoji.EmojiParser;
import com.yovinchen.forum.common.api.ApiResult;
import com.yovinchen.forum.jwt.JwtUtil;
import com.yovinchen.forum.model.dto.CreateTopicDTO;
import com.yovinchen.forum.model.entity.BmsPost;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.model.vo.PostVO;
import com.yovinchen.forum.service.IBmsPostService;
import com.yovinchen.forum.service.IUmsUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Api(tags = "帖子管理接口")
@RestController
@RequestMapping("/post")
public class BmsPostController extends BaseController {
@Resource
private IBmsPostService iBmsPostService;
@Resource
private IUmsUserService umsUserService;
@ApiOperation(value = "获取帖子列表", notes = "根据标签类型获取帖子列表")
@GetMapping("/list")
public ApiResult<Page<PostVO>> list(@ApiParam(name = "tab", value = "标签类型", defaultValue = "latest") @RequestParam(value = "tab", defaultValue = "latest") String tab, @ApiParam(name = "pageNo", value = "页码", defaultValue = "1") @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, @ApiParam(name = "pageSize", value = "每页显示数量", defaultValue = "10") @RequestParam(value = "size", defaultValue = "10") Integer pageSize) {
Page<PostVO> list = iBmsPostService.getList(new Page<>(pageNo, pageSize), tab);
return ApiResult.success(list);
}
@ApiOperation(value = "创建帖子", notes = "通过传入参数来创建一个新的帖子")
@RequestMapping(value = "/create", method = RequestMethod.POST)
public ApiResult<BmsPost> create(@RequestHeader(value = JwtUtil.USER_NAME) String userName, @ApiParam(name = "dto", value = "帖子内容", required = true) @RequestBody CreateTopicDTO dto) {
UmsUser user = umsUserService.getUserByUsername(userName);
BmsPost topic = iBmsPostService.create(dto, user);
return ApiResult.success(topic);
}
@ApiOperation(value = "查看帖子详情", notes = "通过ID查看帖子详情")
@GetMapping()
public ApiResult<Map<String, Object>> view(@ApiParam(name = "id", value = "帖子ID", required = true) @RequestParam("id") String id) {
Map<String, Object> map = iBmsPostService.viewTopic(id);
return ApiResult.success(map);
}
@ApiOperation(value = "获取帖子推荐列表", notes = "通过当前帖子 ID 获取相关的推荐帖子列表")
@GetMapping("/recommend")
public ApiResult<List<BmsPost>> getRecommend(@ApiParam(name = "id", value = "当前帖子ID", required = true) @RequestParam("topicId") String id) {
List<BmsPost> topics = iBmsPostService.getRecommend(id);
return ApiResult.success(topics);
}
@ApiOperation(value = "更新帖子信息", notes = "用户可以通过该接口修改自己的帖子信息")
@PostMapping("/update")
public ApiResult<BmsPost> update(@ApiParam(name = "userName", value = "用户名", required = true) @RequestHeader(value = JwtUtil.USER_NAME) String userName, @Valid @RequestBody BmsPost post) {
UmsUser umsUser = umsUserService.getUserByUsername(userName);
Assert.isTrue(umsUser.getId().equals(post.getUserId()), "非本人无权修改");
post.setModifyTime(new Date());
post.setContent(EmojiParser.parseToAliases(post.getContent()));
iBmsPostService.updateById(post);
return ApiResult.success(post);
}
@ApiOperation(value = "删除帖子", notes = "用户可以通过该接口删除自己的帖子")
@DeleteMapping("/delete/{id}")
public ApiResult<String> delete(@ApiParam(name = "userName", value = "用户名", required = true) @RequestHeader(value = JwtUtil.USER_NAME) String userName, @ApiParam(name = "id", value = "帖子ID", required = true) @PathVariable("id") String id) {
UmsUser umsUser = umsUserService.getUserByUsername(userName);
BmsPost byId = iBmsPostService.getById(id);
Assert.notNull(byId, "来晚一步,话题已不存在");
Assert.isTrue(byId.getUserId().equals(umsUser.getId()), "你为什么可以删除别人的话题???");
iBmsPostService.removeById(id);
return ApiResult.success(null, "删除成功");
}
}

View File

@ -0,0 +1,33 @@
package com.yovinchen.forum.controller;
import com.yovinchen.forum.common.api.ApiResult;
import com.yovinchen.forum.model.entity.BmsPromotion;
import com.yovinchen.forum.service.IBmsPromotionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "推广管理接口")
@RestController
@RequestMapping("/promotion")
public class BmsPromotionController extends BaseController {
@Resource
private IBmsPromotionService bmsPromotionService;
@ApiOperation(value = "获取所有推广信息", notes = "获取所有推广信息列表")
@GetMapping("/all")
public ApiResult<List<BmsPromotion>> list() {
List<BmsPromotion> list = bmsPromotionService.list();
return ApiResult.success(list);
}
}

View File

@ -0,0 +1,77 @@
package com.yovinchen.forum.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yovinchen.forum.common.api.ApiResult;
import com.yovinchen.forum.common.exception.ApiAsserts;
import com.yovinchen.forum.jwt.JwtUtil;
import com.yovinchen.forum.model.entity.BmsFollow;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.service.IBmsFollowService;
import com.yovinchen.forum.service.IUmsUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Api(tags = "关注管理接口")
@RestController
@RequestMapping("/relationship")
public class BmsRelationshipController extends BaseController {
@Resource
private IBmsFollowService bmsFollowService;
@Resource
private IUmsUserService umsUserService;
@GetMapping("/subscribe/{userId}")
@ApiOperation(value = "关注用户", notes = "通过传入用户ID让当前用户关注该用户")
public ApiResult<Object> handleFollow(@RequestHeader(value = JwtUtil.USER_NAME) String userName, @PathVariable("userId") @ApiParam(name = "userId", value = "用户ID", required = true, example = "12345") String parentId) {
UmsUser umsUser = umsUserService.getUserByUsername(userName);
if (parentId.equals(umsUser.getId())) {
ApiAsserts.fail("您脸皮太厚了,怎么可以关注自己呢 😮");
}
BmsFollow one = bmsFollowService.getOne(new LambdaQueryWrapper<BmsFollow>().eq(BmsFollow::getParentId, parentId).eq(BmsFollow::getFollowerId, umsUser.getId()));
if (!ObjectUtils.isEmpty(one)) {
ApiAsserts.fail("已关注");
}
BmsFollow follow = new BmsFollow();
follow.setParentId(parentId);
follow.setFollowerId(umsUser.getId());
bmsFollowService.save(follow);
return ApiResult.success(null, "关注成功");
}
@GetMapping("/unsubscribe/{userId}")
@ApiOperation(value = "取消关注用户", notes = "通过传入用户ID让当前用户取消关注该用户")
public ApiResult<Object> handleUnFollow(@RequestHeader(value = JwtUtil.USER_NAME) String userName, @PathVariable("userId") @ApiParam(name = "userId", value = "用户ID", required = true, example = "12345") String parentId) {
UmsUser umsUser = umsUserService.getUserByUsername(userName);
BmsFollow one = bmsFollowService.getOne(new LambdaQueryWrapper<BmsFollow>().eq(BmsFollow::getParentId, parentId).eq(BmsFollow::getFollowerId, umsUser.getId()));
if (ObjectUtils.isEmpty(one)) {
ApiAsserts.fail("未关注!");
}
bmsFollowService.remove(new LambdaQueryWrapper<BmsFollow>().eq(BmsFollow::getParentId, parentId).eq(BmsFollow::getFollowerId, umsUser.getId()));
return ApiResult.success(null, "取关成功");
}
@GetMapping("/validate/{topicUserId}")
@ApiOperation(value = "查询是否关注该用户", notes = "通过传入用户ID查询当前用户是否已经关注该用户返回结果为布尔类型")
public ApiResult<Map<String, Object>> isFollow(@RequestHeader(value = JwtUtil.USER_NAME) String userName, @PathVariable("topicUserId") @ApiParam(name = "topicUserId", value = "用户ID", required = true, example = "12345") String topicUserId) {
UmsUser umsUser = umsUserService.getUserByUsername(userName);
Map<String, Object> map = new HashMap<>(16);
map.put("hasFollow", false);
if (!ObjectUtils.isEmpty(umsUser)) {
BmsFollow one = bmsFollowService.getOne(new LambdaQueryWrapper<BmsFollow>().eq(BmsFollow::getParentId, topicUserId).eq(BmsFollow::getFollowerId, umsUser.getId()));
if (!ObjectUtils.isEmpty(one)) {
map.put("hasFollow", true);
}
}
return ApiResult.success(map);
}
}

View File

@ -0,0 +1,31 @@
package com.yovinchen.forum.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yovinchen.forum.common.api.ApiResult;
import com.yovinchen.forum.model.vo.PostVO;
import com.yovinchen.forum.service.IBmsPostService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "搜索管理接口")
@RestController
@RequestMapping("/search")
public class BmsSearchController extends BaseController {
@Resource
private IBmsPostService postService;
@GetMapping
@ApiOperation(value = "根据关键字搜索帖子列表", notes = "根据指定关键字,分页查询帖子列表")
public ApiResult<Page<PostVO>> searchList(@ApiParam(name = "keyword", value = "搜索关键字", required = true) @RequestParam("keyword") String keyword, @ApiParam(name = "pageNum", value = "页码", defaultValue = "1") @RequestParam("pageNum") Integer pageNum, @ApiParam(name = "pageSize", value = "每页显示条数", defaultValue = "10") @RequestParam("pageSize") Integer pageSize) {
Page<PostVO> results = postService.searchByKey(keyword, new Page<>(pageNum, pageSize));
return ApiResult.success(results);
}
}

View File

@ -0,0 +1,46 @@
package com.yovinchen.forum.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yovinchen.forum.common.api.ApiResult;
import com.yovinchen.forum.model.entity.BmsPost;
import com.yovinchen.forum.model.entity.BmsTag;
import com.yovinchen.forum.service.IBmsTagService;
import io.swagger.annotations.*;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Api(tags = "标签管理接口")
@RestController
@RequestMapping("/tag")
public class BmsTagController extends BaseController {
@Resource
private IBmsTagService bmsTagService;
@ApiOperation(value = "根据标签名获取帖子列表", notes = "通过标签名获取帖子列表")
@ApiImplicitParams({@ApiImplicitParam(name = "name", value = "标签名", required = true, dataType = "String", paramType = "path"), @ApiImplicitParam(name = "page", value = "页码", defaultValue = "1", dataType = "Integer", paramType = "query"), @ApiImplicitParam(name = "size", value = "每页大小", defaultValue = "10", dataType = "Integer", paramType = "query")})
@GetMapping("/{name}")
public ApiResult<Map<String, Object>> getTopicsByTag(@ApiParam(name = "name", value = "标签名", required = true) @PathVariable("name") String tagName, @ApiParam(name = "page", value = "页码", defaultValue = "1") @RequestParam(value = "page", defaultValue = "1") Integer page, @ApiParam(name = "size", value = "每页大小", defaultValue = "10") @RequestParam(value = "size", defaultValue = "10") Integer size) {
Map<String, Object> map = new HashMap<>(16);
LambdaQueryWrapper<BmsTag> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(BmsTag::getName, tagName);
BmsTag one = bmsTagService.getOne(wrapper);
Assert.notNull(one, "话题不存在,或已被管理员删除");
Page<BmsPost> topics = bmsTagService.selectTopicsByTagId(new Page<>(page, size), one.getId());
// 其他热门标签
Page<BmsTag> hotTags = bmsTagService.page(new Page<>(1, 10), new LambdaQueryWrapper<BmsTag>().notIn(BmsTag::getName, tagName).orderByDesc(BmsTag::getTopicCount));
map.put("topics", topics);
map.put("hotTags", hotTags);
return ApiResult.success(map);
}
}

View File

@ -0,0 +1,34 @@
package com.yovinchen.forum.controller;
import com.yovinchen.forum.common.api.ApiResult;
import com.yovinchen.forum.model.entity.BmsTip;
import com.yovinchen.forum.service.IBmsTipService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "每日一言管理接口")
@RestController
@RequestMapping("/tip")
public class BmsTipController extends BaseController {
@Resource
private IBmsTipService bmsTipService;
/**
* 获取一条随机的每日一言
*
* @return 随机获取到的每日一言信息
*/
@ApiOperation(value = "获取一条随机的每日一言", notes = "获取一条随机的每日一言")
@GetMapping("/today")
public ApiResult<BmsTip> getRandomTip() {
BmsTip tip = bmsTipService.getRandomTip();
return ApiResult.success(tip);
}
}

View File

@ -0,0 +1,11 @@
package com.yovinchen.forum.controller;
/**
* ClassName: GiteeLogin
* Package: com.yovinchen.forum.controller
* /oauth/callback
* @author yovinchen
* @Create 2023/6/14 20:11
*/
public class GiteeLogin {
}

View File

@ -0,0 +1,91 @@
package com.yovinchen.forum.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yovinchen.forum.common.api.ApiResult;
import com.yovinchen.forum.jwt.JwtUtil;
import com.yovinchen.forum.model.dto.LoginDTO;
import com.yovinchen.forum.model.dto.RegisterDTO;
import com.yovinchen.forum.model.entity.BmsPost;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.service.IBmsPostService;
import com.yovinchen.forum.service.IUmsUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
@Api(tags = "用户管理接口")
@RestController
@RequestMapping("/ums/user")
public class UmsUserController extends BaseController {
@Resource
private IUmsUserService iUmsUserService;
@Resource
private IBmsPostService iBmsPostService;
@ApiOperation(value = "用户注册", notes = "用户注册接口")
@PostMapping("/register")
public ApiResult<Map<String, Object>> register(@ApiParam(name = "dto", value = "注册信息", required = true) @Valid @RequestBody RegisterDTO dto) {
UmsUser user = iUmsUserService.executeRegister(dto);
if (ObjectUtils.isEmpty(user)) {
return ApiResult.failed("账号注册失败");
}
Map<String, Object> map = new HashMap<>(16);
map.put("user", user);
return ApiResult.success(map);
}
@ApiOperation(value = "用户登陆", notes = "用户登陆接口")
@RequestMapping(value = "/login", method = RequestMethod.POST)
public ApiResult<Map<String, String>> login(@ApiParam(name = "dto", value = "登陆信息", required = true) @Valid @RequestBody LoginDTO dto) {
String token = iUmsUserService.executeLogin(dto);
if (ObjectUtils.isEmpty(token)) {
return ApiResult.failed("账号密码错误");
}
Map<String, String> map = new HashMap<>(16);
map.put("token", token);
return ApiResult.success(map, "登录成功");
}
@ApiOperation(value = "获取当前用户登陆信息", notes = "获取当前用户登陆信息接口")
@RequestMapping(value = "/info", method = RequestMethod.GET)
public ApiResult<UmsUser> getUser(@ApiParam(name = "userName", value = "用户名", required = true) @RequestHeader(value = JwtUtil.USER_NAME) String userName) {
UmsUser user = iUmsUserService.getUserByUsername(userName);
return ApiResult.success(user);
}
@ApiOperation(value = "登出", notes = "用户登出接口")
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public ApiResult<Object> logOut() {
return ApiResult.success(null, "注销成功");
}
@ApiOperation(value = "根据用户名获取该用户发布的帖子列表", notes = "通过用户名获取帖子列表")
@GetMapping("/{username}")
public ApiResult<Map<String, Object>> getUserByName(@ApiParam(name = "username", value = "用户名", required = true) @PathVariable("username") String username, @ApiParam(name = "pageNo", value = "页码", defaultValue = "1") @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, @ApiParam(name = "size", value = "每页大小", defaultValue = "10") @RequestParam(value = "size", defaultValue = "10") Integer size) {
Map<String, Object> map = new HashMap<>(16);
UmsUser user = iUmsUserService.getUserByUsername(username);
Assert.notNull(user, "用户不存在");
Page<BmsPost> page = iBmsPostService.page(new Page<>(pageNo, size), new LambdaQueryWrapper<BmsPost>().eq(BmsPost::getUserId, user.getId()));
map.put("user", user);
map.put("topics", page);
return ApiResult.success(map);
}
@ApiOperation(value = "修改用户信息", notes = "修改用户信息接口")
@PostMapping("/update")
public ApiResult<UmsUser> updateUser(@ApiParam(name = "umsUser", value = "用户信息", required = true) @RequestBody UmsUser umsUser) {
iUmsUserService.updateById(umsUser);
return ApiResult.success(umsUser);
}
}

View File

@ -0,0 +1,57 @@
package com.yovinchen.forum.jwt;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private static final PathMatcher pathMatcher = new AntPathMatcher();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
if(isProtectedUrl(request)) {
// System.out.println(request.getMethod());
if(!request.getMethod().equals("OPTIONS"))
request = JwtUtil.validateTokenAndAddUserIdToHeader(request);
}
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
return;
}
filterChain.doFilter(request, response);
}
private boolean isProtectedUrl(HttpServletRequest request) {
List<String> protectedPaths = new ArrayList<String>();
protectedPaths.add("/ums/user/info");
protectedPaths.add("/ums/user/update");
protectedPaths.add("/post/create");
protectedPaths.add("/post/update");
protectedPaths.add("/post/delete/*");
protectedPaths.add("/comment/add_comment");
protectedPaths.add("/relationship/subscribe/*");
protectedPaths.add("/relationship/unsubscribe/*");
protectedPaths.add("/relationship/validate/*");
boolean bFind = false;
for( String passedPath : protectedPaths ) {
bFind = pathMatcher.match(passedPath, request.getServletPath());
if( bFind ) {
break;
}
}
return bFind;
}
}

View File

@ -0,0 +1,75 @@
package com.yovinchen.forum.jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.*;
public class JwtUtil {
private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);
public static final long EXPIRATION_TIME = 3600_000_000L; // 1000 hour
public static final String SECRET = "ThisIsASecret";//please change to your own encryption secret.
public static final String TOKEN_PREFIX = "Bearer ";
public static final String HEADER_STRING = "Authorization";
public static final String USER_NAME = "userName";
public static String generateToken(String userId) {
HashMap<String, Object> map = new HashMap<>();
//you can put any data in the map
map.put(USER_NAME, userId);
String jwt = Jwts.builder()
.setClaims(map)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
return jwt; //jwt前面一般都会加Bearer
}
public static HttpServletRequest validateTokenAndAddUserIdToHeader(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
if (token != null) {
// parse the token.
try {
Map<String, Object> body = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody();
return new CustomHttpServletRequest(request, body);
} catch (Exception e) {
logger.info(e.getMessage());
throw new TokenValidationException(e.getMessage());
}
} else {
throw new TokenValidationException("Missing token");
}
}
public static class CustomHttpServletRequest extends HttpServletRequestWrapper {
private Map<String, String> claims;
public CustomHttpServletRequest(HttpServletRequest request, Map<String, ?> claims) {
super(request);
this.claims = new HashMap<>();
claims.forEach((k, v) -> this.claims.put(k, String.valueOf(v)));
}
@Override
public Enumeration<String> getHeaders(String name) {
if (claims != null && claims.containsKey(name)) {
return Collections.enumeration(Arrays.asList(claims.get(name)));
}
return super.getHeaders(name);
}
}
static class TokenValidationException extends RuntimeException {
public TokenValidationException(String msg) {
super(msg);
}
}
}

View File

@ -0,0 +1,9 @@
package com.yovinchen.forum.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yovinchen.forum.model.entity.BmsBillboard;
import org.springframework.stereotype.Repository;
@Repository
public interface BmsBillboardMapper extends BaseMapper<BmsBillboard> {
}

View File

@ -0,0 +1,22 @@
package com.yovinchen.forum.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yovinchen.forum.model.entity.BmsComment;
import com.yovinchen.forum.model.vo.CommentVO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface BmsCommentMapper extends BaseMapper<BmsComment> {
/**
* getCommentsByTopicID
*
* @param topicid
* @return
*/
List<CommentVO> getCommentsByTopicID(@Param("topicid") String topicid);
}

View File

@ -0,0 +1,9 @@
package com.yovinchen.forum.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yovinchen.forum.model.entity.BmsFollow;
import org.springframework.stereotype.Repository;
@Repository
public interface BmsFollowMapper extends BaseMapper<BmsFollow> {
}

View File

@ -0,0 +1,10 @@
package com.yovinchen.forum.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yovinchen.forum.model.entity.BmsPromotion;
import org.springframework.stereotype.Repository;
@Repository
public interface BmsPromotionMapper extends BaseMapper<BmsPromotion> {
}

View File

@ -0,0 +1,11 @@
package com.yovinchen.forum.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yovinchen.forum.model.entity.BmsTag;
import org.springframework.stereotype.Repository;
@Repository
public interface BmsTagMapper extends BaseMapper<BmsTag> {
}

View File

@ -0,0 +1,10 @@
package com.yovinchen.forum.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yovinchen.forum.model.entity.BmsTip;
import org.springframework.stereotype.Repository;
@Repository
public interface BmsTipMapper extends BaseMapper<BmsTip> {
BmsTip getRandomTip();
}

View File

@ -0,0 +1,39 @@
package com.yovinchen.forum.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yovinchen.forum.model.entity.BmsPost;
import com.yovinchen.forum.model.vo.PostVO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface BmsTopicMapper extends BaseMapper<BmsPost> {
/**
* 分页查询首页话题列表
* <p>
*
* @param page
* @param tab
* @return
*/
Page<PostVO> selectListAndPage(@Param("page") Page<PostVO> page, @Param("tab") String tab);
/**
* 获取详情页推荐
*
* @param id
* @return
*/
List<BmsPost> selectRecommend(@Param("id") String id);
/**
* 全文检索
*
* @param page
* @param keyword
* @return
*/
Page<PostVO> searchByKey(@Param("page") Page<PostVO> page, @Param("keyword") String keyword);
}

View File

@ -0,0 +1,20 @@
package com.yovinchen.forum.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yovinchen.forum.model.entity.BmsTopicTag;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.Set;
@Repository
public interface BmsTopicTagMapper extends BaseMapper<BmsTopicTag> {
/**
* 根据标签获取话题ID集合
*
* @param id
* @return
*/
Set<String> getTopicIdsByTagId(@Param("id") String id);
}

View File

@ -0,0 +1,15 @@
package com.yovinchen.forum.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yovinchen.forum.model.entity.UmsUser;
import org.springframework.stereotype.Repository;
/**
* 用户
*
* @author Knox 2020/11/7
*/
@Repository
public interface UmsUserMapper extends BaseMapper<UmsUser> {
}

View File

@ -0,0 +1,25 @@
package com.yovinchen.forum.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(description = "评论DTO")
public class CommentDTO implements Serializable {
private static final long serialVersionUID = -5957433707110390852L;
@ApiModelProperty(value = "话题id", required = true)
private String topic_id;
/**
* 内容
*/
@ApiModelProperty(value = "评论内容", required = true)
private String content;
}

View File

@ -0,0 +1,33 @@
package com.yovinchen.forum.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
@ApiModel(description = "创建话题DTO")
public class CreateTopicDTO implements Serializable {
private static final long serialVersionUID = -5957433707110390852L;
/**
* 标题
*/
@ApiModelProperty(value = "话题标题", required = true)
private String title;
/**
* 内容
*/
@ApiModelProperty(value = "话题内容", required = true)
private String content;
/**
* 标签
*/
@ApiModelProperty(value = "话题标签列表", required = true)
private List<String> tags;
}

View File

@ -0,0 +1,30 @@
package com.yovinchen.forum.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable;
@Data
@ApiModel(description = "登录DTO")
public class LoginDTO implements Serializable {
private static final long serialVersionUID = 602891322506543807L;
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 15, message = "登录用户名长度在2-15")
@ApiModelProperty(value = "用户名", required = true)
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "登录密码长度在6-20")
@ApiModelProperty(value = "密码", required = true)
private String password;
@ApiModelProperty(value = "记住我", example = "true")
private Boolean rememberMe;
}

View File

@ -0,0 +1,38 @@
package com.yovinchen.forum.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
@Data
@ApiModel(description = "注册DTO")
public class RegisterDTO implements Serializable {
private static final long serialVersionUID = 602891322506543807L;
@NotEmpty(message = "请输入账号")
@Length(min = 2, max = 15, message = "长度在2-15")
@ApiModelProperty(value = "用户名", required = true)
private String name;
@NotEmpty(message = "请输入密码")
@Length(min = 6, max = 20, message = "长度在6-20")
@ApiModelProperty(value = "密码", required = true)
private String pass;
@NotEmpty(message = "请再次输入密码")
@Length(min = 6, max = 20, message = "长度在6-20")
@ApiModelProperty(value = "确认密码", required = true)
private String checkPass;
@NotEmpty(message = "请输入电子邮箱")
@Email(message = "邮箱格式不正确")
@ApiModelProperty(value = "电子邮箱", required = true)
private String email;
}

View File

@ -0,0 +1,56 @@
package com.yovinchen.forum.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@ApiModel("公告牌")
@Accessors(chain = true)
@TableName("bms_billboard")
@NoArgsConstructor
@AllArgsConstructor
public class BmsBillboard implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ApiModelProperty("主键")
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 公告牌
*/
@ApiModelProperty("公告内容")
@TableField("content")
private String content;
/**
* 公告时间
*/
@ApiModelProperty("公告时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
/**
* 1展示中0过期
*/
@ApiModelProperty("展示状态false过期true展示中")
@Builder.Default
@TableField("`show`")
private boolean show = false;
}

View File

@ -0,0 +1,68 @@
package com.yovinchen.forum.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@ApiModel("帖子评论")
@TableName("bms_comment")
@AllArgsConstructor
@NoArgsConstructor
public class BmsComment implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ApiModelProperty("主键")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 内容
*/
@ApiModelProperty("内容")
@NotBlank(message = "内容不可以为空")
@TableField(value = "content")
private String content;
/**
* 作者ID
*/
@ApiModelProperty("作者ID")
@TableField("user_id")
private String userId;
/**
* topicID
*/
@ApiModelProperty("话题ID")
@TableField("topic_id")
private String topicId;
/**
* 创建时间
*/
@ApiModelProperty("创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
/**
* 修改时间
*/
@ApiModelProperty("修改时间")
@TableField(value = "modify_time", fill = FieldFill.UPDATE)
private Date modifyTime;
}

View File

@ -0,0 +1,44 @@
package com.yovinchen.forum.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel("用户关注")
@TableName("bms_follow")
public class BmsFollow implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ApiModelProperty("主键")
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 被关注人id
*/
@ApiModelProperty("被关注人ID")
@TableField("parent_id")
private String parentId;
/**
* 关注人id
*/
@ApiModelProperty("关注人ID")
@TableField("follower_id")
private String followerId;
public BmsFollow() {
}
}

View File

@ -0,0 +1,115 @@
package com.yovinchen.forum.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@ApiModel("帖子")
@TableName("bms_post")
@AllArgsConstructor
@NoArgsConstructor
public class BmsPost implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ApiModelProperty("主键")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 标题
*/
@ApiModelProperty("标题")
@NotBlank(message = "标题不可以为空")
@TableField(value = "title")
private String title;
/**
* markdown
*/
@ApiModelProperty("内容")
@NotBlank(message = "内容不可以为空")
@TableField("`content`")
private String content;
/**
* 作者ID
*/
@ApiModelProperty("作者ID")
@TableField("user_id")
private String userId;
/**
* 评论数
*/
@ApiModelProperty("评论数")
@TableField("comments")
@Builder.Default
private Integer comments = 0;
/**
* 收藏数
*/
@ApiModelProperty("收藏数")
@TableField("collects")
@Builder.Default
private Integer collects = 0;
/**
* 浏览数
*/
@ApiModelProperty("浏览数")
@TableField("view")
@Builder.Default
private Integer view = 0;
/**
* 专栏ID默认不分栏
*/
@ApiModelProperty("专栏ID默认不分栏")
@TableField("section_id")
@Builder.Default
private Integer sectionId = 0;
/**
* 置顶
*/
@ApiModelProperty("置顶")
@TableField("top")
@Builder.Default
private Boolean top = false;
/**
* 加精
*/
@ApiModelProperty("加精")
@TableField("essence")
@Builder.Default
private Boolean essence = false;
/**
* 创建时间
*/
@ApiModelProperty("创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
/**
* 修改时间
*/
@ApiModelProperty("修改时间")
@TableField(value = "modify_time", fill = FieldFill.UPDATE)
private Date modifyTime;
}

View File

@ -0,0 +1,54 @@
package com.yovinchen.forum.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@ApiModel("广告活动")
@TableName("bms_promotion")
@Accessors(chain = true)
public class BmsPromotion implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ApiModelProperty("主键")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 广告标题
*/
@ApiModelProperty("广告标题")
@TableField("title")
private String title;
/**
* 广告链接
*/
@ApiModelProperty("广告链接")
@TableField("link")
private String link;
/**
* 说明
*/
@ApiModelProperty("说明")
@TableField("`description`")
private String description;
public BmsPromotion() {
}
}

View File

@ -0,0 +1,38 @@
package com.yovinchen.forum.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Builder
@ApiModel("标签")
@TableName("bms_tag")
@Accessors(chain = true)
public class BmsTag implements Serializable {
private static final long serialVersionUID = 3257790983905872243L;
@ApiModelProperty("主键")
@TableId(type = IdType.ASSIGN_ID)
private String id;
@ApiModelProperty("名称")
@TableField("name")
private String name;
/**
* 当前标签下的话题个数
*/
@ApiModelProperty("当前标签下的话题个数")
@TableField("topic_count")
@Builder.Default
private Integer topicCount = 1;
}

View File

@ -0,0 +1,46 @@
package com.yovinchen.forum.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@ApiModel("小贴士")
@NoArgsConstructor
@TableName("bms_tip")
public class BmsTip implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ApiModelProperty("主键")
private Integer id;
/**
* 内容
*/
@ApiModelProperty("内容")
@TableField("`content`")
private String content;
/**
* 作者
*/
@ApiModelProperty("作者")
private String author;
/**
* 1使用0过期
*/
@ApiModelProperty("状态(1-使用0-过期)")
private boolean type;
}

View File

@ -0,0 +1,33 @@
package com.yovinchen.forum.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@ApiModel("话题标签关联")
@TableName("bms_post_tag")
@Accessors(chain = true)
public class BmsTopicTag implements Serializable {
private static final long serialVersionUID = -5028599844989220715L;
@ApiModelProperty("主键")
@TableId(type = IdType.AUTO)
private Integer id;
@ApiModelProperty("标签id")
@TableField("tag_id")
private String tagId;
@ApiModelProperty("话题id")
@TableField("topic_id")
private String topicId;
}

View File

@ -0,0 +1,99 @@
package com.yovinchen.forum.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@ApiModel("用户")
@TableName("ums_user")
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class UmsUser implements Serializable {
private static final long serialVersionUID = -5051120337175047163L;
@ApiModelProperty("主键")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@ApiModelProperty("用户名")
@TableField("username")
private String username;
@ApiModelProperty("昵称")
@TableField("alias")
private String alias;
@ApiModelProperty(hidden = true)
@JsonIgnore()
@TableField("password")
private String password;
@ApiModelProperty("头像url")
@Builder.Default
@TableField("avatar")
private String avatar = "https://s3.ax1x.com/2020/12/01/DfHNo4.jpg";
@ApiModelProperty("邮箱")
@TableField("email")
private String email;
@ApiModelProperty("手机号")
@TableField("mobile")
private String mobile;
@ApiModelProperty("个人简介")
@Builder.Default
@TableField("bio")
private String bio = "自由职业者";
@ApiModelProperty("积分")
@Builder.Default
@TableField("score")
private Integer score = 0;
@ApiModelProperty(hidden = true)
@JsonIgnore
@TableField("token")
private String token;
@ApiModelProperty("是否激活")
@Builder.Default
@TableField("active")
private Boolean active = true;
/**
* 状态1:使用0:已停用
*/
@ApiModelProperty("状态1:使用0:已停用")
@Builder.Default
@TableField("`status`")
private Boolean status = true;
/**
* 用户角色
*/
@ApiModelProperty("用户角色")
@TableField("role_id")
private Integer roleId;
@ApiModelProperty(hidden = true)
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
@ApiModelProperty(hidden = true)
@TableField(value = "modify_time", fill = FieldFill.INSERT_UPDATE)
private Date modifyTime;
}

View File

@ -0,0 +1,49 @@
package com.yovinchen.forum.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel("评论")
public class CommentVO {
/**
* 主键
*/
@ApiModelProperty("主键")
private String id;
/**
* 评论内容
*/
@ApiModelProperty("评论内容")
private String content;
/**
* 所属话题id
*/
@ApiModelProperty("所属话题id")
private String topicId;
/**
* 评论用户id
*/
@ApiModelProperty("评论用户id")
private String userId;
/**
* 评论用户名
*/
@ApiModelProperty("评论用户名")
private String username;
/**
* 创建时间
*/
@ApiModelProperty("创建时间")
private Date createTime;
}

View File

@ -0,0 +1,105 @@
package com.yovinchen.forum.model.vo;
import com.yovinchen.forum.model.entity.BmsTag;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@Data
@ApiModel("文章")
@NoArgsConstructor
@AllArgsConstructor
public class PostVO implements Serializable {
private static final long serialVersionUID = -261082150965211545L;
/**
* 文章ID
*/
@ApiModelProperty("文章ID")
private String id;
/**
* 用户ID
*/
@ApiModelProperty("用户ID")
private String userId;
/**
* 头像
*/
@ApiModelProperty("头像")
private String avatar;
/**
* 用户昵称
*/
@ApiModelProperty("用户昵称")
private String alias;
/**
* 账号
*/
@ApiModelProperty("账号")
private String username;
/**
* 标题
*/
@ApiModelProperty("标题")
private String title;
/**
* 评论统计
*/
@ApiModelProperty("评论统计")
private Integer comments;
/**
* 是否置顶
*/
@ApiModelProperty("是否置顶")
private Boolean top;
/**
* 是否加精
*/
@ApiModelProperty("是否加精")
private Boolean essence;
/**
* 收藏次数
*/
@ApiModelProperty("收藏次数")
private Integer collects;
/**
* 文章关联标签
*/
@ApiModelProperty("文章关联标签")
private List<BmsTag> tags;
/**
* 浏览量
*/
@ApiModelProperty("浏览量")
private Integer view;
/**
* 创建时间
*/
@ApiModelProperty("创建时间")
private Date createTime;
/**
* 修改时间
*/
@ApiModelProperty("修改时间")
private Date modifyTime;
}

View File

@ -0,0 +1,65 @@
package com.yovinchen.forum.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("用户信息")
public class ProfileVO {
/**
* 用户ID
*/
@ApiModelProperty("用户ID")
private String id;
/**
* 用户名
*/
@ApiModelProperty("用户名")
private String username;
/**
* 别称
*/
@ApiModelProperty("别称")
private String alias;
/**
* 头像
*/
@ApiModelProperty("头像")
private String avatar;
/**
* 关注数
*/
@ApiModelProperty("关注数")
private Integer followCount;
/**
* 关注者数
*/
@ApiModelProperty("关注者数")
private Integer followerCount;
/**
* 文章数
*/
@ApiModelProperty("文章数")
private Integer topicCount;
/**
* 专栏数
*/
@ApiModelProperty("专栏数")
private Integer columns;
/**
* 评论数
*/
@ApiModelProperty("评论数")
private Integer commentCount;
}

View File

@ -0,0 +1,7 @@
package com.yovinchen.forum.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yovinchen.forum.model.entity.BmsBillboard;
public interface IBmsBillboardService extends IService<BmsBillboard> {
}

View File

@ -0,0 +1,22 @@
package com.yovinchen.forum.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yovinchen.forum.model.dto.CommentDTO;
import com.yovinchen.forum.model.entity.BmsComment;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.model.vo.CommentVO;
import java.util.List;
public interface IBmsCommentService extends IService<BmsComment> {
/**
*
*
* @param topicid
* @return {@link BmsComment}
*/
List<CommentVO> getCommentsByTopicID(String topicid);
BmsComment create(CommentDTO dto, UmsUser principal);
}

View File

@ -0,0 +1,8 @@
package com.yovinchen.forum.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yovinchen.forum.model.entity.BmsFollow;
public interface IBmsFollowService extends IService<BmsFollow> {
}

View File

@ -0,0 +1,55 @@
package com.yovinchen.forum.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yovinchen.forum.model.dto.CreateTopicDTO;
import com.yovinchen.forum.model.entity.BmsPost;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.model.vo.PostVO;
import java.util.List;
import java.util.Map;
public interface IBmsPostService extends IService<BmsPost> {
/**
* 获取首页话题列表
*
* @param page
* @param tab
* @return
*/
Page<PostVO> getList(Page<PostVO> page, String tab);
/**
* 发布
*
* @param dto
* @param principal
* @return
*/
BmsPost create(CreateTopicDTO dto, UmsUser principal);
/**
* 查看话题详情
*
* @param id
* @return
*/
Map<String, Object> viewTopic(String id);
/**
* 获取随机推荐10篇
*
* @param id
* @return
*/
List<BmsPost> getRecommend(String id);
/**
* 关键字检索
*
* @param keyword
* @param page
* @return
*/
Page<PostVO> searchByKey(String keyword, Page<PostVO> page);
}

View File

@ -0,0 +1,8 @@
package com.yovinchen.forum.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yovinchen.forum.model.entity.BmsPromotion;
public interface IBmsPromotionService extends IService<BmsPromotion> {
}

View File

@ -0,0 +1,27 @@
package com.yovinchen.forum.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yovinchen.forum.model.entity.BmsPost;
import com.yovinchen.forum.model.entity.BmsTag;
import java.util.List;
public interface IBmsTagService extends IService<BmsTag> {
/**
* 插入标签
*
* @param tags
* @return
*/
List<BmsTag> insertTags(List<String> tags);
/**
* 获取标签关联话题
*
* @param topicPage
* @param id
* @return
*/
Page<BmsPost> selectTopicsByTagId(Page<BmsPost> topicPage, String id);
}

View File

@ -0,0 +1,8 @@
package com.yovinchen.forum.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yovinchen.forum.model.entity.BmsTip;
public interface IBmsTipService extends IService<BmsTip> {
BmsTip getRandomTip();
}

View File

@ -0,0 +1,35 @@
package com.yovinchen.forum.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yovinchen.forum.model.entity.BmsTag;
import com.yovinchen.forum.model.entity.BmsTopicTag;
import java.util.List;
import java.util.Set;
public interface IBmsTopicTagService extends IService<BmsTopicTag> {
/**
* 获取Topic Tag 关联记录
*
* @param topicId TopicId
* @return
*/
List<BmsTopicTag> selectByTopicId(String topicId);
/**
* 创建中间关系
*
* @param id
* @param tags
* @return
*/
void createTopicTag(String id, List<BmsTag> tags);
/**
* 获取标签换脸话题ID集合
*
* @param id
* @return
*/
Set<String> selectTopicIdsByTagId(String id);
}

View File

@ -0,0 +1,40 @@
package com.yovinchen.forum.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yovinchen.forum.model.dto.LoginDTO;
import com.yovinchen.forum.model.dto.RegisterDTO;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.model.vo.ProfileVO;
public interface IUmsUserService extends IService<UmsUser> {
/**
* 注册功能
*
* @param dto
* @return 注册对象
*/
UmsUser executeRegister(RegisterDTO dto);
/**
* 获取用户信息
*
* @param username
* @return dbUser
*/
UmsUser getUserByUsername(String username);
/**
* 用户登录
*
* @param dto
* @return 生成的JWT的token
*/
String executeLogin(LoginDTO dto);
/**
* 获取用户信息
*
* @param id 用户ID
* @return
*/
ProfileVO getUserProfile(String id);
}

View File

@ -0,0 +1,13 @@
package com.yovinchen.forum.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yovinchen.forum.mapper.BmsBillboardMapper;
import com.yovinchen.forum.model.entity.BmsBillboard;
import com.yovinchen.forum.service.IBmsBillboardService;
import org.springframework.stereotype.Service;
@Service
public class IBmsBillboardServiceImpl extends ServiceImpl<BmsBillboardMapper
, BmsBillboard> implements IBmsBillboardService {
}

View File

@ -0,0 +1,43 @@
package com.yovinchen.forum.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yovinchen.forum.mapper.BmsCommentMapper;
import com.yovinchen.forum.model.dto.CommentDTO;
import com.yovinchen.forum.model.entity.BmsComment;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.model.vo.CommentVO;
import com.yovinchen.forum.service.IBmsCommentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class IBmsCommentServiceImpl extends ServiceImpl<BmsCommentMapper, BmsComment> implements IBmsCommentService {
@Override
public List<CommentVO> getCommentsByTopicID(String topicid) {
List<CommentVO> lstBmsComment = new ArrayList<CommentVO>();
try {
lstBmsComment = this.baseMapper.getCommentsByTopicID(topicid);
} catch (Exception e) {
log.info("lstBmsComment失败");
}
return lstBmsComment;
}
@Override
public BmsComment create(CommentDTO dto, UmsUser user) {
BmsComment comment = BmsComment.builder()
.userId(user.getId())
.content(dto.getContent())
.topicId(dto.getTopic_id())
.createTime(new Date())
.build();
this.baseMapper.insert(comment);
return comment;
}
}

View File

@ -0,0 +1,12 @@
package com.yovinchen.forum.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yovinchen.forum.mapper.BmsFollowMapper;
import com.yovinchen.forum.model.entity.BmsFollow;
import com.yovinchen.forum.service.IBmsFollowService;
import org.springframework.stereotype.Service;
@Service
public class IBmsFollowServiceImpl extends ServiceImpl<BmsFollowMapper, BmsFollow> implements IBmsFollowService {
}

View File

@ -0,0 +1,140 @@
package com.yovinchen.forum.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yovinchen.forum.mapper.BmsTagMapper;
import com.yovinchen.forum.mapper.BmsTopicMapper;
import com.yovinchen.forum.mapper.UmsUserMapper;
import com.yovinchen.forum.model.dto.CreateTopicDTO;
import com.yovinchen.forum.model.entity.BmsPost;
import com.yovinchen.forum.model.entity.BmsTag;
import com.yovinchen.forum.model.entity.BmsTopicTag;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.model.vo.PostVO;
import com.yovinchen.forum.model.vo.ProfileVO;
import com.yovinchen.forum.service.IBmsPostService;
import com.yovinchen.forum.service.IBmsTagService;
import com.yovinchen.forum.service.IUmsUserService;
import com.vdurmont.emoji.EmojiParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class IBmsPostServiceImpl extends ServiceImpl<BmsTopicMapper, BmsPost> implements IBmsPostService {
@Resource
private BmsTagMapper bmsTagMapper;
@Resource
private UmsUserMapper umsUserMapper;
@Autowired
@Lazy
private IBmsTagService iBmsTagService;
@Autowired
private IUmsUserService iUmsUserService;
@Autowired
private com.yovinchen.forum.service.IBmsTopicTagService IBmsTopicTagService;
@Override
public Page<PostVO> getList(Page<PostVO> page, String tab) {
// 查询话题
Page<PostVO> iPage = this.baseMapper.selectListAndPage(page, tab);
// 查询话题的标签
setTopicTags(iPage);
return iPage;
}
@Override
@Transactional(rollbackFor = Exception.class)
public BmsPost create(CreateTopicDTO dto, UmsUser user) {
BmsPost topic1 = this.baseMapper.selectOne(new LambdaQueryWrapper<BmsPost>().eq(BmsPost::getTitle, dto.getTitle()));
Assert.isNull(topic1, "话题已存在,请修改");
// 封装
BmsPost topic = BmsPost.builder()
.userId(user.getId())
.title(dto.getTitle())
.content(EmojiParser.parseToAliases(dto.getContent()))
.createTime(new Date())
.build();
this.baseMapper.insert(topic);
// 用户积分增加
int newScore = user.getScore() + 1;
umsUserMapper.updateById(user.setScore(newScore));
// 标签
if (!ObjectUtils.isEmpty(dto.getTags())) {
// 保存标签
List<BmsTag> tags = iBmsTagService.insertTags(dto.getTags());
// 处理标签与话题的关联
IBmsTopicTagService.createTopicTag(topic.getId(), tags);
}
return topic;
}
@Override
public Map<String, Object> viewTopic(String id) {
Map<String, Object> map = new HashMap<>(16);
BmsPost topic = this.baseMapper.selectById(id);
Assert.notNull(topic, "当前话题不存在,或已被作者删除");
// 查询话题详情
topic.setView(topic.getView() + 1);
this.baseMapper.updateById(topic);
// emoji转码
topic.setContent(EmojiParser.parseToUnicode(topic.getContent()));
map.put("topic", topic);
// 标签
QueryWrapper<BmsTopicTag> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(BmsTopicTag::getTopicId, topic.getId());
Set<String> set = new HashSet<>();
for (BmsTopicTag articleTag : IBmsTopicTagService.list(wrapper)) {
set.add(articleTag.getTagId());
}
List<BmsTag> tags = iBmsTagService.listByIds(set);
map.put("tags", tags);
// 作者
ProfileVO user = iUmsUserService.getUserProfile(topic.getUserId());
map.put("user", user);
return map;
}
@Override
public List<BmsPost> getRecommend(String id) {
return this.baseMapper.selectRecommend(id);
}
@Override
public Page<PostVO> searchByKey(String keyword, Page<PostVO> page) {
// 查询话题
Page<PostVO> iPage = this.baseMapper.searchByKey(page, keyword);
// 查询话题的标签
setTopicTags(iPage);
return iPage;
}
private void setTopicTags(Page<PostVO> iPage) {
iPage.getRecords().forEach(topic -> {
List<BmsTopicTag> topicTags = IBmsTopicTagService.selectByTopicId(topic.getId());
if (!topicTags.isEmpty()) {
List<String> tagIds = topicTags.stream().map(BmsTopicTag::getTagId).collect(Collectors.toList());
List<BmsTag> tags = bmsTagMapper.selectBatchIds(tagIds);
topic.setTags(tags);
}
});
}
}

View File

@ -0,0 +1,13 @@
package com.yovinchen.forum.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yovinchen.forum.mapper.BmsPromotionMapper;
import com.yovinchen.forum.model.entity.BmsPromotion;
import com.yovinchen.forum.service.IBmsPromotionService;
import org.springframework.stereotype.Service;
@Service
public class IBmsPromotionServiceImpl extends ServiceImpl<BmsPromotionMapper, BmsPromotion> implements IBmsPromotionService {
}

View File

@ -0,0 +1,60 @@
package com.yovinchen.forum.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yovinchen.forum.mapper.BmsTagMapper;
import com.yovinchen.forum.model.entity.BmsPost;
import com.yovinchen.forum.model.entity.BmsTag;
import com.yovinchen.forum.service.IBmsTagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* Tag 实现类
*
* @author Knox 2020/11/7
*/
@Service
public class IBmsTagServiceImpl extends ServiceImpl<BmsTagMapper, BmsTag> implements IBmsTagService {
@Autowired
private com.yovinchen.forum.service.IBmsTopicTagService IBmsTopicTagService;
@Autowired
private com.yovinchen.forum.service.IBmsPostService IBmsPostService;
@Override
public List<BmsTag> insertTags(List<String> tagNames) {
List<BmsTag> tagList = new ArrayList<>();
for (String tagName : tagNames) {
BmsTag tag = this.baseMapper.selectOne(new LambdaQueryWrapper<BmsTag>().eq(BmsTag::getName, tagName));
if (tag == null) {
tag = BmsTag.builder().name(tagName).build();
this.baseMapper.insert(tag);
} else {
tag.setTopicCount(tag.getTopicCount() + 1);
this.baseMapper.updateById(tag);
}
tagList.add(tag);
}
return tagList;
}
@Override
public Page<BmsPost> selectTopicsByTagId(Page<BmsPost> topicPage, String id) {
// 获取关联的话题ID
Set<String> ids = IBmsTopicTagService.selectTopicIdsByTagId(id);
LambdaQueryWrapper<BmsPost> wrapper = new LambdaQueryWrapper<>();
wrapper.in(BmsPost::getId, ids);
return IBmsPostService.page(topicPage, wrapper);
}
}

View File

@ -0,0 +1,25 @@
package com.yovinchen.forum.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yovinchen.forum.mapper.BmsTipMapper;
import com.yovinchen.forum.model.entity.BmsTip;
import com.yovinchen.forum.service.IBmsTipService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class IBmsTipServiceImpl extends ServiceImpl<BmsTipMapper
, BmsTip> implements IBmsTipService {
@Override
public BmsTip getRandomTip() {
BmsTip todayTip = null;
try {
todayTip = this.baseMapper.getRandomTip();
} catch (Exception e) {
log.info("tip转化失败");
}
return todayTip;
}
}

View File

@ -0,0 +1,45 @@
package com.yovinchen.forum.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yovinchen.forum.mapper.BmsTopicTagMapper;
import com.yovinchen.forum.model.entity.BmsTag;
import com.yovinchen.forum.model.entity.BmsTopicTag;
import com.yovinchen.forum.service.IBmsTopicTagService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Set;
@Service
@Transactional(rollbackFor = Exception.class)
public class IBmsTopicTagServiceImpl extends ServiceImpl<BmsTopicTagMapper, BmsTopicTag> implements IBmsTopicTagService {
@Override
public List<BmsTopicTag> selectByTopicId(String topicId) {
QueryWrapper<BmsTopicTag> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(BmsTopicTag::getTopicId, topicId);
return this.baseMapper.selectList(wrapper);
}
@Override
public void createTopicTag(String id, List<BmsTag> tags) {
// 先删除topicId对应的所有记录
this.baseMapper.delete(new LambdaQueryWrapper<BmsTopicTag>().eq(BmsTopicTag::getTopicId, id));
// 循环保存对应关联
tags.forEach(tag -> {
BmsTopicTag topicTag = new BmsTopicTag();
topicTag.setTopicId(id);
topicTag.setTagId(tag.getId());
this.baseMapper.insert(topicTag);
});
}
@Override
public Set<String> selectTopicIdsByTagId(String id) {
return this.baseMapper.getTopicIdsByTagId(id);
}
}

View File

@ -0,0 +1,94 @@
package com.yovinchen.forum.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yovinchen.forum.common.exception.ApiAsserts;
import com.yovinchen.forum.jwt.JwtUtil;
import com.yovinchen.forum.mapper.BmsFollowMapper;
import com.yovinchen.forum.mapper.BmsTopicMapper;
import com.yovinchen.forum.mapper.UmsUserMapper;
import com.yovinchen.forum.model.dto.LoginDTO;
import com.yovinchen.forum.model.dto.RegisterDTO;
import com.yovinchen.forum.model.entity.BmsFollow;
import com.yovinchen.forum.model.entity.BmsPost;
import com.yovinchen.forum.model.entity.UmsUser;
import com.yovinchen.forum.model.vo.ProfileVO;
import com.yovinchen.forum.service.IUmsUserService;
import com.yovinchen.forum.utils.MD5Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import java.util.Date;
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class IUmsUserServiceImpl extends ServiceImpl<UmsUserMapper, UmsUser> implements IUmsUserService {
@Autowired
private BmsTopicMapper bmsTopicMapper;
@Autowired
private BmsFollowMapper bmsFollowMapper;
@Override
public UmsUser executeRegister(RegisterDTO dto) {
//查询是否有相同用户名的用户
LambdaQueryWrapper<UmsUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(UmsUser::getUsername, dto.getName()).or().eq(UmsUser::getEmail, dto.getEmail());
UmsUser umsUser = baseMapper.selectOne(wrapper);
if (!ObjectUtils.isEmpty(umsUser)) {
ApiAsserts.fail("账号或邮箱已存在!");
}
UmsUser addUser = UmsUser.builder()
.username(dto.getName())
.alias(dto.getName())
.password(MD5Utils.getPwd(dto.getPass()))
.email(dto.getEmail())
.createTime(new Date())
.status(true)
.build();
baseMapper.insert(addUser);
return addUser;
}
@Override
public UmsUser getUserByUsername(String username) {
return baseMapper.selectOne(new LambdaQueryWrapper<UmsUser>().eq(UmsUser::getUsername, username));
}
@Override
public String executeLogin(LoginDTO dto) {
String token = null;
try {
UmsUser user = getUserByUsername(dto.getUsername());
String encodePwd = MD5Utils.getPwd(dto.getPassword());
if(!encodePwd.equals(user.getPassword()))
{
throw new Exception("密码错误");
}
token = JwtUtil.generateToken(String.valueOf(user.getUsername()));
} catch (Exception e) {
log.warn("用户不存在or密码验证失败=======>{}", dto.getUsername());
}
return token;
}
@Override
public ProfileVO getUserProfile(String id) {
ProfileVO profile = new ProfileVO();
UmsUser user = baseMapper.selectById(id);
BeanUtils.copyProperties(user, profile);
// 用户文章数
int count = bmsTopicMapper.selectCount(new LambdaQueryWrapper<BmsPost>().eq(BmsPost::getUserId, id));
profile.setTopicCount(count);
// 粉丝数
int followers = bmsFollowMapper.selectCount((new LambdaQueryWrapper<BmsFollow>().eq(BmsFollow::getParentId, id)));
profile.setFollowerCount(followers);
return profile;
}
}

View File

@ -0,0 +1,56 @@
package com.yovinchen.forum.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
public static String getPwd(String pwd) {
try {
// 创建加密对象
MessageDigest digest = MessageDigest.getInstance("md5");
// 调用加密对象的方法加密的动作已经完成
byte[] bs = digest.digest(pwd.getBytes());
// 接下来我们要对加密后的结果进行优化按照mysql的优化思路走
// mysql的优化思路
// 第一步将数据全部转换成正数
String hexString = "";
for (byte b : bs) {
// 第一步将数据全部转换成正数
// 解释为什么采用b&255
/*
* b:它本来是一个byte类型的数据(1个字节) 255是一个int类型的数据(4个字节)
* byte类型的数据与int类型的数据进行运算会自动类型提升为int类型 eg: b: 1001 1100(原始数据)
* 运算时 b: 0000 0000 0000 0000 0000 0000 1001 1100 255: 0000
* 0000 0000 0000 0000 0000 1111 1111 结果0000 0000 0000 0000
* 0000 0000 1001 1100 此时的temp是一个int类型的整数
*/
int temp = b & 255;
// 第二步将所有的数据转换成16进制的形式
// 注意转换的时候注意if正数>=0&&<16那么如果使用Integer.toHexString()可能会造成缺少位数
// 因此需要对temp进行判断
if (temp < 16 && temp >= 0) {
// 手动补上一个0
hexString = hexString + "0" + Integer.toHexString(temp);
} else {
hexString = hexString + Integer.toHexString(temp);
}
}
return hexString;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
// public static void main(String[] args) {
// String pwd = MD5Utils.getPwd("234");
// System.out.println(pwd);
// }
}

View File

@ -0,0 +1,18 @@
server:
port: 8080
web:
domain: http://localhost
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/doubao?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=GMT%2B8
type: com.zaxxer.hikari.HikariDataSource
logging:
level:
root: info
com.yovinchen.forum: debug

View File

@ -0,0 +1,18 @@
server:
port: 8088
web:
domain: http://localhost
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/ssm_db?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=GMT%2B8
type: com.zaxxer.hikari.HikariDataSource
logging:
level:
root: info
com.yovinchen.forum: info

View File

@ -0,0 +1,3 @@
spring:
profiles:
active: dev

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.yovinchen.forum.mapper.BmsCommentMapper">
<resultMap id="topicVO" type="com.yovinchen.forum.model.vo.CommentVO">
<id column="id" property="id"/>
<result column="content" property="content"/>
<result column="user_id" property="userId"/>
<result column="topic_id" property="topicId"/>
<result column="username" property="username"/>
<result column="create_time" property="createTime"/>
</resultMap>
<select id="getCommentsByTopicID" resultMap="topicVO">
select bms_comment.*,ums_user.username
from bms_comment
join ums_user on ums_user.id = bms_comment.user_id
where topic_id = #{topicid}
order by create_time desc
</select>
</mapper>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.yovinchen.forum.mapper.BmsTopicMapper">
<resultMap id="topicVO" type="com.yovinchen.forum.model.vo.PostVO">
<id column="id" property="id"/>
<result column="title" property="title"/>
<result column="user_id" property="userId"/>
<result column="comments" property="comments"/>
<result column="view" property="view"/>
<result column="collects" property="collects"/>
<result column="top" property="top"/>
<result column="essence" property="essence"/>
<result column="create_time" property="createTime"/>
<result column="modify_time" property="modifyTime"/>
<result column="username" property="username"/>
<result column="alias" property="alias"/>
<result column="avatar" property="avatar"/>
</resultMap>
<select id="selectListAndPage" resultMap="topicVO">
SELECT
t.id,t.title,t.user_id,t.comments,
t.view,t.collects,t.top,t.essence,
t.create_time ,t.modify_time ,
u.username,u.alias, u.avatar
FROM bms_post t
LEFT JOIN ums_user u
ON t.user_id = u.id
<!-- <where>-->
<!-- <if test="tab == 'hot'">-->
<!-- date(t.create_time) &lt;= date_add(curdate(), interval 1 day)-->
<!-- and date(t.create_time) &gt;= date_sub(curdate(), interval 7 day)-->
<!-- </if>-->
<!-- </where>-->
<if test="tab != 'hot'">
order by t.create_time desc
</if>
<if test="tab == 'hot'">
order by t.view desc, t.create_time desc
</if>
</select>
<select id="selectRecommend" resultType="com.yovinchen.forum.model.entity.BmsPost">
select *
from bms_post t
where t.id != #{id}
order by rand(), t.view
limit 10
</select>
<select id="searchByKey" resultMap="topicVO">
SELECT t.id,
t.title,
t.user_id,
t.comments,
t.view,
t.collects,
t.top,
t.essence,
t.create_time,
t.modify_time,
u.username,
u.alias,
u.avatar
FROM bms_post t
LEFT JOIN ums_user u
ON t.user_id = u.id
<where>
<if test="keyword!=null">
and t.title like CONCAT('%','${keyword}')
or t.title like CONCAT('${keyword}','%')
or t.title like CONCAT('%','${keyword}','%')
or t.title = #{keyword}
</if>
</where>
order by t.view desc, t.create_time desc
</select>
</mapper>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.yovinchen.forum.mapper.BmsTopicTagMapper">
<select id="getTopicIdsByTagId" resultType="java.lang.String">
SELECT t.topic_id
from bms_post_tag t
where t.tag_id = #{id}
</select>
</mapper>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.yovinchen.forum.mapper.BmsTipMapper">
<select id="getRandomTip" resultType="com.yovinchen.forum.model.entity.BmsTip">
select *
from bms_tip
order by rand()
limit 1
</select>
</mapper>

View File

@ -0,0 +1,13 @@
package com.yovinchen.forum;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DoubaoApplicationTests {
@Test
void contextLoads() {
}
}

View File

@ -0,0 +1,18 @@
server:
port: 8080
web:
domain: http://localhost
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/doubao?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=GMT%2B8
type: com.zaxxer.hikari.HikariDataSource
logging:
level:
root: info
com.yovinchen.forum: debug

View File

@ -0,0 +1,18 @@
server:
port: 8088
web:
domain: http://localhost
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/ssm_db?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=GMT%2B8
type: com.zaxxer.hikari.HikariDataSource
logging:
level:
root: info
com.yovinchen.forum: info

View File

@ -0,0 +1,3 @@
spring:
profiles:
active: dev

Some files were not shown because too many files have changed in this diff Show More