20240229
事务与代理对象
在java中,若@Transactional事务注解要生效,则被注解的方法需在代理对象内,对于service层中的接口实现类,不是代理对象,而service接口为代理对象,要使接口实现类的函数能使用事务,则需将该方法暴露在service接口中,并注入对应的service接口,例子如下:
//接口实现类
@Service
public class service1Impl implements Service1{
@Autowired
Service1 service1;
public void function1(){
int a = 1;
//此时需要执行事务的function2通过代理对象调用的,事务生效
service1.service2(a);
}
@Override
@Transactional
public void function2(int a){
System.out.println(a);
...执行数据库操作等
}
}
//接口
public interface Service1 {
public void function2(int a);//将实现类暴露在接口中
}
文件分块
将一个文件分块
public void testChunk() throws IOException {
//源文件
File sourceFile = new File("d:/TestBigFile/source/test1.mp4");
//存储分块的位置
String chunkPath = "d:/TestBigFile/chunk/";
File chunkFolder = new File(chunkPath);
if (!chunkFolder.exists()) {
chunkFolder.mkdirs();
}
//分块大小(minio合并时单块最小为5MB)
long chunkSize = 1024 * 1024 * 5;
//分块数量
long chunkNum = (long) Math.ceil(sourceFile.length() * 1.0 / chunkSize);
System.out.println("分块总数:"+chunkNum);
//缓冲区大小
byte[] b = new byte[1024];
//使用RandomAccessFile访问文件
RandomAccessFile raf_read = new RandomAccessFile(sourceFile, "r");
//分块
for (int i = 0; i < chunkNum; i++) {
//创建分块文件
File file = new File(chunkPath + i);
if(file.exists()){
file.delete();
}
boolean newFile = file.createNewFile();
if (newFile) {
//向分块文件中写数据
RandomAccessFile raf_write = new RandomAccessFile(file, "rw");
int len = -1;
while ((len = raf_read.read(b)) != -1) {
raf_write.write(b, 0, len);
//块的大小超过了约定的大小
if (file.length() >= chunkSize) {
break;
}
}
raf_write.close();
System.out.println("完成分块"+i);
}
}
raf_read.close();
}
合并分块
public void testMerge() throws IOException {
//块文件目录
File chunkFolder = new File("d:/TestBigFile/chunk/");
//原始文件
File originalFile = new File("d:/TestBigFile/source/test1.mp4");
//合并文件
File mergeFile = new File("d:/TestBigFile/source/test2.mp4");
if (mergeFile.exists()) {
mergeFile.delete();
}
//创建新的合并文件
mergeFile.createNewFile();
//用于写文件
RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw");
//指针指向文件顶端
raf_write.seek(0);
//缓冲区
byte[] b = new byte[1024];
//分块列表
File[] fileArray = chunkFolder.listFiles();
// 转成集合,便于排序
List<File> fileList = Arrays.asList(fileArray);
// 从小到大排序
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
return Integer.parseInt(o1.getName()) - Integer.parseInt(o2.getName());
}
});
//合并文件
for (File chunkFile : fileList) {
RandomAccessFile raf_read = new RandomAccessFile(chunkFile, "rw");
int len = -1;
while ((len = raf_read.read(b)) != -1) {
raf_write.write(b, 0, len);
}
raf_read.close();
}
raf_write.close();
}
minio初始化
static MinioClient minioClient =
MinioClient.builder()
.endpoint("http://127.0.0.1:9000")
.credentials("minioadmin", "minioadmin")
.build();
将分块上传到minio(上传的为上述已分块的文件分块,共7块)
public void chunkUpload() throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
String filePath = "d:/TestBigFile/chunk/";
for(int i = 0; i < 7; i++){
//文件信息
UploadObjectArgs testbucket = UploadObjectArgs.builder()
.bucket("testbucket")
.object("chunk/" + i)//添加子目录
.filename(filePath + i)
.build();
//上传文件
minioClient.uploadObject(testbucket);
System.out.println("分块" + i + "上传成功");
}
}
将minio上的分块合并
public void MergeMinio() throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
//获取各个分块
List<ComposeSource> list = new ArrayList<>();
for(int i = 0; i < 7; i++){
ComposeSource composeSource = ComposeSource.builder()
.bucket("testbucket")
.object("chunk/" + i)
.build();
list.add(composeSource);
}
ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder()
.bucket("testbucket")
.object("test1.mp4")
.sources(list)//分块列表
.build();
//执行合并
minioClient.composeObject(composeObjectArgs);
}
