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); }