[新增功能](master): 功能开发完成

开发短链功能
master
土豆兄弟 3 years ago
parent 1f438655f5
commit e078723021

@ -2,6 +2,13 @@ package com.by.constants;
/** /**
* *
* @author q
*/ */
public class SystemConstant { public class SystemConstant {
/**
* IP
*/
public static final String DEFAULT_IP = "0.0.0.0";
} }

@ -0,0 +1,47 @@
package com.by.utils;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import java.util.*;
/**
*
*/
public class ShortUrlUtil {
/**
*
*/
private static final Integer BASE_LIMIT_LENGTH = 10;
private ShortUrlUtil() {
}
/**
* [1] : ,
*
* @return
*/
public static Map<String, String> makeShortUrl(List<String> oringinShortUrlList) {
if (CollectionUtil.isEmpty(oringinShortUrlList)) {
return CollectionUtil.newHashMap();
}
Map<String, String> resultMap = new HashMap<>();
oringinShortUrlList.forEach(
each -> {
resultMap.put(RandomUtil.randomString(BASE_LIMIT_LENGTH), each);
}
);
// 校验生成个数不能少
if (oringinShortUrlList.size() != resultMap.size()) {
return CollectionUtil.newHashMap();
}
return resultMap;
}
}

@ -0,0 +1,91 @@
package com.by.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author q
*/
public class ThreadLocalUtil<T> {
private static final ThreadLocal<Map<String, Object>> THREAD_LOCAL = ThreadLocal.withInitial(
() -> new HashMap<>(4)
);
public static Map<String, Object> getThreadLocal(){
return THREAD_LOCAL.get();
}
public static <T> T get(String key) {
Map map = (Map)THREAD_LOCAL.get();
return (T)map.get(key);
}
public static <T> T get(String key,T defaultValue) {
Map map = (Map)THREAD_LOCAL.get();
return (T)map.get(key) == null ? defaultValue : (T)map.get(key);
}
public static void set(String key, Object value) {
Map map = (Map)THREAD_LOCAL.get();
map.put(key, value);
}
public static void set(Map<String, Object> keyValueMap) {
Map map = (Map)THREAD_LOCAL.get();
map.putAll(keyValueMap);
}
public static void remove() {
THREAD_LOCAL.remove();
}
public static <T> Map<String,T> fetchVarsByPrefix(String prefix) {
Map<String,T> vars = new HashMap<>();
if( prefix == null ){
return vars;
}
Map map = (Map)THREAD_LOCAL.get();
Set<Map.Entry> set = map.entrySet();
for( Map.Entry entry : set){
Object key = entry.getKey();
if( key instanceof String ){
if( ((String) key).startsWith(prefix) ){
vars.put((String)key,(T)entry.getValue());
}
}
}
return vars;
}
public static <T> T remove(String key) {
Map map = (Map)THREAD_LOCAL.get();
return (T)map.remove(key);
}
public static void clear(String prefix) {
if( prefix == null ){
return;
}
Map map = (Map)THREAD_LOCAL.get();
Set<Map.Entry> set = map.entrySet();
List<String> removeKeys = new ArrayList<>();
for( Map.Entry entry : set ){
Object key = entry.getKey();
if( key instanceof String ){
if( ((String) key).startsWith(prefix) ){
removeKeys.add((String)key);
}
}
}
for( String key : removeKeys ){
map.remove(key);
}
}
}

@ -1,20 +1,23 @@
package com.by.dto; package com.by.dto;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* @author q * @author q
*/ */
@Data @Data
@AllArgsConstructor
@NoArgsConstructor
public class ShortChainDTO { public class ShortChainDTO {
/** /**
* *
*/ */
private Set<String> shortChainOrigins; private List<String> shortChainOrigins;
/** /**
* *

@ -0,0 +1,29 @@
package com.by.dto;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* dto
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ShortChainPointJsonDTO {
/**
*
*/
@JSONField(name = "originUrl")
private String originUrl;
/**
* 0- 1-
*/
@JSONField(name = "pointTag")
private Integer pointTag;
}

@ -3,12 +3,14 @@ package com.by;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
/** /**
* *
* *
* @author q * @author q
*/ */
@EnableAsync
@SpringBootApplication @SpringBootApplication
public class ShortServerApplication { public class ShortServerApplication {
public static void main(String[] args) { public static void main(String[] args) {

@ -5,16 +5,25 @@ import com.by.api.common.CommonResponse;
import com.by.api.convert.ShortChainVOToDTOConvert; import com.by.api.convert.ShortChainVOToDTOConvert;
import com.by.api.vo.ShortChainRequestVO; import com.by.api.vo.ShortChainRequestVO;
import com.by.api.vo.ShortChainResponseVO; import com.by.api.vo.ShortChainResponseVO;
import com.by.constants.SystemConstant;
import com.by.dto.ShortChainDTO; import com.by.dto.ShortChainDTO;
import com.by.entity.ShortUrl;
import com.by.service.ShortServerService; import com.by.service.ShortServerService;
import com.by.task.ShortChainTask;
import com.by.utils.ThreadLocalUtil;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.List; import java.util.List;
import java.util.Objects;
import static com.by.api.constants.RequestInfoConstant.CUSTOMER_IP_ADDR_KEY;
/** /**
* @author q * @author q
@ -28,22 +37,32 @@ public class ShortServerOpenApiController {
private final ShortServerService shortServerService; private final ShortServerService shortServerService;
public ShortServerOpenApiController(ShortServerService shortServerService) { private final ShortChainTask shortChainTask;
public ShortServerOpenApiController(ShortServerService shortServerService, ShortChainTask shortChainTask) {
this.shortServerService = shortServerService; this.shortServerService = shortServerService;
this.shortChainTask = shortChainTask;
} }
@ApiOperation("批量生成短链接") @ApiOperation("批量生成短链接")
@PostMapping(value = "/trans") @PostMapping(value = "/trans")
@ResponseBody @ResponseBody
public CommonResponse parseContentToShortChain(@Validated @RequestBody ShortChainRequestVO shortChainRequestVO) { public CommonResponse parseContentToShortChain(@Validated @RequestBody ShortChainRequestVO shortChainRequestVO, HttpServletRequest request) {
log.info("=== [ShortServerOpenApiController|parseContentToShortChain, one request is coming, request vo is {} ] ===", shortChainRequestVO.toString()); log.info("=== [ShortServerOpenApiController|parseContentToShortChain, one request is coming, request vo is {} ] ===", shortChainRequestVO.toString());
ShortChainDTO shortChainDTO = ShortChainVOToDTOConvert.convertShortChainRequestVOToDTO(shortChainRequestVO); ShortChainDTO shortChainDTO = ShortChainVOToDTOConvert.convertShortChainRequestVOToDTO(shortChainRequestVO);
// 拿到远程请求客户端的Ip信息
String remoteAddr = request.getRemoteAddr();
if (StringUtils.isNotBlank(remoteAddr)){
ThreadLocalUtil.set(CUSTOMER_IP_ADDR_KEY, remoteAddr);
}else {
ThreadLocalUtil.set(CUSTOMER_IP_ADDR_KEY, SystemConstant.DEFAULT_IP);
}
shortChainDTO = shortServerService.handleOriginUrlsToShortUrls(shortChainDTO); shortChainDTO = shortServerService.handleOriginUrlsToShortUrls(shortChainDTO);
List<String> shortChainResult = shortChainDTO.getShortChainResult(); List<String> shortChainResult = shortChainDTO.getShortChainResult();
ShortChainResponseVO shortChainResponseVO = new ShortChainResponseVO(); ShortChainResponseVO shortChainResponseVO = new ShortChainResponseVO();
if (CollectionUtil.isNotEmpty(shortChainResult)){ if (CollectionUtil.isNotEmpty(shortChainResult)){
shortChainResponseVO.setShortChainResult(shortChainResult); shortChainResponseVO.setShortChainResult(shortChainResult);
@ -53,11 +72,20 @@ public class ShortServerOpenApiController {
} }
@ApiOperation("短链接兑换长链接并进行") @ApiOperation("短链接兑换长链接并进行")
@GetMapping(value = "/redeem") @GetMapping(value = "/s/{redeem}")
public ModelAndView redeemShortChainClick(@RequestParam(value = "a")String param){ public ModelAndView redeemShortChainClick(@PathVariable("redeem") String redeem){
log.info("=== [ShortServerOpenApiController|redeemShortChainClick, one request is coming, request param is {} ] ===", param); log.info("=== [ShortServerOpenApiController|redeemShortChainClick, one request is coming, request param is {} ] ===", redeem);
ShortUrl shortUrl = shortServerService.handleOnceShortUrlToRedirectOriginUrlAndRecord(redeem);
String originUrl = "";
if (!Objects.isNull(shortUrl)){
// 异步进行更新数据库中的点击记录及推送给之前的调用方(可以走消息)
shortChainTask.doRunTask(shortUrl);
originUrl = shortUrl.getOriginUrl();
}
return shortServerService.handleOnceShortUrlToRedirectOriginUrlAndRecord(param); return new ModelAndView("redirect:" + originUrl);
} }
} }

@ -0,0 +1,23 @@
package com.by.api.constants;
/**
*
*/
public class RequestInfoConstant {
/**
*
*/
public static final String CUSTOMER_IP_ADDR_KEY = "customer_ip_addr_key";
/**
*
*/
public static final String LOCAL_SERVER_HOST = "http://s.baiyee.vip/";
/**
* Http
*/
public static final int RETRY_COUNT = 3;
}

@ -5,6 +5,7 @@ import com.by.api.vo.ShortChainRequestVO;
import com.by.dto.ShortChainDTO; import com.by.dto.ShortChainDTO;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -14,6 +15,10 @@ import java.util.Set;
public class ShortChainVOToDTOConvert { public class ShortChainVOToDTOConvert {
/**
* URL Url
*/
private static final String URL_END_TAG = "//";
/** /**
@ -31,9 +36,9 @@ public class ShortChainVOToDTOConvert {
); );
if (CollectionUtil.isNotEmpty(originsUrlSet)){ if (CollectionUtil.isNotEmpty(originsUrlSet)) {
ShortChainDTO shortChainDTO = new ShortChainDTO(); ShortChainDTO shortChainDTO = new ShortChainDTO();
shortChainDTO.setShortChainOrigins(originsUrlSet); shortChainDTO.setShortChainOrigins(new ArrayList<>(originsUrlSet));
return shortChainDTO; return shortChainDTO;
} }
@ -41,10 +46,10 @@ public class ShortChainVOToDTOConvert {
} }
private static String checkUrlAllowed(String baseUrlAddr) { private static String checkUrlAllowed(String baseUrlAddr) {
if (!StringUtils.endsWith(baseUrlAddr.trim(), "//")){ if (!StringUtils.endsWith(baseUrlAddr.trim(), URL_END_TAG)) {
return baseUrlAddr.trim() + "//"; return baseUrlAddr.trim() + URL_END_TAG;
} }
return baseUrlAddr.trim(); return baseUrlAddr.trim();
} }

@ -0,0 +1,68 @@
package com.by.dao;
import com.by.entity.ShortUrl;
import com.by.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import static com.by.api.constants.RequestInfoConstant.CUSTOMER_IP_ADDR_KEY;
/**
* JPA
*/
@Component
@Slf4j
public class ShortUrlDAO {
private final JdbcTemplate jdbcTemplate;
public ShortUrlDAO(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
*
*
* @param list
* @return
*/
public long batchInsertShortUrls(List<ShortUrl> list){
String sql = "INSERT INTO `t_short_url` " +
"(operator_ip,origin_url,short_url,point_tag,expiration_day,valid_tag)" +
"VALUES (?, ?, ?, ?, ?, ?)";
int[] ints = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
preparedStatement.setString(1,list.get(i).getOperatorIp().trim());
preparedStatement.setString(2,list.get(i).getOriginUrl().trim());
preparedStatement.setString(3,list.get(i).getShortUrl().trim());
preparedStatement.setInt(4,list.get(i).getPointTag());
preparedStatement.setInt(5,list.get(i).getExpirationDay());
preparedStatement.setInt(6,list.get(i).getValidTag());
}
@Override
public int getBatchSize() {
return list.size();
}
});
log.info("=== [ ShortUrlDAO|batchInsertShortUrls 受影响的行数为: {} ] === ", ints.length);
// 添加完成后移除保存的ip地址信息
ThreadLocalUtil.remove(CUSTOMER_IP_ADDR_KEY);
return ints.length;
}
}

@ -3,9 +3,23 @@ package com.by.dao;
import com.by.entity.ShortUrl; import com.by.entity.ShortUrl;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
/**
* @author q
*/
@Repository @Repository
public interface ShortUrlRepository extends JpaRepository<ShortUrl, Long>, JpaSpecificationExecutor<ShortUrl> { public interface ShortUrlRepository extends JpaRepository<ShortUrl, Long>, JpaSpecificationExecutor<ShortUrl> {
/**
* @param shortUrl
* @return
*/
ShortUrl findByshortUrl(String shortUrl);
@Modifying
@Query("update ShortUrl t set t.sendTag = ?1 where t.id = ?2")
void updateSendStatus(Integer sendStatus, Long recId);
} }

@ -2,15 +2,26 @@ package com.by.entity;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import com.by.utils.ThreadLocalUtil;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import java.sql.Timestamp; import java.sql.Timestamp;
import static com.by.api.constants.RequestInfoConstant.CUSTOMER_IP_ADDR_KEY;
import static com.by.entity.constants.DBDefaultConstant.DEFAULT_CREATE_EXPIRATION_DAY;
/**
* @author q
*/
@Entity @Entity
@Data @Data
@Table(name = "t_short_url") @Table(name = "t_short_url")
@NoArgsConstructor
public class ShortUrl implements Serializable { public class ShortUrl implements Serializable {
/** /**
@ -25,12 +36,14 @@ public class ShortUrl implements Serializable {
* *
*/ */
@Column(name = "gmt_create", nullable = false) @Column(name = "gmt_create", nullable = false)
@CreatedDate
private Timestamp gmtCreate; private Timestamp gmtCreate;
/** /**
* *
*/ */
@Column(name = "gmt_modified", nullable = false) @Column(name = "gmt_modified", nullable = false)
@LastModifiedDate
private Timestamp gmtModified; private Timestamp gmtModified;
/** /**
@ -64,12 +77,34 @@ public class ShortUrl implements Serializable {
private Integer expirationDay; private Integer expirationDay;
/** /**
* 0- 1- * 0- 1-
*/ */
@Column(name = "valid_tag") @Column(name = "valid_tag")
private Integer validTag; private Integer validTag;
/**
* 0- 1-
*/
@Column(name = "send_tag")
private Integer sendTag;
/**
*
*/
public void copy(ShortUrl source) { public void copy(ShortUrl source) {
BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true)); BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
} }
/**
*
*/
public ShortUrl(String originUrl, String shortUrl,
Integer pointTag, Integer validTag) {
this.operatorIp = ThreadLocalUtil.get(CUSTOMER_IP_ADDR_KEY);
this.originUrl = originUrl;
this.shortUrl = shortUrl;
this.expirationDay = DEFAULT_CREATE_EXPIRATION_DAY;
this.pointTag = pointTag;
this.validTag = validTag;
}
} }

@ -0,0 +1,22 @@
package com.by.entity.constants;
/**
* ,
*/
public class DBDefaultConstant {
/**
* 30
*/
public static final int DEFAULT_CREATE_EXPIRATION_DAY = 30;
/**
* 0
*/
public static final int ZERO_NUM_TAG = 0;
/**
* 1
*/
public static final int ONE_NUM_TAG = 1;
}

@ -0,0 +1,102 @@
package com.by.exception;
import com.by.exception.spi.ErrorCode;
/**
*
* @author q
*/
public class BaiyeException extends RuntimeException {
/**
*
*/
private ErrorCode errorCode;
/*
*/
private BaiyeException(ErrorCode errorCode) {
super(errorCode.toString());
this.errorCode = errorCode;
}
private BaiyeException(ErrorCode errorCode, String errorMessage) {
super(errorCode.toString() + " - " + errorMessage);
this.errorCode = errorCode;
}
private BaiyeException(ErrorCode errorCode, String errorMessage,
Throwable cause) {
super(errorCode.toString() + " - " + getMessage(errorMessage)
+ " - " + getMessage(cause), cause);
this.errorCode = errorCode;
}
/**
*
* @param errorCode
* @return
*/
public static BaiyeException createBaiyeException(ErrorCode errorCode) {
return new BaiyeException(errorCode);
}
/**
*
* @param errorCode
* @param message
* @return
*/
public static BaiyeException createBaiyeException(ErrorCode errorCode, String message) {
return new BaiyeException(errorCode, message);
}
/**
*
* @param errorCode
* @param message
* @param cause
* @return
*/
public static BaiyeException createBaiyeExceptionWithDetail(ErrorCode errorCode, String message,
Throwable cause) {
if (cause instanceof BaiyeException) {
return (BaiyeException) cause;
}
return new BaiyeException(errorCode, message, cause);
}
/**
*
* @param errorCode
* @param cause
* @return
*/
public static BaiyeException asBaiyeException(ErrorCode errorCode, Throwable cause) {
if (cause instanceof BaiyeException) {
return (BaiyeException) cause;
}
return new BaiyeException(errorCode, getMessage(cause), cause);
}
/**
*
*
* @param obj
* @return
*/
private static String getMessage(Object obj) {
if (obj == null) {
return "";
}
if (obj instanceof Throwable) {
return ((Throwable) obj).getMessage();
} else {
return obj.toString();
}
}
}

@ -1,4 +1,4 @@
package com.by.api.exception; package com.by.exception;
import com.by.api.common.CommonResponse; import com.by.api.common.CommonResponse;
import com.by.api.common.ResponseCode; import com.by.api.common.ResponseCode;

@ -0,0 +1,18 @@
package com.by.exception.spi;
/**
* -
*/
public interface ErrorCode {
/**
*
*/
String getCode();
/**
*
*/
String getDescription();
}

@ -0,0 +1,54 @@
package com.by.exception.spi.enums;
import com.by.exception.spi.ErrorCode;
/**
*
*/
public enum CommonErrorCode implements ErrorCode {
/*
*
*/
CONFIG_ERROR(100, "配置异常"),
RUNTIME_ERROR(101, "业务运行时异常"),
DATA_ERROR(102, "数据异常"),;
/**
*
*/
private final int code;
/**
*
*/
private final String describe;
/**
*
*/
private CommonErrorCode(int code, String describe) {
this.code = code;
this.describe = describe;
}
@Override
public String getCode() {
return "";
}
@Override
public String getDescription() {
return "";
}
@Override
public String toString() {
return String.format(
"Code:[%s], Describe:[%s]",
this.code,
this.describe
);
}
}

@ -1,7 +1,7 @@
package com.by.service; package com.by.service;
import com.by.dto.ShortChainDTO; import com.by.dto.ShortChainDTO;
import org.springframework.web.servlet.ModelAndView; import com.by.entity.ShortUrl;
/** /**
* *
@ -21,5 +21,14 @@ public interface ShortServerService {
/** /**
* *
*/ */
ModelAndView handleOnceShortUrlToRedirectOriginUrlAndRecord(String param); ShortUrl handleOnceShortUrlToRedirectOriginUrlAndRecord(String redeem);
/**
* -
* @param recId
* @param sucess
* @return
*/
boolean updateShortUrlToPlatformSendtatus(Long recId, boolean sucess);
} }

@ -1,10 +1,25 @@
package com.by.service.impl; package com.by.service.impl;
import com.by.api.constants.RequestInfoConstant;
import com.by.dao.ShortUrlDAO;
import com.by.dao.ShortUrlRepository;
import com.by.dto.ShortChainDTO; import com.by.dto.ShortChainDTO;
import com.by.entity.ShortUrl;
import com.by.entity.constants.DBDefaultConstant;
import com.by.exception.BaiyeException;
import com.by.exception.spi.enums.CommonErrorCode;
import com.by.service.ShortServerService; import com.by.service.ShortServerService;
import com.by.utils.ShortUrlUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView; 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;
/** /**
* Service * Service
@ -15,27 +30,65 @@ import org.springframework.web.servlet.ModelAndView;
@Slf4j @Slf4j
public class ShortServerServiceImpl implements ShortServerService { public class ShortServerServiceImpl implements ShortServerService {
private final ShortUrlRepository shortUrlRepository;
private final ShortUrlDAO shortUrlDAO;
public ShortServerServiceImpl(ShortUrlRepository shortUrlRepository, ShortUrlDAO shortUrlDAO) {
this.shortUrlRepository = shortUrlRepository;
this.shortUrlDAO = shortUrlDAO;
}
@Override @Override
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public ShortChainDTO handleOriginUrlsToShortUrls(ShortChainDTO shortChainDTO) { public ShortChainDTO handleOriginUrlsToShortUrls(ShortChainDTO shortChainDTO) {
// TODO: 2021/4/14 0014
// 1. 拼接请求调用短链生成器进行所有的短链请求 // 1. 拼接请求调用短链生成器进行所有的短链请求
Map<String, String> makeShortUrlResult = ShortUrlUtil.makeShortUrl(shortChainDTO.getShortChainOrigins());
// 2. 生成的短链请求批量入库 // 2. 生成的短链请求批量入库
List<ShortUrl> shortUrls = new ArrayList<>();
makeShortUrlResult.forEach(
(shortUrl, originUrl) -> {
shortUrls.add(new ShortUrl(originUrl, shortUrl, DBDefaultConstant.ZERO_NUM_TAG, DBDefaultConstant.ZERO_NUM_TAG));
}
);
long result = shortUrlDAO.batchInsertShortUrls(shortUrls);
if (result < 0) {
log.error(" === [ShortServerServiceImpl|handleOriginUrlsToShortUrls , insert data fail, success insert count is {} ] ===", result);
throw BaiyeException.createBaiyeException(CommonErrorCode.DATA_ERROR);
}
// 3. 把短链请求 return 给调用方 // 3. 把短链请求 return 给调用方
return null; return new ShortChainDTO(null, new ArrayList<>(makeShortUrlResult.keySet()));
} }
@Override @Override
public ModelAndView handleOnceShortUrlToRedirectOriginUrlAndRecord(String param) { public ShortUrl handleOnceShortUrlToRedirectOriginUrlAndRecord(String redeem) {
// 1. 查询库中的短链请求 // 1. 查询库中的短链请求
ShortUrl byshortUrl = shortUrlRepository.findByshortUrl(RequestInfoConstant.LOCAL_SERVER_HOST + redeem);
// 2. 拿出真实请求进行跳转 // 2. 拿出真实请求进行跳转
if (Objects.isNull(byshortUrl)) {
return new ShortUrl();
}
// 3. 异步进行更新数据库中的点击记录及推送给之前的调用方(可以走消息) String originUrl = byshortUrl.getOriginUrl();
if (StringUtils.isBlank(originUrl)) {
return new ShortUrl();
}
return byshortUrl;
}
return new ModelAndView("redirect:https://www.baidu.com/"); @Override
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public boolean updateShortUrlToPlatformSendtatus(Long recId, boolean sucess) {
if (recId == null) {
return Boolean.FALSE;
}
if (sucess) {
shortUrlRepository.updateSendStatus(1, recId);
}else {
shortUrlRepository.updateSendStatus(0, recId);
}
return Boolean.TRUE;
} }
} }

@ -1,6 +1,16 @@
package com.by.task; package com.by.task;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.by.api.constants.RequestInfoConstant;
import com.by.dao.ShortUrlRepository;
import com.by.dto.ShortChainPointJsonDTO;
import com.by.entity.ShortUrl;
import com.by.entity.constants.DBDefaultConstant;
import com.by.service.ShortServerService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -8,23 +18,85 @@ import org.springframework.stereotype.Component;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneOffset; import java.time.ZoneOffset;
/**
* @author q
*/
@Component @Component
@Scope("prototype") @Scope("prototype")
@Slf4j @Slf4j
public class ShortChainTask { public class ShortChainTask {
@Value("${upload.platform.url}")
private String uploudPlatformUrl;
private final ShortUrlRepository shortUrlRepository;
private final ShortServerService shortServerService;
public ShortChainTask(ShortUrlRepository shortUrlRepository, ShortServerService shortServerService) {
this.shortUrlRepository = shortUrlRepository;
this.shortServerService = shortServerService;
}
@Async(value = "abTaskExecutor") @Async(value = "abTaskExecutor")
public void doRunTask(){ public void doRunTask(ShortUrl shortUrl) {
Long satrtMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); Long satrtMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
log.info("====== [ task start running, task name is {} ] ======", "ABDownTask"); log.info("====== [ task start running, task name is {} ] ======", "ABDownTask");
runTask(); runTask(shortUrl);
Long endMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); Long endMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
log.info("====== [ task start end, task name is {},cost milliSecond is {} ] ======", "ABDownTask", (endMilliSecond-satrtMilliSecond)); log.info("====== [ task start end, task name is {},cost milliSecond is {} ] ======", "ABDownTask", (endMilliSecond - satrtMilliSecond));
}
private void runTask(ShortUrl shortUrl) {
// 修改状态更新点击状态
shortUrl.setPointTag(DBDefaultConstant.ONE_NUM_TAG);
ShortUrl save = shortUrlRepository.save(shortUrl);
// 更新点击信息给我们的平台
sendPointTagToPlatform(save);
} }
private void runTask() { private void sendPointTagToPlatform(ShortUrl shortUrl) {
// 设置请求失败计数
int count = 0;
// 转成json字符串
ShortChainPointJsonDTO shortChainPointJsonDTO =
new ShortChainPointJsonDTO(shortUrl.getOriginUrl(), DBDefaultConstant.ONE_NUM_TAG);
String jsonSendContent = JSON.toJSONString(shortChainPointJsonDTO);
// 失败重发请求3次
while (count <= RequestInfoConstant.RETRY_COUNT) {
// 调用HTTP请求发送数据
HttpResponse httpResponse = sendReq(jsonSendContent, uploudPlatformUrl);
if (httpResponse.isOk() && httpResponse.body().contains("0")) {
log.info("========== [liehe request success, response is {} ] ==========", httpResponse.body());
shortServerService.updateShortUrlToPlatformSendtatus(shortUrl.getId(), Boolean.TRUE);
break;
} else {
count++;
log.error("========== [liehe request fail, response is {} ] ==========", httpResponse.body());
}
}
if (count > RequestInfoConstant.RETRY_COUNT) {
shortServerService.updateShortUrlToPlatformSendtatus(shortUrl.getId(), Boolean.FALSE);
}
} }
/**
*
*
* @param json Json
* @param url url
* @return
*/
private HttpResponse sendReq(String json, String url) {
return HttpRequest
.post(url)
.body(json)
.execute();
}
} }

@ -1,6 +1,7 @@
package com.by.task.conf; package com.by.task.conf;
import cn.hutool.core.thread.NamedThreadFactory;
import org.apache.tomcat.util.threads.ThreadPoolExecutor; import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -8,7 +9,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -29,12 +29,11 @@ public class ThreadPoolConfig {
@Value(value = "${short.chain.task.queueCapacity}") @Value(value = "${short.chain.task.queueCapacity}")
private int queueCapacity = 100; private int queueCapacity = 100;
@Value(value = "${short.chain.task.ThreadNamePrefix}") @Value(value = "${short.chain.task.ThreadNamePrefix}")
private String ThreadNamePrefix = "MyThreadPoolExecutor-"; private String ThreadNamePrefix = "ShortChainTaskExecutor-";
/** /**
* AB 线 * @return 线
* @return
*/ */
@Bean @Bean
public Executor shortChainTaskExecutor() { public Executor shortChainTaskExecutor() {
@ -45,7 +44,7 @@ public class ThreadPoolConfig {
3, 3,
TimeUnit.SECONDS, TimeUnit.SECONDS,
new LinkedBlockingDeque<>(queueCapacity), new LinkedBlockingDeque<>(queueCapacity),
Executors.defaultThreadFactory(), new NamedThreadFactory(ThreadNamePrefix, false),
new ThreadPoolExecutor.DiscardOldestPolicy() new ThreadPoolExecutor.DiscardOldestPolicy()
); );

Loading…
Cancel
Save