diff --git a/pom.xml b/pom.xml
index 6bb2cbc..d8cda14 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,7 +15,7 @@
short-server-common
short-server-service
- short-server-api
+ short-server-pojo
@@ -31,31 +31,50 @@
1.1.22
1.5.21
5.3.4
+ 1.2.73
+ 1.18.16
+ 3.8.1
-
+
+
+
+
+ io.swagger
+ swagger-annotations
+ ${swagger.version}
+
+
+ io.swagger
+ swagger-models
+ ${swagger.version}
+
+
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${common-lang3.version}
+
+
+
-
-
- io.swagger
- swagger-annotations
- ${swagger.version}
-
-
- io.swagger
- swagger-models
- ${swagger.version}
-
-
-
-
-
- cn.hutool
- hutool-all
- ${hutool.version}
-
-
diff --git a/short-server-api/.gitignore b/short-server-api/.gitignore
deleted file mode 100644
index 864e6e2..0000000
--- a/short-server-api/.gitignore
+++ /dev/null
@@ -1,189 +0,0 @@
-# Created by .ignore support plugin (hsz.mobi)
-
-### project
-log/
-
-### JetBrains template
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-
-# User-specific stuff
-.idea/**/workspace.xml
-.idea/**/tasks.xml
-.idea/**/usage.statistics.xml
-.idea/**/dictionaries
-.idea/**/shelf
-
-# Generated files
-.idea/**/contentModel.xml
-
-# Sensitive or high-churn files
-.idea/**/dataSources/
-.idea/**/dataSources.ids
-.idea/**/dataSources.local.xml
-.idea/**/sqlDataSources.xml
-.idea/**/dynamic.xml
-.idea/**/uiDesigner.xml
-.idea/**/dbnavigator.xml
-
-# Gradle
-.idea/**/gradle.xml
-.idea/**/libraries
-
-# Gradle and Maven with auto-import
-# When using Gradle or Maven with auto-import, you should exclude module files,
-# since they will be recreated, and may cause churn. Uncomment if using
-# auto-import.
-# .idea/artifacts
-# .idea/compiler.xml
-# .idea/jarRepositories.xml
-# .idea/modules.xml
-# .idea/*.iml
-# .idea/modules
-# *.iml
-# *.ipr
-
-# CMake
-cmake-build-*/
-
-# Mongo Explorer plugin
-.idea/**/mongoSettings.xml
-
-# File-based project format
-*.iws
-
-# IntelliJ
-out/
-
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Cursive Clojure plugin
-.idea/replstate.xml
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-com_crashlytics_export_strings.xml
-crashlytics.properties
-crashlytics-build.properties
-fabric.properties
-
-# Editor-based Rest Client
-.idea/httpRequests
-
-# Android studio 3.1+ serialized cache file
-.idea/caches/build_file_checksums.ser
-
-### Maven template
-target/
-pom.xml.tag
-pom.xml.releaseBackup
-pom.xml.versionsBackup
-pom.xml.next
-release.properties
-dependency-reduced-pom.xml
-buildNumber.properties
-.mvn/timing.properties
-# https://github.com/takari/maven-wrapper#usage-without-binary-jar
-.mvn/wrapper/maven-wrapper.jar
-
-### JetBrains template
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-
-# User-specific stuff
-.idea/**/workspace.xml
-.idea/**/tasks.xml
-.idea/**/usage.statistics.xml
-.idea/**/dictionaries
-.idea/**/shelf
-
-# Generated files
-.idea/**/contentModel.xml
-
-# Sensitive or high-churn files
-.idea/**/dataSources/
-.idea/**/dataSources.ids
-.idea/**/dataSources.local.xml
-.idea/**/sqlDataSources.xml
-.idea/**/dynamic.xml
-.idea/**/uiDesigner.xml
-.idea/**/dbnavigator.xml
-
-# Gradle
-.idea/**/gradle.xml
-.idea/**/libraries
-
-# Gradle and Maven with auto-import
-# When using Gradle or Maven with auto-import, you should exclude module files,
-# since they will be recreated, and may cause churn. Uncomment if using
-# auto-import.
-# .idea/artifacts
-# .idea/compiler.xml
-# .idea/jarRepositories.xml
-# .idea/modules.xml
-# .idea/*.iml
-# .idea/modules
-# *.iml
-# *.ipr
-
-# CMake
-cmake-build-*/
-
-# Mongo Explorer plugin
-.idea/**/mongoSettings.xml
-
-# File-based project format
-*.iws
-
-# IntelliJ
-out/
-
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Cursive Clojure plugin
-.idea/replstate.xml
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-com_crashlytics_export_strings.xml
-crashlytics.properties
-crashlytics-build.properties
-fabric.properties
-
-# Editor-based Rest Client
-.idea/httpRequests
-
-# Android studio 3.1+ serialized cache file
-.idea/caches/build_file_checksums.ser
-
-### Java template
-# Compiled class file
-*.class
-
-# Log file
-*.log
-
-# BlueJ files
-*.ctxt
-
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
-
-# Package Files #
-*.jar
-*.war
-*.nar
-*.ear
-*.zip
-*.tar.gz
-*.rar
-
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
-
diff --git a/short-server-common/pom.xml b/short-server-common/pom.xml
index a4c5cc4..b5217e5 100644
--- a/short-server-common/pom.xml
+++ b/short-server-common/pom.xml
@@ -23,6 +23,18 @@
cn.hutool
hutool-all
+
+ com.alibaba
+ fastjson
+
+
+ org.projectlombok
+ lombok
+
+
+ org.apache.commons
+ commons-lang3
+
\ No newline at end of file
diff --git a/short-server-common/src/main/java/com/by/constants/SystemConstant.java b/short-server-common/src/main/java/com/by/constants/SystemConstant.java
new file mode 100644
index 0000000..845e8d4
--- /dev/null
+++ b/short-server-common/src/main/java/com/by/constants/SystemConstant.java
@@ -0,0 +1,7 @@
+package com.by.constants;
+
+/**
+ * 系统常量声明
+ */
+public class SystemConstant {
+}
diff --git a/short-server-api/pom.xml b/short-server-pojo/pom.xml
similarity index 57%
rename from short-server-api/pom.xml
rename to short-server-pojo/pom.xml
index 1612c02..c181009 100644
--- a/short-server-api/pom.xml
+++ b/short-server-pojo/pom.xml
@@ -7,10 +7,9 @@
com.by
1.0-SNAPSHOT
-
4.0.0
- short-server-api
+ short-server-pojo
8
@@ -18,29 +17,10 @@
-
com.by
short-server-common
1.0-SNAPSHOT
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
-
- io.swagger
- swagger-annotations
-
-
- io.swagger
- swagger-models
-
-
-
\ No newline at end of file
diff --git a/short-server-pojo/src/main/java/com/by/dto/ShortChainDTO.java b/short-server-pojo/src/main/java/com/by/dto/ShortChainDTO.java
new file mode 100644
index 0000000..554f00f
--- /dev/null
+++ b/short-server-pojo/src/main/java/com/by/dto/ShortChainDTO.java
@@ -0,0 +1,23 @@
+package com.by.dto;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author q
+ */
+@Data
+public class ShortChainDTO {
+
+ /**
+ * 原始短链集合
+ */
+ private Set shortChainOrigins;
+
+ /**
+ * 短链生成结果
+ */
+ private List shortChainResult;
+}
diff --git a/short-server-service/pom.xml b/short-server-service/pom.xml
index b682dd1..369fc6d 100644
--- a/short-server-service/pom.xml
+++ b/short-server-service/pom.xml
@@ -24,6 +24,22 @@
short-server-common
1.0-SNAPSHOT
+
+ com.by
+ short-server-pojo
+ 1.0-SNAPSHOT
+
+
+
+
+ io.swagger
+ swagger-annotations
+
+
+ io.swagger
+ swagger-models
+
+
diff --git a/short-server-service/src/main/java/com/by/api/ShortServerOpenApiController.java b/short-server-service/src/main/java/com/by/api/ShortServerOpenApiController.java
new file mode 100644
index 0000000..7212f91
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/api/ShortServerOpenApiController.java
@@ -0,0 +1,63 @@
+package com.by.api;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.by.api.common.CommonResponse;
+import com.by.api.convert.ShortChainVOToDTOConvert;
+import com.by.api.vo.ShortChainRequestVO;
+import com.by.api.vo.ShortChainResponseVO;
+import com.by.dto.ShortChainDTO;
+import com.by.service.ShortServerService;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Controller;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.ModelAndView;
+
+import java.util.List;
+
+/**
+ * @author q
+ */
+@Controller
+@Slf4j
+public class ShortServerOpenApiController {
+
+ // TODO: 2021/4/14 0014 添加接口限流
+ // TODO: 2021/4/14 0014 添加接口相关的验证 丰富VO层 加入 appid secret_key 及 时间戳验证
+
+ private final ShortServerService shortServerService;
+
+ public ShortServerOpenApiController(ShortServerService shortServerService) {
+ this.shortServerService = shortServerService;
+ }
+
+ @ApiOperation("批量生成短链接")
+ @PostMapping(value = "/trans")
+ @ResponseBody
+ public CommonResponse parseContentToShortChain(@Validated @RequestBody ShortChainRequestVO shortChainRequestVO) {
+ log.info("=== [ShortServerOpenApiController|parseContentToShortChain, one request is coming, request vo is {} ] ===", shortChainRequestVO.toString());
+
+ ShortChainDTO shortChainDTO = ShortChainVOToDTOConvert.convertShortChainRequestVOToDTO(shortChainRequestVO);
+
+ shortChainDTO = shortServerService.handleOriginUrlsToShortUrls(shortChainDTO);
+
+ List shortChainResult = shortChainDTO.getShortChainResult();
+
+ ShortChainResponseVO shortChainResponseVO = new ShortChainResponseVO();
+ if (CollectionUtil.isNotEmpty(shortChainResult)){
+ shortChainResponseVO.setShortChainResult(shortChainResult);
+ }
+
+ return CommonResponse.createBySuccess(shortChainResponseVO);
+ }
+
+ @ApiOperation("短链接兑换长链接并进行")
+ @GetMapping(value = "/redeem")
+ public ModelAndView redeemShortChainClick(@RequestParam(value = "a")String param){
+ log.info("=== [ShortServerOpenApiController|redeemShortChainClick, one request is coming, request param is {} ] ===", param);
+
+ return shortServerService.handleOnceShortUrlToRedirectOriginUrlAndRecord(param);
+ }
+
+}
diff --git a/short-server-service/src/main/java/com/by/api/common/CommonResponse.java b/short-server-service/src/main/java/com/by/api/common/CommonResponse.java
new file mode 100644
index 0000000..4e77014
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/api/common/CommonResponse.java
@@ -0,0 +1,132 @@
+package com.by.api.common;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+
+/**
+ *
+ * JsonInclude.Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量
+ *
+ * @param 返回的对象实体
+ * @author q
+ */
+@JsonSerialize
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+@NoArgsConstructor
+public class CommonResponse implements Serializable {
+
+ /**
+ * 成功还是失败的状态标识 0,成功 1,失败
+ */
+ private int status;
+
+ /**
+ * 返回信息
+ */
+ private String msg;
+
+ /**
+ * 返回的结果数据
+ */
+ private T data;
+
+
+ /*
+ * 封装所有的构造器为私有的
+ */
+
+ private CommonResponse(int status) {
+ this.status = status;
+ }
+
+ private CommonResponse(int status, T data) { // ps: 当调用T为String类型时候,会默认调用下面的ServerResponse(int status, String msg)类型的构造器
+ this.status = status;
+ this.data = data;
+ }
+
+ private CommonResponse(int status, String msg, T data) {
+ this.status = status;
+ this.msg = msg;
+ this.data = data;
+ }
+
+ private CommonResponse(int status, String msg) {
+ this.status = status;
+ this.msg = msg;
+ }
+
+
+ /*
+ * 对外开放调用的静态方法,用来调用私有构造器,来返回成功结果给前台
+ */
+
+ /**
+ * @return 返回成功码和默认的成功信息
+ */
+ public static CommonResponse createBySuccess() {
+ return new CommonResponse(ResponseCode.SUCCESS.getCode(),ResponseCode.SUCCESS.getDesc());
+ }
+
+ /**
+ *
+ * @param msg 定义的成功信息
+ * @return 返回成功码和成功信息
+ */
+ public static CommonResponse createBySuccessMessage(String msg) {
+ return new CommonResponse(ResponseCode.SUCCESS.getCode(), msg);
+ }
+
+ /**
+ *
+ * @param data 传入实体
+ * @return 返回成功码和数据
+ */
+ public static CommonResponse createBySuccess(T data) {
+ return new CommonResponse(ResponseCode.SUCCESS.getCode(), data);
+ }
+
+ /**
+ *
+ * @param msg 传入信息
+ * @param data 传入实体
+ * @return 返回成功码和成功信息和数据
+ */
+ public static CommonResponse createBySuccess(String msg, T data) {
+ return new CommonResponse(ResponseCode.SUCCESS.getCode(), msg, data);
+ }
+
+ /*
+ 对外开放调用的静态方法,用来调用私有构造器,来返回失败结果给前台
+ */
+
+ /**
+ *
+ * @return 返回错误码和默认的错误
+ */
+ public static CommonResponse createByError(){
+ return new CommonResponse(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getDesc());
+ }
+
+ /**
+ *
+ * @param errorMessage 定义的错误信息
+ * @return 返回错误码和错误信息(传入)
+ */
+ public static CommonResponse createByErrorMessage(String errorMessage){
+ return new CommonResponse(ResponseCode.ERROR.getCode(),errorMessage);
+ }
+
+ /**
+ *
+ * @param errorCode 错误码
+ * @param errorMessage 错误信息
+ * @return 返回错误码(传入)和错误信息(传入)
+ */
+ public static CommonResponse createByErrorCodeMessage(int errorCode,String errorMessage){
+ return new CommonResponse(errorCode,errorMessage);
+ }
+}
diff --git a/short-server-service/src/main/java/com/by/api/common/ResponseCode.java b/short-server-service/src/main/java/com/by/api/common/ResponseCode.java
new file mode 100644
index 0000000..158a161
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/api/common/ResponseCode.java
@@ -0,0 +1,48 @@
+package com.by.api.common;
+
+/**
+ * Description: 自定义Response响应返回体 -> 这边采用的是
+ * @author q
+ */
+public enum ResponseCode {
+
+ /**
+ * 成功
+ */
+ SUCCESS(0,"SUCCESS"),
+ /**
+ * 失败
+ */
+ ERROR(1,"ERROR"),
+
+
+ /*
+ * 请求参数校验
+ */
+ ILLEGAL_ARGUMENT(1,"请求参数格式错误"),
+ EMPTY_ARGUMENT(1,"请求参数为空"),
+
+ /*
+ * 请求结果性的错误
+ */
+ NO_REASON_ERROR(1,"未知异常错误发生"),
+ SYSTEM_ERROR(1,"系统异常"),
+ DECRYPT_ERROR(1,"解密错误,请联系相关人员");
+
+ private final int code;
+ private final String desc;
+
+ ResponseCode(int code, String desc){
+ this.code = code;
+ this.desc = desc;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+}
diff --git a/short-server-service/src/main/java/com/by/api/constants/RequestDetailConstant.java b/short-server-service/src/main/java/com/by/api/constants/RequestDetailConstant.java
new file mode 100644
index 0000000..3c11d6c
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/api/constants/RequestDetailConstant.java
@@ -0,0 +1,11 @@
+package com.by.api.constants;
+
+/**
+ * 详细的请求参数验证 - 错误信息
+ */
+public class RequestDetailConstant {
+
+ public static final String REQUEST_ADDR_EMPTY = "请求的地址为空";
+
+ public static final String REQUEST_PARAMS_EMPTY = "请求参数为空";
+}
diff --git a/short-server-service/src/main/java/com/by/api/convert/ShortChainVOToDTOConvert.java b/short-server-service/src/main/java/com/by/api/convert/ShortChainVOToDTOConvert.java
new file mode 100644
index 0000000..1b3aaa6
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/api/convert/ShortChainVOToDTOConvert.java
@@ -0,0 +1,51 @@
+package com.by.api.convert;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.by.api.vo.ShortChainRequestVO;
+import com.by.dto.ShortChainDTO;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * VO -> DTO
+ */
+public class ShortChainVOToDTOConvert {
+
+
+
+
+ /**
+ * 短链 请求 vo -> dto
+ */
+ public static ShortChainDTO convertShortChainRequestVOToDTO(ShortChainRequestVO shortChainRequestVO) {
+
+ Set originsUrlSet = new HashSet<>(1000);
+
+ String baseUrlAddr = shortChainRequestVO.getBaseUrlAddr();
+ shortChainRequestVO.getVariableList().forEach(
+ each -> {
+ originsUrlSet.add(checkUrlAllowed(baseUrlAddr) + each);
+ }
+
+ );
+
+ if (CollectionUtil.isNotEmpty(originsUrlSet)){
+ ShortChainDTO shortChainDTO = new ShortChainDTO();
+ shortChainDTO.setShortChainOrigins(originsUrlSet);
+ return shortChainDTO;
+ }
+
+ return new ShortChainDTO();
+ }
+
+ private static String checkUrlAllowed(String baseUrlAddr) {
+ if (!StringUtils.endsWith(baseUrlAddr.trim(), "//")){
+ return baseUrlAddr.trim() + "//";
+ }
+ return baseUrlAddr.trim();
+ }
+
+
+}
diff --git a/short-server-service/src/main/java/com/by/api/exception/GlobalExceptionHandle.java b/short-server-service/src/main/java/com/by/api/exception/GlobalExceptionHandle.java
new file mode 100644
index 0000000..b132d69
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/api/exception/GlobalExceptionHandle.java
@@ -0,0 +1,34 @@
+package com.by.api.exception;
+
+import com.by.api.common.CommonResponse;
+import com.by.api.common.ResponseCode;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * 全局异常处理类
+ */
+@ControllerAdvice
+@Slf4j
+public class GlobalExceptionHandle {
+
+
+ /**
+ * 捕获异常级别是Exception级别的异常
+ *
+ * @param exception 异常入参
+ *
+ * @return 统一的业务异常封装
+ */
+ @ExceptionHandler(Exception.class)
+ @ResponseBody
+ public CommonResponse customException(Exception exception) {
+ if (exception != null){
+ log.error(" =============== [ERROR , exception is {} , {}] ===============", exception.getMessage() ,exception);
+ return CommonResponse.createByErrorMessage(ResponseCode.SYSTEM_ERROR.getDesc());
+ }
+ return CommonResponse.createByErrorMessage(ResponseCode.NO_REASON_ERROR.getDesc());
+ }
+}
diff --git a/short-server-service/src/main/java/com/by/api/vo/ShortChainRequestVO.java b/short-server-service/src/main/java/com/by/api/vo/ShortChainRequestVO.java
new file mode 100644
index 0000000..7bdad74
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/api/vo/ShortChainRequestVO.java
@@ -0,0 +1,30 @@
+package com.by.api.vo;
+
+import com.by.api.constants.RequestDetailConstant;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+
+/**
+ * 短链请求结构体
+ *
+ * @author q
+ */
+@Data
+public class ShortChainRequestVO {
+
+ /**
+ * 请求的统一地址
+ */
+ @NotBlank(message = RequestDetailConstant.REQUEST_ADDR_EMPTY)
+ private String baseUrlAddr;
+
+ /**
+ * 每一个需要进行短链拼接的变量内容集合
+ */
+ @NotEmpty(message = RequestDetailConstant.REQUEST_PARAMS_EMPTY)
+ private List variableList;
+}
diff --git a/short-server-service/src/main/java/com/by/api/vo/ShortChainResponseVO.java b/short-server-service/src/main/java/com/by/api/vo/ShortChainResponseVO.java
new file mode 100644
index 0000000..a4048df
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/api/vo/ShortChainResponseVO.java
@@ -0,0 +1,19 @@
+package com.by.api.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 短链返回结构体
+ *
+ * @author q
+ */
+@Data
+public class ShortChainResponseVO {
+
+ /**
+ * 短链生成结果
+ */
+ private List shortChainResult;
+}
diff --git a/short-server-service/src/main/java/com/by/dao/ShortUrlRepository.java b/short-server-service/src/main/java/com/by/dao/ShortUrlRepository.java
new file mode 100644
index 0000000..f62e785
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/dao/ShortUrlRepository.java
@@ -0,0 +1,11 @@
+package com.by.dao;
+
+import com.by.entity.ShortUrl;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ShortUrlRepository extends JpaRepository, JpaSpecificationExecutor {
+
+}
\ No newline at end of file
diff --git a/short-server-service/src/main/java/com/by/entity/ShortUrl.java b/short-server-service/src/main/java/com/by/entity/ShortUrl.java
new file mode 100644
index 0000000..ce3d5aa
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/entity/ShortUrl.java
@@ -0,0 +1,75 @@
+package com.by.entity;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import lombok.Data;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+@Entity
+@Data
+@Table(name = "t_short_url")
+public class ShortUrl implements Serializable {
+
+ /**
+ * id
+ */
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ /**
+ * 创建时间
+ */
+ @Column(name = "gmt_create", nullable = false)
+ private Timestamp gmtCreate;
+
+ /**
+ * 修改时间
+ */
+ @Column(name = "gmt_modified", nullable = false)
+ private Timestamp gmtModified;
+
+ /**
+ * 最后一次操作人的IP地址
+ */
+ @Column(name = "operator_ip", nullable = false)
+ private String operatorIp;
+
+ /**
+ * 原始链接
+ */
+ @Column(name = "origin_url", nullable = false)
+ private String originUrl;
+
+ /**
+ * 生成短链
+ */
+ @Column(name = "short_url")
+ private String shortUrl;
+
+ /**
+ * 点击标识 0-未点击 1-点击
+ */
+ @Column(name = "point_tag", nullable = false)
+ private Integer pointTag;
+
+ /**
+ * 失效倒计时时间(day)
+ */
+ @Column(name = "expiration_day", nullable = false)
+ private Integer expirationDay;
+
+ /**
+ * 有效标识 0-无效 1-有效
+ */
+ @Column(name = "valid_tag")
+ private Integer validTag;
+
+ public void copy(ShortUrl source) {
+ BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
+ }
+}
diff --git a/short-server-service/src/main/java/com/by/service/ShortServerService.java b/short-server-service/src/main/java/com/by/service/ShortServerService.java
new file mode 100644
index 0000000..786f0ca
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/service/ShortServerService.java
@@ -0,0 +1,25 @@
+package com.by.service;
+
+import com.by.dto.ShortChainDTO;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * 短链信息处理接口
+ */
+public interface ShortServerService {
+
+
+ /**
+ * 原始链接处理成短链
+ *
+ * @param shortChainDTO
+ * @return
+ */
+ ShortChainDTO handleOriginUrlsToShortUrls(ShortChainDTO shortChainDTO);
+
+
+ /**
+ * 兑换短链跳转并更新点击记录及回传点击记录
+ */
+ ModelAndView handleOnceShortUrlToRedirectOriginUrlAndRecord(String param);
+}
diff --git a/short-server-service/src/main/java/com/by/service/impl/ShortServerServiceImpl.java b/short-server-service/src/main/java/com/by/service/impl/ShortServerServiceImpl.java
new file mode 100644
index 0000000..61a5bd0
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/service/impl/ShortServerServiceImpl.java
@@ -0,0 +1,41 @@
+package com.by.service.impl;
+
+import com.by.dto.ShortChainDTO;
+import com.by.service.ShortServerService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * 短链服务实现Service
+ *
+ * @author q
+ */
+@Service
+@Slf4j
+public class ShortServerServiceImpl implements ShortServerService {
+
+
+ @Override
+ public ShortChainDTO handleOriginUrlsToShortUrls(ShortChainDTO shortChainDTO) {
+
+ // TODO: 2021/4/14 0014
+ // 1. 拼接请求调用短链生成器进行所有的短链请求
+
+ // 2. 生成的短链请求批量入库
+
+ // 3. 把短链请求 return 给调用方
+ return null;
+ }
+
+ @Override
+ public ModelAndView handleOnceShortUrlToRedirectOriginUrlAndRecord(String param) {
+ // 1. 查询库中的短链请求
+
+ // 2. 拿出真实请求进行跳转
+
+ // 3. 异步进行更新数据库中的点击记录及推送给之前的调用方(可以走消息)
+
+ return new ModelAndView("redirect:https://www.baidu.com/");
+ }
+}
diff --git a/short-server-service/src/main/java/com/by/task/ShortChainTask.java b/short-server-service/src/main/java/com/by/task/ShortChainTask.java
new file mode 100644
index 0000000..d3391e8
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/task/ShortChainTask.java
@@ -0,0 +1,30 @@
+package com.by.task;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Scope;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+@Component
+@Scope("prototype")
+@Slf4j
+public class ShortChainTask {
+
+ @Async(value = "abTaskExecutor")
+ public void doRunTask(){
+ Long satrtMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
+ log.info("====== [ task start running, task name is {} ] ======", "ABDownTask");
+ runTask();
+ Long endMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
+ log.info("====== [ task start end, task name is {},cost milliSecond is {} ] ======", "ABDownTask", (endMilliSecond-satrtMilliSecond));
+ }
+
+ private void runTask() {
+
+ }
+
+
+}
diff --git a/short-server-service/src/main/java/com/by/task/conf/ThreadPoolConfig.java b/short-server-service/src/main/java/com/by/task/conf/ThreadPoolConfig.java
new file mode 100644
index 0000000..1fd08d1
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/task/conf/ThreadPoolConfig.java
@@ -0,0 +1,54 @@
+package com.by.task.conf;
+
+
+import org.apache.tomcat.util.threads.ThreadPoolExecutor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 线程池配置总类,用于配置线程池
+ */
+@Configuration
+@EnableAsync
+public class ThreadPoolConfig {
+
+ /**
+ * 从配置文件中加载线程池相关的配置
+ */
+ @Value(value = "${short.chain.task.corePoolSize}")
+ private int corePoolSize = 4;
+ @Value(value = "${short.chain.task.maxPoolSize}")
+ private int maxPoolSize = 32;
+ @Value(value = "${short.chain.task.queueCapacity}")
+ private int queueCapacity = 100;
+ @Value(value = "${short.chain.task.ThreadNamePrefix}")
+ private String ThreadNamePrefix = "MyThreadPoolExecutor-";
+
+
+ /**
+ * AB 单的异步线程池的配置类
+ * @return
+ */
+ @Bean
+ public Executor shortChainTaskExecutor() {
+
+ ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
+ corePoolSize,
+ maxPoolSize,
+ 3,
+ TimeUnit.SECONDS,
+ new LinkedBlockingDeque<>(queueCapacity),
+ Executors.defaultThreadFactory(),
+ new ThreadPoolExecutor.DiscardOldestPolicy()
+ );
+
+ return threadPoolExecutor;
+ }
+}
diff --git a/short-server-service/src/main/resources/application-dev.yml b/short-server-service/src/main/resources/application-dev.yml
index 77f14e2..37cb887 100644
--- a/short-server-service/src/main/resources/application-dev.yml
+++ b/short-server-service/src/main/resources/application-dev.yml
@@ -4,7 +4,7 @@ spring:
druid:
db-type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/db-short-server?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true
+ url: jdbc:mysql://localhost:3306/db_short_server?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true
username: root
password: root
# 初始连接数
diff --git a/short-server-service/src/main/resources/application-prod.yml b/short-server-service/src/main/resources/application-prod.yml
index aab779e..462ec02 100644
--- a/short-server-service/src/main/resources/application-prod.yml
+++ b/short-server-service/src/main/resources/application-prod.yml
@@ -4,7 +4,7 @@ spring:
druid:
db-type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/eladmin-plat2?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true
+ url: jdbc:mysql://localhost:3306/db_short_server?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true
username: root
password: Yuyou@2020
# 初始连接数
diff --git a/short-server-service/src/main/resources/application.yml b/short-server-service/src/main/resources/application.yml
index 54d64c2..867a41c 100644
--- a/short-server-service/src/main/resources/application.yml
+++ b/short-server-service/src/main/resources/application.yml
@@ -26,3 +26,12 @@ spring:
# 配置日志
logging:
config: classpath:logback.xml
+
+# 线程池配置
+short:
+ chain:
+ task:
+ corePoolSize: 4
+ maxPoolSize: 32
+ queueCapacity: 100
+ ThreadNamePrefix: 'shortChainTaskExecutor-'
\ No newline at end of file
diff --git a/sql/t_short_url.sql b/sql/t_short_url.sql
new file mode 100644
index 0000000..f8a5e14
--- /dev/null
+++ b/sql/t_short_url.sql
@@ -0,0 +1,28 @@
+
+-- ----------------------------
+-- TODO please create database first
+-- ----------------------------
+
+
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for t_short_url
+-- ----------------------------
+DROP TABLE IF EXISTS `t_short_url`;
+CREATE TABLE `t_short_url` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
+ `gmt_create` datetime(0) NOT NULL COMMENT '创建时间',
+ `gmt_modified` datetime(0) NOT NULL COMMENT '修改时间',
+ `operator_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '最后一次操作人的IP地址',
+ `origin_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '原始链接',
+ `short_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '生成短链',
+ `point_tag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '点击标识 0-未点击 1-点击',
+ `expiration_day` int(5) NOT NULL COMMENT '失效倒计时时间(day)',
+ `valid_tag` tinyint(1) NULL DEFAULT NULL COMMENT '有效标识 0-无效 1-有效',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+SET FOREIGN_KEY_CHECKS = 1;