init
This commit is contained in:
commit
9f56a86116
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# 项目排除路径
|
||||
/book-api/target/
|
||||
/book-common/target/
|
||||
/book-mapper/target/
|
||||
/book-model/target/
|
||||
/book-service/target/
|
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
32
.idea/compiler.xml
generated
Normal file
32
.idea/compiler.xml
generated
Normal file
@ -0,0 +1,32 @@
|
||||
<?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="book-model" />
|
||||
<module name="book-common" />
|
||||
<module name="book-service" />
|
||||
<module name="book-api" />
|
||||
<module name="book-mapper" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
<bytecodeTargetLevel>
|
||||
<module name="mybatis-generator-database" target="1.5" />
|
||||
<module name="mybatis-generator-for-imooc" target="1.5" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
<component name="JavacSettings">
|
||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||
<module name="book-api" options="-parameters" />
|
||||
<module name="book-common" options="-parameters" />
|
||||
<module name="book-mapper" options="-parameters" />
|
||||
<module name="book-model" options="-parameters" />
|
||||
<module name="book-service" options="-parameters" />
|
||||
<module name="imooc-red-book-dev" options="-parameters" />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
16
.idea/encodings.xml
generated
Normal file
16
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/book-api/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/book-common/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/book-mapper/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/book-model/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/book-service/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/mybatis-generator-database-mysql8/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/mybatis-generator-database-mysql8/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/mybatis-generator-for-imooc/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/mybatis-generator-for-imooc/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
30
.idea/jarRepositories.xml
generated
Normal file
30
.idea/jarRepositories.xml
generated
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="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>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/public" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
9
.idea/libraries/mybatis_generator_for_imooc_1_0_SNAPSHOT.xml
generated
Normal file
9
.idea/libraries/mybatis_generator_for_imooc_1_0_SNAPSHOT.xml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="mybatis-generator-for-imooc-1.0-SNAPSHOT">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/mybatis-generator-for-imooc/target/mybatis-generator-for-imooc-1.0-SNAPSHOT.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
20
.idea/misc.xml
generated
Normal file
20
.idea/misc.xml
generated
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="ignoredFiles">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$/mybatis-generator-for-imooc/pom.xml" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="workspaceImportForciblyTurnedOn" value="true" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
9
.idea/vlog-1.0.0.iml
generated
Normal file
9
.idea/vlog-1.0.0.iml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
16
README.md
Normal file
16
README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# douyin_dome
|
||||
SpringBoot+Uniapp仿抖音短视频App
|
||||
|
||||
只用修改api模块下面的配置即可运行
|
||||
|
||||
Knife4j 接口文档通过访问 http://ip+prot/doc.html#/home 查看api
|
||||
# 架构
|
||||

|
||||

|
||||
|
||||
# 效果
|
||||
|
||||

|
||||

|
||||

|
||||

|
71
book-api/pom.xml
Normal file
71
book-api/pom.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.imooc</groupId>
|
||||
<artifactId>imooc-red-book-dev</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<!--接口层-->
|
||||
<artifactId>book-api</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- 服务注册与发现 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 分布式(微服务)配置中心 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 微服务的bootstrap -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.imooc</groupId>
|
||||
<artifactId>book-service</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-springdoc-ui</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
23
book-api/src/main/java/com/imooc/Application.java
Normal file
23
book-api/src/main/java/com/imooc/Application.java
Normal file
@ -0,0 +1,23 @@
|
||||
package com.imooc;
|
||||
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
import tk.mybatis.spring.annotation.MapperScan;
|
||||
|
||||
/**
|
||||
* @author vercen
|
||||
* @version 1.0
|
||||
* @date 2023/5/20 14:25
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@MapperScan(basePackages = {"com.imooc.mapper"})
|
||||
@ComponentScan(basePackages = {"com.imooc","org.n3r.idworker"})
|
||||
@EnableMongoRepositories
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.imooc.config;
|
||||
|
||||
import com.imooc.intercepter.PassportInterceptor;
|
||||
import com.imooc.intercepter.UserTokenInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class InterceptorConfig implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public PassportInterceptor passportInterceptor() {
|
||||
return new PassportInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UserTokenInterceptor userTokenInterceptor() {
|
||||
return new UserTokenInterceptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(passportInterceptor())
|
||||
.addPathPatterns("/passport/getSMSCode");
|
||||
|
||||
registry.addInterceptor(userTokenInterceptor())
|
||||
.addPathPatterns("/userInfo/modifyUserInfo")
|
||||
.addPathPatterns("/userInfo/modifyImage");
|
||||
}
|
||||
}
|
33
book-api/src/main/java/com/imooc/config/MinIOConfig.java
Normal file
33
book-api/src/main/java/com/imooc/config/MinIOConfig.java
Normal file
@ -0,0 +1,33 @@
|
||||
package com.imooc.config;
|
||||
|
||||
import com.imooc.utils.MinIOUtils;
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@Data
|
||||
public class MinIOConfig {
|
||||
|
||||
@Value("${minio.endpoint}")
|
||||
private String endpoint;
|
||||
@Value("${minio.fileHost}")
|
||||
private String fileHost;
|
||||
@Value("${minio.bucketName}")
|
||||
private String bucketName;
|
||||
@Value("${minio.accessKey}")
|
||||
private String accessKey;
|
||||
@Value("${minio.secretKey}")
|
||||
private String secretKey;
|
||||
|
||||
@Value("${minio.imgSize}")
|
||||
private Integer imgSize;
|
||||
@Value("${minio.fileSize}")
|
||||
private Integer fileSize;
|
||||
|
||||
@Bean
|
||||
public MinIOUtils creatMinioClient() {
|
||||
return new MinIOUtils(endpoint, bucketName, accessKey, secretKey, imgSize, fileSize);
|
||||
}
|
||||
}
|
40
book-api/src/main/java/com/imooc/config/knife4jConfig.java
Normal file
40
book-api/src/main/java/com/imooc/config/knife4jConfig.java
Normal file
@ -0,0 +1,40 @@
|
||||
package com.imooc.config;
|
||||
|
||||
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.Contact;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
|
||||
|
||||
/**
|
||||
* @author vercen
|
||||
* @version 1.0
|
||||
* @date 2023/5/20 19:55
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSwagger2WebMvc
|
||||
public class knife4jConfig {
|
||||
@Bean
|
||||
public Docket defaultApi2() {
|
||||
Docket docket=new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(new ApiInfoBuilder()
|
||||
//.title("swagger-bootstrap-ui-demo RESTful APIs")
|
||||
.description("短视频实战接口文档")
|
||||
.termsOfServiceUrl("http://www.xx.com/")
|
||||
.contact(new Contact("lee", "http://www.imooc.com/", "abc@imooc.com"))
|
||||
.version("1.0")
|
||||
.build())
|
||||
//分组名称
|
||||
.groupName("2.X版本")
|
||||
.select()
|
||||
//这里指定Controller扫描包路径
|
||||
.apis(RequestHandlerSelectors.basePackage("com.imooc.controller"))
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
return docket;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.imooc.controller;
|
||||
|
||||
import com.imooc.utils.RedisOperator;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
//public class BaseController {
|
||||
//
|
||||
// @Autowired
|
||||
// public RedisOperator redis;
|
||||
//
|
||||
// public static final String MOBILE_SMSCODE = "mobile:smscode";
|
||||
// public static final String REDIS_USER_TOKEN = "redis_user_token";
|
||||
// public static final String REDIS_USER_INFO = "redis_user_info";
|
||||
//
|
||||
//}
|
@ -0,0 +1,46 @@
|
||||
//package com.imooc.controller;
|
||||
//
|
||||
//import com.github.pagehelper.PageInfo;
|
||||
//import com.imooc.utils.RedisOperator;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.validation.BindingResult;
|
||||
//import org.springframework.validation.FieldError;
|
||||
//
|
||||
//import java.util.HashMap;
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//
|
||||
//public class BaseInfoProperties {
|
||||
//
|
||||
// @Autowired
|
||||
// public RedisOperator redis;
|
||||
//
|
||||
// public static final Integer COMMON_START_PAGE = 1;
|
||||
// public static final Integer COMMON_PAGE_SIZE = 10;
|
||||
//
|
||||
// public static final String MOBILE_SMSCODE = "mobile:smscode";
|
||||
// public static final String REDIS_USER_TOKEN = "redis_user_token";
|
||||
// public static final String REDIS_USER_INFO = "redis_user_info";
|
||||
//
|
||||
//
|
||||
// //我的关注总数
|
||||
// public static final String REDIS_MY_FOLLOWS_COUNTS = "redis_my_follows_counts";
|
||||
// // 我的粉丝总数
|
||||
// public static final String REDIS_MY_FANS_COUNTS = "redis_my_fans_counts";
|
||||
//
|
||||
// // 视频和发布者获赞数
|
||||
// public static final String REDIS_VLOG_BE_LIKED_COUNTS = "redis_vlog_be_liked_counts";
|
||||
// public static final String REDIS_VLOGER_BE_LIKED_COUNTS = "redis_vloger_be_liked_counts";
|
||||
//
|
||||
// public PagedGridResult setterPagedGrid(List<?> list,
|
||||
// Integer page) {
|
||||
// PageInfo<?> pageList = new PageInfo<>(list);
|
||||
// PagedGridResult gridResult = new PagedGridResult();
|
||||
// gridResult.setRows(list);
|
||||
// gridResult.setPage(page);
|
||||
// gridResult.setRecords(pageList.getTotal());
|
||||
// gridResult.setTotal(pageList.getPages());
|
||||
// return gridResult;
|
||||
// }
|
||||
//
|
||||
//}
|
@ -0,0 +1,114 @@
|
||||
package com.imooc.controller;
|
||||
|
||||
import com.imooc.base.BaseInfoProperties;
|
||||
import com.imooc.bo.CommentBO;
|
||||
import com.imooc.enums.MessageEnum;
|
||||
import com.imooc.grace.result.GraceJSONResult;
|
||||
import com.imooc.pojo.Comment;
|
||||
import com.imooc.pojo.Vlog;
|
||||
import com.imooc.service.CommentService;
|
||||
import com.imooc.service.MsgService;
|
||||
import com.imooc.service.VlogService;
|
||||
import com.imooc.vo.CommentVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "CommentController 评论模块的接口")
|
||||
@RequestMapping("comment")
|
||||
@RestController
|
||||
public class CommentController extends BaseInfoProperties {
|
||||
|
||||
@Autowired
|
||||
private CommentService commentService;
|
||||
@Autowired
|
||||
private MsgService msgService;
|
||||
@Autowired
|
||||
private VlogService vlogService;
|
||||
//
|
||||
@PostMapping("create")
|
||||
public GraceJSONResult create(@RequestBody @Valid CommentBO commentBO)
|
||||
throws Exception {
|
||||
|
||||
CommentVO commentVO = commentService.createComment(commentBO);
|
||||
return GraceJSONResult.ok(commentVO);
|
||||
}
|
||||
//
|
||||
@GetMapping("counts")
|
||||
public GraceJSONResult counts(@RequestParam String vlogId) {
|
||||
|
||||
String countsStr = redis.get(REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId);
|
||||
if (StringUtils.isBlank(countsStr)) {
|
||||
countsStr = "0";
|
||||
}
|
||||
|
||||
return GraceJSONResult.ok(Integer.valueOf(countsStr));
|
||||
}
|
||||
|
||||
@GetMapping("list")
|
||||
public GraceJSONResult list(@RequestParam String vlogId,
|
||||
@RequestParam(defaultValue = "") String userId,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
|
||||
return GraceJSONResult.ok(
|
||||
commentService.queryVlogComments(
|
||||
vlogId,
|
||||
userId,
|
||||
page,
|
||||
pageSize));
|
||||
}
|
||||
|
||||
@DeleteMapping("delete")
|
||||
public GraceJSONResult delete(@RequestParam String commentUserId,
|
||||
@RequestParam String commentId,
|
||||
@RequestParam String vlogId) {
|
||||
commentService.deleteComment(commentUserId,
|
||||
commentId,
|
||||
vlogId);
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
@PostMapping("like")
|
||||
public GraceJSONResult like(@RequestParam String commentId,
|
||||
@RequestParam String userId) {
|
||||
|
||||
// 故意犯错,bigkey
|
||||
redis.incrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);
|
||||
redis.setHashValue(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId, "1");
|
||||
// redis.hset(REDIS_USER_LIKE_COMMENT, userId, "1");
|
||||
|
||||
|
||||
// 系统消息:点赞评论
|
||||
Comment comment = commentService.getComment(commentId);
|
||||
Vlog vlog = vlogService.getVlog(comment.getVlogId());
|
||||
Map msgContent = new HashMap();
|
||||
msgContent.put("vlogId", vlog.getId());
|
||||
msgContent.put("vlogCover", vlog.getCover());
|
||||
msgContent.put("commentId", commentId);
|
||||
msgService.createMsg(userId,
|
||||
comment.getCommentUserId(),
|
||||
MessageEnum.LIKE_COMMENT.type,
|
||||
msgContent);
|
||||
|
||||
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
@PostMapping("unlike")
|
||||
public GraceJSONResult unlike(@RequestParam String commentId,
|
||||
@RequestParam String userId) {
|
||||
|
||||
redis.decrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);
|
||||
redis.hdel(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId);
|
||||
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
}
|
106
book-api/src/main/java/com/imooc/controller/FansController.java
Normal file
106
book-api/src/main/java/com/imooc/controller/FansController.java
Normal file
@ -0,0 +1,106 @@
|
||||
package com.imooc.controller;
|
||||
|
||||
import com.imooc.base.BaseInfoProperties;
|
||||
import com.imooc.grace.result.GraceJSONResult;
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
import com.imooc.pojo.Users;
|
||||
import com.imooc.service.FansService;
|
||||
import com.imooc.service.UserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "FansController 粉丝相关业务功能的接口")
|
||||
@RequestMapping("fans")
|
||||
@RestController
|
||||
public class FansController extends BaseInfoProperties {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private FansService fansService;
|
||||
|
||||
@PostMapping("follow")
|
||||
public GraceJSONResult follow(@RequestParam String myId,
|
||||
@RequestParam String vlogerId) {
|
||||
|
||||
// 判断两个id不能为空
|
||||
if (StringUtils.isBlank(myId) || StringUtils.isBlank(vlogerId)) {
|
||||
return GraceJSONResult.errorCustom(ResponseStatusEnum.SYSTEM_ERROR);
|
||||
}
|
||||
|
||||
// 判断当前用户,自己不能关注自己
|
||||
if (myId.equalsIgnoreCase(vlogerId)) {
|
||||
return GraceJSONResult.errorCustom(ResponseStatusEnum.SYSTEM_RESPONSE_NO_INFO);
|
||||
}
|
||||
|
||||
// 判断两个id对应的用户是否存在
|
||||
Users vloger = userService.getUser(vlogerId);
|
||||
Users myInfo = userService.getUser(myId);
|
||||
|
||||
// fixme: 两个用户id的数据库查询后的判断,是分开好?还是合并判断好?
|
||||
if (myInfo == null || vloger == null) {
|
||||
return GraceJSONResult.errorCustom(ResponseStatusEnum.SYSTEM_RESPONSE_NO_INFO);
|
||||
}
|
||||
//
|
||||
// 保存粉丝关系到数据库
|
||||
fansService.doFollow(myId, vlogerId);
|
||||
|
||||
// 博主的粉丝+1,我的关注+1
|
||||
redis.increment(REDIS_MY_FOLLOWS_COUNTS + ":" + myId, 1);
|
||||
redis.increment(REDIS_MY_FANS_COUNTS + ":" + vlogerId, 1);
|
||||
|
||||
// 我和博主的关联关系,依赖redis,不要存储数据库,避免db的性能瓶颈
|
||||
redis.set(REDIS_FANS_AND_VLOGGER_RELATIONSHIP + ":" + myId + ":" + vlogerId, "1");
|
||||
//
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
@PostMapping("cancel")
|
||||
public GraceJSONResult cancel(@RequestParam String myId,
|
||||
@RequestParam String vlogerId) {
|
||||
|
||||
// 删除业务的执行
|
||||
fansService.doCancel(myId, vlogerId);
|
||||
|
||||
// 博主的粉丝-1,我的关注-1
|
||||
redis.decrement(REDIS_MY_FOLLOWS_COUNTS + ":" + myId, 1);
|
||||
redis.decrement(REDIS_MY_FANS_COUNTS + ":" + vlogerId, 1);
|
||||
|
||||
// 我和博主的关联关系,依赖redis,不要存储数据库,避免db的性能瓶颈
|
||||
redis.del(REDIS_FANS_AND_VLOGGER_RELATIONSHIP + ":" + myId + ":" + vlogerId);
|
||||
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
@GetMapping("queryDoIFollowVloger")
|
||||
public GraceJSONResult queryDoIFollowVloger(@RequestParam String myId,
|
||||
@RequestParam String vlogerId) {
|
||||
return GraceJSONResult.ok(fansService.queryDoIFollowVloger(myId, vlogerId));
|
||||
}
|
||||
|
||||
@GetMapping("queryMyFollows")
|
||||
public GraceJSONResult queryMyFollows(@RequestParam String myId,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
return GraceJSONResult.ok(
|
||||
fansService.queryMyFollows(
|
||||
myId,
|
||||
page,
|
||||
pageSize));
|
||||
}
|
||||
|
||||
@GetMapping("queryMyFans")
|
||||
public GraceJSONResult queryMyFans(@RequestParam String myId,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
return GraceJSONResult.ok(
|
||||
fansService.queryMyFans(
|
||||
myId,
|
||||
page,
|
||||
pageSize));
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.imooc.controller;
|
||||
|
||||
|
||||
import com.imooc.config.MinIOConfig;
|
||||
import com.imooc.grace.result.GraceJSONResult;
|
||||
import com.imooc.utils.MinIOUtils;
|
||||
import com.imooc.utils.SMSUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "FileController 文件上传测试的接口")
|
||||
@RestController
|
||||
public class FileController {
|
||||
|
||||
@Autowired
|
||||
private MinIOConfig minIOConfig;
|
||||
|
||||
@PostMapping("upload")
|
||||
public GraceJSONResult upload(MultipartFile file) throws Exception {
|
||||
|
||||
String fileName = file.getOriginalFilename();
|
||||
|
||||
MinIOUtils.uploadFile(minIOConfig.getBucketName(),
|
||||
fileName,
|
||||
file.getInputStream());
|
||||
|
||||
String imgUrl = minIOConfig.getFileHost()
|
||||
+ "/"
|
||||
+ minIOConfig.getBucketName()
|
||||
+ "/"
|
||||
+ fileName;
|
||||
|
||||
return GraceJSONResult.ok(imgUrl);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.imooc.controller;
|
||||
|
||||
import com.imooc.base.BaseInfoProperties;
|
||||
import com.imooc.grace.result.GraceJSONResult;
|
||||
import com.imooc.mo.MessageMO;
|
||||
import com.imooc.service.MsgService;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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 java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "MsgController 消息功能模块的接口")
|
||||
@RequestMapping("msg")
|
||||
@RestController
|
||||
public class MsgController extends BaseInfoProperties {
|
||||
|
||||
@Autowired
|
||||
private MsgService msgService;
|
||||
|
||||
@GetMapping("list")
|
||||
public GraceJSONResult list(@RequestParam String userId,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
|
||||
// mongodb 从0分页,区别于数据库
|
||||
if (page == null) {
|
||||
page = COMMON_START_PAGE_ZERO;
|
||||
}
|
||||
if (pageSize == null) {
|
||||
pageSize = COMMON_PAGE_SIZE;
|
||||
}
|
||||
|
||||
List<MessageMO> list = msgService.queryList(userId, page, pageSize);
|
||||
|
||||
return GraceJSONResult.ok(list);
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.imooc.controller;
|
||||
|
||||
import com.imooc.base.BaseInfoProperties;
|
||||
import com.imooc.bo.RegistLoginBO;
|
||||
import com.imooc.grace.result.GraceJSONResult;
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
import com.imooc.pojo.Users;
|
||||
import com.imooc.service.UserService;
|
||||
import com.imooc.utils.IPUtil;
|
||||
import com.imooc.utils.SMSUtils;
|
||||
import com.imooc.vo.UsersVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author vercen
|
||||
* @version 1.0
|
||||
* @date 2023/5/25 10:47
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("passport")
|
||||
@Api(tags = "通行证,验证码登录注册")
|
||||
public class PassportController extends BaseInfoProperties {
|
||||
@Autowired
|
||||
SMSUtils smsUtils;
|
||||
@Autowired
|
||||
UserService userService;
|
||||
@PostMapping("getSMSCode")
|
||||
public Object getSMSCode(@RequestParam String mobile, HttpServletRequest request) throws Exception {
|
||||
if (StringUtils.isBlank(mobile)){
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
//TODO 获得用户ip 限制时间60s只能1次
|
||||
String userIp=IPUtil.getRequestIp(request);
|
||||
|
||||
redis.setnx60s(MOBILE_SMSCODE+":"+userIp, userIp);
|
||||
String code=(int)((Math.random()*9+1)*100000)+"";
|
||||
|
||||
smsUtils.sendSMS(mobile,code);
|
||||
|
||||
log.info(code);
|
||||
redis.set(MOBILE_SMSCODE+":"+mobile, code,30*60);
|
||||
//TODO 验证码放入redis
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
@PostMapping("login")
|
||||
public Object login(@Valid @RequestBody RegistLoginBO registLoginBO){
|
||||
|
||||
String rediscode = redis.get(MOBILE_SMSCODE + ":" + registLoginBO.getMobile());
|
||||
|
||||
if (StringUtils.isBlank(rediscode)|| !rediscode.equalsIgnoreCase(registLoginBO.getSmsCode())){
|
||||
System.out.println("rediscode"+rediscode);
|
||||
System.out.println("registLoginBO.getMobile()"+registLoginBO.getSmsCode());
|
||||
return GraceJSONResult.errorCustom(ResponseStatusEnum.SMS_CODE_ERROR);
|
||||
}
|
||||
|
||||
Users user = userService.queryMobileIsExist(registLoginBO.getMobile());
|
||||
if (user==null){
|
||||
user = userService.createUser(registLoginBO.getMobile());
|
||||
}
|
||||
String uToken = UUID.randomUUID().toString();
|
||||
redis.set(REDIS_USER_TOKEN+":"+user.getId(),uToken);
|
||||
|
||||
//清除验证码
|
||||
redis.del(MOBILE_SMSCODE+":"+user.getMobile());
|
||||
|
||||
//返回给前端
|
||||
UsersVO usersVO = new UsersVO();
|
||||
BeanUtils.copyProperties(user, usersVO);
|
||||
usersVO.setUserToken(uToken);
|
||||
|
||||
return GraceJSONResult.ok(usersVO);
|
||||
|
||||
}
|
||||
|
||||
@PostMapping("logout")
|
||||
public Object logout(@RequestParam String userId){
|
||||
|
||||
redis.del(REDIS_USER_TOKEN+":"+userId);
|
||||
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.imooc.controller;
|
||||
|
||||
import com.imooc.base.RabbitMQConfig;
|
||||
import com.imooc.enums.MessageEnum;
|
||||
import com.imooc.exceptions.GraceException;
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
import com.imooc.mo.MessageMO;
|
||||
import com.imooc.service.MsgService;
|
||||
import com.imooc.utils.JsonUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class RabbitMQConsumer {
|
||||
|
||||
@Autowired
|
||||
private MsgService msgService;
|
||||
|
||||
@RabbitListener(queues = {RabbitMQConfig.QUEUE_SYS_MSG})
|
||||
public void watchQueue(String payload, Message message) {
|
||||
log.info(payload);
|
||||
|
||||
MessageMO messageMO = JsonUtils.jsonToPojo(payload, MessageMO.class);
|
||||
|
||||
String routingKey = message.getMessageProperties().getReceivedRoutingKey();
|
||||
log.info(routingKey);
|
||||
|
||||
// TODO: 下面这段代码可以优化,一个地方是参数优化,另外是枚举的判断优化
|
||||
|
||||
if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.FOLLOW_YOU.enValue)) {
|
||||
msgService.createMsg(messageMO.getFromUserId(),
|
||||
messageMO.getToUserId(),
|
||||
MessageEnum.FOLLOW_YOU.type,
|
||||
null);
|
||||
} else if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.LIKE_VLOG.enValue)) {
|
||||
msgService.createMsg(messageMO.getFromUserId(),
|
||||
messageMO.getToUserId(),
|
||||
MessageEnum.FOLLOW_YOU.type,
|
||||
messageMO.getMsgContent());
|
||||
} else if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.COMMENT_VLOG.enValue)) {
|
||||
msgService.createMsg(messageMO.getFromUserId(),
|
||||
messageMO.getToUserId(),
|
||||
MessageEnum.COMMENT_VLOG.type,
|
||||
messageMO.getMsgContent());
|
||||
} else if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.REPLY_YOU.enValue)) {
|
||||
msgService.createMsg(messageMO.getFromUserId(),
|
||||
messageMO.getToUserId(),
|
||||
MessageEnum.REPLY_YOU.type,
|
||||
messageMO.getMsgContent());
|
||||
} else if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.LIKE_COMMENT.enValue)) {
|
||||
msgService.createMsg(messageMO.getFromUserId(),
|
||||
messageMO.getToUserId(),
|
||||
MessageEnum.LIKE_COMMENT.type,
|
||||
messageMO.getMsgContent());
|
||||
} else {
|
||||
GraceException.display(ResponseStatusEnum.SYSTEM_OPERATION_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
package com.imooc.controller;
|
||||
|
||||
import com.imooc.base.BaseInfoProperties;
|
||||
import com.imooc.bo.UpdatedUserBO;
|
||||
import com.imooc.config.MinIOConfig;
|
||||
import com.imooc.enums.FileTypeEnum;
|
||||
import com.imooc.enums.UserInfoModifyType;
|
||||
import com.imooc.grace.result.GraceJSONResult;
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
import com.imooc.pojo.Users;
|
||||
import com.imooc.service.UserService;
|
||||
import com.imooc.utils.MinIOUtils;
|
||||
import com.imooc.utils.SMSUtils;
|
||||
import com.imooc.vo.UsersVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* @author vercen
|
||||
* @version 1.0
|
||||
* @date 2023/5/20 14:32
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
@Api(tags = "UserInfoController用户信息接口模块")
|
||||
@RequestMapping("userInfo")
|
||||
public class UserInfoController extends BaseInfoProperties {
|
||||
|
||||
@Autowired
|
||||
UserService userService;
|
||||
|
||||
// @ResponseBody
|
||||
@ApiOperation(value = "根据userId返回个人信息")
|
||||
@GetMapping("query")
|
||||
public Object query(@RequestParam String userId){
|
||||
Users user = userService.getUser(userId);
|
||||
|
||||
UsersVO usersVO = new UsersVO();
|
||||
BeanUtils.copyProperties(user, usersVO);
|
||||
|
||||
|
||||
// 我的关注博主总数量
|
||||
String myFollowsCountsStr = redis.get(REDIS_MY_FOLLOWS_COUNTS + ":" + userId);
|
||||
// 我的粉丝总数
|
||||
String myFansCountsStr = redis.get(REDIS_MY_FANS_COUNTS + ":" + userId);
|
||||
// 用户获赞总数,视频博主(点赞/喜欢)总和
|
||||
// String likedVlogCountsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + userId);
|
||||
String likedVlogerCountsStr = redis.get(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + userId);
|
||||
|
||||
Integer myFollowsCounts = 0;
|
||||
Integer myFansCounts = 0;
|
||||
Integer likedVlogCounts = 0;
|
||||
Integer likedVlogerCounts = 0;
|
||||
Integer totalLikeMeCounts = 0;
|
||||
|
||||
|
||||
if (StringUtils.isNotBlank(myFollowsCountsStr)) {
|
||||
myFollowsCounts = Integer.valueOf(myFollowsCountsStr);
|
||||
}
|
||||
if (StringUtils.isNotBlank(myFansCountsStr)) {
|
||||
myFansCounts = Integer.valueOf(myFansCountsStr);
|
||||
}
|
||||
// if (StringUtils.isNotBlank(likedVlogCountsStr)) {
|
||||
// likedVlogCounts = Integer.valueOf(likedVlogCountsStr);
|
||||
// }
|
||||
if (StringUtils.isNotBlank(likedVlogerCountsStr)) {
|
||||
likedVlogerCounts = Integer.valueOf(likedVlogerCountsStr);
|
||||
}
|
||||
totalLikeMeCounts = likedVlogCounts + likedVlogerCounts;
|
||||
|
||||
usersVO.setMyFollowsCounts(myFollowsCounts);
|
||||
usersVO.setMyFansCounts(myFansCounts);
|
||||
usersVO.setTotalLikeMeCounts(totalLikeMeCounts);
|
||||
|
||||
//usersVO.setMyFansCounts((Integer) myFansCounts);
|
||||
|
||||
return GraceJSONResult.ok(usersVO);
|
||||
}
|
||||
|
||||
@PostMapping("modifyUserInfo")
|
||||
public GraceJSONResult modifyUserInfo(@RequestBody UpdatedUserBO updatedUserBO, @RequestParam Integer type) throws Exception {
|
||||
|
||||
UserInfoModifyType.checkUserInfoTypeIsRight(type);
|
||||
Users newUserInfo = userService.updateUserInfo(updatedUserBO, type);
|
||||
return GraceJSONResult.ok(newUserInfo);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private MinIOConfig minIOConfig;
|
||||
|
||||
@PostMapping("modifyImage")
|
||||
public GraceJSONResult modifyImage(@RequestParam String userId,
|
||||
@RequestParam Integer type,
|
||||
MultipartFile file) throws Exception {
|
||||
|
||||
if (type != FileTypeEnum.BGIMG.type && type != FileTypeEnum.FACE.type) {
|
||||
return GraceJSONResult.errorCustom(ResponseStatusEnum.FILE_UPLOAD_FAILD);
|
||||
}
|
||||
|
||||
String fileName = file.getOriginalFilename();
|
||||
|
||||
MinIOUtils.uploadFile(minIOConfig.getBucketName(),
|
||||
fileName,
|
||||
file.getInputStream());
|
||||
|
||||
String imgUrl = minIOConfig.getFileHost()
|
||||
+ "/"
|
||||
+ minIOConfig.getBucketName()
|
||||
+ "/"
|
||||
+ fileName;
|
||||
|
||||
|
||||
// 修改图片地址到数据库
|
||||
UpdatedUserBO updatedUserBO = new UpdatedUserBO();
|
||||
updatedUserBO.setId(userId);
|
||||
|
||||
if (type == FileTypeEnum.BGIMG.type) {
|
||||
updatedUserBO.setBgImg(imgUrl);
|
||||
} else {
|
||||
updatedUserBO.setFace(imgUrl);
|
||||
}
|
||||
Users users = userService.updateUserInfo(updatedUserBO);
|
||||
|
||||
return GraceJSONResult.ok(users);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
225
book-api/src/main/java/com/imooc/controller/VlogController.java
Normal file
225
book-api/src/main/java/com/imooc/controller/VlogController.java
Normal file
@ -0,0 +1,225 @@
|
||||
package com.imooc.controller;
|
||||
|
||||
import com.imooc.base.BaseInfoProperties;
|
||||
import com.imooc.bo.VlogBO;
|
||||
import com.imooc.enums.YesOrNo;
|
||||
import com.imooc.grace.result.GraceJSONResult;
|
||||
import com.imooc.service.VlogService;
|
||||
import com.imooc.utils.PagedGridResult;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "VlogController 短视频相关业务功能的接口")
|
||||
@RequestMapping("vlog")
|
||||
@RestController
|
||||
@RefreshScope
|
||||
public class VlogController extends BaseInfoProperties {
|
||||
|
||||
@Autowired
|
||||
private VlogService vlogService;
|
||||
|
||||
@PostMapping("publish")
|
||||
public GraceJSONResult publish(@RequestBody VlogBO vlogBO) {
|
||||
// FIXME 作业,校验VlogBO
|
||||
vlogService.createVlog(vlogBO);
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
@GetMapping("indexList")
|
||||
public GraceJSONResult indexList(@RequestParam(defaultValue = "") String userId,
|
||||
@RequestParam(defaultValue = "") String search,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
|
||||
if (page == null) {
|
||||
page = COMMON_START_PAGE;
|
||||
}
|
||||
if (pageSize == null) {
|
||||
pageSize = COMMON_PAGE_SIZE;
|
||||
}
|
||||
|
||||
PagedGridResult gridResult = vlogService.getIndexVlogList(userId, search, page, pageSize);
|
||||
return GraceJSONResult.ok(gridResult);
|
||||
}
|
||||
|
||||
@GetMapping("detail")
|
||||
public GraceJSONResult detail(@RequestParam(defaultValue = "") String userId,
|
||||
@RequestParam String vlogId) {
|
||||
return GraceJSONResult.ok(vlogService.getVlogDetailById(userId, vlogId));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("changeToPrivate")
|
||||
public GraceJSONResult changeToPrivate(@RequestParam String userId,
|
||||
@RequestParam String vlogId) {
|
||||
vlogService.changeToPrivateOrPublic(userId,
|
||||
vlogId,
|
||||
YesOrNo.YES.type);
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
@PostMapping("changeToPublic")
|
||||
public GraceJSONResult changeToPublic(@RequestParam String userId,
|
||||
@RequestParam String vlogId) {
|
||||
vlogService.changeToPrivateOrPublic(userId,
|
||||
vlogId,
|
||||
YesOrNo.NO.type);
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping("myPublicList")
|
||||
public GraceJSONResult myPublicList(@RequestParam String userId,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
|
||||
if (page == null) {
|
||||
page = COMMON_START_PAGE;
|
||||
}
|
||||
if (pageSize == null) {
|
||||
pageSize = COMMON_PAGE_SIZE;
|
||||
}
|
||||
|
||||
PagedGridResult gridResult = vlogService.queryMyVlogList(userId,
|
||||
page,
|
||||
pageSize,
|
||||
YesOrNo.NO.type);
|
||||
return GraceJSONResult.ok(gridResult);
|
||||
}
|
||||
|
||||
@GetMapping("myPrivateList")
|
||||
public GraceJSONResult myPrivateList(@RequestParam String userId,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
|
||||
if (page == null) {
|
||||
page = COMMON_START_PAGE;
|
||||
}
|
||||
if (pageSize == null) {
|
||||
pageSize = COMMON_PAGE_SIZE;
|
||||
}
|
||||
|
||||
PagedGridResult gridResult = vlogService.queryMyVlogList(userId,
|
||||
page,
|
||||
pageSize,
|
||||
YesOrNo.YES.type);
|
||||
return GraceJSONResult.ok(gridResult);
|
||||
}
|
||||
|
||||
@GetMapping("myLikedList")
|
||||
public GraceJSONResult myLikedList(@RequestParam String userId,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
|
||||
if (page == null) {
|
||||
page = COMMON_START_PAGE;
|
||||
}
|
||||
if (pageSize == null) {
|
||||
pageSize = COMMON_PAGE_SIZE;
|
||||
}
|
||||
|
||||
PagedGridResult gridResult = vlogService.getMyLikedVlogList(userId,
|
||||
page,
|
||||
pageSize);
|
||||
return GraceJSONResult.ok(gridResult);
|
||||
}
|
||||
|
||||
@Value(("${nacos.counts}"))
|
||||
private Integer nacosConuts;
|
||||
|
||||
|
||||
@PostMapping("like")
|
||||
public GraceJSONResult like(@RequestParam String userId,
|
||||
@RequestParam String vlogerId,
|
||||
@RequestParam String vlogId) {
|
||||
|
||||
// 我点赞的视频,关联关系保存到数据库
|
||||
vlogService.userLikeVlog(userId, vlogId);
|
||||
|
||||
// 点赞后,视频和视频发布者的获赞都会 +1
|
||||
redis.increment(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlogerId, 1);
|
||||
redis.increment(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
|
||||
|
||||
// 我点赞的视频,需要在redis中保存关联关系
|
||||
redis.set(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId, "1");
|
||||
|
||||
log.info("nacosConuts="+nacosConuts);
|
||||
|
||||
String countsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
|
||||
Integer counts=0;
|
||||
if (StringUtils.isNotBlank(countsStr)){
|
||||
|
||||
counts=Integer.valueOf(countsStr);
|
||||
if (counts>=nacosConuts){
|
||||
|
||||
vlogService.flushCounts(vlogId, counts);
|
||||
}
|
||||
}
|
||||
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("unlike")
|
||||
public GraceJSONResult unlike(@RequestParam String userId,
|
||||
@RequestParam String vlogerId,
|
||||
@RequestParam String vlogId) {
|
||||
|
||||
// 我取消点赞的视频,关联关系删除
|
||||
vlogService.userUnLikeVlog(userId, vlogId);
|
||||
|
||||
redis.decrement(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlogerId, 1);
|
||||
redis.decrement(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
|
||||
redis.del(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId);
|
||||
|
||||
return GraceJSONResult.ok();
|
||||
}
|
||||
|
||||
@PostMapping("totalLikedCounts")
|
||||
public GraceJSONResult totalLikedCounts(@RequestParam String vlogId) {
|
||||
return GraceJSONResult.ok(vlogService.getVlogBeLikedCounts(vlogId));
|
||||
}
|
||||
|
||||
@GetMapping("followList")
|
||||
public GraceJSONResult followList(@RequestParam String myId,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
|
||||
if (page == null) {
|
||||
page = COMMON_START_PAGE;
|
||||
}
|
||||
if (pageSize == null) {
|
||||
pageSize = COMMON_PAGE_SIZE;
|
||||
}
|
||||
|
||||
PagedGridResult gridResult = vlogService.getMyFollowVlogList(myId,
|
||||
page,
|
||||
pageSize);
|
||||
return GraceJSONResult.ok(gridResult);
|
||||
}
|
||||
|
||||
@GetMapping("friendList")
|
||||
public GraceJSONResult friendList(@RequestParam String myId,
|
||||
@RequestParam Integer page,
|
||||
@RequestParam Integer pageSize) {
|
||||
|
||||
if (page == null) {
|
||||
page = COMMON_START_PAGE;
|
||||
}
|
||||
if (pageSize == null) {
|
||||
pageSize = COMMON_PAGE_SIZE;
|
||||
}
|
||||
|
||||
PagedGridResult gridResult = vlogService.getMyFriendVlogList(myId,
|
||||
page,
|
||||
pageSize);
|
||||
return GraceJSONResult.ok(gridResult);
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package com.imooc.intercepter;
|
||||
|
||||
import com.imooc.base.BaseInfoProperties;
|
||||
import com.imooc.exceptions.GraceException;
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
import com.imooc.utils.IPUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@Slf4j
|
||||
public class PassportInterceptor extends BaseInfoProperties implements HandlerInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request,
|
||||
HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
// 获得用户的ip
|
||||
String userIp = IPUtil.getRequestIp(request);
|
||||
|
||||
// 得到是否存在的判断
|
||||
boolean keyIsExist = redis.keyIsExist(MOBILE_SMSCODE + ":" + userIp);
|
||||
|
||||
if (keyIsExist) {
|
||||
GraceException.display(ResponseStatusEnum.SMS_NEED_WAIT_ERROR);
|
||||
log.info("短信发送频率太大!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* true: 请求放行
|
||||
* false: 请求拦截
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.imooc.intercepter;
|
||||
|
||||
import com.imooc.base.BaseInfoProperties;
|
||||
import com.imooc.exceptions.GraceException;
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@Slf4j
|
||||
public class UserTokenInterceptor extends BaseInfoProperties implements HandlerInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request,
|
||||
HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
|
||||
// 从header中获得用户id和token
|
||||
String userId = request.getHeader("headerUserId");
|
||||
String userToken = request.getHeader("headerUserToken");
|
||||
|
||||
// 判断header中用户id和token不能为空
|
||||
if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(userToken)) {
|
||||
String redisToken = redis.get(REDIS_USER_TOKEN + ":" + userId);
|
||||
if (StringUtils.isBlank(redisToken)) {
|
||||
GraceException.display(ResponseStatusEnum.UN_LOGIN);
|
||||
return false;
|
||||
} else {
|
||||
// 比较token是否一致,如果不一致,表示用户在别的手机端登录
|
||||
if (!redisToken.equalsIgnoreCase(userToken)) {
|
||||
GraceException.display(ResponseStatusEnum.TICKET_INVALID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GraceException.display(ResponseStatusEnum.UN_LOGIN);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* true: 请求放行
|
||||
* false: 请求拦截
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
}
|
||||
}
|
65
book-api/src/main/resources/application-dev.yml
Normal file
65
book-api/src/main/resources/application-dev.yml
Normal file
@ -0,0 +1,65 @@
|
||||
server:
|
||||
port: ${port:8099}
|
||||
|
||||
spring:
|
||||
datasource: # 数据源的相关配置
|
||||
type: com.zaxxer.hikari.HikariDataSource # 数据源的类型,可以更改为其他的数据源配置,比如druid
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver # mysql/MariaDB 的数据库驱动类名称
|
||||
url: jdbc:mysql://182.92.182.217:3306/tiktok?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
|
||||
username: tiktok
|
||||
password: Bc3T5AA2pBdt2FBk
|
||||
hikari:
|
||||
connection-timeout: 30000 # 等待连接池分配连接的最大时间(毫秒),超过这个时长还没有可用的连接,则会抛出SQLException
|
||||
minimum-idle: 5 # 最小连接数
|
||||
maximum-pool-size: 20 # 最大连接数
|
||||
auto-commit: true # 自动提交
|
||||
idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则会被释放(retired)
|
||||
pool-name: DataSourceHikariCP # 连接池的名字
|
||||
max-lifetime: 18000000 # 连接池的最大生命时长(毫秒),超时则会被释放(retired)
|
||||
connection-test-query: SELECT 1
|
||||
redis:
|
||||
host: 182.92.182.217
|
||||
port: 6379
|
||||
password: '!aw5)lJf'
|
||||
database: 1 # 使用的数据库编号
|
||||
jedis:
|
||||
pool:
|
||||
max-idle: 6 # 最大空闲连接
|
||||
max-active: 32 # 连接池最大连接数
|
||||
max-wait: 100 # 连接池最大阻塞等待时间, -1表示没有限制
|
||||
min-idle: 4 # 最小空闲连接
|
||||
timeout: 50000
|
||||
data:
|
||||
mongodb:
|
||||
# uri: mongodb://root:root@192.168.1.202:27017
|
||||
# database: imooc-red-book
|
||||
uri: mongodb://admin:A1969bf8@82.156.121.2:37017/admin
|
||||
rabbitmq:
|
||||
host: 182.92.182.217
|
||||
port: 5672
|
||||
username: admin
|
||||
password: 123123
|
||||
virtual-host: imooc-red-book
|
||||
application:
|
||||
name: imooc-red-book-nacos
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 182.92.182.217:8848 # nacos 所在的地址
|
||||
|
||||
# 打开监控
|
||||
management:
|
||||
endpoint:
|
||||
web:
|
||||
exposure:
|
||||
include: '*'
|
||||
|
||||
# MinIO 配置
|
||||
minio:
|
||||
endpoint: http://82.156.121.2:29000 # MinIO服务地址
|
||||
fileHost: http://82.156.121.2:29000 # 文件地址host
|
||||
bucketName: bucket # 存储桶bucket名称
|
||||
accessKey: NJ2GN2wLVkMnyrznbE9t # 用户名
|
||||
secretKey: nrT3e3pRWF5HXQRiIxxDhq20eJ0YrN8lvx5p8bK6 # 密码
|
||||
imgSize: 1024 # 图片大小限制,单位:m
|
||||
fileSize: 1024 # 文件大小限制,单位:m
|
65
book-api/src/main/resources/application-prod.yml
Normal file
65
book-api/src/main/resources/application-prod.yml
Normal file
@ -0,0 +1,65 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
datasource: # 数据源的相关配置
|
||||
type: com.zaxxer.hikari.HikariDataSource # 数据源的类型,可以更改为其他的数据源配置,比如druid
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver # mysql/MariaDB 的数据库驱动类名称
|
||||
url: jdbc:mysql://182.92.182.217/tiktok?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
|
||||
username: tiktok
|
||||
password: Bc3T5AA2pBdt2FBk
|
||||
hikari:
|
||||
connection-timeout: 30000 # 等待连接池分配连接的最大时间(毫秒),超过这个时长还没有可用的连接,则会抛出SQLException
|
||||
minimum-idle: 5 # 最小连接数
|
||||
maximum-pool-size: 20 # 最大连接数
|
||||
auto-commit: true # 自动提交
|
||||
idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则会被释放(retired)
|
||||
pool-name: DataSourceHikariCP # 连接池的名字
|
||||
max-lifetime: 18000000 # 连接池的最大生命时长(毫秒),超时则会被释放(retired)
|
||||
connection-test-query: SELECT 1
|
||||
redis:
|
||||
host: 182.92.182.217
|
||||
port: 6379
|
||||
password: '!aw5)lJf'
|
||||
database: 1 # 使用的数据库编号
|
||||
jedis:
|
||||
pool:
|
||||
max-idle: 6 # 最大空闲连接
|
||||
max-active: 32 # 连接池最大连接数
|
||||
max-wait: 100 # 连接池最大阻塞等待时间, -1表示没有限制
|
||||
min-idle: 4 # 最小空闲连接
|
||||
timeout: 50000
|
||||
data:
|
||||
mongodb:
|
||||
uri: mongodb://admin:A1969bf8@82.156.121.2:37017/admin
|
||||
rabbitmq:
|
||||
host: 182.92.182.217
|
||||
port: 5672
|
||||
username: admin
|
||||
password: 123123
|
||||
virtual-host: imooc-red-book
|
||||
application:
|
||||
name: imooc-red-book-nacos
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 182.92.182.217:8848 # nacos 所在的地址
|
||||
|
||||
|
||||
# 打开监控
|
||||
management:
|
||||
endpoint:
|
||||
web:
|
||||
exposure:
|
||||
include: '*'
|
||||
|
||||
|
||||
# MinIO 配置
|
||||
minio:
|
||||
endpoint: http://82.156.121.2:29000 # MinIO服务地址
|
||||
fileHost: http://82.156.121.2:29000 # 文件地址host
|
||||
bucketName: bucket # 存储桶bucket名称
|
||||
accessKey: NJ2GN2wLVkMnyrznbE9t # 用户名
|
||||
secretKey: nrT3e3pRWF5HXQRiIxxDhq20eJ0YrN8lvx5p8bK6 # 密码
|
||||
imgSize: 1024 # 图片大小限制,单位:m
|
||||
fileSize: 1024 # 文件大小限制,单位:m
|
43
book-api/src/main/resources/application.yml
Normal file
43
book-api/src/main/resources/application.yml
Normal file
@ -0,0 +1,43 @@
|
||||
server:
|
||||
# port: 8099
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
max-swallow-size: -1 # tomcat默认大小2M,超过2M的文件不会被捕获,需要调整此处大小为100MB或者-1即可
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: imooc-red-book-nacos
|
||||
profiles:
|
||||
active: dev
|
||||
nacos:
|
||||
counts: 10
|
||||
banner:
|
||||
location: classpath:banner/banner.txt
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 1024MB # 文件上传大小限制,设置最大值,不能超过该值,否则报错
|
||||
# max-file-size: 500KB # 文件上传大小限制,设置最大值,不能超过该值,否则报错
|
||||
max-request-size: 1024MB # 文件最大请求限制,用于批量上传
|
||||
# max-request-size: 500KB
|
||||
nacos:
|
||||
counts: 10
|
||||
# 整合mybatis
|
||||
mybatis:
|
||||
type-aliases-package: com.imooc.pojo # 所有pojo类所在的包路径
|
||||
mapper-locations: classpath:mapper/*.xml # mapper映射文件
|
||||
|
||||
# 通用mapper工具的配置
|
||||
mapper:
|
||||
mappers: com.imooc.my.mapper.MyMapper # 配置MyMapper,包含了一些封装好的CRUD方法
|
||||
not-empty: false # 在进行数据库操作的时候,username != null 是否会追加 username != ''
|
||||
identity: MYSQL
|
||||
|
||||
# 分页插件助手的配置
|
||||
pagehelper:
|
||||
helper-dialect: MYSQL
|
||||
support-methods-arguments: true
|
||||
|
||||
# 日志级别
|
||||
logging:
|
||||
level:
|
||||
root: info
|
22
book-api/src/main/resources/banner/banner.txt
Normal file
22
book-api/src/main/resources/banner/banner.txt
Normal file
@ -0,0 +1,22 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// _ooOoo_ //
|
||||
// o8888888o //
|
||||
// 88" . "88 //
|
||||
// (| ^_^ |) //
|
||||
// O\ = /O //
|
||||
// ____/`---'\____ //
|
||||
// .' \\| |// `. //
|
||||
// / \\||| : |||// \ //
|
||||
// / _||||| -:- |||||- \ //
|
||||
// | | \\\ - /// | | //
|
||||
// | \_| ''\---/'' | | //
|
||||
// \ .-\__ `-` ___/-. / //
|
||||
// ___`. .' /--.--\ `. . ___ //
|
||||
// ."" '< `.___\_<|>_/___.' >'"". //
|
||||
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
|
||||
// \ \ `-. \_ __\ /__ _/ .-` / / //
|
||||
// ========`-.____`-.___\_____/___.-`____.-'======== //
|
||||
// `=---=' //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// 佛祖保佑 永无BUG 永不修改 //
|
||||
////////////////////////////////////////////////////////////////////
|
BIN
book-api/src/main/resources/banner/cat.png
Normal file
BIN
book-api/src/main/resources/banner/cat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 897 KiB |
57
book-api/src/main/resources/banner/qiaoba.txt
Normal file
57
book-api/src/main/resources/banner/qiaoba.txt
Normal file
@ -0,0 +1,57 @@
|
||||
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttjtttjttjjtjW#Li;;ijE#Ettttjttjjjtttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttjtttLGtWtttt#i;itttttttjti;tWtttjWtDEjtttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttjjjttfjLjWtEjjtjtjttttttjjtjttLWt;jEjjttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttDf;tjt;jWjjfLtttttttttttttttttttLDjjjjEtjj#ELttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttt#DjGjfjtjjtjjfLttttttttttttttttttjL#jjjjtttjtfLGfjtttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttjfLjGttWjjjjLLtttttttttttttttttttLEjjjjjtttjjjjDjtttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttjjjjDttLjjjjLLttttttttttttttttttjLLjLjjjttijjjjLjtttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttjjjjjtttjjjfLLtttttttWEttf jtttttLDjLjjjjttEjfjLttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttijjjjjtjDjjjjLLjttttjG GL :jttttLWjjjjttKjWjKjKttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttijjjWjGjfjLjjLLjttttt,. ftttjLGjjtttj;jjj#jKjtttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttEj#ffjjjfjjjWfLfjtttttf KtttttfLL;jjffjjLjjjjjttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttjjtjjjjjfLj#fLftttttjf tttttLLL#fjfjjjfjKjfttjttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttDjjjjjjLjGj#LLLttttjD . . .jtttLLLWGGffjjjGjtjtttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttj;jjjjGLLDt#LLLtjjtjK Ej jtttLLLWjKLLLjjjjWttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttjGLLLLLLWKGLLttjtEWL;;;fKKjtttfWEWDLfLLLGWttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttfLLLfLGLD,,;ttjtttttti;;#LGLLLL#jttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttD::.#G;;jtjjjtttttjjtjtti;W:,:Wtttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttt;EjW,jtjjjjttjjttjtjtjjjjtj,Lj;jttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttE;;tjjtjjjKLLLLLLLLLGKjtjtjLLiWjttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttf,tjjttWLLLfLLLLLLLLfLfLKjtLLLfjttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttj,jjttEfLLLLLLLLLLLLLLLLLLLELLLLLttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttjittjtfLLLLLLLLfDEKDLfLfLfLfLLfLLLWtttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttjjffLLLLEGfjjjfjjjjjjGjKLLLfLfLLftjtttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttjjjLLLLKfjj;j;;;;;;;;,;jfjWLLLfLfLtttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttKLLLKf;ifj;i;;;;;;;j.E;;fLLLLGLLtttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttjtjLLLEG,;DWKWi;;;;;;;WWKE;;LfLLLLGtttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttWELLLLL;; WKKD;;;;;;jKKK.;;LLLLLWftttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttffLLLL:;EWKW,,;Di,;;KWKf;;fLLLLLjtttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttWLLLLLE;,E.;;;;;,;;;;tDi;#LLLLfDttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttKLLLLL;;;;;;;;tK,L;;;;;;LLLLfLtttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttjLLLLW,;;;;;EEED;;;;;;WLLLDtttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttttjtKEL,;;;;;EjjW;;;;;KtEGjjjttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttttjtttttW,,;;jttj,i;tWKffKfjtttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttDLjttfGWtjti,;Kjttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttDjittfj;,;;D;;;;ttttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttttttttttttE;;EEjWi;DGKj,iEjtjttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttt;,;;WWt;;;Dtttfttttttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttttttttttt;t;;;;;;;;;;Gtttttttttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttttttttjj,K;;;;;;;;;;;;jttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttjf;;j;;;;;;;;;;;;tttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttftGKE;;,;,,;;;;;ijttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttEfijDGGGGGGGGGGGKjttttttttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttttttttfjtGGGGGGGGGGEDWtttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttfEEDEEEEEEEKttttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttLDEWWEEEttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttttttttttjtttKWjtKWjttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttttEjtjjijtttttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttK,Gttf,fDtttttttttttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttttttttttttWjD;tt;,fWtttttttttttttttttttttttttttttttttttttttttttttt
|
||||
ttttttttttttttttttttttttttttttttttttttttttttttjttttttttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
|
||||
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
|
8
book-api/src/main/resources/bootstrap.yml
Normal file
8
book-api/src/main/resources/bootstrap.yml
Normal file
@ -0,0 +1,8 @@
|
||||
spring:
|
||||
application:
|
||||
name: imooc-red-book-nacos
|
||||
cloud:
|
||||
nacos:
|
||||
config:
|
||||
server-addr: 182.92.182.217:8848
|
||||
file-extension: yaml
|
116
book-common/pom.xml
Normal file
116
book-common/pom.xml
Normal file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.imooc</groupId>
|
||||
<artifactId>imooc-red-book-dev</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>book-common</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- 引入SpringBoot 依赖-->
|
||||
<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.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 引入 redis 依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 引入 RabbitMQ 依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- lombok工具 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<!-- apache 工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</dependency>
|
||||
<!-- google 工具类 -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<!-- joda-time 时间工具 -->
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--腾讯云短信-->
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java</artifactId>
|
||||
<version>3.1.270</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>8.2.1</version>
|
||||
</dependency>
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>com.aliyun</groupId>-->
|
||||
<!-- <artifactId>dysmsapi20170525</artifactId>-->
|
||||
<!-- <version>2.0.23</version>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
17
book-common/src/main/java/com/imooc/enums/FileTypeEnum.java
Normal file
17
book-common/src/main/java/com/imooc/enums/FileTypeEnum.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.imooc.enums;
|
||||
|
||||
/**
|
||||
* @Desc: 文件类型 枚举
|
||||
*/
|
||||
public enum FileTypeEnum {
|
||||
BGIMG(1, "用户背景图"),
|
||||
FACE(2, "用户头像");
|
||||
|
||||
public final Integer type;
|
||||
public final String value;
|
||||
|
||||
FileTypeEnum(Integer type, String value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
22
book-common/src/main/java/com/imooc/enums/MessageEnum.java
Normal file
22
book-common/src/main/java/com/imooc/enums/MessageEnum.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.imooc.enums;
|
||||
|
||||
/**
|
||||
* @Desc: 消息类型
|
||||
*/
|
||||
public enum MessageEnum {
|
||||
FOLLOW_YOU(1, "关注", "follow"),
|
||||
LIKE_VLOG(2, "点赞视频", "likeVideo"),
|
||||
COMMENT_VLOG(3, "评论视频", "comment"),
|
||||
REPLY_YOU(4, "回复评论", "replay"),
|
||||
LIKE_COMMENT(5, "点赞评论", "likeComment");
|
||||
|
||||
public final Integer type;
|
||||
public final String value;
|
||||
public final String enValue;
|
||||
|
||||
MessageEnum(Integer type, String value, String enValue) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.enValue = enValue;
|
||||
}
|
||||
}
|
18
book-common/src/main/java/com/imooc/enums/Sex.java
Normal file
18
book-common/src/main/java/com/imooc/enums/Sex.java
Normal file
@ -0,0 +1,18 @@
|
||||
package com.imooc.enums;
|
||||
|
||||
/**
|
||||
* @Desc: 性别 枚举
|
||||
*/
|
||||
public enum Sex {
|
||||
woman(0, "女"),
|
||||
man(1, "男"),
|
||||
secret(2, "保密");
|
||||
|
||||
public final Integer type;
|
||||
public final String value;
|
||||
|
||||
Sex(Integer type, String value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.imooc.enums;
|
||||
|
||||
import com.imooc.exceptions.GraceException;
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
|
||||
/**
|
||||
* @Desc: 修改用户信息类型 枚举
|
||||
*/
|
||||
public enum UserInfoModifyType {
|
||||
NICKNAME(1, "昵称"),
|
||||
IMOOCNUM(2, "慕课号"),
|
||||
SEX(3, "性别"),
|
||||
BIRTHDAY(4, "生日"),
|
||||
LOCATION(5, "所在地"),
|
||||
DESC(6, "简介");
|
||||
|
||||
public final Integer type;
|
||||
public final String value;
|
||||
|
||||
UserInfoModifyType(Integer type, String value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static void checkUserInfoTypeIsRight(Integer type) {
|
||||
if (type != UserInfoModifyType.NICKNAME.type &&
|
||||
type != UserInfoModifyType.IMOOCNUM.type &&
|
||||
type != UserInfoModifyType.SEX.type &&
|
||||
type != UserInfoModifyType.BIRTHDAY.type &&
|
||||
type != UserInfoModifyType.LOCATION.type &&
|
||||
type != UserInfoModifyType.DESC.type) {
|
||||
GraceException.display(ResponseStatusEnum.USER_INFO_UPDATED_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
17
book-common/src/main/java/com/imooc/enums/YesOrNo.java
Normal file
17
book-common/src/main/java/com/imooc/enums/YesOrNo.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.imooc.enums;
|
||||
|
||||
/**
|
||||
* @Desc: 是否 枚举
|
||||
*/
|
||||
public enum YesOrNo {
|
||||
NO(0, "否"),
|
||||
YES(1, "是");
|
||||
|
||||
public final Integer type;
|
||||
public final String value;
|
||||
|
||||
YesOrNo(Integer type, String value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.imooc.exceptions;
|
||||
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
|
||||
/**
|
||||
* 优雅的处理异常,统一封装
|
||||
*/
|
||||
public class GraceException {
|
||||
|
||||
public static void display(ResponseStatusEnum responseStatusEnum) {
|
||||
throw new MyCustomException(responseStatusEnum);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.imooc.exceptions;
|
||||
|
||||
import com.imooc.grace.result.GraceJSONResult;
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MaxUploadSizeExceededException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 统一异常拦截处理
|
||||
* 可以针对异常的类型进行捕获,然后返回json信息到前端
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class GraceExceptionHandler {
|
||||
|
||||
@ExceptionHandler(MyCustomException.class)
|
||||
@ResponseBody
|
||||
public GraceJSONResult returnMyException(MyCustomException e) {
|
||||
//e.printStackTrace();
|
||||
return GraceJSONResult.exception(e.getResponseStatusEnum());
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseBody
|
||||
public GraceJSONResult returnMethodArgumentNotValid(MethodArgumentNotValidException e) {
|
||||
BindingResult result = e.getBindingResult();
|
||||
Map<String, String> map = getErrors(result);
|
||||
return GraceJSONResult.errorMap(map);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MaxUploadSizeExceededException.class)
|
||||
@ResponseBody
|
||||
public GraceJSONResult returnMaxUploadSize(MaxUploadSizeExceededException e) {
|
||||
// e.printStackTrace();
|
||||
return GraceJSONResult.errorCustom(ResponseStatusEnum.FILE_MAX_SIZE_2MB_ERROR);
|
||||
}
|
||||
|
||||
public Map<String, String> getErrors(BindingResult result) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
List<FieldError> errorList = result.getFieldErrors();
|
||||
for (FieldError ff : errorList) {
|
||||
// 错误所对应的属性字段名
|
||||
String field = ff.getField();
|
||||
// 错误的信息
|
||||
String msg = ff.getDefaultMessage();
|
||||
map.put(field, msg);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.imooc.exceptions;
|
||||
|
||||
import com.imooc.grace.result.ResponseStatusEnum;
|
||||
|
||||
/**
|
||||
* 自定义异常
|
||||
* 目的:统一处理异常信息
|
||||
* 便于解耦,拦截器、service与controller 异常错误的解耦,
|
||||
* 不会被service返回的类型而限制
|
||||
*/
|
||||
public class MyCustomException extends RuntimeException {
|
||||
|
||||
private ResponseStatusEnum responseStatusEnum;
|
||||
|
||||
public MyCustomException(ResponseStatusEnum responseStatusEnum) {
|
||||
super("异常状态码为:" + responseStatusEnum.status()
|
||||
+ ";具体异常信息为:" + responseStatusEnum.msg());
|
||||
this.responseStatusEnum = responseStatusEnum;
|
||||
}
|
||||
|
||||
public ResponseStatusEnum getResponseStatusEnum() {
|
||||
return responseStatusEnum;
|
||||
}
|
||||
|
||||
public void setResponseStatusEnum(ResponseStatusEnum responseStatusEnum) {
|
||||
this.responseStatusEnum = responseStatusEnum;
|
||||
}
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
package com.imooc.grace.result;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 自定义响应数据类型枚举升级版本
|
||||
*
|
||||
* @Title: IMOOCJSONResult.java
|
||||
* @Package com.imooc.utils
|
||||
* @Description: 自定义响应数据结构
|
||||
* 本类可提供给 H5/ios/安卓/公众号/小程序 使用
|
||||
* 前端接受此类数据(json object)后,可自行根据业务去实现相关功能
|
||||
*
|
||||
* @Copyright: Copyright (c) 2020
|
||||
* @Company: www.imooc.com
|
||||
* @author 慕课网 - 风间影月
|
||||
* @version V2.0
|
||||
*/
|
||||
public class GraceJSONResult {
|
||||
|
||||
// 响应业务状态码
|
||||
private Integer status;
|
||||
|
||||
// 响应消息
|
||||
private String msg;
|
||||
|
||||
// 是否成功
|
||||
private Boolean success;
|
||||
|
||||
// 响应数据,可以是Object,也可以是List或Map等
|
||||
private Object data;
|
||||
|
||||
/**
|
||||
* 成功返回,带有数据的,直接往OK方法丢data数据即可
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static GraceJSONResult ok(Object data) {
|
||||
return new GraceJSONResult(data);
|
||||
}
|
||||
/**
|
||||
* 成功返回,不带有数据的,直接调用ok方法,data无须传入(其实就是null)
|
||||
* @return
|
||||
*/
|
||||
public static GraceJSONResult ok() {
|
||||
return new GraceJSONResult(ResponseStatusEnum.SUCCESS);
|
||||
}
|
||||
public GraceJSONResult(Object data) {
|
||||
this.status = ResponseStatusEnum.SUCCESS.status();
|
||||
this.msg = ResponseStatusEnum.SUCCESS.msg();
|
||||
this.success = ResponseStatusEnum.SUCCESS.success();
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 错误返回,直接调用error方法即可,当然也可以在ResponseStatusEnum中自定义错误后再返回也都可以
|
||||
* @return
|
||||
*/
|
||||
public static GraceJSONResult error() {
|
||||
return new GraceJSONResult(ResponseStatusEnum.FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误返回,map中包含了多条错误信息,可以用于表单验证,把错误统一的全部返回出去
|
||||
* @param map
|
||||
* @return
|
||||
*/
|
||||
public static GraceJSONResult errorMap(Map map) {
|
||||
return new GraceJSONResult(ResponseStatusEnum.FAILED, map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误返回,直接返回错误的消息
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public static GraceJSONResult errorMsg(String msg) {
|
||||
return new GraceJSONResult(ResponseStatusEnum.FAILED, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误返回,token异常,一些通用的可以在这里统一定义
|
||||
* @return
|
||||
*/
|
||||
public static GraceJSONResult errorTicket() {
|
||||
return new GraceJSONResult(ResponseStatusEnum.TICKET_INVALID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义错误范围,需要传入一个自定义的枚举,可以到[ResponseStatusEnum.java[中自定义后再传入
|
||||
* @param responseStatus
|
||||
* @return
|
||||
*/
|
||||
public static GraceJSONResult errorCustom(ResponseStatusEnum responseStatus) {
|
||||
return new GraceJSONResult(responseStatus);
|
||||
}
|
||||
public static GraceJSONResult exception(ResponseStatusEnum responseStatus) {
|
||||
return new GraceJSONResult(responseStatus);
|
||||
}
|
||||
|
||||
public GraceJSONResult(ResponseStatusEnum responseStatus) {
|
||||
this.status = responseStatus.status();
|
||||
this.msg = responseStatus.msg();
|
||||
this.success = responseStatus.success();
|
||||
}
|
||||
public GraceJSONResult(ResponseStatusEnum responseStatus, Object data) {
|
||||
this.status = responseStatus.status();
|
||||
this.msg = responseStatus.msg();
|
||||
this.success = responseStatus.success();
|
||||
this.data = data;
|
||||
}
|
||||
public GraceJSONResult(ResponseStatusEnum responseStatus, String msg) {
|
||||
this.status = responseStatus.status();
|
||||
this.msg = msg;
|
||||
this.success = responseStatus.success();
|
||||
}
|
||||
|
||||
public GraceJSONResult() {
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Boolean getSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(Boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
package com.imooc.grace.result;
|
||||
|
||||
/**
|
||||
*
|
||||
* @Title: IMOOCJSONResult.java
|
||||
* @Package com.imooc.utils
|
||||
* @Description: 自定义响应数据结构
|
||||
* 本类可提供给 H5/ios/安卓/公众号/小程序 使用
|
||||
* 前端接受此类数据(json object)后,可自行根据业务去实现相关功能
|
||||
*
|
||||
* 200:表示成功
|
||||
* 500:表示错误,错误信息在msg字段中
|
||||
* 501:bean验证错误,不管多少个错误都以map形式返回
|
||||
* 502:拦截器拦截到用户token出错
|
||||
* 555:异常抛出信息
|
||||
* 556: 用户qq校验异常
|
||||
* 557: 校验用户是否在CAS登录,用户门票的校验
|
||||
* @Copyright: Copyright (c) 2020
|
||||
* @Company: www.imooc.com
|
||||
* @author 慕课网 - 风间影月
|
||||
* @version V1.0
|
||||
*/
|
||||
public class IMOOCJSONResult {
|
||||
|
||||
// 响应业务状态
|
||||
private Integer status;
|
||||
|
||||
// 响应消息
|
||||
private String msg;
|
||||
|
||||
// 响应中的数据
|
||||
private Object data;
|
||||
|
||||
private String ok; // 不使用
|
||||
|
||||
public static IMOOCJSONResult build(Integer status, String msg, Object data) {
|
||||
return new IMOOCJSONResult(status, msg, data);
|
||||
}
|
||||
|
||||
public static IMOOCJSONResult build(Integer status, String msg, Object data, String ok) {
|
||||
return new IMOOCJSONResult(status, msg, data, ok);
|
||||
}
|
||||
|
||||
public static IMOOCJSONResult ok(Object data) {
|
||||
return new IMOOCJSONResult(data);
|
||||
}
|
||||
|
||||
public static IMOOCJSONResult ok() {
|
||||
return new IMOOCJSONResult(null);
|
||||
}
|
||||
|
||||
public static IMOOCJSONResult errorMsg(String msg) {
|
||||
return new IMOOCJSONResult(500, msg, null);
|
||||
}
|
||||
|
||||
public static IMOOCJSONResult errorUserTicket(String msg) {
|
||||
return new IMOOCJSONResult(557, msg, null);
|
||||
}
|
||||
|
||||
public static IMOOCJSONResult errorMap(Object data) {
|
||||
return new IMOOCJSONResult(501, "error", data);
|
||||
}
|
||||
|
||||
public static IMOOCJSONResult errorTokenMsg(String msg) {
|
||||
return new IMOOCJSONResult(502, msg, null);
|
||||
}
|
||||
|
||||
public static IMOOCJSONResult errorException(String msg) {
|
||||
return new IMOOCJSONResult(555, msg, null);
|
||||
}
|
||||
|
||||
public static IMOOCJSONResult errorUserQQ(String msg) {
|
||||
return new IMOOCJSONResult(556, msg, null);
|
||||
}
|
||||
|
||||
public IMOOCJSONResult() {
|
||||
|
||||
}
|
||||
|
||||
public IMOOCJSONResult(Integer status, String msg, Object data) {
|
||||
this.status = status;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public IMOOCJSONResult(Integer status, String msg, Object data, String ok) {
|
||||
this.status = status;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
this.ok = ok;
|
||||
}
|
||||
|
||||
public IMOOCJSONResult(Object data) {
|
||||
this.status = 200;
|
||||
this.msg = "OK";
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Boolean isOK() {
|
||||
return this.status == 200;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getOk() {
|
||||
return ok;
|
||||
}
|
||||
|
||||
public void setOk(String ok) {
|
||||
this.ok = ok;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package com.imooc.grace.result;
|
||||
|
||||
/**
|
||||
* 响应结果枚举,用于提供给GraceJSONResult返回给前端的
|
||||
* 本枚举类中包含了很多的不同的状态码供使用,可以自定义
|
||||
* 便于更优雅的对状态码进行管理,一目了然
|
||||
*/
|
||||
public enum ResponseStatusEnum {
|
||||
|
||||
SUCCESS(200, true, "操作成功!"),
|
||||
FAILED(500, false, "操作失败!"),
|
||||
|
||||
// 50x
|
||||
UN_LOGIN(501,false,"请登录后再继续操作!"),
|
||||
TICKET_INVALID(502,false,"会话失效,请重新登录!"),
|
||||
NO_AUTH(503,false,"您的权限不足,无法继续操作!"),
|
||||
MOBILE_ERROR(504,false,"短信发送失败,请稍后重试!"),
|
||||
SMS_NEED_WAIT_ERROR(505,false,"短信发送太快啦~请稍后再试!"),
|
||||
SMS_CODE_ERROR(506,false,"验证码过期或不匹配,请稍后再试!"),
|
||||
USER_FROZEN(507,false,"用户已被冻结,请联系管理员!"),
|
||||
USER_UPDATE_ERROR(508,false,"用户信息更新失败,请联系管理员!"),
|
||||
USER_INACTIVE_ERROR(509,false,"请前往[账号设置]修改信息激活后再进行后续操作!"),
|
||||
USER_INFO_UPDATED_ERROR(5091,false,"用户信息修改失败!"),
|
||||
USER_INFO_UPDATED_NICKNAME_EXIST_ERROR(5092,false,"昵称已经存在!"),
|
||||
USER_INFO_UPDATED_IMOOCNUM_EXIST_ERROR(5092,false,"慕课号已经存在!"),
|
||||
USER_INFO_CANT_UPDATED_IMOOCNUM_ERROR(5092,false,"慕课号无法修改!"),
|
||||
FILE_UPLOAD_NULL_ERROR(510,false,"文件不能为空,请选择一个文件再上传!"),
|
||||
FILE_UPLOAD_FAILD(511,false,"文件上传失败!"),
|
||||
FILE_FORMATTER_FAILD(512,false,"文件图片格式不支持!"),
|
||||
FILE_MAX_SIZE_500KB_ERROR(5131,false,"仅支持500kb大小以下的图片上传!"),
|
||||
FILE_MAX_SIZE_2MB_ERROR(5132,false,"仅支持2MB大小以下的图片上传!"),
|
||||
FILE_NOT_EXIST_ERROR(514,false,"你所查看的文件不存在!"),
|
||||
USER_STATUS_ERROR(515,false,"用户状态参数出错!"),
|
||||
USER_NOT_EXIST_ERROR(516,false,"用户不存在!"),
|
||||
|
||||
// 自定义系统级别异常 54x
|
||||
SYSTEM_INDEX_OUT_OF_BOUNDS(541, false, "系统错误,数组越界!"),
|
||||
SYSTEM_ARITHMETIC_BY_ZERO(542, false, "系统错误,无法除零!"),
|
||||
SYSTEM_NULL_POINTER(543, false, "系统错误,空指针!"),
|
||||
SYSTEM_NUMBER_FORMAT(544, false, "系统错误,数字转换异常!"),
|
||||
SYSTEM_PARSE(545, false, "系统错误,解析异常!"),
|
||||
SYSTEM_IO(546, false, "系统错误,IO输入输出异常!"),
|
||||
SYSTEM_FILE_NOT_FOUND(547, false, "系统错误,文件未找到!"),
|
||||
SYSTEM_CLASS_CAST(548, false, "系统错误,类型强制转换错误!"),
|
||||
SYSTEM_PARSER_ERROR(549, false, "系统错误,解析出错!"),
|
||||
SYSTEM_DATE_PARSER_ERROR(550, false, "系统错误,日期解析出错!"),
|
||||
|
||||
// admin 管理系统 56x
|
||||
ADMIN_USERNAME_NULL_ERROR(561, false, "管理员登录名不能为空!"),
|
||||
ADMIN_USERNAME_EXIST_ERROR(562, false, "管理员登录名已存在!"),
|
||||
ADMIN_NAME_NULL_ERROR(563, false, "管理员负责人不能为空!"),
|
||||
ADMIN_PASSWORD_ERROR(564, false, "密码不能为空后者两次输入不一致!"),
|
||||
ADMIN_CREATE_ERROR(565, false, "添加管理员失败!"),
|
||||
ADMIN_PASSWORD_NULL_ERROR(566, false, "密码不能为空!"),
|
||||
ADMIN_NOT_EXIT_ERROR(567, false, "管理员不存在或密码错误!"),
|
||||
ADMIN_FACE_NULL_ERROR(568, false, "人脸信息不能为空!"),
|
||||
ADMIN_FACE_LOGIN_ERROR(569, false, "人脸识别失败,请重试!"),
|
||||
CATEGORY_EXIST_ERROR(570, false, "文章分类已存在,请换一个分类名!"),
|
||||
|
||||
// 媒体中心 相关错误 58x
|
||||
ARTICLE_COVER_NOT_EXIST_ERROR(580, false, "文章封面不存在,请选择一个!"),
|
||||
ARTICLE_CATEGORY_NOT_EXIST_ERROR(581, false, "请选择正确的文章领域!"),
|
||||
ARTICLE_CREATE_ERROR(582, false, "创建文章失败,请重试或联系管理员!"),
|
||||
ARTICLE_QUERY_PARAMS_ERROR(583, false, "文章列表查询参数错误!"),
|
||||
ARTICLE_DELETE_ERROR(584, false, "文章删除失败!"),
|
||||
ARTICLE_WITHDRAW_ERROR(585, false, "文章撤回失败!"),
|
||||
ARTICLE_REVIEW_ERROR(585, false, "文章审核出错!"),
|
||||
ARTICLE_ALREADY_READ_ERROR(586, false, "文章重复阅读!"),
|
||||
|
||||
// 人脸识别错误代码
|
||||
FACE_VERIFY_TYPE_ERROR(600, false, "人脸比对验证类型不正确!"),
|
||||
FACE_VERIFY_LOGIN_ERROR(601, false, "人脸登录失败!"),
|
||||
|
||||
// 系统错误,未预期的错误 555
|
||||
SYSTEM_ERROR(555, false, "系统繁忙,请稍后再试!"),
|
||||
SYSTEM_OPERATION_ERROR(556, false, "操作失败,请重试或联系管理员"),
|
||||
SYSTEM_RESPONSE_NO_INFO(557, false, ""),
|
||||
SYSTEM_ERROR_GLOBAL(558, false, "全局降级:系统繁忙,请稍后再试!"),
|
||||
SYSTEM_ERROR_FEIGN(559, false, "客户端Feign降级:系统繁忙,请稍后再试!"),
|
||||
SYSTEM_ERROR_ZUUL(560, false, "请求系统过于繁忙,请稍后再试!");
|
||||
|
||||
|
||||
// 响应业务状态
|
||||
private Integer status;
|
||||
// 调用是否成功
|
||||
private Boolean success;
|
||||
// 响应消息,可以为成功或者失败的消息
|
||||
private String msg;
|
||||
|
||||
ResponseStatusEnum(Integer status, Boolean success, String msg) {
|
||||
this.status = status;
|
||||
this.success = success;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public Integer status() {
|
||||
return status;
|
||||
}
|
||||
public Boolean success() {
|
||||
return success;
|
||||
}
|
||||
public String msg() {
|
||||
return msg;
|
||||
}
|
||||
}
|
680
book-common/src/main/java/com/imooc/utils/DateUtil.java
Normal file
680
book-common/src/main/java/com/imooc/utils/DateUtil.java
Normal file
@ -0,0 +1,680 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
public class DateUtil {
|
||||
|
||||
/**
|
||||
* Base ISO 8601 Date format yyyyMMdd i.e., 20021225 for the 25th day of December in the year 2002
|
||||
*/
|
||||
public static final String ISO_DATE_FORMAT = "yyyyMMdd";
|
||||
|
||||
/**
|
||||
* Expanded ISO 8601 Date format yyyy-MM-dd i.e., 2002-12-25 for the 25th day of December in the year 2002
|
||||
*/
|
||||
public static final String ISO_EXPANDED_DATE_FORMAT = "yyyy-MM-dd";
|
||||
|
||||
/**
|
||||
* yyyy-MM-dd hh:mm:ss
|
||||
*/
|
||||
public static String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
|
||||
public static String DATE_PATTERN = "yyyyMMddHHmmss";
|
||||
|
||||
/**
|
||||
* 则个
|
||||
*/
|
||||
private static boolean LENIENT_DATE = false;
|
||||
|
||||
|
||||
private static Random random = new Random();
|
||||
private static final int ID_BYTES = 10;
|
||||
|
||||
public synchronized static String generateId() {
|
||||
StringBuffer result = new StringBuffer();
|
||||
result = result.append(System.currentTimeMillis());
|
||||
for (int i = 0; i < ID_BYTES; i++) {
|
||||
result = result.append(random.nextInt(10));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
protected static final float normalizedJulian(float JD) {
|
||||
|
||||
float f = Math.round(JD + 0.5f) - 0.5f;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Date from a julian. The Julian date will be converted to noon GMT,
|
||||
* such that it matches the nearest half-integer (i.e., a julian date of 1.4 gets
|
||||
* changed to 1.5, and 0.9 gets changed to 0.5.)
|
||||
*
|
||||
* @param JD the Julian date
|
||||
* @return the Gregorian date
|
||||
*/
|
||||
public static final Date toDate(float JD) {
|
||||
|
||||
/* To convert a Julian Day Number to a Gregorian date, assume that it is for 0 hours, Greenwich time (so
|
||||
* that it ends in 0.5). Do the following calculations, again dropping the fractional part of all
|
||||
* multiplicatons and divisions. Note: This method will not give dates accurately on the
|
||||
* Gregorian Proleptic Calendar, i.e., the calendar you get by extending the Gregorian
|
||||
* calendar backwards to years earlier than 1582. using the Gregorian leap year
|
||||
* rules. In particular, the method fails if Y<400. */
|
||||
float Z = (normalizedJulian(JD)) + 0.5f;
|
||||
float W = (int) ((Z - 1867216.25f) / 36524.25f);
|
||||
float X = (int) (W / 4f);
|
||||
float A = Z + 1 + W - X;
|
||||
float B = A + 1524;
|
||||
float C = (int) ((B - 122.1) / 365.25);
|
||||
float D = (int) (365.25f * C);
|
||||
float E = (int) ((B - D) / 30.6001);
|
||||
float F = (int) (30.6001f * E);
|
||||
int day = (int) (B - D - F);
|
||||
int month = (int) (E - 1);
|
||||
|
||||
if (month > 12) {
|
||||
month = month - 12;
|
||||
}
|
||||
|
||||
int year = (int) (C - 4715); //(if Month is January or February) or C-4716 (otherwise)
|
||||
|
||||
if (month > 2) {
|
||||
year--;
|
||||
}
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.set(Calendar.YEAR, year);
|
||||
c.set(Calendar.MONTH, month - 1); // damn 0 offsets
|
||||
c.set(Calendar.DATE, day);
|
||||
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the days between two dates. Positive values indicate that
|
||||
* the second date is after the first, and negative values indicate, well,
|
||||
* the opposite. Relying on specific times is problematic.
|
||||
*
|
||||
* @param early the "first date"
|
||||
* @param late the "second date"
|
||||
* @return the days between the two dates
|
||||
*/
|
||||
public static final int daysBetween(Date early, Date late) {
|
||||
|
||||
Calendar c1 = Calendar.getInstance();
|
||||
Calendar c2 = Calendar.getInstance();
|
||||
c1.setTime(early);
|
||||
c2.setTime(late);
|
||||
|
||||
return daysBetween(c1, c2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the days between two dates. Positive values indicate that
|
||||
* the second date is after the first, and negative values indicate, well,
|
||||
* the opposite.
|
||||
*
|
||||
* @param early
|
||||
* @param late
|
||||
* @return the days between two dates.
|
||||
*/
|
||||
public static final int daysBetween(Calendar early, Calendar late) {
|
||||
|
||||
return (int) (toJulian(late) - toJulian(early));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算时间差
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @return
|
||||
*/
|
||||
public static final String timeBetween(Date startDate, Date endDate) {
|
||||
long nd = 1000 * 24 * 60 * 60;
|
||||
long nh = 1000 * 60 * 60;
|
||||
long nm = 1000 * 60;
|
||||
// long ns = 1000;
|
||||
// 获得两个时间的毫秒时间差异
|
||||
long diff = endDate.getTime() - startDate.getTime();
|
||||
// 计算差多少天
|
||||
long day = diff / nd;
|
||||
// 计算差多少小时
|
||||
long hour = diff % nd / nh;
|
||||
// 计算差多少分钟
|
||||
long min = diff % nd % nh / nm;
|
||||
// 计算差多少秒//输出结果
|
||||
// long sec = diff % nd % nh % nm / ns;
|
||||
return day + "天" + hour + "小时" + min + "分钟";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Julian date based on the input parameter. This is
|
||||
* based from calculations found at
|
||||
* <a href="http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html">Julian Day Calculations
|
||||
* (Gregorian Calendar)</a>, provided by Bill Jeffrys.
|
||||
* @param c a calendar instance
|
||||
* @return the julian day number
|
||||
*/
|
||||
public static final float toJulian(Calendar c) {
|
||||
|
||||
int Y = c.get(Calendar.YEAR);
|
||||
int M = c.get(Calendar.MONTH);
|
||||
int D = c.get(Calendar.DATE);
|
||||
int A = Y / 100;
|
||||
int B = A / 4;
|
||||
int C = 2 - A + B;
|
||||
float E = (int) (365.25f * (Y + 4716));
|
||||
float F = (int) (30.6001f * (M + 1));
|
||||
float JD = C + D + E + F - 1524.5f;
|
||||
|
||||
return JD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Julian date based on the input parameter. This is
|
||||
* based from calculations found at
|
||||
* <a href="http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html">Julian Day Calculations
|
||||
* (Gregorian Calendar)</a>, provided by Bill Jeffrys.
|
||||
* @param date
|
||||
* @return the julian day number
|
||||
*/
|
||||
public static final float toJulian(Date date) {
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(date);
|
||||
|
||||
return toJulian(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isoString
|
||||
* @param fmt
|
||||
* @param field Calendar.YEAR/Calendar.MONTH/Calendar.DATE
|
||||
* @param amount
|
||||
* @return
|
||||
* @throws ParseException
|
||||
*/
|
||||
public static final String dateIncrease(String isoString, String fmt,
|
||||
int field, int amount) {
|
||||
|
||||
try {
|
||||
Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone(
|
||||
"GMT"));
|
||||
cal.setTime(stringToDate(isoString, fmt, true));
|
||||
cal.add(field, amount);
|
||||
|
||||
return dateToString(cal.getTime(), fmt);
|
||||
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Field Rolling function.
|
||||
* Rolls (up/down) a single unit of time on the given time field.
|
||||
*
|
||||
* @param isoString
|
||||
* @param field the time field.
|
||||
* @param up Indicates if rolling up or rolling down the field value.
|
||||
* @param expanded use formating char's
|
||||
* @exception ParseException if an unknown field value is given.
|
||||
*/
|
||||
public static final String roll(String isoString, String fmt, int field,
|
||||
boolean up) throws ParseException {
|
||||
|
||||
Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone(
|
||||
"GMT"));
|
||||
cal.setTime(stringToDate(isoString, fmt));
|
||||
cal.roll(field, up);
|
||||
|
||||
return dateToString(cal.getTime(), fmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Field Rolling function.
|
||||
* Rolls (up/down) a single unit of time on the given time field.
|
||||
*
|
||||
* @param isoString
|
||||
* @param field the time field.
|
||||
* @param up Indicates if rolling up or rolling down the field value.
|
||||
* @exception ParseException if an unknown field value is given.
|
||||
*/
|
||||
public static final String roll(String isoString, int field, boolean up) throws
|
||||
ParseException {
|
||||
|
||||
return roll(isoString, DATETIME_PATTERN, field, up);
|
||||
}
|
||||
|
||||
/**
|
||||
* java.util.Date
|
||||
* @param dateText
|
||||
* @param format
|
||||
* @param lenient
|
||||
* @return
|
||||
*/
|
||||
public static Date stringToDate(String dateText, String format,
|
||||
boolean lenient) {
|
||||
|
||||
if (dateText == null) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
DateFormat df = null;
|
||||
|
||||
try {
|
||||
|
||||
if (format == null) {
|
||||
df = new SimpleDateFormat();
|
||||
} else {
|
||||
df = new SimpleDateFormat(format);
|
||||
}
|
||||
|
||||
// setLenient avoids allowing dates like 9/32/2001
|
||||
// which would otherwise parse to 10/2/2001
|
||||
df.setLenient(false);
|
||||
|
||||
return df.parse(dateText);
|
||||
} catch (ParseException e) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Timestamp
|
||||
*/
|
||||
public static java.sql.Timestamp getCurrentTimestamp() {
|
||||
return new java.sql.Timestamp(new Date().getTime());
|
||||
}
|
||||
|
||||
/** java.util.Date
|
||||
* @param dateText
|
||||
* @param format
|
||||
* @return
|
||||
*/
|
||||
public static Date stringToDate(String dateString, String format) {
|
||||
|
||||
return stringToDate(dateString, format, LENIENT_DATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* java.util.Date
|
||||
* @param dateText
|
||||
*/
|
||||
public static Date stringToDate(String dateString) {
|
||||
return stringToDate(dateString, ISO_EXPANDED_DATE_FORMAT, LENIENT_DATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @param pattern
|
||||
* @param date
|
||||
*/
|
||||
public static String dateToString(Date date, String pattern) {
|
||||
|
||||
if (date == null) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
SimpleDateFormat sfDate = new SimpleDateFormat(pattern);
|
||||
sfDate.setLenient(false);
|
||||
|
||||
return sfDate.format(date);
|
||||
} catch (Exception e) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* yyyy-MM-dd
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static String dateToString(Date date) {
|
||||
return dateToString(date, ISO_EXPANDED_DATE_FORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public static Date getCurrentDateTime() {
|
||||
Calendar calNow = Calendar.getInstance();
|
||||
Date dtNow = calNow.getTime();
|
||||
|
||||
return dtNow;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pattern
|
||||
* @return
|
||||
*/
|
||||
public static String getCurrentDateString(String pattern) {
|
||||
return dateToString(getCurrentDateTime(), pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* yyyy-MM-dd
|
||||
* @return
|
||||
*/
|
||||
public static String getCurrentDateString() {
|
||||
return dateToString(getCurrentDateTime(), ISO_EXPANDED_DATE_FORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回固定格式的当前时间
|
||||
* yyyy-MM-dd hh:mm:ss
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static String dateToStringWithTime( ) {
|
||||
|
||||
return dateToString(new Date(), DATETIME_PATTERN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* yyyy-MM-dd hh:mm:ss
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static String dateToStringWithTime(Date date) {
|
||||
|
||||
return dateToString(date, DATETIME_PATTERN);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param date
|
||||
* @param days
|
||||
* @return java.util.Date
|
||||
*/
|
||||
public static Date dateIncreaseByDay(Date date, int days) {
|
||||
|
||||
Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone(
|
||||
"GMT"));
|
||||
cal.setTime(date);
|
||||
cal.add(Calendar.DATE, days);
|
||||
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param date
|
||||
* @param days
|
||||
* @return java.util.Date
|
||||
*/
|
||||
public static Date dateIncreaseByMonth(Date date, int mnt) {
|
||||
|
||||
Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone(
|
||||
"GMT"));
|
||||
cal.setTime(date);
|
||||
cal.add(Calendar.MONTH, mnt);
|
||||
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param date
|
||||
* @param mnt
|
||||
* @return java.util.Date
|
||||
*/
|
||||
public static Date dateIncreaseByYear(Date date, int mnt) {
|
||||
|
||||
Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone(
|
||||
"GMT"));
|
||||
cal.setTime(date);
|
||||
cal.add(Calendar.YEAR, mnt);
|
||||
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param date yyyy-MM-dd
|
||||
* @param days
|
||||
* @return yyyy-MM-dd
|
||||
*/
|
||||
public static String dateIncreaseByDay(String date, int days) {
|
||||
return dateIncreaseByDay(date, ISO_DATE_FORMAT, days);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date
|
||||
* @param fmt
|
||||
* @param days
|
||||
* @return
|
||||
*/
|
||||
public static String dateIncreaseByDay(String date, String fmt, int days) {
|
||||
return dateIncrease(date, fmt, Calendar.DATE, days);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param src
|
||||
* @param srcfmt
|
||||
* @param desfmt
|
||||
* @return
|
||||
*/
|
||||
public static String stringToString(String src, String srcfmt,
|
||||
String desfmt) {
|
||||
return dateToString(stringToDate(src, srcfmt), desfmt);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param date
|
||||
* @return string
|
||||
*/
|
||||
public static String getYear(Date date) {
|
||||
SimpleDateFormat formater = new SimpleDateFormat(
|
||||
"yyyy");
|
||||
String cur_year = formater.format(date);
|
||||
return cur_year;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param date
|
||||
* @return string
|
||||
*/
|
||||
public static String getMonth(Date date) {
|
||||
SimpleDateFormat formater = new SimpleDateFormat(
|
||||
"MM");
|
||||
String cur_month = formater.format(date);
|
||||
return cur_month;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date
|
||||
* @return string
|
||||
*/
|
||||
public static String getDay(Date date) {
|
||||
SimpleDateFormat formater = new SimpleDateFormat(
|
||||
"dd");
|
||||
String cur_day = formater.format(date);
|
||||
return cur_day;
|
||||
}
|
||||
|
||||
public static int getDayInt(Date date) {
|
||||
SimpleDateFormat formater = new SimpleDateFormat(
|
||||
"dd");
|
||||
String cur_day = formater.format(date);
|
||||
return Integer.valueOf(cur_day);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date
|
||||
* @return string
|
||||
*/
|
||||
public static String getHour(Date date) {
|
||||
SimpleDateFormat formater = new SimpleDateFormat(
|
||||
"HH");
|
||||
String cur_day = formater.format(date);
|
||||
return cur_day;
|
||||
}
|
||||
|
||||
public static int getMinsFromDate(Date dt) {
|
||||
GregorianCalendar cal = new GregorianCalendar();
|
||||
cal.setTime(dt);
|
||||
int hour = cal.get(Calendar.HOUR_OF_DAY);
|
||||
int min = cal.get(Calendar.MINUTE);
|
||||
return ((hour * 60) + min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to convert String to Date Object. If invalid input then current or next day date
|
||||
* is returned (Added by Ali Naqvi on 2006-5-16).
|
||||
* @param str String input in YYYY-MM-DD HH:MM[:SS] format.
|
||||
* @param isExpiry boolean if set and input string is invalid then next day date is returned
|
||||
* @return Date
|
||||
*/
|
||||
public static Date convertToDate(String str, boolean isExpiry) {
|
||||
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
Date dt = null;
|
||||
try {
|
||||
dt = fmt.parse(str);
|
||||
} catch (ParseException ex) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
if (isExpiry) {
|
||||
cal.add(Calendar.DAY_OF_MONTH, 1);
|
||||
cal.set(Calendar.HOUR_OF_DAY, 23);
|
||||
cal.set(Calendar.MINUTE, 59);
|
||||
} else {
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
}
|
||||
dt = cal.getTime();
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
public static Date convertToDate(String str) {
|
||||
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd hh:mm");
|
||||
Date dt = null;
|
||||
try {
|
||||
dt = fmt.parse(str);
|
||||
} catch (ParseException ex) {
|
||||
dt = new Date();
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
public static String dateFromat(Date date, int minute) {
|
||||
String dateFormat = null;
|
||||
int year = Integer.parseInt(getYear(date));
|
||||
int month = Integer.parseInt(getMonth(date));
|
||||
int day = Integer.parseInt(getDay(date));
|
||||
int hour = minute / 60;
|
||||
int min = minute % 60;
|
||||
dateFormat = String.valueOf(year)
|
||||
+
|
||||
(month > 9 ? String.valueOf(month) :
|
||||
"0" + String.valueOf(month))
|
||||
+
|
||||
(day > 9 ? String.valueOf(day) : "0" + String.valueOf(day))
|
||||
+ " "
|
||||
+
|
||||
(hour > 9 ? String.valueOf(hour) : "0" + String.valueOf(hour))
|
||||
+
|
||||
(min > 9 ? String.valueOf(min) : "0" + String.valueOf(min))
|
||||
+ "00";
|
||||
return dateFormat;
|
||||
}
|
||||
|
||||
public static String sDateFormat() {
|
||||
return new SimpleDateFormat(DATE_PATTERN).format(Calendar.getInstance().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @Description: 获得本月的第一天日期
|
||||
* @return
|
||||
*
|
||||
* @author leechenxiang
|
||||
* @date 2017年5月31日 下午1:37:34
|
||||
*/
|
||||
public static String getFirstDateOfThisMonth() {
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat(ISO_EXPANDED_DATE_FORMAT);
|
||||
|
||||
Calendar calendarFirst = Calendar.getInstance();
|
||||
calendarFirst = Calendar.getInstance();
|
||||
calendarFirst.add(Calendar.MONTH, 0);
|
||||
calendarFirst.set(Calendar.DAY_OF_MONTH, 1);
|
||||
String firstDate = format.format(calendarFirst.getTime());
|
||||
|
||||
return firstDate;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @Description: 获得本月的最后一天日期
|
||||
* @return
|
||||
*
|
||||
* @author leechenxiang
|
||||
* @date 2017年5月31日 下午1:37:50
|
||||
*/
|
||||
public static String getLastDateOfThisMonth() {
|
||||
SimpleDateFormat format = new SimpleDateFormat(ISO_EXPANDED_DATE_FORMAT);
|
||||
|
||||
Calendar calendarLast = Calendar.getInstance();
|
||||
calendarLast.setTime(new Date());
|
||||
calendarLast.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||||
|
||||
String lastDate = format.format(calendarLast.getTime());
|
||||
return lastDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 判断字符串日期是否匹配指定的格式化日期
|
||||
*/
|
||||
public static boolean isValidDate(String strDate, String formatter) {
|
||||
SimpleDateFormat sdf = null;
|
||||
ParsePosition pos = new ParsePosition(0);
|
||||
|
||||
if (StringUtils.isBlank(strDate) || StringUtils.isBlank(formatter)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
sdf = new SimpleDateFormat(formatter);
|
||||
sdf.setLenient(false);
|
||||
Date date = sdf.parse(strDate, pos);
|
||||
if (date == null) {
|
||||
return false;
|
||||
} else {
|
||||
if (pos.getIndex() > sdf.format(date).length()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// String timeDir=DateUtil.dateToString(new Date(),DateUtil.ISO_EXPANDED_DATE_FORMAT);
|
||||
// System.out.println(timeDir);
|
||||
boolean flag = DateUtil.isValidDate("1990-10-32", DateUtil.ISO_EXPANDED_DATE_FORMAT);
|
||||
System.out.println(flag);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
/**
|
||||
* 通用脱敏工具类
|
||||
* 可用于:
|
||||
* 用户名
|
||||
* 手机号
|
||||
* 邮箱
|
||||
* 地址等
|
||||
*/
|
||||
public class DesensitizationUtil {
|
||||
|
||||
private static final int SIZE = 6;
|
||||
private static final String SYMBOL = "*";
|
||||
|
||||
public static void main(String[] args) {
|
||||
String name = commonDisplay("慕课网");
|
||||
String mobile = commonDisplay("13900000000");
|
||||
String mail = commonDisplay("admin@imooc.com");
|
||||
String address = commonDisplay("北京大运河东路888号");
|
||||
|
||||
System.out.println(name);
|
||||
System.out.println(mobile);
|
||||
System.out.println(mail);
|
||||
System.out.println(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用脱敏方法
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static String commonDisplay(String value) {
|
||||
if (null == value || "".equals(value)) {
|
||||
return value;
|
||||
}
|
||||
int len = value.length();
|
||||
int pamaone = len / 2;
|
||||
int pamatwo = pamaone - 1;
|
||||
int pamathree = len % 2;
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if (len <= 2) {
|
||||
if (pamathree == 1) {
|
||||
return SYMBOL;
|
||||
}
|
||||
stringBuilder.append(SYMBOL);
|
||||
stringBuilder.append(value.charAt(len - 1));
|
||||
} else {
|
||||
if (pamatwo <= 0) {
|
||||
stringBuilder.append(value.substring(0, 1));
|
||||
stringBuilder.append(SYMBOL);
|
||||
stringBuilder.append(value.substring(len - 1, len));
|
||||
|
||||
} else if (pamatwo >= SIZE / 2 && SIZE + 1 != len) {
|
||||
int pamafive = (len - SIZE) / 2;
|
||||
stringBuilder.append(value.substring(0, pamafive));
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
stringBuilder.append(SYMBOL);
|
||||
}
|
||||
if ((pamathree == 0 && SIZE / 2 == 0) || (pamathree != 0 && SIZE % 2 != 0)) {
|
||||
stringBuilder.append(value.substring(len - pamafive, len));
|
||||
} else {
|
||||
stringBuilder.append(value.substring(len - (pamafive + 1), len));
|
||||
}
|
||||
} else {
|
||||
int pamafour = len - 2;
|
||||
stringBuilder.append(value.substring(0, 1));
|
||||
for (int i = 0; i < pamafour; i++) {
|
||||
stringBuilder.append(SYMBOL);
|
||||
}
|
||||
stringBuilder.append(value.substring(len - 1, len));
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
37
book-common/src/main/java/com/imooc/utils/IPUtil.java
Normal file
37
book-common/src/main/java/com/imooc/utils/IPUtil.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 用户获得用户ip的工具类
|
||||
*/
|
||||
public class IPUtil {
|
||||
|
||||
/**
|
||||
* 获取请求IP:
|
||||
* 用户的真实IP不能使用request.getRemoteAddr()
|
||||
* 这是因为可能会使用一些代理软件,这样ip获取就不准确了
|
||||
* 此外我们如果使用了多级(LVS/Nginx)反向代理的话,ip需要从X-Forwarded-For中获得第一个非unknown的IP才是用户的有效ip。
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static String getRequestIp(HttpServletRequest request) {
|
||||
String ip = request.getHeader("x-forwarded-for");
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
}
|
74
book-common/src/main/java/com/imooc/utils/JsonUtils.java
Normal file
74
book-common/src/main/java/com/imooc/utils/JsonUtils.java
Normal file
@ -0,0 +1,74 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @Title: JsonUtils.java
|
||||
* @Package com.imooc.utils
|
||||
* @Description: json转换类
|
||||
* Copyright: Copyright (c)
|
||||
* Company: www.imooc.com
|
||||
*
|
||||
* @author imooc
|
||||
*/
|
||||
public class JsonUtils {
|
||||
|
||||
// 定义jackson对象
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* 将对象转换成json字符串。
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static String objectToJson(Object data) {
|
||||
try {
|
||||
String string = MAPPER.writeValueAsString(data);
|
||||
return string;
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将json结果集转化为对象
|
||||
*
|
||||
* @param jsonData json数据
|
||||
* @param beanType 对象中的object类型
|
||||
* @return
|
||||
*/
|
||||
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
|
||||
try {
|
||||
T t = MAPPER.readValue(jsonData, beanType);
|
||||
return t;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将json数据转换成pojo对象list
|
||||
* @param jsonData
|
||||
* @param beanType
|
||||
* @return
|
||||
*/
|
||||
public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
|
||||
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
|
||||
try {
|
||||
List<T> list = MAPPER.readValue(jsonData, javaType);
|
||||
return list;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
432
book-common/src/main/java/com/imooc/utils/MinIOUtils.java
Normal file
432
book-common/src/main/java/com/imooc/utils/MinIOUtils.java
Normal file
@ -0,0 +1,432 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
import io.minio.*;
|
||||
import io.minio.http.Method;
|
||||
import io.minio.messages.Bucket;
|
||||
import io.minio.messages.DeleteObject;
|
||||
import io.minio.messages.Item;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* MinIO工具类
|
||||
*/
|
||||
@Slf4j
|
||||
public class MinIOUtils {
|
||||
|
||||
private static MinioClient minioClient;
|
||||
|
||||
private static String endpoint;
|
||||
private static String bucketName;
|
||||
private static String accessKey;
|
||||
private static String secretKey;
|
||||
private static Integer imgSize;
|
||||
private static Integer fileSize;
|
||||
|
||||
|
||||
private static final String SEPARATOR = "/";
|
||||
|
||||
public MinIOUtils() {
|
||||
}
|
||||
|
||||
public MinIOUtils(String endpoint, String bucketName, String accessKey, String secretKey, Integer imgSize, Integer fileSize) {
|
||||
MinIOUtils.endpoint = endpoint;
|
||||
MinIOUtils.bucketName = bucketName;
|
||||
MinIOUtils.accessKey = accessKey;
|
||||
MinIOUtils.secretKey = secretKey;
|
||||
MinIOUtils.imgSize = imgSize;
|
||||
MinIOUtils.fileSize = fileSize;
|
||||
createMinioClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建基于Java端的MinioClient
|
||||
*/
|
||||
public void createMinioClient() {
|
||||
try {
|
||||
if (null == minioClient) {
|
||||
log.info("开始创建 MinioClient...");
|
||||
minioClient = MinioClient
|
||||
.builder()
|
||||
.endpoint(endpoint)
|
||||
.credentials(accessKey, secretKey)
|
||||
.build();
|
||||
createBucket(bucketName);
|
||||
log.info("创建完毕 MinioClient...");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("MinIO服务器异常:{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传文件前缀路径
|
||||
* @return
|
||||
*/
|
||||
public static String getBasisUrl() {
|
||||
return endpoint + SEPARATOR + bucketName + SEPARATOR;
|
||||
}
|
||||
|
||||
/****************************** Operate Bucket Start ******************************/
|
||||
|
||||
/**
|
||||
* 启动SpringBoot容器的时候初始化Bucket
|
||||
* 如果没有Bucket则创建
|
||||
* @throws Exception
|
||||
*/
|
||||
private static void createBucket(String bucketName) throws Exception {
|
||||
if (!bucketExists(bucketName)) {
|
||||
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断Bucket是否存在,true:存在,false:不存在
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static boolean bucketExists(String bucketName) throws Exception {
|
||||
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得Bucket的策略
|
||||
* @param bucketName
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String getBucketPolicy(String bucketName) throws Exception {
|
||||
String bucketPolicy = minioClient
|
||||
.getBucketPolicy(
|
||||
GetBucketPolicyArgs
|
||||
.builder()
|
||||
.bucket(bucketName)
|
||||
.build()
|
||||
);
|
||||
return bucketPolicy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得所有Bucket列表
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static List<Bucket> getAllBuckets() throws Exception {
|
||||
return minioClient.listBuckets();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据bucketName获取其相关信息
|
||||
* @param bucketName
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static Optional<Bucket> getBucket(String bucketName) throws Exception {
|
||||
return getAllBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据bucketName删除Bucket,true:删除成功; false:删除失败,文件或已不存在
|
||||
* @param bucketName
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void removeBucket(String bucketName) throws Exception {
|
||||
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
|
||||
}
|
||||
|
||||
/****************************** Operate Bucket End ******************************/
|
||||
|
||||
|
||||
/****************************** Operate Files Start ******************************/
|
||||
|
||||
/**
|
||||
* 判断文件是否存在
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 文件名
|
||||
* @return
|
||||
*/
|
||||
public static boolean isObjectExist(String bucketName, String objectName) {
|
||||
boolean exist = true;
|
||||
try {
|
||||
minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
|
||||
} catch (Exception e) {
|
||||
exist = false;
|
||||
}
|
||||
return exist;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件夹是否存在
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 文件夹名称
|
||||
* @return
|
||||
*/
|
||||
public static boolean isFolderExist(String bucketName, String objectName) {
|
||||
boolean exist = false;
|
||||
try {
|
||||
Iterable<Result<Item>> results = minioClient.listObjects(
|
||||
ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build());
|
||||
for (Result<Item> result : results) {
|
||||
Item item = result.get();
|
||||
if (item.isDir() && objectName.equals(item.objectName())) {
|
||||
exist = true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exist = false;
|
||||
}
|
||||
return exist;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件前缀查询文件
|
||||
* @param bucketName 存储桶
|
||||
* @param prefix 前缀
|
||||
* @param recursive 是否使用递归查询
|
||||
* @return MinioItem 列表
|
||||
* @throws Exception
|
||||
*/
|
||||
public static List<Item> getAllObjectsByPrefix(String bucketName,
|
||||
String prefix,
|
||||
boolean recursive) throws Exception {
|
||||
List<Item> list = new ArrayList<>();
|
||||
Iterable<Result<Item>> objectsIterator = minioClient.listObjects(
|
||||
ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());
|
||||
if (objectsIterator != null) {
|
||||
for (Result<Item> o : objectsIterator) {
|
||||
Item item = o.get();
|
||||
list.add(item);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件流
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 文件名
|
||||
* @return 二进制流
|
||||
*/
|
||||
public static InputStream getObject(String bucketName, String objectName) throws Exception {
|
||||
return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 断点下载
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 文件名称
|
||||
* @param offset 起始字节的位置
|
||||
* @param length 要读取的长度
|
||||
* @return 二进制流
|
||||
*/
|
||||
public InputStream getObject(String bucketName, String objectName, long offset, long length)throws Exception {
|
||||
return minioClient.getObject(
|
||||
GetObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(objectName)
|
||||
.offset(offset)
|
||||
.length(length)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路径下文件列表
|
||||
* @param bucketName 存储桶
|
||||
* @param prefix 文件名称
|
||||
* @param recursive 是否递归查找,false:模拟文件夹结构查找
|
||||
* @return 二进制流
|
||||
*/
|
||||
public static Iterable<Result<Item>> listObjects(String bucketName, String prefix,
|
||||
boolean recursive) {
|
||||
return minioClient.listObjects(
|
||||
ListObjectsArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.prefix(prefix)
|
||||
.recursive(recursive)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用MultipartFile进行文件上传
|
||||
* @param bucketName 存储桶
|
||||
* @param file 文件名
|
||||
* @param objectName 对象名
|
||||
* @param contentType 类型
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static ObjectWriteResponse uploadFile(String bucketName, MultipartFile file,
|
||||
String objectName, String contentType) throws Exception {
|
||||
InputStream inputStream = file.getInputStream();
|
||||
return minioClient.putObject(
|
||||
PutObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(objectName)
|
||||
.contentType(contentType)
|
||||
.stream(inputStream, inputStream.available(), -1)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传本地文件
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 对象名称
|
||||
* @param fileName 本地文件路径
|
||||
*/
|
||||
public static ObjectWriteResponse uploadFile(String bucketName, String objectName,
|
||||
String fileName) throws Exception {
|
||||
return minioClient.uploadObject(
|
||||
UploadObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(objectName)
|
||||
.filename(fileName)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过流上传文件
|
||||
*
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 文件对象
|
||||
* @param inputStream 文件流
|
||||
*/
|
||||
public static ObjectWriteResponse uploadFile(String bucketName, String objectName, InputStream inputStream) throws Exception {
|
||||
return minioClient.putObject(
|
||||
PutObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(objectName)
|
||||
.stream(inputStream, inputStream.available(), -1)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件夹或目录
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 目录路径
|
||||
*/
|
||||
public static ObjectWriteResponse createDir(String bucketName, String objectName) throws Exception {
|
||||
return minioClient.putObject(
|
||||
PutObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(objectName)
|
||||
.stream(new ByteArrayInputStream(new byte[]{}), 0, -1)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件信息, 如果抛出异常则说明文件不存在
|
||||
*
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 文件名称
|
||||
*/
|
||||
public static String getFileStatusInfo(String bucketName, String objectName) throws Exception {
|
||||
return minioClient.statObject(
|
||||
StatObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(objectName)
|
||||
.build()).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝文件
|
||||
*
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 文件名
|
||||
* @param srcBucketName 目标存储桶
|
||||
* @param srcObjectName 目标文件名
|
||||
*/
|
||||
public static ObjectWriteResponse copyFile(String bucketName, String objectName,
|
||||
String srcBucketName, String srcObjectName) throws Exception {
|
||||
return minioClient.copyObject(
|
||||
CopyObjectArgs.builder()
|
||||
.source(CopySource.builder().bucket(bucketName).object(objectName).build())
|
||||
.bucket(srcBucketName)
|
||||
.object(srcObjectName)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 文件名称
|
||||
*/
|
||||
public static void removeFile(String bucketName, String objectName) throws Exception {
|
||||
minioClient.removeObject(
|
||||
RemoveObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(objectName)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除文件
|
||||
* @param bucketName 存储桶
|
||||
* @param keys 需要删除的文件列表
|
||||
* @return
|
||||
*/
|
||||
public static void removeFiles(String bucketName, List<String> keys) {
|
||||
List<DeleteObject> objects = new LinkedList<>();
|
||||
keys.forEach(s -> {
|
||||
objects.add(new DeleteObject(s));
|
||||
try {
|
||||
removeFile(bucketName, s);
|
||||
} catch (Exception e) {
|
||||
log.error("批量删除失败!error:{}",e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件外链
|
||||
* @param bucketName 存储桶
|
||||
* @param objectName 文件名
|
||||
* @param expires 过期时间 <=7 秒 (外链有效时间(单位:秒))
|
||||
* @return url
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {
|
||||
GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().expiry(expires).bucket(bucketName).object(objectName).build();
|
||||
return minioClient.getPresignedObjectUrl(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得文件外链
|
||||
* @param bucketName
|
||||
* @param objectName
|
||||
* @return url
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String getPresignedObjectUrl(String bucketName, String objectName) throws Exception {
|
||||
GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(objectName)
|
||||
.method(Method.GET).build();
|
||||
return minioClient.getPresignedObjectUrl(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将URLDecoder编码转成UTF8
|
||||
* @param str
|
||||
* @return
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
public static String getUtf8ByURLDecoder(String str) throws UnsupportedEncodingException {
|
||||
String url = str.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
|
||||
return URLDecoder.decode(url, "UTF-8");
|
||||
}
|
||||
|
||||
/****************************** Operate Files End ******************************/
|
||||
|
||||
|
||||
}
|
9
book-common/src/main/java/com/imooc/utils/MyInfo.java
Normal file
9
book-common/src/main/java/com/imooc/utils/MyInfo.java
Normal file
@ -0,0 +1,9 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
public class MyInfo {
|
||||
|
||||
public static String getMobile() {
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @Title: PagedGridResult.java
|
||||
* @Package com.imooc.utils
|
||||
* @Description: 用来返回分页Grid的数据格式
|
||||
* Copyright: Copyright (c) 2021
|
||||
*/
|
||||
public class PagedGridResult {
|
||||
|
||||
private int page; // 当前页数
|
||||
private long total; // 总页数
|
||||
private long records; // 总记录数
|
||||
private List<?> rows; // 每行显示的内容
|
||||
|
||||
public int getPage() {
|
||||
return page;
|
||||
}
|
||||
public void setPage(int page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public long getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(long total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public void setTotal(int total) {
|
||||
this.total = total;
|
||||
}
|
||||
public long getRecords() {
|
||||
return records;
|
||||
}
|
||||
public void setRecords(long records) {
|
||||
this.records = records;
|
||||
}
|
||||
public List<?> getRows() {
|
||||
return rows;
|
||||
}
|
||||
public void setRows(List<?> rows) {
|
||||
this.rows = rows;
|
||||
}
|
||||
}
|
287
book-common/src/main/java/com/imooc/utils/RedisOperator.java
Normal file
287
book-common/src/main/java/com/imooc/utils/RedisOperator.java
Normal file
@ -0,0 +1,287 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.StringRedisConnection;
|
||||
import org.springframework.data.redis.core.RedisCallback;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @Title: Redis 工具类
|
||||
* @author 风间影月
|
||||
*/
|
||||
@Component
|
||||
public class RedisOperator {
|
||||
|
||||
@Autowired
|
||||
private StringRedisTemplate redisTemplate;
|
||||
|
||||
// Key(键),简单的key-value操作
|
||||
|
||||
/**
|
||||
* 判断key是否存在
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public boolean keyIsExist(String key) {
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:TTL key,以秒为单位,返回给定 key的剩余生存时间(TTL, time to live)。
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public long ttl(String key) {
|
||||
return redisTemplate.getExpire(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:expire 设置过期时间,单位秒
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public void expire(String key, long timeout) {
|
||||
redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:increment key,增加key一次
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public long increment(String key, long delta) {
|
||||
return redisTemplate.opsForValue().increment(key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 累加,使用hash
|
||||
*/
|
||||
public long incrementHash(String name, String key, long delta) {
|
||||
return redisTemplate.opsForHash().increment(name, key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 累减,使用hash
|
||||
*/
|
||||
public long decrementHash(String name, String key, long delta) {
|
||||
delta = delta * (-1);
|
||||
return redisTemplate.opsForHash().increment(name, key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash 设置value
|
||||
*/
|
||||
public void setHashValue(String name, String key, String value) {
|
||||
redisTemplate.opsForHash().put(name, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash 获得value
|
||||
*/
|
||||
public String getHashValue(String name, String key) {
|
||||
return (String)redisTemplate.opsForHash().get(name, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:decrement key,减少key一次
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public long decrement(String key, long delta) {
|
||||
return redisTemplate.opsForValue().decrement(key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:KEYS pattern,查找所有符合给定模式 pattern的 key
|
||||
*/
|
||||
public Set<String> keys(String pattern) {
|
||||
return redisTemplate.keys(pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:DEL key,删除一个key
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public void del(String key) {
|
||||
redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
// String(字符串)
|
||||
|
||||
/**
|
||||
* 实现命令:SET key value,设置一个key-value(将字符串值 value关联到 key)
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void set(String key, String value) {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:SET key value EX seconds,设置key-value和超时时间(秒)
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param timeout
|
||||
* (以秒为单位)
|
||||
*/
|
||||
public void set(String key, String value, long timeout) {
|
||||
redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果key不存在,则设置,如果存在,则报错
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void setnx60s(String key, String value) {
|
||||
redisTemplate.opsForValue().setIfAbsent(key, value, 60, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果key不存在,则设置,如果存在,则报错
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void setnx(String key, String value) {
|
||||
redisTemplate.opsForValue().setIfAbsent(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:GET key,返回 key所关联的字符串值。
|
||||
*
|
||||
* @param key
|
||||
* @return value
|
||||
*/
|
||||
public String get(String key) {
|
||||
return (String)redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询,对应mget
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
public List<String> mget(List<String> keys) {
|
||||
return redisTemplate.opsForValue().multiGet(keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询,管道pipeline
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
public List<Object> batchGet(List<String> keys) {
|
||||
|
||||
// nginx -> keepalive
|
||||
// redis -> pipeline
|
||||
|
||||
List<Object> result = redisTemplate.executePipelined(new RedisCallback<String>() {
|
||||
@Override
|
||||
public String doInRedis(RedisConnection connection) throws DataAccessException {
|
||||
StringRedisConnection src = (StringRedisConnection)connection;
|
||||
|
||||
for (String k : keys) {
|
||||
src.get(k);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Hash(哈希表)
|
||||
|
||||
/**
|
||||
* 实现命令:HSET key field value,将哈希表 key中的域 field的值设为 value
|
||||
*
|
||||
* @param key
|
||||
* @param field
|
||||
* @param value
|
||||
*/
|
||||
public void hset(String key, String field, Object value) {
|
||||
redisTemplate.opsForHash().put(key, field, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:HGET key field,返回哈希表 key中给定域 field的值
|
||||
*
|
||||
* @param key
|
||||
* @param field
|
||||
* @return
|
||||
*/
|
||||
public String hget(String key, String field) {
|
||||
return (String) redisTemplate.opsForHash().get(key, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:HDEL key field [field ...],删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
|
||||
*
|
||||
* @param key
|
||||
* @param fields
|
||||
*/
|
||||
public void hdel(String key, Object... fields) {
|
||||
redisTemplate.opsForHash().delete(key, fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:HGETALL key,返回哈希表 key中,所有的域和值。
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Map<Object, Object> hgetall(String key) {
|
||||
return redisTemplate.opsForHash().entries(key);
|
||||
}
|
||||
|
||||
// List(列表)
|
||||
|
||||
/**
|
||||
* 实现命令:LPUSH key value,将一个值 value插入到列表 key的表头
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return 执行 LPUSH命令后,列表的长度。
|
||||
*/
|
||||
public long lpush(String key, String value) {
|
||||
return redisTemplate.opsForList().leftPush(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:LPOP key,移除并返回列表 key的头元素。
|
||||
*
|
||||
* @param key
|
||||
* @return 列表key的头元素。
|
||||
*/
|
||||
public String lpop(String key) {
|
||||
return (String)redisTemplate.opsForList().leftPop(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:RPUSH key value,将一个值 value插入到列表 key的表尾(最右边)。
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return 执行 LPUSH命令后,列表的长度。
|
||||
*/
|
||||
public long rpush(String key, String value) {
|
||||
return redisTemplate.opsForList().rightPush(key, value);
|
||||
}
|
||||
|
||||
}
|
74
book-common/src/main/java/com/imooc/utils/SMSUtils.java
Normal file
74
book-common/src/main/java/com/imooc/utils/SMSUtils.java
Normal file
@ -0,0 +1,74 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
import com.tencentcloudapi.common.Credential;
|
||||
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||
import com.tencentcloudapi.common.profile.ClientProfile;
|
||||
import com.tencentcloudapi.common.profile.HttpProfile;
|
||||
import com.tencentcloudapi.sms.v20210111.SmsClient;
|
||||
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
|
||||
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SMSUtils {
|
||||
@Autowired
|
||||
private TencentCloudProperties tencentCloudProperties;
|
||||
|
||||
public void sendSMS(String phone, String code) throws Exception {
|
||||
try {
|
||||
/* 必要步骤:
|
||||
* 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey。
|
||||
* 这里采用的是从环境变量读取的方式,需要在环境变量中先设置这两个值。
|
||||
* 你也可以直接在代码中写死密钥对,但是小心不要将代码复制、上传或者分享给他人,
|
||||
* 以免泄露密钥对危及你的财产安全。
|
||||
* CAM密匙查询获取: https://console.cloud.tencent.com/cam/capi*/
|
||||
Credential cred = new Credential(tencentCloudProperties.getSecretId(),
|
||||
tencentCloudProperties.getSecretKey());
|
||||
|
||||
// 实例化一个http选项,可选的,没有特殊需求可以跳过
|
||||
HttpProfile httpProfile = new HttpProfile();
|
||||
|
||||
// httpProfile.setReqMethod("POST"); // 默认使用POST
|
||||
|
||||
/* SDK会自动指定域名。通常是不需要特地指定域名的,但是如果你访问的是金融区的服务
|
||||
* 则必须手动指定域名,例如sms的上海金融区域名: sms.ap-shanghai-fsi.tencentcloudapi.com */
|
||||
httpProfile.setEndpoint("sms.tencentcloudapi.com");
|
||||
|
||||
// 实例化一个client选项
|
||||
ClientProfile clientProfile = new ClientProfile();
|
||||
clientProfile.setHttpProfile(httpProfile);
|
||||
// 实例化要请求产品的client对象,clientProfile是可选的
|
||||
SmsClient client = new SmsClient(cred, "ap-nanjing", clientProfile);
|
||||
|
||||
// 实例化一个请求对象,每个接口都会对应一个request对象
|
||||
SendSmsRequest req = new SendSmsRequest();
|
||||
String[] phoneNumberSet1 = {"+86" + phone};//电话号码
|
||||
req.setPhoneNumberSet(phoneNumberSet1);
|
||||
req.setSmsSdkAppId("1400966042"); // 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId
|
||||
req.setSignName("无终街科技"); // 签名
|
||||
req.setTemplateId("2375314"); // 模板id:必须填写已审核通过的模板 ID。模板ID可登录 [短信控制台] 查看
|
||||
|
||||
/* 模板参数(自定义占位变量): 若无模板参数,则设置为空 */
|
||||
String[] templateParamSet1 = {code};
|
||||
req.setTemplateParamSet(templateParamSet1);
|
||||
|
||||
// 返回的resp是一个SendSmsResponse的实例,与请求对象对应
|
||||
SendSmsResponse resp = client.SendSms(req);
|
||||
// 输出json格式的字符串回包
|
||||
// System.out.println(SendSmsResponse.toJsonString(resp));
|
||||
} catch (TencentCloudSDKException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
new SMSUtils().sendSMS("15237439161", "7896");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
package com.imooc.utils;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author vercen
|
||||
* @version 1.0
|
||||
* @date 2023/5/25 10:21
|
||||
* 获取短信配置
|
||||
*/
|
||||
@Component
|
||||
@Data
|
||||
@PropertySource("classpath:tencentcloud.properties")
|
||||
@ConfigurationProperties(prefix = "tencent.cloud")
|
||||
public class TencentCloudProperties {
|
||||
|
||||
private String secretId;
|
||||
private String secretKey;
|
||||
|
||||
}
|
35
book-common/src/main/java/org/n3r/idworker/Code.java
Normal file
35
book-common/src/main/java/org/n3r/idworker/Code.java
Normal file
@ -0,0 +1,35 @@
|
||||
package org.n3r.idworker;
|
||||
|
||||
import org.n3r.idworker.strategy.DefaultRandomCodeStrategy;
|
||||
|
||||
public class Code {
|
||||
private static RandomCodeStrategy strategy;
|
||||
|
||||
static {
|
||||
RandomCodeStrategy strategy = new DefaultRandomCodeStrategy();
|
||||
strategy.init();
|
||||
configure(strategy);
|
||||
}
|
||||
|
||||
public static synchronized void configure(RandomCodeStrategy custom) {
|
||||
if (strategy == custom) return;
|
||||
if (strategy != null) strategy.release();
|
||||
|
||||
strategy = custom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Next Unique code.
|
||||
* The max length will be 1024-Integer.MAX-Integer.MAX(2147483647) which has 4+10+10+2*1=26 characters.
|
||||
* The min length will be 0-0.
|
||||
*
|
||||
* @return unique string code.
|
||||
*/
|
||||
public static synchronized String next() {
|
||||
long workerId = Id.getWorkerId();
|
||||
int prefix = strategy.prefix();
|
||||
int next = strategy.next();
|
||||
|
||||
return String.format("%d-%03d-%06d", workerId, prefix, next);
|
||||
}
|
||||
}
|
19
book-common/src/main/java/org/n3r/idworker/DayCode.java
Normal file
19
book-common/src/main/java/org/n3r/idworker/DayCode.java
Normal file
@ -0,0 +1,19 @@
|
||||
package org.n3r.idworker;
|
||||
|
||||
import org.n3r.idworker.strategy.DayPrefixRandomCodeStrategy;
|
||||
|
||||
public class DayCode {
|
||||
static RandomCodeStrategy strategy;
|
||||
|
||||
static {
|
||||
DayPrefixRandomCodeStrategy dayPrefixCodeStrategy = new DayPrefixRandomCodeStrategy("yyMM");
|
||||
dayPrefixCodeStrategy.setMinRandomSize(7);
|
||||
dayPrefixCodeStrategy.setMaxRandomSize(7);
|
||||
strategy = dayPrefixCodeStrategy;
|
||||
strategy.init();
|
||||
}
|
||||
|
||||
public static synchronized String next() {
|
||||
return String.format("%d-%04d-%07d", Id.getWorkerId(), strategy.prefix(), strategy.next());
|
||||
}
|
||||
}
|
29
book-common/src/main/java/org/n3r/idworker/Id.java
Normal file
29
book-common/src/main/java/org/n3r/idworker/Id.java
Normal file
@ -0,0 +1,29 @@
|
||||
package org.n3r.idworker;
|
||||
|
||||
import org.n3r.idworker.strategy.DefaultWorkerIdStrategy;
|
||||
|
||||
public class Id {
|
||||
private static WorkerIdStrategy workerIdStrategy;
|
||||
private static IdWorker idWorker;
|
||||
|
||||
static {
|
||||
configure(DefaultWorkerIdStrategy.instance);
|
||||
}
|
||||
|
||||
public static synchronized void configure(WorkerIdStrategy custom) {
|
||||
if (workerIdStrategy == custom) return;
|
||||
|
||||
if (workerIdStrategy != null) workerIdStrategy.release();
|
||||
workerIdStrategy = custom;
|
||||
workerIdStrategy.initialize();
|
||||
idWorker = new IdWorker(workerIdStrategy.availableWorkerId());
|
||||
}
|
||||
|
||||
public static long next() {
|
||||
return idWorker.nextId();
|
||||
}
|
||||
|
||||
public static long getWorkerId() {
|
||||
return idWorker.getWorkerId();
|
||||
}
|
||||
}
|
91
book-common/src/main/java/org/n3r/idworker/IdWorker.java
Normal file
91
book-common/src/main/java/org/n3r/idworker/IdWorker.java
Normal file
@ -0,0 +1,91 @@
|
||||
package org.n3r.idworker;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class IdWorker {
|
||||
protected long epoch = 1288834974657L;
|
||||
// protected long epoch = 1387886498127L; // 2013-12-24 20:01:38.127
|
||||
|
||||
|
||||
protected long workerIdBits = 10L;
|
||||
protected long maxWorkerId = -1L ^ (-1L << workerIdBits);
|
||||
protected long sequenceBits = 11L;
|
||||
|
||||
protected long workerIdShift = sequenceBits;
|
||||
protected long timestampLeftShift = sequenceBits + workerIdBits;
|
||||
protected long sequenceMask = -1L ^ (-1L << sequenceBits);
|
||||
|
||||
protected long lastMillis = -1L;
|
||||
|
||||
protected final long workerId;
|
||||
protected long sequence = 0L;
|
||||
protected Logger logger = LoggerFactory.getLogger(IdWorker.class);
|
||||
|
||||
public IdWorker(long workerId) {
|
||||
this.workerId = checkWorkerId(workerId);
|
||||
|
||||
logger.debug("worker starting. timestamp left shift {}, worker id {}", timestampLeftShift, workerId);
|
||||
}
|
||||
|
||||
public long getEpoch() {
|
||||
return epoch;
|
||||
}
|
||||
|
||||
private long checkWorkerId(long workerId) {
|
||||
// sanity check for workerId
|
||||
if (workerId > maxWorkerId || workerId < 0) {
|
||||
int rand = new SecureRandom().nextInt((int) maxWorkerId + 1);
|
||||
logger.warn("worker Id can't be greater than {} or less than 0, use a random {}", maxWorkerId, rand);
|
||||
return rand;
|
||||
}
|
||||
|
||||
return workerId;
|
||||
}
|
||||
|
||||
public synchronized long nextId() {
|
||||
long timestamp = millisGen();
|
||||
|
||||
if (timestamp < lastMillis) {
|
||||
logger.error("clock is moving backwards. Rejecting requests until {}.", lastMillis);
|
||||
throw new InvalidSystemClock(String.format(
|
||||
"Clock moved backwards. Refusing to generate id for {} milliseconds", lastMillis - timestamp));
|
||||
}
|
||||
|
||||
if (lastMillis == timestamp) {
|
||||
sequence = (sequence + 1) & sequenceMask;
|
||||
if (sequence == 0)
|
||||
timestamp = tilNextMillis(lastMillis);
|
||||
} else {
|
||||
sequence = 0;
|
||||
}
|
||||
|
||||
lastMillis = timestamp;
|
||||
long diff = timestamp - getEpoch();
|
||||
return (diff << timestampLeftShift) |
|
||||
(workerId << workerIdShift) |
|
||||
sequence;
|
||||
}
|
||||
|
||||
protected long tilNextMillis(long lastMillis) {
|
||||
long millis = millisGen();
|
||||
while (millis <= lastMillis)
|
||||
millis = millisGen();
|
||||
|
||||
return millis;
|
||||
}
|
||||
|
||||
protected long millisGen() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public long getLastMillis() {
|
||||
return lastMillis;
|
||||
}
|
||||
|
||||
public long getWorkerId() {
|
||||
return workerId;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.n3r.idworker;
|
||||
|
||||
public class InvalidSystemClock extends RuntimeException {
|
||||
public InvalidSystemClock(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.n3r.idworker;
|
||||
|
||||
public interface RandomCodeStrategy {
|
||||
void init();
|
||||
|
||||
int prefix();
|
||||
|
||||
int next();
|
||||
|
||||
void release();
|
||||
}
|
64
book-common/src/main/java/org/n3r/idworker/Sid.java
Normal file
64
book-common/src/main/java/org/n3r/idworker/Sid.java
Normal file
@ -0,0 +1,64 @@
|
||||
package org.n3r.idworker;
|
||||
|
||||
import org.n3r.idworker.strategy.DefaultWorkerIdStrategy;
|
||||
import org.n3r.idworker.utils.Utils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class Sid {
|
||||
private static WorkerIdStrategy workerIdStrategy;
|
||||
private static IdWorker idWorker;
|
||||
|
||||
static {
|
||||
configure(DefaultWorkerIdStrategy.instance);
|
||||
}
|
||||
|
||||
|
||||
public static synchronized void configure(WorkerIdStrategy custom) {
|
||||
if (workerIdStrategy != null) {
|
||||
workerIdStrategy.release();
|
||||
}
|
||||
workerIdStrategy = custom;
|
||||
idWorker = new IdWorker(workerIdStrategy.availableWorkerId()) {
|
||||
@Override
|
||||
public long getEpoch() {
|
||||
return Utils.midnightMillis();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 一天最大毫秒86400000,最大占用27比特
|
||||
* 27+10+11=48位 最大值281474976710655(15字),YK0XXHZ827(10字)
|
||||
* 6位(YYMMDD)+15位,共21位
|
||||
*
|
||||
* @return 固定21位数字字符串
|
||||
*/
|
||||
|
||||
public static String next() {
|
||||
long id = idWorker.nextId();
|
||||
String yyMMdd = new SimpleDateFormat("yyMMdd").format(new Date());
|
||||
return yyMMdd + String.format("%014d", id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回固定16位的字母数字混编的字符串。
|
||||
*/
|
||||
public String nextShort() {
|
||||
long id = idWorker.nextId();
|
||||
String yyMMdd = new SimpleDateFormat("yyMMdd").format(new Date());
|
||||
return yyMMdd + Utils.padLeft(Utils.encode(id), 10, '0');
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String aa = new Sid().nextShort();
|
||||
String bb = new Sid().next();
|
||||
|
||||
System.out.println(aa);
|
||||
System.out.println(bb);
|
||||
}
|
||||
}
|
12
book-common/src/main/java/org/n3r/idworker/Test.java
Normal file
12
book-common/src/main/java/org/n3r/idworker/Test.java
Normal file
@ -0,0 +1,12 @@
|
||||
package org.n3r.idworker;
|
||||
|
||||
public class Test {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
for (int i = 0 ; i < 1000 ; i ++) {
|
||||
// System.out.println(Sid.nextShort());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package org.n3r.idworker;
|
||||
|
||||
public interface WorkerIdStrategy {
|
||||
void initialize();
|
||||
|
||||
long availableWorkerId();
|
||||
|
||||
void release();
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package org.n3r.idworker.strategy;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class DayPrefixRandomCodeStrategy extends DefaultRandomCodeStrategy {
|
||||
private final String dayFormat;
|
||||
private String lastDay;
|
||||
|
||||
public DayPrefixRandomCodeStrategy(String dayFormat) {
|
||||
this.dayFormat = dayFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
String day = createDate();
|
||||
if (day.equals(lastDay))
|
||||
throw new RuntimeException("init failed for day unrolled");
|
||||
|
||||
lastDay = day;
|
||||
|
||||
availableCodes.clear();
|
||||
release();
|
||||
|
||||
prefixIndex = Integer.parseInt(lastDay);
|
||||
if (tryUsePrefix()) return;
|
||||
|
||||
throw new RuntimeException("prefix is not available " + prefixIndex);
|
||||
}
|
||||
|
||||
private String createDate() {
|
||||
return new SimpleDateFormat(dayFormat).format(new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int next() {
|
||||
if (!lastDay.equals(createDate())) init();
|
||||
|
||||
return super.next();
|
||||
}
|
||||
}
|
@ -0,0 +1,197 @@
|
||||
package org.n3r.idworker.strategy;
|
||||
|
||||
import org.n3r.idworker.Id;
|
||||
import org.n3r.idworker.RandomCodeStrategy;
|
||||
import org.n3r.idworker.utils.Utils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.BitSet;
|
||||
import java.util.Queue;
|
||||
|
||||
public class DefaultRandomCodeStrategy implements RandomCodeStrategy {
|
||||
public static final int MAX_BITS = 1000000;
|
||||
|
||||
Logger log = LoggerFactory.getLogger(DefaultRandomCodeStrategy.class);
|
||||
|
||||
File idWorkerHome = Utils.createIdWorkerHome();
|
||||
volatile FileLock fileLock;
|
||||
BitSet codesFilter;
|
||||
|
||||
int prefixIndex = -1;
|
||||
File codePrefixIndex;
|
||||
|
||||
int minRandomSize = 6;
|
||||
int maxRandomSize = 6;
|
||||
|
||||
public DefaultRandomCodeStrategy() {
|
||||
destroyFileLockWhenShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
release();
|
||||
|
||||
while (++prefixIndex < 1000) {
|
||||
if (tryUsePrefix()) return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("all prefixes are used up, the world maybe ends!");
|
||||
}
|
||||
|
||||
public DefaultRandomCodeStrategy setMinRandomSize(int minRandomSize) {
|
||||
this.minRandomSize = minRandomSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DefaultRandomCodeStrategy setMaxRandomSize(int maxRandomSize) {
|
||||
this.maxRandomSize = maxRandomSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected boolean tryUsePrefix() {
|
||||
codePrefixIndex = new File(idWorkerHome, Id.getWorkerId() + ".code.prefix." + prefixIndex);
|
||||
|
||||
if (!createPrefixIndexFile()) return false;
|
||||
if (!createFileLock()) return false;
|
||||
if (!createBloomFilter()) return false;
|
||||
|
||||
log.info("get available prefix index file {}", codePrefixIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean createFileLock() {
|
||||
if (fileLock != null) fileLock.destroy();
|
||||
fileLock = new FileLock(codePrefixIndex);
|
||||
return fileLock.tryLock();
|
||||
}
|
||||
|
||||
private boolean createBloomFilter() {
|
||||
codesFilter = fileLock.readObject();
|
||||
if (codesFilter == null) {
|
||||
log.info("create new bloom filter");
|
||||
codesFilter = new BitSet(MAX_BITS); // 2^24
|
||||
} else {
|
||||
int size = codesFilter.cardinality();
|
||||
if (size >= MAX_BITS) {
|
||||
log.warn("bloom filter with prefix file {} is already full", codePrefixIndex);
|
||||
return false;
|
||||
}
|
||||
log.info("recreate bloom filter with cardinality {}", size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void destroyFileLockWhenShutdown() {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
release();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean createPrefixIndexFile() {
|
||||
try {
|
||||
codePrefixIndex.createNewFile();
|
||||
return codePrefixIndex.exists();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.warn("create file {} error {}", codePrefixIndex, e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prefix() {
|
||||
return prefixIndex;
|
||||
}
|
||||
|
||||
static final int CACHE_CODES_NUM = 1000;
|
||||
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
Queue<Integer> availableCodes = new ArrayDeque<Integer>(CACHE_CODES_NUM);
|
||||
|
||||
@Override
|
||||
public int next() {
|
||||
if (availableCodes.isEmpty()) generate();
|
||||
|
||||
return availableCodes.poll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void release() {
|
||||
if (fileLock != null) {
|
||||
fileLock.writeObject(codesFilter);
|
||||
fileLock.destroy();
|
||||
fileLock = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void generate() {
|
||||
for (int i = 0; i < CACHE_CODES_NUM; ++i)
|
||||
availableCodes.add(generateOne());
|
||||
|
||||
fileLock.writeObject(codesFilter);
|
||||
}
|
||||
|
||||
private int generateOne() {
|
||||
while (true) {
|
||||
int code = secureRandom.nextInt(max(maxRandomSize));
|
||||
boolean existed = contains(code);
|
||||
|
||||
code = !existed ? add(code) : tryFindAvailableCode(code);
|
||||
if (code >= 0) return code;
|
||||
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
private int tryFindAvailableCode(int code) {
|
||||
int next = codesFilter.nextClearBit(code);
|
||||
if (next != -1 && next < max(maxRandomSize)) return add(next);
|
||||
|
||||
next = codesFilter.previousClearBit(code);
|
||||
if (next != -1) return add(next);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int add(int code) {
|
||||
codesFilter.set(code);
|
||||
return code;
|
||||
}
|
||||
|
||||
private boolean contains(int code) {
|
||||
return codesFilter.get(code);
|
||||
}
|
||||
|
||||
|
||||
private int max(int size) {
|
||||
switch (size) {
|
||||
case 1: // fall through
|
||||
case 2: // fall through
|
||||
case 3: // fall through
|
||||
case 4:
|
||||
return 10000;
|
||||
case 5:
|
||||
return 100000;
|
||||
case 6:
|
||||
return 1000000;
|
||||
case 7:
|
||||
return 10000000;
|
||||
case 8:
|
||||
return 100000000;
|
||||
case 9:
|
||||
return 1000000000;
|
||||
default:
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
package org.n3r.idworker.strategy;
|
||||
|
||||
import org.n3r.idworker.WorkerIdStrategy;
|
||||
import org.n3r.idworker.utils.HttpReq;
|
||||
import org.n3r.idworker.utils.Ip;
|
||||
import org.n3r.idworker.utils.Props;
|
||||
import org.n3r.idworker.utils.Utils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
public class DefaultWorkerIdStrategy implements WorkerIdStrategy {
|
||||
static long workerIdBits = 10L;
|
||||
static long maxWorkerId = -1L ^ (-1L << workerIdBits);
|
||||
static Random random = new SecureRandom();
|
||||
|
||||
public static final WorkerIdStrategy instance = new DefaultWorkerIdStrategy();
|
||||
|
||||
private final Properties props =
|
||||
Props.tryProperties("idworker-client.properties", Utils.DOT_IDWORKERS);
|
||||
private final String idWorkerServerUrl =
|
||||
props.getProperty("server.address", "http://id.worker.server:18001");
|
||||
|
||||
String userName = System.getProperty("user.name");
|
||||
|
||||
String ipDotUsername = Ip.ip + "." + userName;
|
||||
String ipudotlock = ipDotUsername + ".lock.";
|
||||
int workerIdIndex = ipudotlock.length();
|
||||
long workerId;
|
||||
FileLock fileLock;
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(DefaultWorkerIdStrategy.class);
|
||||
private boolean inited;
|
||||
|
||||
|
||||
private void init() {
|
||||
workerId = findAvailWorkerId();
|
||||
if (workerId >= 0) {
|
||||
destroyFileLockWhenShutdown();
|
||||
startSyncThread();
|
||||
} else {
|
||||
syncWithWorkerIdServer();
|
||||
workerId = findAvailWorkerId();
|
||||
if (workerId < 0) workerId = increaseWithWorkerIdServer();
|
||||
}
|
||||
|
||||
if (workerId < 0) workerId = tryToCreateOnIp();
|
||||
if (workerId < 0) {
|
||||
logger.warn("DANGEROUS!!! Try to use random worker id.");
|
||||
workerId = tryToRandomOnIp(); // Try avoiding! it could cause duplicated
|
||||
}
|
||||
|
||||
if (workerId < 0) {
|
||||
logger.warn("the world may be ended!");
|
||||
throw new RuntimeException("the world may be ended");
|
||||
}
|
||||
}
|
||||
|
||||
private void destroyFileLockWhenShutdown() {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileLock.destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startSyncThread() {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
syncWithWorkerIdServer();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private long increaseWithWorkerIdServer() {
|
||||
String incId = HttpReq.get(idWorkerServerUrl)
|
||||
.req("/inc")
|
||||
.param("ipu", ipDotUsername)
|
||||
.exec();
|
||||
if (incId == null || incId.trim().isEmpty()) return -1L;
|
||||
|
||||
long lid = Long.parseLong(incId);
|
||||
|
||||
return checkAvail(lid);
|
||||
}
|
||||
|
||||
private long tryToCreateOnIp() {
|
||||
long wid = Ip.lip & maxWorkerId;
|
||||
|
||||
return checkAvail(wid);
|
||||
}
|
||||
|
||||
private long tryToRandomOnIp() {
|
||||
long avaiWorkerId = -1L;
|
||||
long tryTimes = -1;
|
||||
|
||||
while (avaiWorkerId < 0 && ++tryTimes < maxWorkerId) {
|
||||
long wid = Ip.lip & random.nextInt((int) maxWorkerId);
|
||||
|
||||
avaiWorkerId = checkAvail(wid);
|
||||
}
|
||||
return avaiWorkerId;
|
||||
}
|
||||
|
||||
private long checkAvail(long wid) {
|
||||
long availWorkerId = -1L;
|
||||
try {
|
||||
File idWorkerHome = Utils.createIdWorkerHome();
|
||||
new File(idWorkerHome, ipudotlock + String.format("%04d", wid)).createNewFile();
|
||||
availWorkerId = findAvailWorkerId();
|
||||
} catch (IOException e) {
|
||||
logger.warn("checkAvail error", e);
|
||||
}
|
||||
|
||||
return availWorkerId;
|
||||
}
|
||||
|
||||
private void syncWithWorkerIdServer() {
|
||||
String syncIds = HttpReq.get(idWorkerServerUrl).req("/sync")
|
||||
.param("ipu", ipDotUsername).param("ids", buildWorkerIdsOfCurrentIp())
|
||||
.exec();
|
||||
if (syncIds == null || syncIds.trim().isEmpty()) return;
|
||||
|
||||
String[] syncIdsArr = syncIds.split(",");
|
||||
File idWorkerHome = Utils.createIdWorkerHome();
|
||||
for (String syncId : syncIdsArr) {
|
||||
try {
|
||||
new File(idWorkerHome, ipudotlock + syncId).createNewFile();
|
||||
} catch (IOException e) {
|
||||
logger.warn("create workerid lock file error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String buildWorkerIdsOfCurrentIp() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
File idWorkerHome = Utils.createIdWorkerHome();
|
||||
for (File lockFile : idWorkerHome.listFiles()) {
|
||||
// check the format like 10.142.1.151.lock.0001
|
||||
if (!lockFile.getName().startsWith(ipudotlock)) continue;
|
||||
|
||||
String workerId = lockFile.getName().substring(workerIdIndex);
|
||||
if (!workerId.matches("\\d\\d\\d\\d")) continue;
|
||||
|
||||
if (sb.length() > 0) sb.append(',');
|
||||
sb.append(workerId);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the local available worker id.
|
||||
*
|
||||
* @return -1 when N/A
|
||||
*/
|
||||
private long findAvailWorkerId() {
|
||||
File idWorkerHome = Utils.createIdWorkerHome();
|
||||
|
||||
for (File lockFile : idWorkerHome.listFiles()) {
|
||||
// check the format like 10.142.1.151.lock.0001
|
||||
if (!lockFile.getName().startsWith(ipudotlock)) continue;
|
||||
|
||||
String workerId = lockFile.getName().substring(workerIdIndex);
|
||||
if (!workerId.matches("\\d\\d\\d\\d")) continue;
|
||||
|
||||
FileLock fileLock = new FileLock(lockFile);
|
||||
if (!fileLock.tryLock()) {
|
||||
fileLock.destroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
this.fileLock = fileLock;
|
||||
return Long.parseLong(workerId);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
if (inited) return;
|
||||
init();
|
||||
this.inited = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long availableWorkerId() {
|
||||
return workerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if (fileLock != null) fileLock.destroy();
|
||||
inited = false;
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
package org.n3r.idworker.strategy;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.OverlappingFileLockException;
|
||||
|
||||
/**
|
||||
* A file lock a la flock/funlock
|
||||
* <p/>
|
||||
* The given path will be created and opened if it doesn't exist.
|
||||
*/
|
||||
public class FileLock {
|
||||
private final File file;
|
||||
private FileChannel channel;
|
||||
private java.nio.channels.FileLock flock = null;
|
||||
Logger logger = LoggerFactory.getLogger(FileLock.class);
|
||||
|
||||
public FileLock(File file) {
|
||||
this.file = file;
|
||||
|
||||
try {
|
||||
file.createNewFile(); // create the file if it doesn't exist
|
||||
channel = new RandomAccessFile(file, "rw").getChannel();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lock the file or throw an exception if the lock is already held
|
||||
*/
|
||||
public void lock() {
|
||||
try {
|
||||
synchronized (this) {
|
||||
logger.trace("Acquiring lock on {}", file.getAbsolutePath());
|
||||
flock = channel.lock();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to lock the file and return true if the locking succeeds
|
||||
*/
|
||||
public boolean tryLock() {
|
||||
synchronized (this) {
|
||||
logger.trace("Acquiring lock on {}", file.getAbsolutePath());
|
||||
try {
|
||||
// weirdly this method will return null if the lock is held by another
|
||||
// process, but will throw an exception if the lock is held by this process
|
||||
// so we have to handle both cases
|
||||
flock = channel.tryLock();
|
||||
return flock != null;
|
||||
} catch (OverlappingFileLockException e) {
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock the lock if it is held
|
||||
*/
|
||||
public void unlock() {
|
||||
synchronized (this) {
|
||||
logger.trace("Releasing lock on {}", file.getAbsolutePath());
|
||||
if (flock == null) return;
|
||||
try {
|
||||
flock.release();
|
||||
} catch (ClosedChannelException e) {
|
||||
// Ignore
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy this lock, closing the associated FileChannel
|
||||
*/
|
||||
public void destroy() {
|
||||
synchronized (this) {
|
||||
unlock();
|
||||
if (!channel.isOpen()) return;
|
||||
|
||||
try {
|
||||
channel.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T readObject() {
|
||||
try {
|
||||
InputStream is = Channels.newInputStream(channel);
|
||||
ObjectInputStream objectReader = new ObjectInputStream(is);
|
||||
return (T) objectReader.readObject();
|
||||
} catch (EOFException e) {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public synchronized boolean writeObject(Object object) {
|
||||
if (!channel.isOpen()) return false;
|
||||
|
||||
try {
|
||||
channel.position(0);
|
||||
OutputStream out = Channels.newOutputStream(channel);
|
||||
ObjectOutputStream objectOutput = new ObjectOutputStream(out);
|
||||
objectOutput.writeObject(object);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
113
book-common/src/main/java/org/n3r/idworker/utils/HttpReq.java
Normal file
113
book-common/src/main/java/org/n3r/idworker/utils/HttpReq.java
Normal file
@ -0,0 +1,113 @@
|
||||
package org.n3r.idworker.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.*;
|
||||
|
||||
public class HttpReq {
|
||||
private final String baseUrl;
|
||||
private String req;
|
||||
private StringBuilder params = new StringBuilder();
|
||||
Logger logger = LoggerFactory.getLogger(HttpReq.class);
|
||||
|
||||
public HttpReq(String baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public static HttpReq get(String baseUrl) {
|
||||
return new HttpReq(baseUrl);
|
||||
}
|
||||
|
||||
public HttpReq req(String req) {
|
||||
this.req = req;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpReq param(String name, String value) {
|
||||
if (params.length() > 0) params.append('&');
|
||||
try {
|
||||
params.append(name).append('=').append(URLEncoder.encode(value, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public String exec() {
|
||||
HttpURLConnection http = null;
|
||||
try {
|
||||
http = (HttpURLConnection) new URL(baseUrl
|
||||
+ (req == null ? "" : req)
|
||||
+ (params.length() > 0 ? ("?" + params) : "")).openConnection();
|
||||
http.setRequestProperty("Accept-Charset", "UTF-8");
|
||||
HttpURLConnection.setFollowRedirects(false);
|
||||
http.setConnectTimeout(5 * 1000);
|
||||
http.setReadTimeout(5 * 1000);
|
||||
http.connect();
|
||||
|
||||
int status = http.getResponseCode();
|
||||
String charset = getCharset(http.getHeaderField("Content-Type"));
|
||||
|
||||
if (status == 200) {
|
||||
return readResponseBody(http, charset);
|
||||
} else {
|
||||
logger.warn("non 200 respoonse :" + readErrorResponseBody(http, status, charset));
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("exec error {}", e.getMessage());
|
||||
return null;
|
||||
} finally {
|
||||
if (http != null) http.disconnect();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static String readErrorResponseBody(HttpURLConnection http, int status, String charset) throws IOException {
|
||||
InputStream errorStream = http.getErrorStream();
|
||||
if (errorStream != null) {
|
||||
String error = toString(charset, errorStream);
|
||||
return ("STATUS CODE =" + status + "\n\n" + error);
|
||||
} else {
|
||||
return ("STATUS CODE =" + status);
|
||||
}
|
||||
}
|
||||
|
||||
private static String readResponseBody(HttpURLConnection http, String charset) throws IOException {
|
||||
InputStream inputStream = http.getInputStream();
|
||||
|
||||
return toString(charset, inputStream);
|
||||
}
|
||||
|
||||
private static String toString(String charset, InputStream inputStream) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
int length;
|
||||
while ((length = inputStream.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, length);
|
||||
}
|
||||
|
||||
return new String(baos.toByteArray(), charset);
|
||||
}
|
||||
|
||||
private static String getCharset(String contentType) {
|
||||
if (contentType == null) return "UTF-8";
|
||||
|
||||
String charset = null;
|
||||
for (String param : contentType.replace(" ", "").split(";")) {
|
||||
if (param.startsWith("charset=")) {
|
||||
charset = param.split("=", 2)[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return charset == null ? "UTF-8" : charset;
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package org.n3r.idworker.utils;
|
||||
|
||||
/**
|
||||
* This utility provides methods to either convert an IPv4 address to its long format or a 32bit dotted format.
|
||||
*
|
||||
* @author Aion
|
||||
* Created on 22/11/12
|
||||
*/
|
||||
public class IPv4Utils {
|
||||
|
||||
/**
|
||||
* Returns the long format of the provided IP address.
|
||||
*
|
||||
* @param ipAddress the IP address
|
||||
* @return the long format of <code>ipAddress</code>
|
||||
* @throws IllegalArgumentException if <code>ipAddress</code> is invalid
|
||||
*/
|
||||
public static long toLong(String ipAddress) {
|
||||
if (ipAddress == null || ipAddress.isEmpty()) {
|
||||
throw new IllegalArgumentException("ip address cannot be null or empty");
|
||||
}
|
||||
String[] octets = ipAddress.split(java.util.regex.Pattern.quote("."));
|
||||
if (octets.length != 4) {
|
||||
throw new IllegalArgumentException("invalid ip address");
|
||||
}
|
||||
long ip = 0;
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
long octet = Long.parseLong(octets[3 - i]);
|
||||
if (octet > 255 || octet < 0) {
|
||||
throw new IllegalArgumentException("invalid ip address");
|
||||
}
|
||||
ip |= octet << (i * 8);
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 32bit dotted format of the provided long ip.
|
||||
*
|
||||
* @param ip the long ip
|
||||
* @return the 32bit dotted format of <code>ip</code>
|
||||
* @throws IllegalArgumentException if <code>ip</code> is invalid
|
||||
*/
|
||||
public static String toString(long ip) {
|
||||
// if ip is bigger than 255.255.255.255 or smaller than 0.0.0.0
|
||||
if (ip > 4294967295l || ip < 0) {
|
||||
throw new IllegalArgumentException("invalid ip");
|
||||
}
|
||||
StringBuilder ipAddress = new StringBuilder();
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
int shift = i * 8;
|
||||
ipAddress.append((ip & (0xff << shift)) >> shift);
|
||||
if (i > 0) {
|
||||
ipAddress.append(".");
|
||||
}
|
||||
}
|
||||
return ipAddress.toString();
|
||||
}
|
||||
|
||||
}
|
50
book-common/src/main/java/org/n3r/idworker/utils/Ip.java
Normal file
50
book-common/src/main/java/org/n3r/idworker/utils/Ip.java
Normal file
@ -0,0 +1,50 @@
|
||||
package org.n3r.idworker.utils;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class Ip {
|
||||
static Logger logger = LoggerFactory.getLogger(Ip.class);
|
||||
|
||||
public static String ip;
|
||||
public static long lip;
|
||||
|
||||
static {
|
||||
try {
|
||||
InetAddress localHostLANAddress = getFirstNonLoopbackAddress();
|
||||
ip = localHostLANAddress.getHostAddress();
|
||||
|
||||
byte[] address = localHostLANAddress.getAddress();
|
||||
lip = ((address [0] & 0xFFL) << (3*8)) +
|
||||
((address [1] & 0xFFL) << (2*8)) +
|
||||
((address [2] & 0xFFL) << (1*8)) +
|
||||
(address [3] & 0xFFL);
|
||||
} catch (Exception e) {
|
||||
logger.error("get ipv4 failed ", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static InetAddress getFirstNonLoopbackAddress() throws SocketException {
|
||||
Enumeration en = NetworkInterface.getNetworkInterfaces();
|
||||
while (en.hasMoreElements()) {
|
||||
NetworkInterface i = (NetworkInterface) en.nextElement();
|
||||
for (Enumeration en2 = i.getInetAddresses(); en2.hasMoreElements(); ) {
|
||||
InetAddress addr = (InetAddress) en2.nextElement();
|
||||
if (addr.isLoopbackAddress()) continue;
|
||||
|
||||
if (addr instanceof Inet4Address) {
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
70
book-common/src/main/java/org/n3r/idworker/utils/Props.java
Normal file
70
book-common/src/main/java/org/n3r/idworker/utils/Props.java
Normal file
@ -0,0 +1,70 @@
|
||||
package org.n3r.idworker.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Properties;
|
||||
|
||||
import static java.io.File.separator;
|
||||
import static org.n3r.idworker.utils.Serializes.closeQuietly;
|
||||
|
||||
public class Props {
|
||||
static Logger log = LoggerFactory.getLogger(Props.class);
|
||||
|
||||
public static Properties tryProperties(String propertiesFileName, String userHomeBasePath) {
|
||||
Properties properties = new Properties();
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = Props.tryResource(propertiesFileName, userHomeBasePath, Silent.ON);
|
||||
if (is != null) properties.load(is);
|
||||
} catch (IOException e) {
|
||||
log.error("load properties error: {}", e.getMessage());
|
||||
} finally {
|
||||
closeQuietly(is);
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
||||
enum Silent {ON, OFF}
|
||||
|
||||
public static InputStream tryResource(String propertiesFileName, String userHomeBasePath, Silent silent) {
|
||||
InputStream is = currentDirResource(new File(propertiesFileName));
|
||||
if (is != null) return is;
|
||||
|
||||
is = userHomeResource(propertiesFileName, userHomeBasePath);
|
||||
if (is != null) return is;
|
||||
|
||||
is = classpathResource(propertiesFileName);
|
||||
if (is != null || silent == Silent.ON) return is;
|
||||
|
||||
throw new RuntimeException("fail to find " + propertiesFileName + " in current dir or classpath");
|
||||
}
|
||||
|
||||
private static InputStream userHomeResource(String pathname, String appHome) {
|
||||
String filePath = System.getProperty("user.home") + separator + appHome;
|
||||
File dir = new File(filePath);
|
||||
if (!dir.exists()) return null;
|
||||
|
||||
return currentDirResource(new File(dir, pathname));
|
||||
}
|
||||
|
||||
private static InputStream currentDirResource(File file) {
|
||||
if (!file.exists()) return null;
|
||||
|
||||
try {
|
||||
return new FileInputStream(file);
|
||||
} catch (FileNotFoundException e) {
|
||||
// This should not happened
|
||||
log.error("read file {} error", file, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream classpathResource(String resourceName) {
|
||||
return Props.class.getClassLoader().getResourceAsStream(resourceName);
|
||||
}
|
||||
|
||||
}
|
118
book-common/src/main/java/org/n3r/idworker/utils/Serializes.java
Normal file
118
book-common/src/main/java/org/n3r/idworker/utils/Serializes.java
Normal file
@ -0,0 +1,118 @@
|
||||
package org.n3r.idworker.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Serializes {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> List<T> readObjects(File file) {
|
||||
ArrayList<T> objects = new ArrayList<T>();
|
||||
ObjectInputStream objectReader = null;
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(file);
|
||||
objectReader = new ObjectInputStream(fis);
|
||||
while (true)
|
||||
objects.add((T) objectReader.readObject());
|
||||
|
||||
} catch (EOFException e) {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
closeQuietly(objectReader);
|
||||
closeQuietly(fis);
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T readObject(File file) {
|
||||
ObjectInputStream objectReader = null;
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(file);
|
||||
objectReader = new ObjectInputStream(fis);
|
||||
return (T) objectReader.readObject();
|
||||
|
||||
} catch (EOFException e) {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
closeQuietly(objectReader);
|
||||
closeQuietly(fis);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void writeObject(File file, Object object) {
|
||||
ObjectOutputStream objectOutput = null;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(file);
|
||||
objectOutput = new ObjectOutputStream(fos);
|
||||
objectOutput.writeObject(object);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
closeQuietly(objectOutput);
|
||||
closeQuietly(fos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeObject(FileOutputStream fos, Object object) {
|
||||
FileChannel channel = fos.getChannel();
|
||||
if (!channel.isOpen()) throw new RuntimeException("channel is closed");
|
||||
|
||||
try {
|
||||
channel.position(0);
|
||||
ObjectOutputStream objectOutput = new ObjectOutputStream(fos);
|
||||
objectOutput.writeObject(object);
|
||||
fos.flush();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeObjects(File file, Object... objects) {
|
||||
ObjectOutputStream objectOutput = null;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(file);
|
||||
objectOutput = new ObjectOutputStream(fos);
|
||||
|
||||
for (Object object : objects)
|
||||
objectOutput.writeObject(object);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
closeQuietly(objectOutput);
|
||||
closeQuietly(fos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void closeQuietly(OutputStream os) {
|
||||
if (os != null) try {
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void closeQuietly(InputStream is) {
|
||||
if (is != null) try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
}
|
||||
}
|
114
book-common/src/main/java/org/n3r/idworker/utils/Utils.java
Normal file
114
book-common/src/main/java/org/n3r/idworker/utils/Utils.java
Normal file
@ -0,0 +1,114 @@
|
||||
package org.n3r.idworker.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public static final String DOT_IDWORKERS = ".idworkers";
|
||||
|
||||
public static ClassLoader getClassLoader() {
|
||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
return contextClassLoader != null ? contextClassLoader : Utils.class.getClassLoader();
|
||||
}
|
||||
|
||||
|
||||
public static InputStream classResourceToStream(String resourceName) {
|
||||
return getClassLoader().getResourceAsStream(resourceName);
|
||||
}
|
||||
|
||||
|
||||
public static String firstLine(String classResourceName) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = classResourceToStream(classResourceName);
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
|
||||
|
||||
return bufferedReader.readLine();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
} finally {
|
||||
if (inputStream != null) try {
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String checkNotEmpty(String param, String name) {
|
||||
if (param == null || param.isEmpty())
|
||||
throw new IllegalArgumentException(name + " is empty");
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
|
||||
public static long midnightMillis() {
|
||||
// today
|
||||
Calendar date = Calendar.getInstance();
|
||||
// reset hour, minutes, seconds and millis
|
||||
date.set(Calendar.HOUR_OF_DAY, 0);
|
||||
date.set(Calendar.MINUTE, 0);
|
||||
date.set(Calendar.SECOND, 0);
|
||||
date.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
return date.getTimeInMillis();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 2013-12-25 00:00:00.000
|
||||
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Timestamp(midnightMillis())));
|
||||
System.out.println(encode(281474976710655L));
|
||||
}
|
||||
|
||||
public static long decode(String s, String symbols) {
|
||||
final int B = symbols.length();
|
||||
long num = 0;
|
||||
for (char ch : s.toCharArray()) {
|
||||
num *= B;
|
||||
num += symbols.indexOf(ch);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static String encode(long num) {
|
||||
return encode(num, defaultRange);
|
||||
}
|
||||
|
||||
public static String encode(long num, String symbols) {
|
||||
final int B = symbols.length();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (num != 0) {
|
||||
sb.append(symbols.charAt((int) (num % B)));
|
||||
num /= B;
|
||||
}
|
||||
return sb.reverse().toString();
|
||||
}
|
||||
|
||||
// all un-clearly-recognized letters are skiped.
|
||||
static String defaultRange = "0123456789ABCDFGHKMNPRSTWXYZ";
|
||||
|
||||
public static String padLeft(String str, int size, char padChar) {
|
||||
if (str.length() >= size) return str;
|
||||
|
||||
StringBuilder s = new StringBuilder();
|
||||
for (int i = size - str.length(); i > 0; --i) {
|
||||
s.append(padChar);
|
||||
}
|
||||
s.append(str);
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
public static File createIdWorkerHome() {
|
||||
String userHome = System.getProperty("user.home");
|
||||
File idWorkerHome = new File(userHome + File.separator + DOT_IDWORKERS);
|
||||
idWorkerHome.mkdirs();
|
||||
if (idWorkerHome.isDirectory()) return idWorkerHome;
|
||||
|
||||
throw new RuntimeException("failed to create .idworkers at user home");
|
||||
}
|
||||
}
|
2
book-common/src/main/resources/tencentcloud.properties
Normal file
2
book-common/src/main/resources/tencentcloud.properties
Normal file
@ -0,0 +1,2 @@
|
||||
tencent.cloud.secretId=AKIDvhEVWHm0xe5JGxOZXGitnRovlKcfRzIN
|
||||
tencent.cloud.secretKey=qPhiTxA7oENFrCH5dvxiCQN4UdWAYgYA
|
29
book-mapper/pom.xml
Normal file
29
book-mapper/pom.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.imooc</groupId>
|
||||
<artifactId>imooc-red-book-dev</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<!--数据层-->
|
||||
<artifactId>book-mapper</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.imooc</groupId>
|
||||
<artifactId>book-model</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
package com.imooc.mapper;
|
||||
|
||||
import com.imooc.my.mapper.MyMapper;
|
||||
import com.imooc.pojo.Comment;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface CommentMapper extends MyMapper<Comment> {
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.imooc.mapper;
|
||||
|
||||
import com.imooc.vo.CommentVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Repository
|
||||
public interface CommentMapperCustom {
|
||||
|
||||
public List<CommentVO> getCommentList(@Param("paramMap") Map<String, Object> map);
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.imooc.mapper;
|
||||
|
||||
import com.imooc.my.mapper.MyMapper;
|
||||
import com.imooc.pojo.Fans;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface FansMapper extends MyMapper<Fans> {
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.imooc.mapper;
|
||||
|
||||
import com.imooc.my.mapper.MyMapper;
|
||||
import com.imooc.pojo.Fans;
|
||||
import com.imooc.vo.FansVO;
|
||||
import com.imooc.vo.VlogerVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Repository
|
||||
public interface FansMapperCustom extends MyMapper<Fans> {
|
||||
|
||||
public List<VlogerVO> queryMyFollows(@Param("paramMap") Map<String, Object> map);
|
||||
|
||||
public List<FansVO> queryMyFans(@Param("paramMap") Map<String, Object> map);
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.imooc.mapper;
|
||||
|
||||
import com.imooc.my.mapper.MyMapper;
|
||||
import com.imooc.pojo.MyLikedVlog;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface MyLikedVlogMapper extends MyMapper<MyLikedVlog> {
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.imooc.mapper;
|
||||
|
||||
import com.imooc.my.mapper.MyMapper;
|
||||
import com.imooc.pojo.Users;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface UsersMapper extends MyMapper<Users> {
|
||||
}
|
10
book-mapper/src/main/java/com/imooc/mapper/VlogMapper.java
Normal file
10
book-mapper/src/main/java/com/imooc/mapper/VlogMapper.java
Normal file
@ -0,0 +1,10 @@
|
||||
package com.imooc.mapper;
|
||||
|
||||
import com.imooc.my.mapper.MyMapper;
|
||||
import com.imooc.pojo.Vlog;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
|
||||
@Repository
|
||||
public interface VlogMapper extends MyMapper<Vlog> {
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.imooc.mapper;
|
||||
|
||||
import com.imooc.vo.IndexVlogVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Repository
|
||||
public interface VlogMapperCustom {
|
||||
|
||||
public List<IndexVlogVO> getIndexVlogList(@Param("paramMap")Map<String, Object> map);
|
||||
|
||||
public List<IndexVlogVO> getVlogDetailById(@Param("paramMap")Map<String, Object> map);
|
||||
|
||||
public List<IndexVlogVO> getMyLikedVlogList(@Param("paramMap")Map<String, Object> map);
|
||||
|
||||
public List<IndexVlogVO> getMyFollowVlogList(@Param("paramMap")Map<String, Object> map);
|
||||
|
||||
public List<IndexVlogVO> getMyFriendVlogList(@Param("paramMap")Map<String, Object> map);
|
||||
|
||||
}
|
34
book-mapper/src/main/java/com/imooc/my/mapper/MyMapper.java
Normal file
34
book-mapper/src/main/java/com/imooc/my/mapper/MyMapper.java
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2016 abel533@gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.imooc.my.mapper;
|
||||
|
||||
import tk.mybatis.mapper.common.Mapper;
|
||||
import tk.mybatis.mapper.common.MySqlMapper;
|
||||
|
||||
/**
|
||||
* 继承自己的MyMapper
|
||||
*/
|
||||
public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.imooc.repository;
|
||||
|
||||
import com.imooc.mo.MessageMO;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface MessageRepository extends MongoRepository<MessageMO, String> {
|
||||
|
||||
// 通过实现Repository,自定义条件查询
|
||||
List<MessageMO> findAllByToUserIdEqualsOrderByCreateTimeDesc(String toUserId,
|
||||
Pageable pageable);
|
||||
// void deleteAllByFromUserIdAndToUserIdAndMsgType();
|
||||
}
|
17
book-mapper/src/main/resources/mapper/CommentMapper.xml
Normal file
17
book-mapper/src/main/resources/mapper/CommentMapper.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?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.imooc.mapper.CommentMapper" >
|
||||
<resultMap id="BaseResultMap" type="com.imooc.pojo.Comment" >
|
||||
<!--
|
||||
WARNING - @mbg.generated
|
||||
-->
|
||||
<id column="id" property="id" jdbcType="VARCHAR" />
|
||||
<result column="vloger_id" property="vlogerId" jdbcType="VARCHAR" />
|
||||
<result column="father_comment_id" property="fatherCommentId" jdbcType="VARCHAR" />
|
||||
<result column="vlog_id" property="vlogId" jdbcType="VARCHAR" />
|
||||
<result column="comment_user_id" property="commentUserId" jdbcType="VARCHAR" />
|
||||
<result column="content" property="content" jdbcType="VARCHAR" />
|
||||
<result column="like_counts" property="likeCounts" jdbcType="INTEGER" />
|
||||
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
|
||||
</resultMap>
|
||||
</mapper>
|
@ -0,0 +1,46 @@
|
||||
<?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.imooc.mapper.CommentMapperCustom" >
|
||||
|
||||
<!--
|
||||
FIXME
|
||||
思考:阿里规范明确规定不能超过三表关联,这里达到了四张表
|
||||
我们应该如何优化呢?使得sql脚本查询表位三表或者两表查询
|
||||
来实现呢又或者说我们能不能不使用数据库,使用别的手段(中间件)?mycat
|
||||
-->
|
||||
<select id="getCommentList" parameterType="map" resultType="com.imooc.vo.CommentVO">
|
||||
|
||||
SELECT
|
||||
c.id as commentId,
|
||||
c.vlog_id as vlogId,
|
||||
u.id as vlogerId,
|
||||
u.nickname as commentUserNickname,
|
||||
u.face as commentUserFace,
|
||||
c.father_comment_id as fatherCommentId,
|
||||
c.comment_user_id as commentUserId,
|
||||
c.content as content,
|
||||
c.like_counts as likeCounts,
|
||||
fu.nickname as replyedUserNickname,
|
||||
c.create_time as createTime
|
||||
FROM
|
||||
`comment` as c
|
||||
LEFT JOIN
|
||||
users as u
|
||||
ON
|
||||
c.comment_user_id = u.id
|
||||
LEFT JOIN
|
||||
`comment` as fc
|
||||
ON
|
||||
c.father_comment_id = fc.id
|
||||
LEFT JOIN
|
||||
users as fu
|
||||
ON
|
||||
fc.comment_user_id = fu.id
|
||||
WHERE
|
||||
c.vlog_id = #{paramMap.vlogId}
|
||||
ORDER BY
|
||||
c.like_counts DESC,
|
||||
c.create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
13
book-mapper/src/main/resources/mapper/FansMapper.xml
Normal file
13
book-mapper/src/main/resources/mapper/FansMapper.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?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.imooc.mapper.FansMapper" >
|
||||
<resultMap id="BaseResultMap" type="com.imooc.pojo.Fans" >
|
||||
<!--
|
||||
WARNING - @mbg.generated
|
||||
-->
|
||||
<id column="id" property="id" jdbcType="VARCHAR" />
|
||||
<result column="vloger_id" property="vlogerId" jdbcType="VARCHAR" />
|
||||
<result column="fan_id" property="fanId" jdbcType="VARCHAR" />
|
||||
<result column="is_fan_friend_of_mine" property="isFanFriendOfMine" jdbcType="INTEGER" />
|
||||
</resultMap>
|
||||
</mapper>
|
45
book-mapper/src/main/resources/mapper/FansMapperCustom.xml
Normal file
45
book-mapper/src/main/resources/mapper/FansMapperCustom.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?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.imooc.mapper.FansMapperCustom" >
|
||||
|
||||
<select id="queryMyFollows" resultType="com.imooc.vo.VlogerVO" parameterType="map">
|
||||
|
||||
SELECT
|
||||
u.id as vlogerId,
|
||||
u.nickname as nickname,
|
||||
u.face as face
|
||||
FROM
|
||||
fans f
|
||||
LEFT JOIN
|
||||
users u
|
||||
ON
|
||||
f.vloger_id = u.id
|
||||
WHERE
|
||||
f.fan_id = #{paramMap.myId}
|
||||
ORDER BY
|
||||
u.nickname
|
||||
ASC
|
||||
|
||||
</select>
|
||||
|
||||
<select id="queryMyFans" resultType="com.imooc.vo.FansVO" parameterType="map">
|
||||
|
||||
SELECT
|
||||
u.id as fanId,
|
||||
u.nickname as nickname,
|
||||
u.face as face
|
||||
FROM
|
||||
fans f
|
||||
LEFT JOIN
|
||||
users u
|
||||
ON
|
||||
f.fan_id = u.id
|
||||
WHERE
|
||||
f.vloger_id = #{paramMap.myId}
|
||||
ORDER BY
|
||||
u.nickname
|
||||
ASC
|
||||
|
||||
</select>
|
||||
|
||||
</mapper>
|
12
book-mapper/src/main/resources/mapper/MyLikedVlogMapper.xml
Normal file
12
book-mapper/src/main/resources/mapper/MyLikedVlogMapper.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?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.imooc.mapper.MyLikedVlogMapper" >
|
||||
<resultMap id="BaseResultMap" type="com.imooc.pojo.MyLikedVlog" >
|
||||
<!--
|
||||
WARNING - @mbg.generated
|
||||
-->
|
||||
<id column="id" property="id" jdbcType="VARCHAR" />
|
||||
<result column="user_id" property="userId" jdbcType="VARCHAR" />
|
||||
<result column="vlog_id" property="vlogId" jdbcType="VARCHAR" />
|
||||
</resultMap>
|
||||
</mapper>
|
25
book-mapper/src/main/resources/mapper/UsersMapper.xml
Normal file
25
book-mapper/src/main/resources/mapper/UsersMapper.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?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.imooc.mapper.UsersMapper" >
|
||||
<resultMap id="BaseResultMap" type="com.imooc.pojo.Users" >
|
||||
<!--
|
||||
WARNING - @mbg.generated
|
||||
-->
|
||||
<id column="id" property="id" jdbcType="VARCHAR" />
|
||||
<result column="mobile" property="mobile" jdbcType="VARCHAR" />
|
||||
<result column="nickname" property="nickname" jdbcType="VARCHAR" />
|
||||
<result column="imooc_num" property="imoocNum" jdbcType="VARCHAR" />
|
||||
<result column="face" property="face" jdbcType="VARCHAR" />
|
||||
<result column="sex" property="sex" jdbcType="INTEGER" />
|
||||
<result column="birthday" property="birthday" jdbcType="DATE" />
|
||||
<result column="country" property="country" jdbcType="VARCHAR" />
|
||||
<result column="province" property="province" jdbcType="VARCHAR" />
|
||||
<result column="city" property="city" jdbcType="VARCHAR" />
|
||||
<result column="district" property="district" jdbcType="VARCHAR" />
|
||||
<result column="description" property="description" jdbcType="VARCHAR" />
|
||||
<result column="bg_img" property="bgImg" jdbcType="VARCHAR" />
|
||||
<result column="can_imooc_num_be_updated" property="canImoocNumBeUpdated" jdbcType="INTEGER" />
|
||||
<result column="created_time" property="createdTime" jdbcType="TIMESTAMP" />
|
||||
<result column="updated_time" property="updatedTime" jdbcType="TIMESTAMP" />
|
||||
</resultMap>
|
||||
</mapper>
|
21
book-mapper/src/main/resources/mapper/VlogMapper.xml
Normal file
21
book-mapper/src/main/resources/mapper/VlogMapper.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?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.imooc.mapper.VlogMapper" >
|
||||
<resultMap id="BaseResultMap" type="com.imooc.pojo.Vlog" >
|
||||
<!--
|
||||
WARNING - @mbg.generated
|
||||
-->
|
||||
<id column="id" property="id" jdbcType="VARCHAR" />
|
||||
<result column="vloger_id" property="vlogerId" jdbcType="VARCHAR" />
|
||||
<result column="url" property="url" jdbcType="VARCHAR" />
|
||||
<result column="cover" property="cover" jdbcType="VARCHAR" />
|
||||
<result column="title" property="title" jdbcType="VARCHAR" />
|
||||
<result column="width" property="width" jdbcType="INTEGER" />
|
||||
<result column="height" property="height" jdbcType="INTEGER" />
|
||||
<result column="like_counts" property="likeCounts" jdbcType="INTEGER" />
|
||||
<result column="comments_counts" property="commentsCounts" jdbcType="INTEGER" />
|
||||
<result column="is_private" property="isPrivate" jdbcType="INTEGER" />
|
||||
<result column="created_time" property="createdTime" jdbcType="TIMESTAMP" />
|
||||
<result column="updated_time" property="updatedTime" jdbcType="TIMESTAMP" />
|
||||
</resultMap>
|
||||
</mapper>
|
161
book-mapper/src/main/resources/mapper/VlogMapperCustom.xml
Normal file
161
book-mapper/src/main/resources/mapper/VlogMapperCustom.xml
Normal file
@ -0,0 +1,161 @@
|
||||
<?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.imooc.mapper.VlogMapperCustom" >
|
||||
|
||||
<select id="getIndexVlogList" parameterType="map" resultType="com.imooc.vo.IndexVlogVO">
|
||||
SELECT
|
||||
v.id as vlogId,
|
||||
v.vloger_id as vlogerId,
|
||||
u.face as vlogerFace,
|
||||
u.nickname as vlogerName,
|
||||
v.title as content,
|
||||
v.url as url,
|
||||
v.cover as cover,
|
||||
v.width as width,
|
||||
v.height as height,
|
||||
v.like_counts as likeCounts,
|
||||
v.comments_counts as commentsCounts,
|
||||
v.is_private as isPrivate
|
||||
FROM
|
||||
vlog v
|
||||
LEFT JOIN
|
||||
users u
|
||||
ON
|
||||
v.vloger_id = u.id
|
||||
WHERE
|
||||
v.is_private = 0
|
||||
<if test="paramMap.search != null and paramMap.search != ''">
|
||||
AND v.title like '%${paramMap.search}%'
|
||||
</if>
|
||||
ORDER BY
|
||||
v.created_time
|
||||
DESC
|
||||
</select>
|
||||
|
||||
|
||||
<select id="getVlogDetailById" parameterType="map" resultType="com.imooc.vo.IndexVlogVO">
|
||||
SELECT
|
||||
v.id as vlogId,
|
||||
v.vloger_id as vlogerId,
|
||||
u.face as vlogerFace,
|
||||
u.nickname as vlogerName,
|
||||
v.title as content,
|
||||
v.url as url,
|
||||
v.cover as cover,
|
||||
v.width as width,
|
||||
v.height as height,
|
||||
v.like_counts as likeCounts,
|
||||
v.comments_counts as commentsCounts,
|
||||
v.is_private as isPrivate
|
||||
FROM
|
||||
vlog v
|
||||
LEFT JOIN
|
||||
users u
|
||||
ON
|
||||
v.vloger_id = u.id
|
||||
WHERE
|
||||
v.id = #{paramMap.vlogId}
|
||||
</select>
|
||||
|
||||
<select id="getMyLikedVlogList" parameterType="map" resultType="com.imooc.vo.IndexVlogVO">
|
||||
SELECT
|
||||
v.id as vlogId,
|
||||
v.vloger_id as vlogerId,
|
||||
-- u.face as vlogerFace,
|
||||
-- u.nickname as vlogerName,
|
||||
v.title as content,
|
||||
v.url as url,
|
||||
v.cover as cover,
|
||||
v.width as width,
|
||||
v.height as height,
|
||||
v.like_counts as likeCounts,
|
||||
v.comments_counts as commentsCounts,
|
||||
v.is_private as isPrivate
|
||||
FROM
|
||||
vlog v
|
||||
LEFT JOIN
|
||||
my_liked_vlog mlv
|
||||
ON
|
||||
v.id = mlv.vlog_id
|
||||
LEFT JOIN
|
||||
users u
|
||||
ON
|
||||
mlv.user_id = u.id
|
||||
WHERE
|
||||
u.id = #{paramMap.userId}
|
||||
AND
|
||||
v.is_private = 0
|
||||
ORDER BY
|
||||
v.created_time
|
||||
DESC
|
||||
</select>
|
||||
|
||||
<select id="getMyFollowVlogList" parameterType="map" resultType="com.imooc.vo.IndexVlogVO">
|
||||
SELECT
|
||||
v.id as vlogId,
|
||||
v.vloger_id as vlogerId,
|
||||
u.face as vlogerFace,
|
||||
u.nickname as vlogerName,
|
||||
v.title as content,
|
||||
v.url as url,
|
||||
v.cover as cover,
|
||||
v.width as width,
|
||||
v.height as height,
|
||||
v.like_counts as likeCounts,
|
||||
v.comments_counts as commentsCounts,
|
||||
v.is_private as isPrivate
|
||||
FROM
|
||||
vlog v
|
||||
LEFT JOIN
|
||||
fans f
|
||||
ON
|
||||
v.vloger_id = f.vloger_id
|
||||
LEFT JOIN
|
||||
users u
|
||||
ON
|
||||
f.vloger_id = u.id
|
||||
WHERE
|
||||
v.is_private = 0
|
||||
AND
|
||||
f.fan_id = #{paramMap.myId}
|
||||
ORDER BY
|
||||
v.created_time
|
||||
DESC
|
||||
</select>
|
||||
|
||||
<select id="getMyFriendVlogList" parameterType="map" resultType="com.imooc.vo.IndexVlogVO">
|
||||
SELECT
|
||||
v.id as vlogId,
|
||||
v.vloger_id as vlogerId,
|
||||
u.face as vlogerFace,
|
||||
u.nickname as vlogerName,
|
||||
v.title as content,
|
||||
v.url as url,
|
||||
v.cover as cover,
|
||||
v.width as width,
|
||||
v.height as height,
|
||||
v.like_counts as likeCounts,
|
||||
v.comments_counts as commentsCounts,
|
||||
v.is_private as isPrivate
|
||||
FROM
|
||||
vlog v
|
||||
LEFT JOIN
|
||||
fans f
|
||||
ON
|
||||
v.vloger_id = f.fan_id
|
||||
LEFT JOIN
|
||||
users u
|
||||
ON
|
||||
f.fan_id = u.id
|
||||
WHERE
|
||||
v.is_private = 0
|
||||
AND
|
||||
f.vloger_id = #{paramMap.myId}
|
||||
AND
|
||||
f.is_fan_friend_of_mine = 1
|
||||
ORDER BY
|
||||
v.created_time
|
||||
DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
63
book-model/pom.xml
Normal file
63
book-model/pom.xml
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.imooc</groupId>
|
||||
<artifactId>imooc-red-book-dev</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>book-model</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.imooc</groupId>
|
||||
<artifactId>book-common</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- hibernate 验证框架 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- mysql 驱动 -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.26</version>
|
||||
</dependency>
|
||||
<!-- mybatis -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- 通用mapper逆向工具 -->
|
||||
<dependency>
|
||||
<groupId>tk.mybatis</groupId>
|
||||
<artifactId>mapper-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- pagehelper -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- mongodb -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
32
book-model/src/main/java/com/imooc/bo/CommentBO.java
Normal file
32
book-model/src/main/java/com/imooc/bo/CommentBO.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.imooc.bo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class CommentBO {
|
||||
|
||||
@NotBlank(message = "留言信息不完整")
|
||||
private String vlogerId;
|
||||
|
||||
@NotBlank(message = "留言信息不完整")
|
||||
private String fatherCommentId;
|
||||
|
||||
@NotBlank(message = "留言信息不完整")
|
||||
private String vlogId;
|
||||
|
||||
@NotBlank(message = "当前用户信息不正确,请尝试重新登录")
|
||||
private String commentUserId;
|
||||
|
||||
@NotBlank(message = "评论内容不能为空")
|
||||
@Length(max = 50, message = "评论内容长度不能超过50")
|
||||
private String content;
|
||||
}
|
23
book-model/src/main/java/com/imooc/bo/RegistLoginBO.java
Normal file
23
book-model/src/main/java/com/imooc/bo/RegistLoginBO.java
Normal file
@ -0,0 +1,23 @@
|
||||
package com.imooc.bo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RegistLoginBO {
|
||||
|
||||
@NotBlank(message = "手机号不能为空")
|
||||
@Length(min = 11, max = 11, message = "手机长度不正确")
|
||||
private String mobile;
|
||||
@NotBlank(message = "验证码不能为空")
|
||||
private String smsCode;
|
||||
|
||||
}
|
28
book-model/src/main/java/com/imooc/bo/UpdatedUserBO.java
Normal file
28
book-model/src/main/java/com/imooc/bo/UpdatedUserBO.java
Normal file
@ -0,0 +1,28 @@
|
||||
package com.imooc.bo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class UpdatedUserBO {
|
||||
private String id;
|
||||
private String nickname;
|
||||
private String imoocNum;
|
||||
private String face;
|
||||
private Integer sex;
|
||||
private Date birthday;
|
||||
private String country;
|
||||
private String province;
|
||||
private String city;
|
||||
private String district;
|
||||
private String description;
|
||||
private String bgImg;
|
||||
private Integer canImoocNumBeUpdated;
|
||||
}
|
22
book-model/src/main/java/com/imooc/bo/VlogBO.java
Normal file
22
book-model/src/main/java/com/imooc/bo/VlogBO.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.imooc.bo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class VlogBO {
|
||||
private String id;
|
||||
private String vlogerId;
|
||||
private String url;
|
||||
private String cover;
|
||||
private String title;
|
||||
private Integer width;
|
||||
private Integer height;
|
||||
private Integer likeCounts;
|
||||
private Integer commentsCounts;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user