diff --git a/README.md b/README.md
index d1af570..d7f1609 100644
--- a/README.md
+++ b/README.md
@@ -21,9 +21,50 @@
short-server-common - 公共模块
short-server-pojo - dto/bo 用于模块之间的传输实体/领域模型定义
short-server-service - 短链生成服务
-#### 调用方式及API
+#### 附加功能说明
+
+ 支持默认定时30天的清除短链(默认开启)
+ 支持带签名区分的短链形式,例如:
+ request:
+ {
+ "baseUrlAddr": "htttps://www.baidu.com/xxdsd/sdsdsds?sadsads=xxxx",
+ "variableList": [
+ 13111112211,
+ 12111112222
+ ]
+ }
+ response:
+ {
+ "status": 0,
+ "data": {
+ "shortChainResult": [
+ "e4ig5miu1n|13111112211",
+ "rtyt8vhx6l|12111112222"
+ ]}
+ }
+ 也支持不带签名的短链(这里只支持单条调用)
+ request:
+ {
+ "baseUrlAddr": "htttps://www.baidu.com/xxdsd/sdsdsds?sadsads=xxxx"
+ }
+ response:
+ {
+ "status": 0,
+ "data": {
+ "shortChainResult": [
+ "e4ig5miu1n"
+ ]}
+ }
+#### 调用方式及API
+
+ 批量生成短链API : {{host}}:{{ip}}/send
+ 短链兑换真实地址API : {{host}}:{{ip}}/返回的短链
#### 部署方式
-
-
+
+ by-short-server 目录下 mvn clean install 进行打包
+
+ 上传到服务器
+
+ 运行 ./script 下的 run-short-server.sh 脚本启动
diff --git a/pom.xml b/pom.xml
index d8cda14..544726b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
1.2.73
1.18.16
3.8.1
+ 2.3.2
@@ -72,6 +73,11 @@
commons-lang3
${common-lang3.version}
+
+ org.quartz-scheduler
+ quartz
+ ${quarz.version}
+
diff --git a/script/run-short-server.sh b/script/run-short-server.sh
new file mode 100644
index 0000000..893282a
--- /dev/null
+++ b/script/run-short-server.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+source stop-short-server.sh
+source start-short-server.sh
diff --git a/script/start-short-server.sh b/script/start-short-server.sh
new file mode 100644
index 0000000..07d08c4
--- /dev/null
+++ b/script/start-short-server.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+echo "Start run short-server-service-1.0 Application..."
+
+nohup java -jar short-server-service-1.0-SNAPSHOT.jar 1> short-Log.log 2>log/short-errorLog.log &
diff --git a/script/stop-short-server.sh b/script/stop-short-server.sh
new file mode 100644
index 0000000..2d27cc8
--- /dev/null
+++ b/script/stop-short-server.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+
+pid=`ps -ef | grep short-server-service-1.0-SNAPSHOT | grep -v grep| awk '{print $2}'`
+
+if [ -z "$pid" ];
+then
+ echo "Application is already stopped" $pid
+else
+ echo $pid is killed
+ kill -9 $pid
+fi
diff --git a/short-server-common/pom.xml b/short-server-common/pom.xml
index b5217e5..f7ac11d 100644
--- a/short-server-common/pom.xml
+++ b/short-server-common/pom.xml
@@ -35,6 +35,10 @@
org.apache.commons
commons-lang3
+
+ org.quartz-scheduler
+ quartz
+
\ No newline at end of file
diff --git a/short-server-common/src/main/java/com/by/utils/CronUtil.java b/short-server-common/src/main/java/com/by/utils/CronUtil.java
new file mode 100644
index 0000000..d9e6852
--- /dev/null
+++ b/short-server-common/src/main/java/com/by/utils/CronUtil.java
@@ -0,0 +1,125 @@
+package com.by.utils;
+
+import org.quartz.CronExpression;
+
+import java.text.ParseException;
+
+
+/**
+ * Cron表达式解析
+ *
+ * 父类是关于操作定时任务的
+ *
+ * @author q 直接哪里使用的,并不是本人写的,有点不符合代码规范
+ */
+public class CronUtil {
+
+ /**
+ * 装换成中文表示形式
+ * @param cronExp
+ * @return
+ */
+ public static String translateToChinese(String cronExp) {
+ if (cronExp == null || cronExp.length() < 1) {
+ return "cron表达式为空";
+ }
+ CronExpression exp = null;
+ // 初始化cron表达式解析器
+ try {
+ exp = new CronExpression(cronExp);
+ } catch (ParseException e) {
+ return "corn表达式不正确";
+ }
+ String[] tmpCorns = cronExp.split(" ");
+ StringBuffer sBuffer = new StringBuffer();
+ if (tmpCorns.length == 6) {
+ //解析月
+ if (!tmpCorns[4].equals("*")) {
+ sBuffer.append(tmpCorns[4]).append("月");
+ } else {
+ sBuffer.append("每月");
+ }
+ //解析周
+ if (!tmpCorns[5].equals("*") && !tmpCorns[5].equals("?")) {
+ char[] tmpArray = tmpCorns[5].toCharArray();
+ for (char tmp : tmpArray) {
+ switch (tmp) {
+ case '1':
+ sBuffer.append("星期天");
+ break;
+ case '2':
+ sBuffer.append("星期一");
+ break;
+ case '3':
+ sBuffer.append("星期二");
+ break;
+ case '4':
+ sBuffer.append("星期三");
+ break;
+ case '5':
+ sBuffer.append("星期四");
+ break;
+ case '6':
+ sBuffer.append("星期五");
+ break;
+ case '7':
+ sBuffer.append("星期六");
+ break;
+ case '-':
+ sBuffer.append("至");
+ break;
+ default:
+ sBuffer.append(tmp);
+ break;
+ }
+ }
+ }
+
+ //解析日
+ if (!tmpCorns[3].equals("?")) {
+ if (!"*".equals(tmpCorns[3]) && !(tmpCorns[3]).contains("/")) {
+ sBuffer.append(tmpCorns[3]).append("日");
+ }else if(!tmpCorns[3].equals("*") && (tmpCorns[3]).contains("/")){
+
+ String[] split = tmpCorns[3].split("/");
+ if(split.length == 2 ){
+ sBuffer.append("从第").append(split[0]).append("天开始,每").append(split[1]).append("天,");
+ }
+ }
+ else {
+ sBuffer.append("每日");
+ }
+ }
+
+ //解析时
+ if (!tmpCorns[2].equals("*")) {
+ sBuffer.append(tmpCorns[2]).append("时");
+ } else {
+ sBuffer.append("每时");
+ }
+
+ //解析分
+ if (!tmpCorns[1].equals("*")) {
+ sBuffer.append(tmpCorns[1]).append("分");
+ } else {
+ sBuffer.append("每分");
+ }
+
+ //解析秒
+ if (!tmpCorns[0].equals("*")) {
+ sBuffer.append(tmpCorns[0]).append("秒");
+ } else {
+ sBuffer.append("每秒");
+ }
+ }
+
+ return sBuffer.append("执行").toString();
+
+ }
+
+ public static void main(String[] args) {
+ String CRON_EXPRESSION = "0 0 0 1/1 * ?";
+ System.out.println(CRON_EXPRESSION +" - "+CronUtil.translateToChinese(CRON_EXPRESSION));
+
+ }
+}
diff --git a/short-server-service/src/main/java/com/by/ShortServerApplication.java b/short-server-service/src/main/java/com/by/ShortServerApplication.java
index ef9d01d..f299317 100644
--- a/short-server-service/src/main/java/com/by/ShortServerApplication.java
+++ b/short-server-service/src/main/java/com/by/ShortServerApplication.java
@@ -4,6 +4,7 @@ package com.by;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 项目启动入口
@@ -11,6 +12,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
* @author q
*/
@EnableAsync
+@EnableScheduling
@SpringBootApplication
public class ShortServerApplication {
public static void main(String[] args) {
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
index f24b8b0..0f6c6ee 100644
--- 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
@@ -30,12 +30,15 @@ public class ShortChainVOToDTOConvert {
Set originsUrlSet = new HashSet<>(1000);
String baseUrlAddr = shortChainRequestVO.getBaseUrlAddr();
- shortChainRequestVO.getVariableList().forEach(
- each -> {
- originsUrlSet.add(baseUrlAddr + SymbolConstant.SPLIT_VERTICAL + each);
- }
- );
+ if (CollectionUtil.isNotEmpty(shortChainRequestVO.getVariableList())){
+ shortChainRequestVO.getVariableList().forEach(
+ each -> {
+ originsUrlSet.add(baseUrlAddr + SymbolConstant.SPLIT_VERTICAL + each);
+ }
+
+ );
+ }
if (CollectionUtil.isNotEmpty(originsUrlSet)) {
ShortChainDTO shortChainDTO = new ShortChainDTO();
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
index f63f1a7..df1e22e 100644
--- 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
@@ -6,7 +6,6 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotEmpty;
import java.util.List;
@@ -29,6 +28,5 @@ public class ShortChainRequestVO {
/**
* 每一个需要进行短链拼接的变量内容集合
*/
- @NotEmpty(message = RequestDetailConstant.REQUEST_PARAMS_EMPTY)
private List variableList;
}
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
index f8b1f44..a970b81 100644
--- a/short-server-service/src/main/java/com/by/dao/ShortUrlRepository.java
+++ b/short-server-service/src/main/java/com/by/dao/ShortUrlRepository.java
@@ -7,6 +7,8 @@ import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
+import java.util.List;
+
/**
* @author q
*/
@@ -22,4 +24,51 @@ public interface ShortUrlRepository extends JpaRepository, JpaSp
@Modifying
@Query("update ShortUrl t set t.sendTag = ?1 where t.id = ?2")
void updateSendStatus(Integer sendStatus, Long recId);
+
+
+ /**
+ * @param expirationDay 查询大于参数的过期时间
+ * @return 满足过期时间大于参数的集合
+ */
+ @Query
+ List findAllByExpirationDayAfter(Integer expirationDay);
+
+ /**
+ * @param expirationDay 查询等于参数的过期时间
+ * @return 满足过期时间等于参数的集合
+ */
+ @Query
+ List findAllByExpirationDay(Integer expirationDay);
+
+ /**
+ * 批量把过期时间减一
+ *
+ * @param ids 所有需要的id
+ * @return 更改的结果
+ */
+ @Modifying
+ @Query( value = "UPDATE ShortUrl t set t.expirationDay = t.expirationDay-1 WHERE t.id IN (?1)")
+ Integer batchUpdateExpirationDay(List ids);
+
+ /**
+ * (软)删除过期时间为day的所有记录 - 推荐手动失效场景
+ *
+ * @param ids 指定删除的时间
+ * @return (软)删除的条数
+ */
+ @Modifying
+ @Query( value = "UPDATE ShortUrl t set t.validTag = 1 WHERE t.id IN (?1)")
+ Integer batchSoftDeleteExpirationDayIs(List ids);
+
+
+ /**
+ * (直接)删除过期时间为day的所有记录 - 过期后自动删除基本没有保存的必要
+ *
+ * @param expirationDay 指定删除的时间
+ * @return (直接)删除的条数
+ */
+ @Modifying
+ @Query( value = "DELETE FROM ShortUrl t WHERE t.expirationDay = ?1")
+ Integer batchDeleteExpirationDayIs(Integer expirationDay);
+
}
\ No newline at end of file
diff --git a/short-server-service/src/main/java/com/by/entity/constants/DBDefaultConstant.java b/short-server-service/src/main/java/com/by/entity/constants/DBDefaultConstant.java
index 5b6dd18..4cfd5d7 100644
--- a/short-server-service/src/main/java/com/by/entity/constants/DBDefaultConstant.java
+++ b/short-server-service/src/main/java/com/by/entity/constants/DBDefaultConstant.java
@@ -15,6 +15,12 @@ public class DBDefaultConstant {
*/
public static final int ZERO_NUM_TAG = 0;
+ /**
+ * 0L
+ */
+ public static final Long LONG_ZERO_NUM_TAG = 0L;
+
+
/**
* 1
*/
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
index 59985e9..6a449e9 100644
--- a/short-server-service/src/main/java/com/by/service/ShortServerService.java
+++ b/short-server-service/src/main/java/com/by/service/ShortServerService.java
@@ -31,4 +31,9 @@ public interface ShortServerService {
* @return
*/
boolean updateShortUrlToPlatformSendtatus(Long recId, boolean sucess);
+
+ /**
+ * 按天更新短链的过期时间 默认是保存30天
+ */
+ Integer updateShortUrlRecOnDay();
}
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
index dbf5fe1..ff72e22 100644
--- 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
@@ -1,5 +1,6 @@
package com.by.service.impl;
+import cn.hutool.core.collection.CollectionUtil;
import com.by.constants.SymbolConstant;
import com.by.dao.ShortUrlDAO;
import com.by.dao.ShortUrlRepository;
@@ -16,10 +17,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* 短链服务实现Service
@@ -52,7 +51,13 @@ public class ShortServerServiceImpl implements ShortServerService {
makeShortUrlResult.forEach(
(shortUrl, originUrl) -> {
shortUrls.add(new ShortUrl(originUrl, shortUrl, DBDefaultConstant.ZERO_NUM_TAG, DBDefaultConstant.ZERO_NUM_TAG));
- resultShortUrls.add(shortUrl + SymbolConstant.SPLIT_VERTICAL + StringUtils.substringAfterLast(originUrl, SymbolConstant.SPLIT_VERTICAL));
+ String orginSplit = StringUtils.substringAfterLast(originUrl, SymbolConstant.SPLIT_VERTICAL);
+ if (StringUtils.isNotBlank(orginSplit)){
+ resultShortUrls.add(shortUrl + SymbolConstant.SPLIT_VERTICAL + orginSplit);
+ }else {
+ resultShortUrls.add(shortUrl);
+ }
+
}
);
@@ -94,4 +99,24 @@ public class ShortServerServiceImpl implements ShortServerService {
}
return Boolean.TRUE;
}
+
+ @Override
+ @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
+ public Integer updateShortUrlRecOnDay() {
+
+ Integer deleteCount = shortUrlRepository.batchDeleteExpirationDayIs(DBDefaultConstant.ZERO_NUM_TAG);
+ if (!Objects.isNull(deleteCount) && deleteCount > 0){
+ log.info(" === [ShortServerServiceImpl|handleOriginUrlsToShortUrls, success delete expiration count is {} ] === ", deleteCount);
+ }
+
+ List allByExpirationDayAfter = shortUrlRepository.findAllByExpirationDayAfter(DBDefaultConstant.ZERO_NUM_TAG);
+
+ if (CollectionUtil.isEmpty(allByExpirationDayAfter)){
+ return DBDefaultConstant.ZERO_NUM_TAG;
+ }
+
+ return shortUrlRepository.batchUpdateExpirationDay(allByExpirationDayAfter.stream()
+ .map(ShortUrl::getId)
+ .collect(Collectors.toList()));
+ }
}
diff --git a/short-server-service/src/main/java/com/by/task/CheckShortUrlScheduleTask.java b/short-server-service/src/main/java/com/by/task/CheckShortUrlScheduleTask.java
new file mode 100644
index 0000000..4331872
--- /dev/null
+++ b/short-server-service/src/main/java/com/by/task/CheckShortUrlScheduleTask.java
@@ -0,0 +1,41 @@
+package com.by.task;
+
+import com.by.service.ShortServerService;
+import com.by.utils.CronUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+/**
+ * 检查并更新定时任务记录的Task
+ *
+ * @author q
+ */
+@Component
+@Slf4j
+public class CheckShortUrlScheduleTask {
+
+ public static final String EXECUTE_CRON = "0 0 0 1/1 * ? ";
+
+ private final ShortServerService shortServerService;
+
+ public CheckShortUrlScheduleTask(ShortServerService shortServerService) {
+ this.shortServerService = shortServerService;
+ }
+
+ /**
+ * 每天执行保存短链时间减一的操作 Task
+ */
+ @Scheduled(cron = EXECUTE_CRON)
+ public void execute() {
+ log.info("=== [CheckShortUrlScheduleTask|execute is running. Cron rule is {}, Chinese translated to {} Thread is {} ] ===",
+ EXECUTE_CRON,
+ CronUtil.translateToChinese(EXECUTE_CRON),
+ Thread.currentThread().getName()
+ );
+
+ Integer updateRecCount = shortServerService.updateShortUrlRecOnDay();
+
+ log.info("=== [CheckShortUrlScheduleTask|execute update rec is {} . Thread is {} ] ===", updateRecCount, Thread.currentThread().getName());
+ }
+}
diff --git a/short-server-service/src/test/java/com/by/DaoTest.java b/short-server-service/src/test/java/com/by/DaoTest.java
new file mode 100644
index 0000000..9409d07
--- /dev/null
+++ b/short-server-service/src/test/java/com/by/DaoTest.java
@@ -0,0 +1,23 @@
+package com.by;
+
+import com.by.service.ShortServerService;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@Slf4j
+@SpringBootTest
+@RunWith(SpringRunner.class)
+public class DaoTest {
+
+ @Autowired
+ private ShortServerService shortServerService;
+
+ @Test
+ public void test1(){
+ System.out.println(shortServerService.updateShortUrlRecOnDay());
+ }
+}