Преглед изворни кода

修正多线程上传的实现

zhourui пре 5 година
родитељ
комит
1923ec08a0

+ 94 - 54
o2server/x_base_core_project/src/main/java/com/x/base/core/entity/StorageObject.java

@@ -35,17 +35,14 @@ public abstract class StorageObject extends SliceJpaObject {
 
 	private static FileSystemManager FILESYSTEMANAGERINSTANCE;
 
-	private FileSystemManager getFileSystemManager() throws Exception {
+	private synchronized FileSystemManager getFileSystemManager() throws Exception {
 		if (FILESYSTEMANAGERINSTANCE == null) {
-			synchronized (StorageObject.class) {
-				if (FILESYSTEMANAGERINSTANCE == null) {
-					StandardFileSystemManager fs = new StandardFileSystemManager();
-					fs.setFilesCache(new NullFilesCache());
-					fs.setCacheStrategy(CacheStrategy.ON_RESOLVE);
-					fs.init();
-					FILESYSTEMANAGERINSTANCE = fs;
-				}
-			}
+			StandardFileSystemManager fs = new StandardFileSystemManager();
+			fs.setFilesCache(new NullFilesCache());
+			fs.setCacheStrategy(CacheStrategy.ON_RESOLVE);
+			fs.init();
+			FILESYSTEMANAGERINSTANCE = fs;
+
 		}
 		return FILESYSTEMANAGERINSTANCE;
 	}
@@ -120,12 +117,13 @@ public abstract class StorageObject extends SliceJpaObject {
 		return this.updateContent(mapping, input);
 	}
 
-	/** 更新Content内容 */
-	public Long updateContent(StorageMapping mapping, byte[] bytes) throws Exception {
-		try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
-			return updateContent(mapping, bais);
-		}
-	}
+	// /** 更新Content内容 */
+	// public Long updateContent(StorageMapping mapping, byte[] bytes) throws
+	// Exception {
+	// try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
+	// return updateContent(mapping, bais);
+	// }
+	// }
 
 	/** 更新Content内容 */
 	public Long updateContent(StorageMapping mapping, byte[] bytes, String name) throws Exception {
@@ -149,6 +147,69 @@ public abstract class StorageObject extends SliceJpaObject {
 
 	/** 更新Content内容 */
 	public Long updateContent(StorageMapping mapping, InputStream input) throws Exception {
+		return updateContent(mapping, IOUtils.toByteArray(input));
+		// long length = -1L;
+		// FileSystemManager manager = this.getFileSystemManager();
+		// String prefix = this.getPrefix(mapping);
+		// String path = this.path();
+		// if (StringUtils.isEmpty(path)) {
+		// throw new Exception("path can not be empty.");
+		// }
+		// FileSystemOptions options = this.getOptions(mapping);
+		// try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+		// /* 由于可以在传输过程中取消传输,先拷贝到内存 */
+		// IOUtils.copyLarge(input, baos);
+		// FileObject fo = null;
+		// OutputStream output = null;
+		// try {
+		// /*
+		// * 需要进行两次判断,在前端使用nginx分发的情况下,可能同时触发多个文件的上传,多个文件同时上传可能会同时创建文件的存储目录,会在后台导致错误
+		// * org.apache.commons.vfs2.FileSystemException: Could not create folder
+		// *
+		// "ftp://processPlatform:***@o2.server01.com:20040/20200601/1beb018a-5009-4baa-a9ef-7e903f9d48ef".
+		// * 这种情况下再次发起请求尝试获取文件可以解决这个问题.
+		// */
+		// try {
+		// fo = manager.resolveFile(prefix + PATHSEPARATOR + path, options);
+		// output = fo.getContent().getOutputStream();
+		// } catch (FileSystemException fse) {
+		// // 此段代码全部关闭对象,并要进行webdav判断进行关闭。
+		// if (null != output) {
+		// output.close();
+		// }
+		// if (null != fo) {
+		// if (!Objects.equals(StorageProtocol.webdav, mapping.getProtocol())) {
+		// /* webdav关闭会试图去关闭commons.httpClient */
+		// manager.closeFileSystem(fo.getFileSystem());
+		// }
+		// fo.close();
+		// }
+		// fo = manager.resolveFile(prefix + PATHSEPARATOR + path, options);
+		// output = fo.getContent().getOutputStream();
+		// }
+		// length = IOUtils.copyLarge(new ByteArrayInputStream(baos.toByteArray()),
+		// output);
+		// this.setLength(length);
+		// if (!Objects.equals(StorageProtocol.webdav, mapping.getProtocol())) {
+		// /* webdav关闭会试图去关闭commons.httpClient */
+		// manager.closeFileSystem(fo.getFileSystem());
+		// }
+		// } finally {
+		// if (null != output) {
+		// output.close();
+		// }
+		// if (null != fo) {
+		// fo.close();
+		// }
+		// }
+		// }
+		// this.setStorage(mapping.getName());
+		// this.setLastUpdateTime(new Date());
+		// return length;
+	}
+
+	/** 更新Content内容 */
+	public Long updateContent(StorageMapping mapping, byte[] bytes) throws Exception {
 		long length = -1L;
 		FileSystemManager manager = this.getFileSystemManager();
 		String prefix = this.getPrefix(mapping);
@@ -157,52 +218,31 @@ public abstract class StorageObject extends SliceJpaObject {
 			throw new Exception("path can not be empty.");
 		}
 		FileSystemOptions options = this.getOptions(mapping);
-		try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
-			/* 由于可以在传输过程中取消传输,先拷贝到内存 */
-			IOUtils.copyLarge(input, baos);
-			FileObject fo = null;
-			OutputStream output = null;
-			try {
-				/*
-				*需要进行两次判断,在前端使用nginx分发的情况下,可能同时触发多个文件的上传,多个文件同时上传可能会同时创建文件的存储目录,会在后台导致错误
-				*org.apache.commons.vfs2.FileSystemException: Could not create folder "ftp://processPlatform:***@o2.server01.com:20040/20200601/1beb018a-5009-4baa-a9ef-7e903f9d48ef".
-				*这种情况下再次发起请求尝试获取文件可以解决这个问题。
-				*/
-				try {
-					fo = manager.resolveFile(prefix + PATHSEPARATOR + path, options);
-					output = fo.getContent().getOutputStream();
-				} catch (FileSystemException fse) {
-					//此段代码全部关闭对象,并要进行webdav判断进行关闭。
-					if (null != output) {
-						output.close();
-					}
-					if (null != fo) {
-						if (!Objects.equals(StorageProtocol.webdav, mapping.getProtocol())) {
-							/* webdav关闭会试图去关闭commons.httpClient */
-							manager.closeFileSystem(fo.getFileSystem());
-						}
-						fo.close();
-					}
-					fo = manager.resolveFile(prefix + PATHSEPARATOR + path, options);
-					output = fo.getContent().getOutputStream();
-				}
-				length = IOUtils.copyLarge(new ByteArrayInputStream(baos.toByteArray()), output);
+		/*
+		 * 需要进行两次判断,在前端使用nginx分发的情况下,可能同时触发多个文件的上传,多个文件同时上传可能会同时创建文件的存储目录,会在后台导致错误
+		 * org.apache.commons.vfs2.FileSystemException: Could not create folder
+		 * "ftp://processPlatform:***@o2.server01.com:20040/20200601/1beb018a-5009-4baa-a9ef-7e903f9d48ef".
+		 * 这种情况下再次发起请求尝试获取文件可以解决这个问题.
+		 */
+		for (int i = 0; i < 2; i++) {
+			try (FileObject fo = manager.resolveFile(prefix + PATHSEPARATOR + path, options);
+					OutputStream output = fo.getContent().getOutputStream()) {
+				length = IOUtils.copyLarge(new ByteArrayInputStream(bytes), output);
 				this.setLength(length);
 				if (!Objects.equals(StorageProtocol.webdav, mapping.getProtocol())) {
 					/* webdav关闭会试图去关闭commons.httpClient */
 					manager.closeFileSystem(fo.getFileSystem());
 				}
-			} finally {
-				if (null != output) {
-					output.close();
-				}
-				if (null != fo) {
-					fo.close();
+				this.setStorage(mapping.getName());
+				this.setLastUpdateTime(new Date());
+				break;
+			} catch (FileSystemException fse) {
+				if (i != 0) {
+					// 第一次错误先跳过,直接执行第二次.如果第二次错误那么报错.
+					throw fse;
 				}
 			}
 		}
-		this.setStorage(mapping.getName());
-		this.setLastUpdateTime(new Date());
 		return length;
 	}
 

+ 15 - 21
o2server/x_base_core_project/src/main/java/com/x/base/core/project/build/CreateConfigSample.java

@@ -11,28 +11,26 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.commons.lang3.reflect.MethodUtils;
-
 import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.config.AppStyle;
 import com.x.base.core.project.config.CenterServer;
+import com.x.base.core.project.config.ClientInit;
 import com.x.base.core.project.config.Collect;
 import com.x.base.core.project.config.Communicate;
+import com.x.base.core.project.config.Components;
 import com.x.base.core.project.config.ConfigObject;
 import com.x.base.core.project.config.Dingding;
 import com.x.base.core.project.config.DumpRestoreData;
 import com.x.base.core.project.config.DumpRestoreStorage;
 import com.x.base.core.project.config.Exmail;
-import com.x.base.core.project.config.ExternalDataSource;
 import com.x.base.core.project.config.LogLevel;
 import com.x.base.core.project.config.Meeting;
 import com.x.base.core.project.config.Messages;
 import com.x.base.core.project.config.Node;
 import com.x.base.core.project.config.Person;
+import com.x.base.core.project.config.Portal;
 import com.x.base.core.project.config.ProcessPlatform;
+import com.x.base.core.project.config.PushConfig;
 import com.x.base.core.project.config.Qiyeweixin;
 import com.x.base.core.project.config.Query;
 import com.x.base.core.project.config.Token;
@@ -44,6 +42,11 @@ import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.tools.DefaultCharset;
 
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.apache.commons.lang3.reflect.MethodUtils;
+
 public class CreateConfigSample {
 
 	private static Logger logger = LoggerFactory.getLogger(CreateConfigSample.class);
@@ -54,25 +57,28 @@ public class CreateConfigSample {
 		List<Class<?>> classes = new ArrayList<Class<?>>();
 		classes.add(AppStyle.class);
 		classes.add(CenterServer.class);
+		classes.add(ClientInit.class);
 		classes.add(Collect.class);
+		classes.add(Communicate.class);
+		classes.add(Components.class);
 		classes.add(Dingding.class);
 		classes.add(DumpRestoreData.class);
 		classes.add(DumpRestoreStorage.class);
+		classes.add(Exmail.class);
 		classes.add(LogLevel.class);
 		classes.add(Meeting.class);
 		classes.add(Messages.class);
 		classes.add(Node.class);
 		classes.add(Person.class);
+		classes.add(Portal.class);
 		classes.add(ProcessPlatform.class);
+		classes.add(PushConfig.class);
 		classes.add(Qiyeweixin.class);
 		classes.add(Query.class);
 		classes.add(Token.class);
 		classes.add(Vfs.class);
 		classes.add(WorkTime.class);
 		classes.add(ZhengwuDingding.class);
-		//classes.add(ExternalDataSource.class);
-		classes.add(Exmail.class);
-		classes.add(Communicate.class);
 
 		Collections.sort(classes, new Comparator<Class<?>>() {
 			public int compare(Class<?> c1, Class<?> c2) {
@@ -90,21 +96,9 @@ public class CreateConfigSample {
 			logger.print("create file:{}.", file.getAbsoluteFile());
 			FileUtils.write(file, XGsonBuilder.toJson(map), DefaultCharset.charset);
 		}
-		//convertExternalDataSource2ExternalDataSources(dir);
 		renameNode(dir);
 	}
 
-//	private static void convertExternalDataSource2ExternalDataSources(File dir) throws Exception, IOException {
-//		File file_externalDataSource = new File(dir, "externalDataSources.json");
-//		File file_externalDataSources = new File(dir, "externalDataSources.json");
-//		JsonElement jsonElement = XGsonBuilder.instance().fromJson(
-//				FileUtils.readFileToString(file_externalDataSource, DefaultCharset.charset), JsonElement.class);
-//		List<JsonElement> list = new ArrayList<>();
-//		list.add(jsonElement);
-//		FileUtils.writeStringToFile(file_externalDataSources, XGsonBuilder.toJson(list), DefaultCharset.charset);
-//		file_externalDataSource.delete();
-//	}
-
 	private static void renameNode(File dir) throws Exception, IOException {
 		File file_node = new File(dir, "node.json");
 		File file_node_local = new File(dir, "node_127.0.0.1.json");

+ 11 - 11
o2server/x_hotpic_assemble_control/src/main/webapp/describe/describe.json

@@ -169,16 +169,21 @@
         {
           "name": "delete",
           "className": "com.x.base.core.project.jaxrs.StandardJaxrsAction",
-          "description": "根据ID删除指定的热图信息",
+          "description": "根据应用类型以及信息ID删除热图信息",
           "type": "DELETE",
-          "path": "jaxrs/user/hotpic/{id}",
+          "path": "jaxrs/user/hotpic/{application}/{infoId}",
           "contentType": "application/json",
           "resultContentType": "application/json; charset\u003dUTF-8",
           "useJsonElementParameter": false,
           "useStringParameter": false,
           "pathParameters": [
             {
-              "name": "id",
+              "name": "application",
+              "type": "String",
+              "description": ""
+            },
+            {
+              "name": "infoId",
               "type": "String",
               "description": ""
             }
@@ -191,21 +196,16 @@
         {
           "name": "delete",
           "className": "com.x.base.core.project.jaxrs.StandardJaxrsAction",
-          "description": "根据应用类型以及信息ID删除热图信息",
+          "description": "根据ID删除指定的热图信息",
           "type": "DELETE",
-          "path": "jaxrs/user/hotpic/{application}/{infoId}",
+          "path": "jaxrs/user/hotpic/{id}",
           "contentType": "application/json",
           "resultContentType": "application/json; charset\u003dUTF-8",
           "useJsonElementParameter": false,
           "useStringParameter": false,
           "pathParameters": [
             {
-              "name": "application",
-              "type": "String",
-              "description": ""
-            },
-            {
-              "name": "infoId",
+              "name": "id",
               "type": "String",
               "description": ""
             }

+ 14 - 14
o2server/x_jpush_assemble_control/src/main/webapp/describe/describe.json

@@ -651,21 +651,15 @@
         },
         {
           "name": "save",
-          "className": "com.x.jpush.assemble.control.jaxrs.sample.ActionUpdate",
-          "description": "更新新示例-信息",
-          "type": "PUT",
+          "className": "com.x.jpush.assemble.control.jaxrs.sample.ActionSave",
+          "description": "创建新示例-信息",
+          "type": "POST",
           "path": "jaxrs/sample",
           "contentType": "application/json",
           "resultContentType": "application/json; charset\u003dUTF-8",
           "useJsonElementParameter": false,
           "useStringParameter": false,
-          "pathParameters": [
-            {
-              "name": "id",
-              "type": "String",
-              "description": "需要更新的-信息ID"
-            }
-          ],
+          "pathParameters": [],
           "formParameters": [],
           "queryParameters": [],
           "ins": [
@@ -709,15 +703,21 @@
         },
         {
           "name": "save",
-          "className": "com.x.jpush.assemble.control.jaxrs.sample.ActionSave",
-          "description": "创建新示例-信息",
-          "type": "POST",
+          "className": "com.x.jpush.assemble.control.jaxrs.sample.ActionUpdate",
+          "description": "更新新示例-信息",
+          "type": "PUT",
           "path": "jaxrs/sample",
           "contentType": "application/json",
           "resultContentType": "application/json; charset\u003dUTF-8",
           "useJsonElementParameter": false,
           "useStringParameter": false,
-          "pathParameters": [],
+          "pathParameters": [
+            {
+              "name": "id",
+              "type": "String",
+              "description": "需要更新的-信息ID"
+            }
+          ],
           "formParameters": [],
           "queryParameters": [],
           "ins": [