Commit 9742023a authored by 侯力峰's avatar 侯力峰
Browse files

首次开源发布

parent 444abeb0
Pipeline #2755 canceled with stages
package cn.spatiotemporal.core.ftp;
import java.io.IOException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import cn.spatiotemporal.core.config.ftp.FtpProperties;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FtpClientPooledObjectFactory implements PooledObjectFactory<FTPClient> {
private FtpProperties ftpProperties;
public FtpClientPooledObjectFactory(FtpProperties ftpProperties) {
this.ftpProperties = ftpProperties;
}
@Override
public PooledObject<FTPClient> makeObject() throws Exception {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(ftpProperties.getIp(), Integer.valueOf(ftpProperties.getPort()));
ftpClient.login(ftpProperties.getUsername(), ftpProperties.getPassword());
log.info("连接ftp服务返回码:" + ftpClient.getReplyCode());
ftpClient.setBufferSize(ftpProperties.getBufferSize());
ftpClient.setControlEncoding(ftpProperties.getEncoding());
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
return new DefaultPooledObject<>(ftpClient);
} catch (Exception e) {
if (ftpClient.isAvailable()) {
ftpClient.disconnect();
}
ftpClient = null;
log.error("建立ftp连接失败!", (Object) e.getStackTrace());
throw new Exception("建立ftp连接失败!", e);
}
}
@Override
public void destroyObject(PooledObject<FTPClient> pooledObject) throws Exception {
FTPClient ftpClient = getObject(pooledObject);
if (null != ftpClient && ftpClient.isConnected()) {
ftpClient.disconnect();
}
}
@Override
public boolean validateObject(PooledObject<FTPClient> pooledObject) {
FTPClient ftpClient = getObject(pooledObject);
if (null == ftpClient || !ftpClient.isConnected()) {
return false;
}
try {
ftpClient.changeWorkingDirectory("/");
return true;
} catch (IOException e) {
log.error("验证ftp连接失败!", (Object) e.getStackTrace());
return false;
}
}
@Override
public void activateObject(PooledObject<FTPClient> pooledObject) throws Exception {
}
@Override
public void passivateObject(PooledObject<FTPClient> pooledObject) throws Exception {
}
private FTPClient getObject(PooledObject<FTPClient> pooledObject) {
if (null == pooledObject || null == pooledObject.getObject()) {
return null;
}
return pooledObject.getObject();
}
}
package cn.spatiotemporal.core.ftp;
public interface FtpConstants {
//ftp文件路径编码格式
String DEFAULT_FTP_PATH_ENCODING="ISO-8859-1";
}
package cn.spatiotemporal.core.ftp;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.commons.net.ftp.FTPClient;
public interface FtpDao {
FTPClient getCurrentClient();
boolean uploadFile(String path, String fileName, String originFileName);
boolean uploadFile(String path, String fileName, InputStream inputStream) throws IOException;
boolean downloadFile(String path, String fileName, String localPath);
boolean deleteFile(String path, String fileName);
boolean createDirectory(String remote);
boolean existFile(String path);
boolean makeDirectory(String directory);
List<String> retrieveFileNames(String remotePath);
}
package cn.spatiotemporal.core.ftp;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.pool2.ObjectPool;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import cn.spatiotemporal.core.config.ftp.FtpProperties;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Getter
@Setter
public class FtpTemplate implements FtpDao {
private final FtpProperties ftpProperties;
//连接池初始化标志
private boolean hasInit = false;
//连接池
private ObjectPool<FTPClient> ftpClientPool;
private FTPClient currentClient = null;
public FtpTemplate(FtpProperties ftpProperties) {
this.ftpProperties = ftpProperties;
}
/**
* 上传文件
*
* @param path ftp服务器保存地址
* @param fileName 上传到ftp的文件名
* @param originFileName 等待上传的文件名(绝对地址或路径)
*/
@Override
public boolean uploadFile(String path, String fileName, String originFileName) {
boolean flag = false;
try {
InputStream inputStream = new FileInputStream(new File(originFileName));
flag=uploadFile( path, fileName, inputStream);
} catch (Exception e) {
//log.error("上传文件出错!", (Object) e.getStackTrace());
e.printStackTrace();
}
return flag;
}
/**
* 上传文件
*
* @param path ftp服务器保存地址
* @param fileName 上传到ftp的文件名
* @param inputStream 文件流
*/
@Override
public boolean uploadFile(String path, String fileName, InputStream inputStream) throws IOException {
boolean flag = false;
currentClient = getFtpClient();
try {
currentClient.setFileType(FTPClient.BINARY_FILE_TYPE);
createDirectory(path);
currentClient.makeDirectory(path);
currentClient.changeWorkingDirectory(path);
currentClient.storeFile(fileName, inputStream);
flag = true;
} catch (Exception e) {
//log.error("上传文件出错!:{}", e);
e.printStackTrace();
} finally {
if(null!=inputStream) inputStream.close();
releaseFtpClient(currentClient);
currentClient = null;
}
return flag;
}
/**
* 下载文件
*
* @param path ftp服务器文件路径
* @param fileName 文件名称
* @param localPath 下载后的路径
*/
@Override
public boolean downloadFile(String path, String fileName, String localPath) {
boolean flag = false;
OutputStream outputStream = null;
currentClient = getFtpClient();
try {
currentClient.changeWorkingDirectory(path);
FTPFile[] files = currentClient.listFiles();
for (FTPFile file : files) {
if (fileName.equalsIgnoreCase(file.getName())) {
File localFile = new File(localPath + "/" + file.getName());
outputStream = new FileOutputStream(localFile);
currentClient.retrieveFile(file.getName(), outputStream);
outputStream.close();
}
}
flag = true;
} catch (IOException e) {
log.error("下载文件出错!", (Object) e.getStackTrace());
} finally {
releaseFtpClient(currentClient);
if (null != outputStream) {
try {
outputStream.close();
} catch (IOException e) {
log.error("关闭输出流出错!", (Object) e.getStackTrace());
}
}
currentClient = null;
}
return flag;
}
/**
* 删除文件
*
* @param path ftp文件路径
* @param fileName 文件名
*/
@Override
public boolean deleteFile(String path, String fileName) {
boolean flag = false;
currentClient = getFtpClient();
try {
currentClient.changeWorkingDirectory(path);
currentClient.dele(fileName);
currentClient.logout();
flag = true;
} catch (IOException e) {
log.error("删除文件出错!", (Object) e.getStackTrace());
} finally {
releaseFtpClient(currentClient);
currentClient = null;
}
return flag;
}
/**
* 创建多层目录,如果ftp服务器已存在该目录,则不创建,如果没有,则创建
*
* @param remote 创建的目录
* @param currentClient
*/
@Override
public boolean createDirectory(String remote) {
String directory = remote + "/";
boolean flag = true;
if (currentClient == null) {
currentClient = getFtpClient();
}
try {
//如果远程目录不存在,则递归创建远程目录
if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(directory)) {
int start = 0;
int end = 0;
if (directory.startsWith("/")) {
start = 1;
}
end = directory.indexOf("/", start);
String path = "";
String paths = "";
do {
String subDirectory = new String(remote.substring(start, end).getBytes(ftpProperties.getEncoding()), FtpConstants.DEFAULT_FTP_PATH_ENCODING);
path = path + "/" + subDirectory;
if (!existFile(path)) {
if (makeDirectory(subDirectory)) {
changeWorkingDirectory(subDirectory);
} else {
log.warn("创建目录[" + subDirectory + "]失败");
changeWorkingDirectory(subDirectory);
flag = false;
}
} else {
changeWorkingDirectory(subDirectory);
}
paths = paths + "/" + subDirectory;
start = end + 1;
end = directory.indexOf("/", start);
} while (end <= start);
}
} catch (IOException e) {
log.error("创建目录["+remote+"]失败!", (Object) e.getStackTrace());
flag = false;
}
return flag;
}
/**
* 判断ftp服务器的路径或文件是否存在
*
* @param path
* @param currentClient
*/
@Override
public boolean existFile(String path) {
boolean flag = false;
if (currentClient == null) {
currentClient = getFtpClient();
}
try {
FTPFile[] files = currentClient.listFiles(path);
if (files.length > 0) {
flag = true;
}
} catch (IOException e) {
log.error("判断目录["+path+"]是否存在失败!", (Object) e.getStackTrace());
flag = false;
}
return flag;
}
/**
* 创建目录
*
* @param directory
* @param currentClient
*/
@Override
public boolean makeDirectory(String directory) {
boolean flag = true;
if (currentClient == null) {
currentClient = getFtpClient();
}
try {
flag = currentClient.makeDirectory(directory);
if (flag) {
log.info("创建文件夹:" + directory);
}
} catch (IOException e) {
log.error("创建文件夹" + directory + "失败!", (Object) e.getStackTrace());
flag = false;
}
return flag;
}
/**
* 切换目录
*
* @param directory 要切换的目录
* @param currentClient ftp客户端
*/
public boolean changeWorkingDirectory(String directory) {
boolean flag = true;
if (currentClient == null) {
currentClient = getFtpClient();
}
try {
flag = currentClient.changeWorkingDirectory(directory);
if (flag) {
log.info("进入文件夹:" + directory);
}
} catch (IOException e) {
log.error("进入文件夹:"+directory+"错误!", (Object) e.getStackTrace());
flag = false;
}
return flag;
}
/**
* 按行读取FTP文件
*
* @param remoteFilePath ftp路径
*/
public List<String> readFileByLine(String remoteFilePath) throws IOException {
currentClient = getFtpClient();
try (InputStream inputStream = currentClient.retrieveFileStream(encodingPath(remoteFilePath));
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
return reader.lines()
.map(line -> StringUtils.trimToEmpty(line))
.filter(line -> StringUtils.isNotEmpty(line))
.collect(Collectors.toList());
} finally {
currentClient.completePendingCommand();
releaseFtpClient(currentClient);
currentClient = null;
}
}
/**
* 获取指定路径下的ftp文件
*
* @param remotePath 指定路径
*/
public FTPFile[] retrieveFtpFiles(String remotePath) {
currentClient = getFtpClient();
try {
return currentClient.listFiles(encodingPath(remotePath + "/"), file -> file != null && file.getSize() > 0);
} catch (IOException e) {
log.error("获取路径["+remotePath+"]下的文件列表失败!", (Object) e.getStackTrace());
return null;
} finally {
releaseFtpClient(currentClient);
currentClient = null;
}
}
/**
* 获取指定ftp路径下的文件名称
*
* @param remotePath 指定ftp路径
*/
@Override
public List<String> retrieveFileNames(String remotePath) {
FTPFile[] files = retrieveFtpFiles(remotePath);
if (ArrayUtils.isEmpty(files)) {
return new ArrayList<>();
}
return Arrays.stream(files).filter(Objects::nonNull).map(FTPFile::getName).collect(Collectors.toList());
}
/**
* 获取编码后的文件路径
*/
private String encodingPath(String path) throws UnsupportedEncodingException {
//在FTP协议中,规定文件名编码格式为ISO-8859-1,所以目录名或文件名需要转码
return new String(path.replaceAll("//", "/").getBytes(ftpProperties.getEncoding()), FtpConstants.DEFAULT_FTP_PATH_ENCODING);
}
/**
* 获取ftp客户端
*/
private FTPClient getFtpClient() {
checkFtpClientPoolAvailable();
FTPClient ftpClient = null;
Exception exception = null;
//获取连接,做多尝试n次
try {
for (int i = 0; i < ftpProperties.getRetryCount(); i++) {
ftpClient = ftpClientPool.borrowObject();
ftpClient.enterLocalPassiveMode();//设置为被动模式
ftpClient.changeWorkingDirectory("/");
break;
}
} catch (Exception e) {
log.error("无法在连接池中获取ftp客户端!", (Object) e.getStackTrace());
exception = e;
}
if (null == ftpClient) {
throw new RuntimeException("无法在连接池中获取ftp客户端", exception);
}
return ftpClient;
}
/**
* 释放ftp客户端
*
* @param ftpClient
*/
private void releaseFtpClient(FTPClient ftpClient) {
if (null != ftpClient) {
try {
//从ftp连接池中移除ftp客户端
ftpClientPool.returnObject(ftpClient);
} catch (Exception e) {
try {
//判断客户端是否可用
if (ftpClient.isAvailable()) {
//销毁连接
ftpClient.disconnect();
}
} catch (IOException ex) {
log.error("销毁ftp连接失败!", (Object) e.getStackTrace());
}
log.error("从ftp连接池移除ftp客户端失败!", (Object) e.getStackTrace());
}
}
}
/**
* 检查ftp连接池是否可用
*/
private void checkFtpClientPoolAvailable() {
Assert.state(hasInit, "ftp未启用或连接失败!");
}
}
This diff is collapsed.
package cn.spatiotemporal.core.utils;
import java.util.HashMap;
import java.util.Map;
import org.springframework.cglib.beans.BeanMap;
/**
* bean与map互转工具类
* @author marquis
* @since 2022-02-22
*
*/
public class BeanMapUtils {
/**
* bean转map
* @param <T>
* @param bean
* @return
*/
public static <T> Map<String, Object> bean2Map(T bean) {
if (bean == null) {
return null;
}
Map<String, Object> map = new HashMap<String, Object>();
BeanMap beanMap = BeanMap.create(bean);
map.putAll(beanMap);
return map;
}
/**
* map转bean
* @param map
* @param clazz
* @return
*/
public static <T> T map2Bean(Map<String, Object> map, Class<T> clazz) {
if (map == null || map.isEmpty()) {
return null;
}
try {
T bean = clazz.newInstance();
BeanMap.create(bean).putAll(map);
return bean;
} catch (InstantiationException e) {
return null;
} catch (IllegalAccessException e) {
return null;
}
}
}
package cn.spatiotemporal.core.utils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Year;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
/**
* @ClassName: DateUtils
* @Description: ThreadLocal线程安全的DateUtils
* @date 2020年1月9日 上午10:43:42
*
* @author Q.JI
* @version
* @since JDK 1.8
*/
public class DateUtils {
private DateUtils() {
}
private static final ZoneId ZONE_ID = ZoneId.systemDefault();
/**
* LocalDateTime转化为Date
*
* @param localDateTime
* @return
*/
public static Date toDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZONE_ID).toInstant());
}
/**
* LocalDateTime转化为Date
*
* @param localDateTime
* @return
*/
public static Date toDate(LocalDate localDate) {
return Date.from(localDate.atStartOfDay(ZONE_ID).toInstant());
}
/**
* Date转化为LocalDateTime
*
* @param date
* @return
*/
public static LocalDateTime toLocalDateTime(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZONE_ID);
}
/**
* LocalDate转化为LocalDateTime
*
* @param localDate
* @return
*/
public static LocalDateTime toLocalDateTime(LocalDate localDate) {
return LocalDateTime.of(localDate, LocalTime.MIN);
}
/**
* Date转化为LocalDate
*
* @param date
* @return
*/
public static LocalDate toLocalDate(Date date) {
return date.toInstant().atZone(ZONE_ID).toLocalDate();
}
/**
* Date转化为字符串
*
* @param date
* @param formatter
* @return
*/
public static String format(Date date, DateFormatter formatter) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZONE_ID);
return formatter.getDateTimeFormatter().format(localDateTime);
}
/**
* Date转化为字符串
*
* @param date
* @param format
* @return
*/
public static String format(Date date, String format) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZONE_ID);
return DateTimeFormatter.ofPattern(format, Locale.CHINA).format(localDateTime);
}
/**
* 字符串转化为Date
*
* @param text
* @param formatter
* @return
*/
public static Date parse(String text, DateFormatter formatter) {
return formatter.parse(text);
}
/**
*
* @Title: increase
* @Description: 时间相加减运算
* @param date
* @param dateType
* @param amount
* @param formatter
* @return
* String
*/
public static String increase(Date date, int dateType, int amount, DateFormatter formatter) {
Date myDate = null;
if (date != null) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(dateType, amount);
myDate = calendar.getTime();
}
return format(myDate, formatter);
}
/**
*
* @ClassName: DateFormatter
* @Description: 时间格式枚举
* @date 2020年1月17日 下午4:04:01
*
* @author Q.JI
* @version
* @since JDK 1.8
*/
public static enum DateFormatter {
/**
* 格式yyyy
*/
YEAR_FORMATTER(DateTimeFormatter.ofPattern("yyyy", Locale.CHINA)) {
@Override
public Date parse(String text) {
Year year = Year.parse(text, dateTimeFormatter);
return Date.from(year.atDay(1).atStartOfDay(ZONE_ID).toInstant());
}
},
/**
* yyyy-MM
*/
YEAR_MONTH_FORMATTER(DateTimeFormatter.ofPattern("yyyy-MM", Locale.CHINA)) {
@Override
public Date parse(String text) {
YearMonth yearMonth = YearMonth.parse(text, dateTimeFormatter);
return Date.from(yearMonth.atDay(1).atStartOfDay(ZONE_ID).toInstant());
}
},
/**
* 格式yyyy-MM-dd
*/
DATE_FORMATTER(DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.CHINA)) {
@Override
public Date parse(String text) {
LocalDate localDate = LocalDate.parse(text, dateTimeFormatter);
return Date.from(localDate.atStartOfDay(ZONE_ID).toInstant());
}
},
/**
* 格式yyyy-MM-dd HH:mm:ss
*/
DATE_TIME_FORMATTER(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA)) {
@Override
public Date parse(String text) {
LocalDateTime localDateTime = LocalDateTime.parse(text, dateTimeFormatter);
return Date.from(localDateTime.atZone(ZONE_ID).toInstant());
}
},
/**
* 格式yyyy-MM-dd_HH
*/
DATE_HOUR_FORMATTER(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH", Locale.CHINA)) {
@Override
public Date parse(String text) {
LocalDate localDate = LocalDate.parse(text, dateTimeFormatter);
return Date.from(localDate.atStartOfDay(ZONE_ID).toInstant());
}
},
/**
* 格式yyyyMMdd
*/
YYYYMMDD_FORMATTER(DateTimeFormatter.ofPattern("yyyyMMdd", Locale.CHINA)) {
@Override
public Date parse(String text) {
LocalDateTime localDateTime = LocalDateTime.parse(text, dateTimeFormatter);
return Date.from(localDateTime.atZone(ZONE_ID).toInstant());
}
},
/**
* 格式yyyyMMddHHmmss
*/
YYYYMMDDHHMMSS_FORMATTER(DateTimeFormatter.ofPattern("yyyyMMddHHmmss", Locale.CHINA)) {
@Override
public Date parse(String text) {
LocalDateTime localDateTime = LocalDateTime.parse(text, dateTimeFormatter);
return Date.from(localDateTime.atZone(ZONE_ID).toInstant());
}
},
/**
* 格式yyyyMMdd_HHmmss
*/
YYYYMMDD_HHMMSS_FORMATTER(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss", Locale.CHINA)) {
@Override
public Date parse(String text) {
LocalDateTime localDateTime = LocalDateTime.parse(text, dateTimeFormatter);
return Date.from(localDateTime.atZone(ZONE_ID).toInstant());
}
};
protected DateTimeFormatter dateTimeFormatter;
private DateFormatter(DateTimeFormatter dateTimeFormatter) {
this.dateTimeFormatter = dateTimeFormatter;
}
public DateTimeFormatter getDateTimeFormatter() {
return dateTimeFormatter;
}
public abstract Date parse(String text);
}
}
This diff is collapsed.
package cn.spatiotemporal.core.utils;
import java.util.List;
import java.util.Map;
/**
* @ClassName: Pack
* @Description: protostuff pack
* @date 2020年1月11日 上午10:44:56
*
* @author Q.JI
* @version
* @since JDK 1.8
*/
public class Pack {
List<?> list;
Map<?, ?> map;
/**
* @return the list
*/
public List<?> getList() {
return list;
}
/**
* @param list the list to set
*/
public void setList(List<?> list) {
this.list = list;
}
/**
* @return the map
*/
public Map<?, ?> getMap() {
return map;
}
/**
* @param map the map to set
*/
public void setMap(Map<?, ?> map) {
this.map = map;
}
}
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment