parent
1f438655f5
commit
e078723021
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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.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
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue