1、SFTP文件上次工具类
<!--sftp jsch-->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.entity.ContentType;
import org.springframework.mock.web.MockMultipartFile;
import java.io.*;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Vector;
public class SFTPUtil {
private ChannelSftp sftp;
private Session session;
/**
* FTP 登录用户名
*/
private String username;
/**
* FTP 登录密码
*/
private String password;
/**
* 私钥
*/
private String privateKey;
/**
* FTP 服务器地址IP地址
*/
private String host;
/**
* FTP 端口
*/
private int port;
/**
* 构造基于密码认证的sftp对象
*
* @param username
* @param password
* @param host
* @param port
*/
public SFTPUtil(String username, String password, String host, int port) {
this.username = username;
this.password = password;
this.host = host;
this.port = port;
}
/**
* 构造基于秘钥认证的sftp对象
*
* @param username
* @param host
* @param port
* @param privateKey
*/
public void SFTPUtil(String username, String host, int port, String privateKey) {
this.username = username;
this.host = host;
this.port = port;
this.privateKey = privateKey;
}
public void SFTPUtil() {
}
/**
* 连接sftp服务器
*
* @throws Exception
*/
public void login() {
try {
JSch jsch = new JSch();
if (privateKey != null) {
jsch.addIdentity(privateKey);// 设置私钥
log.info("sftp connect,path of private key file:{}", privateKey);
}
log.info("sftp connect by host:{} username:{}", host, username);
session = jsch.getSession(username, host, port);
log.info("Session is build");
if (password != null) {
session.setPassword(password);
}
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
log.info("Session is connected");
Channel channel = session.openChannel("sftp");
channel.connect();
log.info("channel is connected");
sftp = (ChannelSftp) channel;
log.info(String.format("sftp server host:[%s] port:[%s] is connect successfull", host, port));
} catch (JSchException e) {
log.error("Cannot connect to specified sftp server : {}:{} \n Exception message is: {}", new Object[]{host, port, e.getMessage()});
}
}
/**
* 关闭连接 server
*/
public void logout() {
if (sftp != null) {
if (sftp.isConnected()) {
sftp.disconnect();
log.info("sftp is closed already");
}
}
if (session != null) {
if (session.isConnected()) {
session.disconnect();
log.info("sshSession is closed already");
}
}
}
/**
* 将输入流的数据上传到sftp作为文件
*
* @param directory 上传到该目录
* @param sftpFileName sftp端文件名
* @param input 输入流
* @throws SftpException
* @throws Exception
*/
public void upload(String directory, String sftpFileName, InputStream input) throws SftpException {
try {
sftp.cd(directory);
} catch (SftpException e) {
log.warn("directory is not exist");
sftp.mkdir(directory);
sftp.cd(directory);
}
sftp.put(input, sftpFileName);
log.info("file:{} is upload successful", sftpFileName);
}
/**
* 上传单个文件
*
* @param directory 上传到sftp目录
* @param uploadFile 要上传的文件,包括路径
* @throws FileNotFoundException
* @throws SftpException
* @throws Exception
*/
public void upload(String directory, String uploadFile) throws FileNotFoundException, SftpException {
File file = new File(uploadFile);
upload(directory, file.getName(), new FileInputStream(file));
}
/**
* 将byte[]上传到sftp,作为文件。注意:从String生成byte[]是,要指定字符集。
*
* @param directory 上传到sftp目录
* @param sftpFileName 文件在sftp端的命名
* @param byteArr 要上传的字节数组
* @throws SftpException
* @throws Exception
*/
public void upload(String directory, String sftpFileName, byte[] byteArr) throws SftpException {
upload(directory, sftpFileName, new ByteArrayInputStream(byteArr));
}
/**
* 将字符串按照指定的字符编码上传到sftp
*
* @param directory 上传到sftp目录
* @param sftpFileName 文件在sftp端的命名
* @param dataStr 待上传的数据
* @param charsetName sftp上的文件,按该字符编码保存
* @throws UnsupportedEncodingException
* @throws SftpException
* @throws Exception
*/
public void upload(String directory, String sftpFileName, String dataStr, String charsetName) throws UnsupportedEncodingException, SftpException {
upload(directory, sftpFileName, new ByteArrayInputStream(dataStr.getBytes(charsetName)));
}
/**
* 下载文件
*
* @param directory 下载目录
* @param downloadFile 下载的文件
* @param saveFile 存在本地的路径
* @throws SftpException
* @throws FileNotFoundException
* @throws Exception
*/
public void download(String directory, String downloadFile, String saveFile) throws SftpException, FileNotFoundException {
if (directory != null && !"".equals(directory)) {
sftp.cd(directory);
}
File file = new File(saveFile);
sftp.get(downloadFile, new FileOutputStream(file));
log.info("file:{} is download successful", downloadFile);
}
/**
* 下载文件
*
* @param directory 下载目录
* @param downloadFile 下载的文件名
* @return 字节数组
* @throws SftpException
* @throws IOException
* @throws Exception
*/
public byte[] download(String directory, String downloadFile) throws SftpException, IOException {
if (directory != null && !"".equals(directory)) {
sftp.cd(directory);
}
InputStream is = sftp.get(downloadFile);
byte[] fileData = IOUtils.toByteArray(is);
log.info("file:{} is download successful", downloadFile);
return fileData;
}
/**
* 删除文件
*
* @param directory 要删除文件所在目录
* @param deleteFile 要删除的文件
* @throws SftpException
* @throws Exception
*/
public void delete(String directory, String deleteFile) throws SftpException {
sftp.cd(directory);
sftp.rm(deleteFile);
}
/**
* 列出目录下的文件
*
* @param directory 要列出的目录
* @return
* @throws SftpException
*/
public Vector<?> listFiles(String directory) throws SftpException {
return sftp.ls(directory);
}
public ArrayList<String> listFile(String dir) throws SftpException{
ArrayList<String> files = new ArrayList<String>();
sftp.cd(dir);
Vector<String> lss = sftp.ls("*");
for (int i = 0; i < lss.size(); i++)
{
Object obj = lss.elementAt(i);
if (obj instanceof com.jcraft.jsch.ChannelSftp.LsEntry)
{
ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) obj;
if (true && !entry.getAttrs().isDir())
{
files.add(entry.getFilename());
}
if (true && entry.getAttrs().isDir())
{
if (!entry.getFilename().equals(".") && !entry.getFilename().equals(".."))
{
files.add(entry.getFilename());
}
}
}
}
return files;
}
//上传文件测试
public static void main(String[] args) throws SftpException {
// SFTPUtil sftp = new SFTPUtil("root", "li983798.", "47.102.142.218", 22);
SFTPUtil sftp = new SFTPUtil("hzwq", "hzwq2021", "192.168.15.71", 22);
// File file = new File("F:\\aeac.tar.gz");
InputStream is = null;
System.out.println("file.exists()");
try {
sftp.login();
MockMultipartFile multipartFile = null;
try (InputStream inputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\lixin\\Desktop\\x1.zip"))) {
multipartFile = new MockMultipartFile(
"test.zip", "test.zip", ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
}
//上传文件
sftp.upload("/home/hzwq/C_MODEL/test/20220331","计算模型.zip",multipartFile.getInputStream());
System.out.println("上传成功");
//下载文件
//byte[] download = sftp.download("/usr/local", "xxx.zip");
//列出当前目录下的所有文件目录或文件
// ArrayList<String> strings = sftp.listFile("/usr/local/zookeeper");
// System.out.println(strings);
// Vector files = sftp.listFiles("/usr/local/zookeeper");
// Iterator iterator = files.iterator();
// List<String> fileList = new ArrayList<>();
// while (iterator.hasNext()) {
// ChannelSftp.LsEntry file = (ChannelSftp.LsEntry) iterator.next();
// //文件名称
// String fileName = file.getFilename();
// fileList.add(fileName);
// }
// System.out.println("--------------------------------------");
// System.out.println(fileList);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
sftp.logout();
}
}
}
2、ZIP工具类
<!--压缩或解压缩zip 防止会出现中文乱码问题-->
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.9.4</version>
</dependency>
<!-- 解压缩 https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
</dependency>
import cn.hutool.core.util.CharsetUtil;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;
import java.io.*;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.*;
import java.util.*;
import java.util.zip.ZipInputStream;
/**
* @ClassName ZipUtil
* @Description 压缩或解压缩zip:由于直接使用java.util.zip工具包下的类,会出现中文乱码问题,所以使用ant.jar中的org.apache.tools.zip下的工具类
* @Author
* @Date 2020/3/8 11:30
* @Version 1.0
*/
public class ZipUtil {
/**
* 直接替换zip中的文件
*/
public void replace() {
Path myFilePath = Paths.get("C:\\Users\\lixin\\Desktop\\xxx.docx");
Path zipFilePath = Paths.get("C:\\Users\\lixin\\Desktop\\test2.zip");
try (FileSystem fs = FileSystems.newFileSystem(zipFilePath, null)) {
Path fileInsideZipPath = fs.getPath("new 2.txt");
System.out.println(fileInsideZipPath.toAbsolutePath());
Files.copy(myFilePath, fileInsideZipPath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean add(String zipUrl, String fromUrl, String toUrl) throws IOException {
zipUrl = "D:/temp/playbook_1936_拍照商品照片.zip";
fromUrl = "C:/图片/000.png";
toUrl = "/33/44/000.png";
Map<String, String> env = new HashMap<>();
env.put("create", "true");
//使用语法定位文件系统
//在java.net.JarURLConnection中定义
Path path = Paths.get(zipUrl);
URI uri = URI.create("jar:" + path.toUri());
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
Path externalTxtFile = Paths.get(fromUrl);
Path pathInZipfile = zipfs.getPath(toUrl);
//将文件复制到zip文件中
Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 输出压缩文件中的名称
*/
public static void fileExist() {
ZipInputStream in = null;
java.util.zip.ZipEntry entry = null;
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(new File("E:\\gd\\xxx.zip"));
BufferedInputStream bis = new BufferedInputStream(inputStream);
//String code = CodeDetector.getEncode(bis, false);
in = new ZipInputStream(bis, CharsetUtil.CHARSET_GBK);
while ((entry = in.getNextEntry()) != null) {
if (entry.isDirectory()) {
System.out.println("文件夹" + entry.getName());
} else {
//压缩文件夹中的文件名称
System.out.println("文件名 " + entry.getName());
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// tar压缩
public void tar() throws IOException {
//源文件或目录
File srcDir = new File("/test");
//目标文件
String targetFile = "/test.tar";
try (TarArchiveOutputStream tos = new TarArchiveOutputStream(
new FileOutputStream(targetFile))) {
tarRecursive(tos, srcDir, "");
}
}
/**
* 递归压缩目录下的文件和目录
*
* @param tos
* @param srcFile
* @param basePath
* @throws IOException
*/
private void tarRecursive(TarArchiveOutputStream tos, File srcFile, String basePath) throws IOException {
if (srcFile.isDirectory()) {
File[] files = srcFile.listFiles();
String nextBasePath = basePath + srcFile.getName() + "/";
if (ArrayUtils.isEmpty(files)) {
// 空目录
TarArchiveEntry entry = new TarArchiveEntry(srcFile, nextBasePath);
tos.putArchiveEntry(entry);
tos.closeArchiveEntry();
} else {
for (File file : files) {
tarRecursive(tos, file, nextBasePath);
}
}
} else {
TarArchiveEntry entry = new TarArchiveEntry(srcFile, basePath + srcFile.getName());
tos.putArchiveEntry(entry);
FileUtils.copyFile(srcFile, tos);
tos.closeArchiveEntry();
}
}
// tar解压
public void untar() throws IOException {
InputStream is = new FileInputStream("/test.tar");
String outPath = "/test";
try (TarArchiveInputStream tis = new TarArchiveInputStream(is)) {
TarArchiveEntry nextEntry;
while ((nextEntry = tis.getNextTarEntry()) != null) {
String name = nextEntry.getName();
File file = new File(outPath, name);
//如果是目录,创建目录
if (nextEntry.isDirectory()) {
file.mkdir();
} else {
//文件则写入具体的路径中
FileUtils.copyToFile(tis, file);
file.setLastModified(nextEntry.getLastModifiedDate().getTime());
}
}
}
}
/**
* 解压缩.zip文件
*
* @param zipFile 压缩文件路径
* @param targetDir 要解压存放的目录
* @throws IOException
* @throws ArchiveException
*/
public static void decompressor(String zipFile, String targetDir) throws IOException, ArchiveException {
File archiveFile = new File(zipFile);
// 文件不存在,跳过
if (!archiveFile.exists())
return;
ArchiveInputStream input = new ArchiveStreamFactory().createArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile)));
ArchiveEntry entry = null;
while ((entry = input.getNextEntry()) != null) {
if (!input.canReadEntryData(entry)) {
// log something?
continue;
}
String name = Paths.get(targetDir, entry.getName()).toString();
File f = new File(name);
if (entry.isDirectory()) {
if (!f.isDirectory() && !f.mkdirs()) {
throw new IOException("failed to create directory " + f);
}
} else {
File parent = f.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException("failed to create directory " + parent);
}
try (OutputStream o = Files.newOutputStream(f.toPath())) {
IOUtils.copy(input, o);
}
}
}
input.close();
}
/**
* 解压 zip 文件
*
* @param zipFile zip 压缩文件
* @param destDir zip 压缩文件解压后保存的目录
* @return 返回 zip 压缩文件里的文件名的 list
* @throws Exception
*/
public static List<String> unZip(File zipFile, String destDir) throws Exception {
// 如果 destDir 为 null, 空字符串, 或者全是空格, 则解压到压缩文件所在目录
if (StringUtils.isBlank(destDir)) {
destDir = zipFile.getParent();
}
destDir = destDir.endsWith(File.separator) ? destDir : destDir + File.separator;
ZipArchiveInputStream is = null;
List<String> fileNames = new ArrayList<String>();
try {
is = new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile), BUFFER_SIZE));
ZipArchiveEntry entry = null;
while ((entry = is.getNextZipEntry()) != null) {
fileNames.add(entry.getName());
if (entry.isDirectory()) {
File directory = new File(destDir, entry.getName());
directory.mkdirs();
} else {
OutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(new File(destDir, entry.getName())), BUFFER_SIZE);
IOUtils.copy(is, os);
} finally {
IOUtils.closeQuietly(os);
}
}
}
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
IOUtils.closeQuietly(is);
}
return fileNames;
}
/**
* @param zip 压缩目的地址
* @param srcFiles 压缩的源文件
* @return void
* @Author AlphaJunS
* @Date 11:32 2020/3/8
* @Description
*/
public static void zipFile(String zip, File[] srcFiles) {
try {
if (zip.endsWith(".zip") || zip.endsWith(".ZIP")) {
FileOutputStream fos = new FileOutputStream(new File(zip));
ZipOutputStream _zipOut = new ZipOutputStream(fos);
_zipOut.setEncoding("GBK");
for (File _f : srcFiles) {
handlerFile(zip, _zipOut, _f, "");
}
fos.close();
_zipOut.close();
} else {
System.out.println("target file[" + zip + "] is not .zip type file");
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
/**
* @param zip 压缩的目的地址
* @param zipOut
* @param srcFile 被压缩的文件信息
* @param path 在zip中的相对路径
* @return void
* @Author
* @Description
*/
private static void handlerFile(String zip, ZipOutputStream zipOut, File srcFile, String path) throws IOException {
System.out.println(" begin to compression file[" + srcFile.getName() + "]");
if (!"".equals(path) && !path.endsWith(File.separator)) {
path += File.separator;
}
if (!srcFile.getPath().equals(zip)) {
if (srcFile.isDirectory()) {
File[] _files = srcFile.listFiles();
if (_files.length == 0) {
zipOut.putNextEntry(new ZipEntry(path + srcFile.getName() + File.separator));
zipOut.closeEntry();
} else {
for (File _f : _files) {
handlerFile(zip, zipOut, _f, path + srcFile.getName());
}
}
} else {
InputStream _in = new FileInputStream(srcFile);
zipOut.putNextEntry(new ZipEntry(path + srcFile.getName()));
int len = 0;
byte[] _byte = new byte[1024];
while ((len = _in.read(_byte)) > 0) {
zipOut.write(_byte, 0, len);
}
_in.close();
zipOut.closeEntry();
}
}
}
/**
* @param zipPath 待解压缩的ZIP文件名
* @param descDir 目标目录
* @return java.util.List<java.io.File>
* @Author AlphaJunS
* @Description 解压缩ZIP文件,将ZIP文件里的内容解压到targetDIR目录下
*/
public static List<File> unzipFile(String zipPath, String descDir) {
return unzipFile(new File(zipPath), descDir);
}
/**
* @param zipFile 解压缩文件
* @param descDir 压缩的目标地址,如:D:\\测试 或 /mnt/d/测试
* @return java.util.List<java.io.File>
* @Author
* @Description 对.zip文件进行解压缩 默认只支持GBK格式的文件
*/
public static List<File> unzipFile(File zipFile, String descDir) {
List<File> _list = new ArrayList<File>();
try {
ZipFile _zipFile = new ZipFile(zipFile, "GBK");
for (Enumeration entries = _zipFile.getEntries(); entries.hasMoreElements(); ) {
ZipEntry entry = (ZipEntry) entries.nextElement();
File _file = new File(descDir + File.separator + entry.getName());
if (entry.isDirectory()) {
_file.mkdirs();
} else {
File _parent = _file.getParentFile();
if (!_parent.exists()) {
_parent.mkdirs();
}
InputStream _in = _zipFile.getInputStream(entry);
OutputStream _out = new FileOutputStream(_file);
int len = 0;
byte[] _byte = new byte[1024];
while ((len = _in.read(_byte)) > 0) {
_out.write(_byte, 0, len);
}
_in.close();
_out.flush();
_out.close();
_list.add(_file);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return _list;
}
/**
* @param delpath 要删除的文件夹或文件路径
* @return void
* @Author AlphaJunS
* @Description 对临时生成的文件夹和文件夹下的文件进行删除
*/
public static void deletefile(String delpath) {
try {
File file = new File(delpath);
if (!file.isDirectory()) {
file.delete();
} else if (file.isDirectory()) {
String[] fileList = file.list();
for (int i = 0; i < fileList.length; i++) {
File delfile = new File(delpath + File.separator + fileList[i]);
if (!delfile.isDirectory()) {
delfile.delete();
} else if (delfile.isDirectory()) {
deletefile(delpath + File.separator + fileList[i]);
}
}
file.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
//##############################################################原生zip
private static final int BUFFER_SIZE = 2 * 1024;
/**
* 压缩成ZIP 方法1
*
* @param srcDir 压缩文件夹路径
* @param out 压缩文件输出流
* @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure)
throws RuntimeException {
long start = System.currentTimeMillis();
java.util.zip.ZipOutputStream zos = null;
try {
zos = new java.util.zip.ZipOutputStream(out);
File sourceFile = new File(srcDir);
compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
long end = System.currentTimeMillis();
//log.info("压缩完成,耗时:{}" + (end - start) +" ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
} finally {
if (zos != null) {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 压缩成ZIP 方法2
*
* @param srcFiles 需要压缩的文件列表
* @param out 压缩文件输出流
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip(List<File> srcFiles, OutputStream out) throws RuntimeException {
long start = System.currentTimeMillis();
java.util.zip.ZipOutputStream zos = null;
try {
zos = new java.util.zip.ZipOutputStream(out);
for (File srcFile : srcFiles) {
byte[] buf = new byte[BUFFER_SIZE];
zos.putNextEntry(new java.util.zip.ZipEntry(srcFile.getName()));
int len;
FileInputStream in = new FileInputStream(srcFile);
while ((len = in.read(buf)) != -1) {
zos.write(buf, 0, len);
}
zos.closeEntry();
in.close();
}
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) + " ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
} finally {
if (zos != null) {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 递归压缩方法
*
* @param sourceFile 源文件
* @param zos zip输出流
* @param name 压缩后的名称
* @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws Exception
*/
public static void compress(File sourceFile, java.util.zip.ZipOutputStream zos, String name,
boolean KeepDirStructure) throws Exception {
byte[] buf = new byte[BUFFER_SIZE];
if (sourceFile.isFile()) {
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
zos.putNextEntry(new java.util.zip.ZipEntry(name));
// copy文件到zip输出流中
int len;
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1) {
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
} else {
File[] listFiles = sourceFile.listFiles();
if (listFiles == null || listFiles.length == 0) {
// 需要保留原来的文件结构时,需要对空文件夹进行处理
if (KeepDirStructure) {
// 空文件夹的处理
zos.putNextEntry(new java.util.zip.ZipEntry(name + "/"));
// 没有文件,不需要文件的copy
zos.closeEntry();
}
} else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
if (KeepDirStructure) {
// 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
} else {
compress(file, zos, file.getName(), KeepDirStructure);
}
}
}
}
}
}
3、list转换
public class ObjectToBeanUtils {
/*
* Object对象转换为List<T>
*/
public static <t> List<t> objtolist(Object obj, Class<t> cla) throws Exception {
List<t> list = new ArrayList<t>();
if (obj instanceof ArrayList<?>) {
for (Object o : (List<?>) obj) {
list.add(cla.cast(o));
}
return list;
}
return null;
}
/**
* 把List<Object[]>转换成List<T>
*/
public static <T> List<T> objectToBean(List<Object[]> objList, Class<T> clz) throws Exception {
if (objList == null || objList.size() == 0) {
return null;
}
Class<?>[] cz = null;
Constructor<?>[] cons = clz.getConstructors();
for (Constructor<?> ct : cons) {
Class<?>[] clazz = ct.getParameterTypes();
if (objList.get(0).length == clazz.length) {
cz = clazz;
break;
}
}
List<T> list = new ArrayList<T>();
for (Object[] obj : objList) {
Constructor<T> cr = clz.getConstructor(cz);
list.add(cr.newInstance(obj));
}
return list;
}
}
4、HiveDbUtil 根据类获取其指定的字段信息
import lombok.Data;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Optional;
/**
* @author lixing
* @date 2021/9/3 10:51
*/
@Service
public class HiveDbUtil {
static final Integer defaultLimitcount = 1000;
/**
* 查询表名
* @param cls
* @return
*/
public static String getTableName(Class cls) {
// boolean annotationPresent = cls.isAnnotationPresent(Table.class); 判断person对象上是否有Table注解
// Table infoAnno = (Table) cls.getAnnotation(Table.class);//获取该对象上Table类型的注解
// Annotation[] annotations = cls.getAnnotations();//返回所有的注解
Annotation annotation = cls.getAnnotation(Table.class);
Assert.notNull(annotation, cls.toString() + "未设置@Table注释");
Table table = (Table) annotation;
return table.name();
}
/**
* 查询表的主键名
* @param cls
* @return
*/
public static String getPrimaryKey(Class cls) {
Field[] fields = cls.getDeclaredFields();
String keyName = null;
for (Field field : fields) {
if (field.getAnnotation(Id.class) != null && field.getAnnotation(Column.class) != null) {
keyName = field.getAnnotation(Column.class).name();
break;
}
}
Assert.notNull(cls.getName(), cls.toString() + "未设置@Id @Column注解");
return keyName;
}
/**
* 根据实体类的名称查询出真实的字段名
* @param cls
* @param name
* @return
*/
public static String getColumnName(Class cls, String name) {
Field[] fields = cls.getDeclaredFields();
String columnName = null;
for (Field field : fields) {
if (name.equals(field.getName()) && field.getAnnotation(Column.class) != null) {
columnName = field.getAnnotation(Column.class).name();
break;
}
}
Assert.notNull(columnName, cls.toString() + "未找到" + name + "对应的字段");
return columnName;
}
/**
* 组合得到通过主键查询数据
* @param cls
* @return
*/
@SuppressWarnings("all")//抑制编译器产生警告信息。
public static String getFindByIdSql(Class cls) {
return String.format("select * from %s where %s=?", getTableName(cls), getPrimaryKey(cls));
}
/**
* all to suppress all warnings (抑制所有警告)
* boxing to suppress warnings relative to boxing/unboxing operations(抑制装箱、拆箱操作时候的警告)
* cast to suppress warnings relative to cast operations (抑制映射相关的警告)
* dep-ann to suppress warnings relative to deprecated annotation(抑制启用注释的警告)
* deprecation to suppress warnings relative to deprecation(抑制过期方法警告)
* fallthrough to suppress warnings relative to missing breaks in switch statements(抑制确在switch中缺失breaks的警告)
* finally to suppress warnings relative to finally block that don’t return (抑制finally模块没有返回的警告)
* hiding to suppress warnings relative to locals that hide variable()
* incomplete-switch to suppress warnings relative to missing entries in a switch statement (enum case)(忽略没有完整的switch语句)
* nls to suppress warnings relative to non-nls string literals(忽略非nls格式的字符)
* null to suppress warnings relative to null analysis(忽略对null的操作)
* rawtypes to suppress warnings relative to un-specific types when using generics on class params(使用generics时忽略没有指定相应的类型)
* restriction to suppress warnings relative to usage of discouraged or forbidden references
* serial to suppress warnings relative to missing serialVersionUID field for a serializable class(忽略在serializable类中没有声明serialVersionUID变量)
* static-access to suppress warnings relative to incorrect static access(抑制不正确的静态访问方式警告)
* synthetic-access to suppress warnings relative to unoptimized access from inner classes(抑制子类没有按最优方法访问内部类的警告)
* unchecked to suppress warnings relative to unchecked operations(抑制没有进行类型检查操作的警告)
* unqualified-field-access to suppress warnings relative to field access unqualified (抑制没有权限访问的域的警告)
* unused to suppress warnings relative to unused code (抑制没被使用过的代码的警告)
*/
}
5、HttpUtil请求
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
/**
* java原生HttpURLConnection
* @author lixing
* @date 2021/9/17 9:38
*/
@Slf4j
public class HttpUtil {
/**
* 向指定URL发送GET方法的请求
*
* @param httpurl 请求参数用?拼接在url后边,请求参数应该是 name1=value1&name2=value2 的形式。
* @return result 所代表远程资源的响应结果
*/
public static String doGet(String httpurl) {
HttpURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = null;// 返回结果字符串
try {
// 创建远程url连接对象
URL url = new URL(httpurl);
// 通过远程url连接对象打开一个连接,强转成httpURLConnection类
connection = (HttpURLConnection) url.openConnection();
// 设置连接方式:get
connection.setRequestMethod("GET");
// 设置连接主机服务器的超时时间:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取远程返回的数据时间:60000毫秒
connection.setReadTimeout(60000);
// 发送请求
connection.connect();
// 通过connection连接,获取输入流
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 封装输入流is,并指定字符集
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
// 存放数据
StringBuffer sbf = new StringBuffer();
String temp = null;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
connection.disconnect();// 关闭远程连接
}
return result;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param httpUrl 发送请求的 URL
* @param param 请求参数应该是{"key":"==g43sEvsUcbcunFv3mHkIzlHO4iiUIT R7WwXuSVKTK0yugJnZSlr6qNbxsL8OqCUAFyCDCoRKQ882m6cTTi0q9uCJsq JJvxS+8mZVRP/7lWfEVt8/N9mKplUA68SWJEPSXyz4MDeFam766KEyvqZ99d"}的形式。
* @return 所代表远程资源的响应结果
*/
public static String doPost(String httpUrl, String param) {
HttpURLConnection connection = null;
InputStream is = null;
OutputStream os = null;
BufferedReader br = null;
String result = null;
try {
URL url = new URL(httpUrl);
// 通过远程url连接对象打开连接
connection = (HttpURLConnection) url.openConnection();
// 设置连接请求方式
connection.setRequestMethod("POST");
// 设置连接主机服务器超时时间:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取主机服务器返回数据超时时间:60000毫秒
connection.setReadTimeout(60000);
// 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
connection.setDoOutput(true);
// 默认值为:true,当前向远程服务读取数据时,设置为true,该参数可有可无
connection.setDoInput(true);
// 设置传入参数的格式:请求参数应该是 name1=value1&name2=value2 的形式。
connection.setRequestProperty("Content-Type", "application/json");
// 设置鉴权信息:Authorization: Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0
//connection.setRequestProperty("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
// 通过连接对象获取一个输出流
os = connection.getOutputStream();
// 通过输出流对象将参数写出去/传输出去,它是通过字节数组写出的
os.write(param.getBytes());
// 通过连接对象获取一个输入流,向远程读取
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 对输入流对象进行包装:charset根据工作项目组的要求来设置
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sbf = new StringBuffer();
String temp = null;
// 循环遍历一行一行读取数据
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != os) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 断开与远程地址url的连接
connection.disconnect();
}
return result;
}
/**
* @param httpUrl 请求的url
* @param param form表单的参数(key,value形式)
* @return
*/
public static String doPostForm(String httpUrl, Map param) {
HttpURLConnection connection = null;
InputStream is = null;
OutputStream os = null;
BufferedReader br = null;
String result = null;
try {
URL url = new URL(httpUrl);
// 通过远程url连接对象打开连接
connection = (HttpURLConnection) url.openConnection();
// 设置连接请求方式
connection.setRequestMethod("POST");
// 设置连接主机服务器超时时间:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取主机服务器返回数据超时时间:60000毫秒
connection.setReadTimeout(60000);
// 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
connection.setDoOutput(true);
// 默认值为:true,当前向远程服务读取数据时,设置为true,该参数可有可无
connection.setDoInput(true);
// 设置传入参数的格式:请求参数应该是 name1=value1&name2=value2 的形式。
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// 设置鉴权信息:Authorization: Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0
//connection.setRequestProperty("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
// 通过连接对象获取一个输出流
os = connection.getOutputStream();
// 通过输出流对象将参数写出去/传输出去,它是通过字节数组写出的(form表单形式的参数实质也是key,value值的拼接,类似于get请求参数的拼接)
os.write(createLinkString(param).getBytes());
// 通过连接对象获取一个输入流,向远程读取
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 对输入流对象进行包装:charset根据工作项目组的要求来设置
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sbf = new StringBuffer();
String temp = null;
// 循环遍历一行一行读取数据
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != os) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 断开与远程地址url的连接
connection.disconnect();
}
return result;
}
/**
* 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
*
* @param params 需要排序并参与字符拼接的参数组
* @return 拼接后字符串
*/
public static String createLinkString(Map<String, String> params) {
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
StringBuilder prestr = new StringBuilder();
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符
prestr.append(key).append("=").append(value);
} else {
prestr.append(key).append("=").append(value).append("&");
}
}
return prestr.toString();
}
public static void main(String[] args) {
String url = "http://localhost:8082/api/conf/findConfList?type=1";
String getResult = HttpUtil.doGet(url);
System.out.println(getResult);
url = "http://localhost:8082/api/core/login";
JSONObject json = new JSONObject();
json.put("key", "==g43sEvsUcbcunFv3mHkIzlHO4iiUIT R7WwXuSVKTK0yugJnZSlr6qNbxsL8OqCUAFyCDCoRKQ882m6cTTi0q9uCJsq JJvxS+8mZVRP/7lWfEVt8/N9mKplUA68SWJEPSXyz4MDeFam766KEyvqZ99d");
String postResult = HttpUtil.doPost(url, json.toJSONString());
System.out.println(postResult);
url = "http://localhost:8082/api/test/testSendForm";
Map<String, String> map = new HashMap<>();
map.put("name", "测试表单请求");
String formResult = HttpUtil.doPostForm(url, map);
System.out.println(formResult);
}
}
6、自定义注解
import java.lang.annotation.*;
//@Documented:注解信息会被添加到Java文档中
//@Retention:注解的生命周期,表示注解会被保留到什么阶段,可以选择编译阶段、类加载阶段,或运行阶段
//@Target:注解作用的位置,ElementType.METHOD表示该注解仅能作用于方法上
/**
* Redis分布式锁注解,用于注释方法,表示该方法需要持有锁的人才能调用
* @author lixing
* @date 2021/9/15 9:19
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface RedisLock {
/**
* redis的key,留空的话为类名加方法名
* @return
*/
String key() default "";
/**
* 锁持有时间
* @return
*/
long timeout() default 300;
/**
* 是否在操作后立即释放锁
* @return
*/
boolean releaseOnSuccess() default false;
/**
* 如果未获得锁,则执行该方法回调
* @return
*/
Class<? extends RedisLockCallback> callback() default RedisLockCallback.class;
}
public interface RedisLockCallback {
default Object failback(Object ... obj){
return "cannot get the lock";
}
}
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Redis Lock的AOP实现类
*
* @author lixing
* @date 2021/9/15 9:36
*/
@Aspect
@Component
public class RedisLockAspect {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private ApplicationContext applicationContext;
/**
* 切点,拦截带有@RedisLock的注解方法
*/
@Pointcut("@annotation(com.Utils.redisUtil.RedisLock)")
void cutPoint() {
}
;
/*@Before("cutPoint() && @annotation(RedisLock)")
public void advice(RedisLock lock) {
System.out.println("--- lock的内容为[" + lock.key() +lock.timeout() + "] ---");
}*/
/*@Before("cutPoint() && @annotation(RedisLock)")
public void advice(JoinPoint joinPoint, RedisLock logger) {
System.out.println("注解作用的方法名: " + joinPoint.getSignature().getName());
System.out.println("所在类的简单类名: " + joinPoint.getSignature().getDeclaringType().getSimpleName());
System.out.println("所在类的完整类名: " + joinPoint.getSignature().getDeclaringType());
System.out.println("目标方法的声明类型: " + Modifier.toString(joinPoint.getSignature().getModifiers()));
}*/
@Around("cutPoint()")
public Object around(ProceedingJoinPoint point) throws Throwable {
//获取当前请求对象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String urlStr = request.getRequestURL().toString();
String remoteUser = request.getRemoteUser();
// # 可以发挥反射的功能获取关于类的任何信息,例如获取类名如下
// String className = joinPoint.getTarget().getClass().getName();
// getSignature());是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
// 获取切入点方法的名字
// String methodName = joinPoint.getSignature().getName()
// 获取切入点方法的参数列表
// Object[] args = joinPoint.getArgs();
//返回结果
// Object result = point.proceed();
//获取类的字节码对象,通过字节码对象获取方法信息
Class<?> targetCls = point.getTarget().getClass();
Signature signature = point.getSignature();
//获取方法签名(通过此签名获取目标方法信息)
MethodSignature methodSignature = (MethodSignature) signature;
/*Method declaredMethod = targetCls.getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes());
RedisLock annotation = declaredMethod.getAnnotation(RedisLock.class);*/
Method method = methodSignature.getMethod();
//获取方法上的注解
RedisLock redisLock = method.getAnnotation(RedisLock.class);
String key = redisLock.key();
if (StringUtils.isEmpty(key)) {
String userId = "";
String paatId = "";
//获取方法的参数
for (Object arg : point.getArgs()) {
//User 可以自行替换
if (arg instanceof User) {
User user = (User) arg;
userId = String.valueOf(user.getId());
paatId = user.getName();
}
}
key = targetCls.getName() + "-" + method.getName() + "-" + paatId + userId;
}
//通过setnx设置值,如果值不存在,则获得锁
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(key, point.getThis().toString(), redisLock.timeout(), TimeUnit.MINUTES);
if (aBoolean) {
try {
//环绕通知=前置+目标方法执行+后置通知,proceed方法就是用于启动目标方法执行的
Object result = point.proceed();
return result;
} finally {
//如果设置删除操作完成后删除token,则删除key释放锁
if (redisLock.releaseOnSuccess()) {
redisTemplate.delete(key);
}
}
} else {
//查找错误处理器
RedisLockCallback redisLockCallback = applicationContext.getBean(redisLock.callback());
return redisLockCallback.failback(point.getArgs());
}
}
/*
public interface JoinPoint {
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
Object getThis(); //返回AOP代理对象,也就是com.sun.proxy.$Proxy18
Object getTarget(); //返回目标对象,一般我们都需要它或者(也就是定义方法的接口或类,为什么会是接口呢?这主要是在目标对象本身是动态代理的情况下,例如Mapper。所以返回的是定义方法的对象如aoptest.daoimpl.GoodDaoImpl或com.b.base.BaseMapper<T, E, PK>)
Object[] getArgs(); //返回被通知方法参数列表
Signature getSignature(); //返回当前连接点签名 其getName()方法返回方法的FQN,如void aoptest.dao.GoodDao.delete()或com.b.base.BaseMapper.insert(T)(需要注意的是,很多时候我们定义了子类继承父类的时候,我们希望拿到基于子类的FQN,这直接可拿不到,要依赖于AopUtils.getTargetClass(point.getTarget())获取原始代理对象,下面会详细讲解)
SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
String getKind(); //连接点类型
StaticPart getStaticPart(); //返回连接点静态部分
}
public interface ProceedingJoinPoint extends JoinPoint {
public Object proceed() throws Throwable;
public Object proceed(Object[] args) throws Throwable;
}
JoinPoint.StaticPart:提供访问连接点的静态部分,如被通知方法签名、连接点类型等:
public interface StaticPart {
Signature getSignature(); //返回当前连接点签名
String getKind(); //连接点类型
int getId(); //唯一标识
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
}*/
/**
* 根据方法和传入的参数获取请求参数
*/
private Object getParameter(Method method, Object[] args) {
List<Object> argList = new ArrayList<>();
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
//将RequestBody注解修饰的参数作为请求参数
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
if (requestBody != null) {
argList.add(args[i]);
}
//将RequestParam注解修饰的参数作为请求参数
RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
if (requestParam != null) {
Map<String, Object> map = new HashMap<>();
String key = parameters[i].getName();
if (!StringUtils.isEmpty(requestParam.value())) {
key = requestParam.value();
}
map.put(key, args[i]);
argList.add(map);
}
}
if (argList.size() == 0) {
return null;
} else if (argList.size() == 1) {
return argList.get(0);
} else {
return argList;
}
}
}
import java.lang.annotation.*;
/**
* 接口签名验证
* @author lixing
* @date 2021/9/15 10:30
*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SecuritySign {
/**
* 入参是否验证
* @return
*/
boolean isCheck() default true;
}
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
/**
* @author lixing
* @date 2021/9/15 10:32
*/
@Aspect
@Component
@Slf4j
public class SecuritySignAspect {
@Pointcut("@annotation(com.Utils.redisUtil.SecuritySign)")
void securitySignPointcut() {
}
@Around("securitySignPointcut()")
public Object doAround(ProceedingJoinPoint point) throws Throwable {
//接收到请求,记录请求内容
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
//记录请求内容
log.info("request url : ", request.getRequestURL().toString());
log.info("request method : ", request.getMethod());
log.info("request ip : ", request.getRemoteAddr());
//获取注解的属性值
SecuritySign securitySign = ((MethodSignature) point.getSignature()).getMethod().getAnnotation(SecuritySign.class);
if (securitySign.isCheck()) {
CommonResponse response = new CommonResponse();
HashMap<String, Object> requestParam = new HashMap<>();
Enumeration<String> enums = request.getParameterNames();
while (enums.hasMoreElements()) {
String paranName = enums.nextElement();
//通过参数名获取参数值
String parameterValue = request.getParameter(paranName);
requestParam.put(paranName, parameterValue);
}
//验证参数是否正确
if (requestParam == null || StringUtils.isEmpty(requestParam.get("appId"))) {
response = CommonResponse.fail();
return response;
}
//验证签名是否为空
if (requestParam == null || StringUtils.isEmpty(requestParam.get("sign"))) {
response = CommonResponse.fail();
return response;
}
}
Object object = point.proceed();
return object;
}
}
Q.E.D.