martin 3 anos atrás
pai
commit
985410015e
17 arquivos alterados com 872 adições e 37 exclusões
  1. 0 1
      simulation-oauth-client/src/main/java/com/css/simulation/oauth/client/configuration/oauth/OauthParameter.java
  2. 9 8
      simulation-oauth-client/src/main/java/com/css/simulation/oauth/client/controller/SignController.java
  3. 24 0
      simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/cofiguration/oauth/MyAccessTokenConverter.java
  4. 20 0
      simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/cofiguration/oauth/MyUserAuthenticationConverter.java
  5. 3 4
      simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/cofiguration/oauth/OauthAuthorizationServerConfiguration.java
  6. 4 1
      simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/cofiguration/security/MyUserDetailsService.java
  7. 13 0
      simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/controller/OauthServerController.java
  8. 2 0
      simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/pojo/po/UserPO.java
  9. 2 0
      simulation-resource-common/src/main/java/com/css/simulation/resource/common/SimulationResourceCommonApplication.java
  10. 15 7
      simulation-resource-common/src/main/java/com/css/simulation/resource/common/controller/MinioController.java
  11. 704 0
      simulation-resource-common/src/main/java/com/css/simulation/resource/common/util/FileUtil.java
  12. 3 0
      simulation-resource-common/src/main/resources/bootstrap.yml
  13. 24 14
      simulation-resource-scheduler/pom.xml
  14. 2 2
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/SimulationResourceSchedulerApplication.java
  15. 22 0
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/configuration/feign/FeignConfiguration.java
  16. 15 0
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/feign/DemoService.java
  17. 10 0
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/feign/fallback/DemoServiceFallback.java

+ 0 - 1
simulation-oauth-client/src/main/java/com/css/simulation/oauth/client/configuration/oauth/OauthParameter.java

@@ -24,6 +24,5 @@ public class OauthParameter {
     private String simulationClientId;
     private String simulationClientSecret;
     private String simulationTokenUri;
-    private String simulationHome;
 
 }

+ 9 - 8
simulation-oauth-client/src/main/java/com/css/simulation/oauth/client/controller/SignController.java

@@ -1,8 +1,11 @@
 package com.css.simulation.oauth.client.controller;
 
+import api.common.pojo.common.ResponseBodyVO;
+import api.common.pojo.common.SimulationTokenVO;
 import api.common.pojo.po.UserPO;
 import api.common.util.EncryptUtil;
 import api.common.util.HttpUtil;
+import api.common.util.JsonUtil;
 import com.css.simulation.oauth.client.configuration.oauth.OauthParameter;
 import com.css.simulation.oauth.client.mapper.UserMapper;
 import lombok.SneakyThrows;
@@ -16,8 +19,6 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
 import javax.annotation.Resource;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
 
 @Controller
 @RequestMapping("/sign")
@@ -40,7 +41,7 @@ public class SignController {
     @RequestMapping("/hello")
     @ResponseBody
     public String hello() {
-        return "hello gateway!";
+        return "hello clent!";
     }
 
 
@@ -65,9 +66,10 @@ public class SignController {
      *
      * @return token 信息
      */
-    @RequestMapping("/home")
+    @RequestMapping("/single")
     @SneakyThrows
-    public String home(@RequestParam("code") String code, @RequestParam("ticket") String ticket, HttpServletResponse response) {
+    @ResponseBody
+    public ResponseBodyVO<SimulationTokenVO> home(@RequestParam("code") String code, @RequestParam("ticket") String ticket) {
         //1 根据统一凭条 code 获取统一平台 access_token
         /*
         响应体
@@ -141,9 +143,8 @@ public class SignController {
                 "&password=" + password;
         String simulationToken = HttpUtil.post(closeableHttpClient, requestConfig, simulationTokenUrl, null, null).toString();
         System.out.println("------- 仿真平台令牌信息为:" + simulationToken);
-
-        response.addCookie(new Cookie("token", simulationToken));
-        return "redirect:" + oauthParameter.getSimulationHome();
+        SimulationTokenVO simulationTokenVO = JsonUtil.jsonObjectToBean(new JSONObject(simulationToken),SimulationTokenVO.class);
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS,simulationTokenVO);
     }
 
 }

+ 24 - 0
simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/cofiguration/oauth/MyAccessTokenConverter.java

@@ -0,0 +1,24 @@
+//package com.css.simulation.oauth.server.cofiguration.oauth;
+//
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
+//import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
+//import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
+//
+//import javax.annotation.Resource;
+//
+//@Configuration
+//public class MyAccessTokenConverter {
+//
+//    @Resource
+//    private UserAuthenticationConverter userAuthenticationConverter;
+//
+//    @Bean
+//    public AccessTokenConverter accessTokenConverter() {
+//        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
+//        accessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
+//        return accessTokenConverter;
+//    }
+//
+//}

+ 20 - 0
simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/cofiguration/oauth/MyUserAuthenticationConverter.java

@@ -0,0 +1,20 @@
+//package com.css.simulation.oauth.server.cofiguration.oauth;
+//
+//import org.springframework.security.core.Authentication;
+//import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
+//import org.springframework.stereotype.Component;
+//
+//import java.util.LinkedHashMap;
+//import java.util.Map;
+//
+//@Component
+//public class MyUserAuthenticationConverter extends DefaultUserAuthenticationConverter {
+//
+//    @Override
+//    public Map<String, ?> convertUserAuthentication(Authentication authentication) {
+//        Map<String, Object> response = new LinkedHashMap<>();
+//        response.put(USERNAME, authentication.getName());
+//        return response;
+//    }
+//
+//}

+ 3 - 4
simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/cofiguration/oauth/OauthAuthorizationServerConfiguration.java

@@ -13,7 +13,6 @@ import org.springframework.security.oauth2.config.annotation.configurers.ClientD
 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
-import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
 import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
 import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
 import org.springframework.security.oauth2.provider.token.TokenStore;
@@ -33,8 +32,8 @@ public class OauthAuthorizationServerConfiguration extends AuthorizationServerCo
     private AuthenticationManager authenticationManager;        // 认证管理器,来自 Spring Security
     @Resource
     private UserDetailsService userDetailsService;        // 用户信息验证服务,来自 Spring Security
-    @Resource
-    private AuthorizationCodeServices authorizationCodeServices;    // 授权码管理服务
+//    @Resource
+//    private AccessTokenConverter accessTokenConverter;
     @Resource
     private TokenStore tokenStore;  // 令牌管理服务
     @Resource
@@ -79,7 +78,7 @@ public class OauthAuthorizationServerConfiguration extends AuthorizationServerCo
 
         endpoints.authenticationManager(authenticationManager)      // 认证管理器(密码模式)
                 .userDetailsService(userDetailsService)           // 用户信息管理(密码模式)
-                .authorizationCodeServices(authorizationCodeServices)   // 授权码服务(授权码模式)
+//                .accessTokenConverter(accessTokenConverter)         // token 信息管理
                 .tokenStore(tokenStore)   // 令牌存储
                 .tokenServices(authorizationServerTokenServices)    // 令牌管理服务
                 .exceptionTranslator(defaultWebResponseExceptionTranslator)

+ 4 - 1
simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/cofiguration/security/MyUserDetailsService.java

@@ -19,7 +19,10 @@ public class MyUserDetailsService implements UserDetailsService {
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
         UserPO userPO = userMapper.selectByUsername(username);
-        return new MyUserDetails(userPO.getUsername(), userPO.getPassword());
+        return new MyUserDetails(
+                userPO.getUsername(),
+                userPO.getPassword()
+        );
     }
 
 

+ 13 - 0
simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/controller/OauthServerController.java

@@ -0,0 +1,13 @@
+package com.css.simulation.oauth.server.controller;
+
+
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class OauthServerController {
+
+
+
+
+
+}

+ 2 - 0
simulation-oauth-server/src/main/java/com/css/simulation/oauth/server/pojo/po/UserPO.java

@@ -18,6 +18,8 @@ public class UserPO implements Serializable {
     private String username;        // 登录用户名
     private String nickname;        // 用户昵称,用于显示
     private String password;        // 密码(加密)
+    private String phone;
+    private String job;
     private String isDeleted = "0";
 
 }

+ 2 - 0
simulation-resource-common/src/main/java/com/css/simulation/resource/common/SimulationResourceCommonApplication.java

@@ -3,8 +3,10 @@ package com.css.simulation.resource.common;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
 
 @SpringBootApplication
+@EnableResourceServer
 public class SimulationResourceCommonApplication {
 
     public static void main(String[] args) {

+ 15 - 7
simulation-resource-common/src/main/java/com/css/simulation/resource/common/controller/MinioController.java

@@ -1,16 +1,19 @@
 package com.css.simulation.resource.common.controller;
 
 import com.css.simulation.resource.common.pojo.parameter.MinioParameter;
+import com.css.simulation.resource.common.util.FileUtil;
 import com.css.simulation.resource.common.util.MinioUtil;
 import io.minio.MinioClient;
 import io.minio.errors.*;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.InputStream;
 import java.security.InvalidKeyException;
@@ -31,26 +34,31 @@ public class MinioController {
 
     @RequestMapping("/upload")
     public void upload(
-            MultipartFile multipartFile,
-            @RequestBody @Validated MinioParameter minioParameter
+            @RequestParam("file") MultipartFile multipartFile,
+            @RequestParam("bucketName") String bucketName,
+            @RequestParam("objectName") String objectName
+//            @RequestBody @Validated MinioParameter minioParameter
     ) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
         MinioUtil.uploadFromMultipartFile(
                 minioClient,
                 multipartFile,
-                minioParameter.getBucketName(),
-                minioParameter.getObjectName()
+                bucketName,
+                objectName
         );
     }
 
     @RequestMapping("/download")
-    public InputStream download(
-            @RequestBody @Validated MinioParameter minioParameter
+    public void download(
+            @RequestBody @Validated MinioParameter minioParameter,
+            HttpServletResponse response
     ) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
-        return MinioUtil.downloadToStream(
+        InputStream inputStream = MinioUtil.downloadToStream(
                 minioClient,
                 minioParameter.getBucketName(),
                 minioParameter.getObjectName()
         );
+        String fileName = FileUtil.getFileName(minioParameter.getObjectName());
+        FileUtil.downloadForHttp(fileName, inputStream, response, 1024);
     }
 
 }

+ 704 - 0
simulation-resource-common/src/main/java/com/css/simulation/resource/common/util/FileUtil.java

@@ -0,0 +1,704 @@
+package com.css.simulation.resource.common.util;
+
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.*;
+
+public class FileUtil {
+
+    // -------------------------------- A --------------------------------
+
+    /**
+     * 添加文件后缀
+     *
+     * @param url 路径
+     * @return 有后缀名的文件
+     */
+    public static String addSeparator(String url) {
+        if (File.separator.equals(url.charAt(url.length() - 1) + "")) {
+            return url;
+        }
+        return url + File.separator;
+    }
+
+    /**
+     * 添加文件后缀
+     *
+     * @param ambiguousFileName 不确定是否有后缀的文件名
+     * @return 有后缀名的文件
+     */
+    public static String addSuffix(String ambiguousFileName, String suffix) {
+        if (ambiguousFileName == null || "".equals(ambiguousFileName)) {
+            throw new RuntimeException("文件名参数为空!");
+        }
+        String[] split = ambiguousFileName.split("\\.");
+        return split[0] + suffix;
+    }
+
+
+    // -------------------------------- B --------------------------------
+    // -------------------------------- C --------------------------------
+
+    /**
+     * 检查文件
+     * 0 代表不存在
+     * 1 代表是文件
+     * 2 代表是目录
+     *
+     * @param file 文件
+     * @return 是否正确
+     */
+    public static String checkFile(File file) {
+        if (!file.exists()) {
+            return "0";
+        }
+        if (file.isFile()) {
+            return "1";
+        }
+        if (file.isDirectory()) {
+            return "2";
+        }
+        return null;
+    }
+
+
+    /**
+     * 检查文件后缀
+     *
+     * @param file   文件
+     * @param suffix 文件后缀
+     * @return 是否正确
+     */
+    public static boolean checkFileType(File file, String suffix) {
+        String fileName = file.getName();
+        int fileNameLength = fileName.length();
+        int suffixLength = suffix.length();
+        if (fileNameLength < suffixLength) {
+            return false;
+        }
+        return suffix.equals(fileName.substring(fileNameLength - suffixLength));
+    }
+
+
+    /**
+     * 自适应转换文件大小的单位
+     *
+     * @param dataSize long 型的文件大小
+     * @return 带单位的 String 类型文件大小
+     */
+    public static String convertUnit(long dataSize) {
+        String dataSizeStr = null;
+        if (dataSize >= 0 && dataSize < 1024) {
+            dataSizeStr = dataSize + "B";
+        } else if (dataSize >= 1024 && dataSize < 1024 * 1024) {
+            dataSizeStr = dataSize / 1024 + "KB";
+        } else if (dataSize >= 1024 * 1024 && dataSize < 1024 * 1024 * 1024) {
+            dataSizeStr = dataSize / 1024 / 1024 + "MB";
+        } else if (dataSize >= 1024 * 1024 * 1024 && dataSize < 1024 * 1024 * 1024 * 1024L) {
+            dataSizeStr = dataSize / 1024 / 1024 / 1024 + "GB";
+        } else if (dataSize >= 1024 * 1024 * 1024 * 1024L) {
+            dataSizeStr = dataSize / 1024 / 1024 / 1024 / 1024 + "TB";
+        }
+        return dataSizeStr;
+    }
+
+    /**
+     * 计算目录包含的文件数量
+     *
+     * @param directory 目录的 File 对象
+     * @return 文件数量
+     */
+    public static int count(File directory) {
+        return Objects.requireNonNull(directory.listFiles()).length;
+    }
+
+    /**
+     * 计算目录包含的文件数量
+     *
+     * @param directoryPath 目录的路径
+     * @return 文件数量
+     */
+    public static int count(String directoryPath) throws Exception {
+        return count(getDirectory(directoryPath));
+    }
+
+    /**
+     * 复制文件
+     *
+     * @param source 原始文件路径
+     * @param target 目标路径
+     * @throws Exception 异常
+     */
+    public static void copy(String source, String target) throws Exception {
+        File targetFile = new File(target);
+        boolean delete = true;
+        if (targetFile.exists()) {
+            delete = targetFile.delete();
+        }
+        if (delete) {
+            createParentDirectory(target);
+            Files.copy(getFile(source).toPath(), new File(target).toPath());
+        } else {
+            throw new Exception("删除 " + target + " 失败!");
+        }
+
+    }
+
+    /**
+     * 创建目录
+     */
+    public static boolean createDirectory(String path) {
+        boolean mkdir = false;
+        File file = new File(path);
+        if (!file.exists()) {
+            mkdir = file.mkdirs();
+        }
+        return mkdir;
+    }
+
+
+    /**
+     * 创建父目录
+     */
+    public static boolean createParentDirectory(String path) {
+        boolean mkdir = false;
+        File file = new File(path);
+        if (!file.getParentFile().exists()) {
+            mkdir = file.getParentFile().mkdirs();
+        }
+        return mkdir;
+    }
+
+    /**
+     * 创建父目录
+     */
+    public static boolean createParentDirectory(File file) {
+        boolean mkdir = true;
+        if (!file.getParentFile().exists()) {
+            mkdir = file.getParentFile().mkdirs();
+        }
+        return mkdir;
+    }
+
+    /**
+     * 创建文件。
+     */
+    public static boolean createFile(String path) throws IOException {
+        File file = new File(path);
+        boolean result = createParentDirectory(file);
+        if (!file.exists()) {
+            result = file.createNewFile();
+        }
+        return result;
+    }
+
+    /**
+     * 创建文件。
+     */
+    public static boolean createFile(File file) throws IOException {
+        boolean result = createParentDirectory(file);
+        if (!file.exists()) {
+            result = file.createNewFile();
+        }
+        return result;
+    }
+
+
+    /**
+     * 拷贝文件。
+     */
+    public static void copyFile(String readFrom, String writeTo) throws IOException {
+        createParentDirectory(writeTo);
+        FileInputStream fileInputStream = new FileInputStream(readFrom);
+        FileOutputStream fileOutputStream = new FileOutputStream(writeTo);
+        FileChannel readChannel = fileInputStream.getChannel();
+        FileChannel writeChannel = fileOutputStream.getChannel();
+        //自动生成与文件大小相同但不超过 8096 的缓存,即缓存最大为 8096。
+        writeChannel.transferFrom(readChannel, 0, readChannel.size());
+        writeChannel.close();
+        readChannel.close();
+        fileOutputStream.close();
+        fileInputStream.close();
+    }
+
+
+    public static void copyBytes(InputStream in, OutputStream out, int bufferSize) throws IOException {
+        byte[] buffer = new byte[bufferSize];
+        for (int bytesRead = in.read(buffer); bytesRead >= 0; bytesRead = in.read(buffer)) {
+            out.write(buffer, 0, bytesRead);
+        }
+    }
+
+
+    // -------------------------------- D --------------------------------
+
+
+    /**
+     * 供 http 下载使用
+     *
+     * @param fileName   文件名
+     * @param in         输入流
+     * @param response   响应对象
+     * @param bufferSize 缓存大小
+     * @throws IOException 异常
+     */
+    public static void downloadForHttp(String fileName, InputStream in, HttpServletResponse response, int bufferSize) throws IOException {
+        response.setContentType("application/octet-stream;charset=utf-8");
+        response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
+        copyBytes(in, response.getOutputStream(), bufferSize);
+    }
+
+    // -------------------------------- F --------------------------------
+    // -------------------------------- G --------------------------------
+
+    /**
+     * 获得去除文件后缀的文件名
+     */
+    public static List<String> getAbsolutePathList(File[] files) {
+        List<String> absolutePathList = new ArrayList<>();
+        for (File file : files) {
+            absolutePathList.add(file.getAbsolutePath());
+        }
+        return absolutePathList;
+    }
+
+    /**
+     * 获得目录的 File 对象
+     */
+    public static File getDirectory(String path) throws Exception {
+        // 获取文件
+        File file = new File(path);
+        if (!file.exists()) {
+            throw new Exception("文件" + path + "不存在!");
+        }
+        if (!file.isDirectory()) {
+            throw new Exception("文件" + path + "不是目录!");
+        }
+        return file;
+    }
+
+    /**
+     * 获得去除文件后缀的文件名
+     */
+    public static File getFile(String path) throws Exception {
+        // 获取文件
+        File file = new File(path);
+        if (!file.exists()) {
+            throw new Exception("文件" + path + "不存在!");
+        }
+        return file;
+    }
+
+    /**
+     * 获得去除文件后缀的文件名
+     */
+    public static String getFilename(File file) {
+        return file.getName().split("\\.")[0];
+    }
+
+    /**
+     * 获得去除文件后缀的文件名
+     */
+    public static String getFilename(String path) throws Exception {
+        return getFilename(getFile(path));
+    }
+
+    /**
+     * 获得去除文件后缀的文件名
+     */
+    public static List<String> getFilenameList(File[] files) {
+        List<String> fileNameList = new ArrayList<>();
+        for (File file : files) {
+            fileNameList.add(file.getName());
+        }
+        return fileNameList;
+    }
+
+    /**
+     * 获取文件行数
+     *
+     * @param path 文件路径
+     * @return 文件行数
+     * @throws IOException 异常
+     */
+    public static long getFileLineNum(String path) throws IOException {
+        return Files.lines(Paths.get(path)).count();
+    }
+
+    /**
+     * 获取文件名称
+     *
+     * @param path 文件路径
+     * @return 文件名
+     */
+    public static String getFileName(String path) {
+        return new File(path).getName();
+    }
+
+    /**
+     * 获取 classpath 文件
+     *
+     * @param relativePath 相对路径
+     */
+    public static File getResourceFile(String relativePath) throws IOException {
+        return ResourceUtils.getFile("classpath:" + relativePath);
+    }
+
+    /**
+     * 获取所有文件列表。
+     *
+     * @param root 文件 File 对象。
+     */
+    public static List<File> list(File root) throws Exception {
+
+        List<File> result = new LinkedList<>();
+        //1 判断文件是否存在
+        if (!root.exists()) {
+            throw new Exception("文件" + root.getAbsolutePath() + "不存在!");
+        }
+        //2 判断是否是文件
+        if (root.isFile()) {
+            return new ArrayList<>(Collections.singletonList(root));
+        }
+        //3 判断是否是目录
+        if (root.isDirectory()) {
+            File[] children = root.listFiles();
+            if (children != null) {
+                for (File child : children) {
+                    result.addAll(list(child));
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 获取所有文件列表。
+     *
+     * @param rootPath 文件 File 对象。
+     */
+    public static List<String> list(String rootPath) throws Exception {
+
+        List<String> result = new ArrayList<>();
+        File root = new File(rootPath);
+        //1 判断文件是否存在
+        if (!root.exists()) {
+            throw new Exception("文件" + root.getAbsolutePath() + "不存在!");
+        }
+        //2 判断是否是文件
+        if (root.isFile()) {
+            return new ArrayList<>(Collections.singletonList(rootPath));
+        }
+        //3 判断是否是目录
+        if (root.isDirectory()) {
+            File[] children = root.listFiles();
+            if (children != null) {
+                for (File child : children) {
+                    result.addAll(list(child.getAbsolutePath()));
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 获取所有同一类型的文件列表。
+     *
+     * @param root   文件 File 对象。
+     * @param suffix 文件后缀类型。
+     */
+    public static List<File> listMatchSuffix(File root, String suffix) throws Exception {
+        List<File> result = new LinkedList<>();
+        //1 判断文件是否存在
+        if (!root.exists()) {
+            throw new Exception("文件" + root.getAbsolutePath() + "不存在!");
+        }
+        //2 判断是否是文件
+        if (root.isFile() && checkFileType(root, suffix)) {
+            return new ArrayList<>(Collections.singletonList(root));
+        }
+        //3 判断是否是目录
+        if (root.isDirectory()) {
+            File[] children = root.listFiles();
+            if (children != null) {
+                for (File child : children) {
+                    result.addAll(listMatchSuffix(child, suffix));
+                }
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * 获取所有同一名称的文件列表。
+     *
+     * @param root         文件 File 对象。
+     * @param fullFilename 带后缀的文件名。
+     */
+    public static List<File> listMatchName(File root, String fullFilename) throws Exception {
+        List<File> result = new LinkedList<>();
+        //1 判断文件是否存在
+        if (!root.exists()) {
+            throw new Exception("文件" + root.getAbsolutePath() + "不存在!");
+        }
+        //2 判断是否是文件且文件名是否一致
+        if (root.isFile() && fullFilename.equals(root.getName())) {
+            return new ArrayList<>(Collections.singletonList(root));
+        }
+        //3 判断是否是目录
+        if (root.isDirectory()) {
+            File[] children = root.listFiles();
+            if (children != null) {
+                for (File child : children) {
+                    result.addAll(listMatchName(child, fullFilename));
+                }
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * 获得父级文件。
+     *
+     * @return 父级文件
+     */
+    public static File getParentFile(String path) throws Exception {
+        return getParentFile(getFile(path));
+    }
+
+    /**
+     * 获得父级文件。
+     *
+     * @return 父级文件
+     */
+    public static File getParentFile(File file) {
+        return file.getParentFile();
+    }
+
+    /**
+     * 获得父级目录名。
+     */
+    public static String getParentDirectoryName(File file) {
+        return getParentFile(file).getName().split("\\.")[0];
+    }
+
+    /**
+     * 获得父级目录名。
+     */
+    public static String getParentDirectoryName(String path) throws Exception {
+        return getParentDirectoryName(getFile(path));
+    }
+
+    /**
+     * 获取路径下的所有文件总大小
+     */
+    public static double getSize(File file) throws Exception {
+        //判断文件是否存在
+        if (file.exists()) {
+            //如果是目录则递归计算其内容的总大小
+            if (file.isDirectory()) {
+                File[] children = file.listFiles();
+                if (children == null) {
+                    return 0;
+                }
+                double size = 0;
+                for (File f : children)
+                    size += getSize(f);
+                return size;
+            } else {//如果是文件则直接返回其大小,以“兆”为单位
+                return (double) file.length() / 1024 / 1024;
+            }
+        } else {
+            throw new Exception("文件或者文件夹不存在,请检查路径" + file.getAbsolutePath() + "是否正确!");
+        }
+    }
+
+
+    public static String getSuffix(String path) {
+        String[] split = path.split("\\.");
+        return split[split.length - 1];
+    }
+
+    /**
+     * 计算文件大小,递归算法
+     */
+    public static long getTotalSizeOfFilesInDir(final File file) throws Exception {
+        //判断文件是否存在
+        if (file.exists()) {
+            if (file.isFile()) {
+                return file.length();
+            }
+            final File[] children = file.listFiles();
+            long total = 0;
+            if (children != null) {
+                for (final File child : children) {
+                    total += getTotalSizeOfFilesInDir(child);
+                }
+            }
+            return total;
+        } else {
+            throw new Exception("文件或者文件夹不存在,请检查路径" + file.getAbsolutePath() + "是否正确!");
+        }
+    }
+
+
+    // -------------------------------- H --------------------------------
+    // -------------------------------- I --------------------------------
+
+
+    // -------------------------------- J --------------------------------
+    // -------------------------------- K --------------------------------
+    // -------------------------------- L --------------------------------
+    // -------------------------------- M --------------------------------
+
+
+    /**
+     * 修改文件。
+     */
+    public static void modifyFile(String path, int offset, byte[] bytes) throws IOException {
+        createFile(path);
+        RandomAccessFile randomAccessFile = new RandomAccessFile(path, "rw");
+        FileChannel channel = randomAccessFile.getChannel();
+        MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, offset, bytes.length);
+        mappedByteBuffer.put(bytes);
+        channel.close();
+    }
+
+    /**
+     * 移动文件或者重命名文件
+     *
+     * @param source 原始文件路径
+     * @param target 目标路径
+     * @return 是否操作成功
+     * @throws Exception 异常
+     */
+    public static boolean mv(String source, String target) throws Exception {
+        return getFile(source).renameTo(new File(target));
+    }
+
+
+    // -------------------------------- N --------------------------------
+    // -------------------------------- O --------------------------------
+    // -------------------------------- P --------------------------------
+    // -------------------------------- Q --------------------------------
+    // -------------------------------- R --------------------------------
+
+    public static String readFile(String path) throws Exception {
+        return readFile(getFile(path));
+    }
+
+    public static String readFile(File file) throws Exception {
+        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
+        StringBuilder stringBuilder = new StringBuilder();
+        String line;
+        while ((line = reader.readLine()) != null) {
+            stringBuilder.append(line);
+        }
+        reader.close();
+        return String.valueOf(stringBuilder);
+    }
+
+    public static String readInputStream(InputStream inputStream) throws Exception {
+        StringBuilder result = new StringBuilder();
+        byte[] buf = new byte[1024];//创建字节数组,存储临时读取的数据
+        int len = 0;//记录数据读取的长度
+        //循环读取数据
+        while ((len = inputStream.read(buf)) != -1) { //长度为-1则读取完毕
+            result.append(new String(buf, 0, len));
+        }
+        inputStream.close();
+        return result.toString();
+    }
+
+    /**
+     * 删除文件或递归删除目录
+     * 递归删除目录下的所有文件及子目录下所有文件
+     */
+    public static boolean rm(File path) {
+        if (path.isDirectory()) {
+            String[] children = path.list();
+            if (children != null) {
+                for (String child : children) {
+                    boolean success = rm(new File(path, child));
+                    if (!success) {
+                        return false;
+                    }
+                }
+            }
+        }
+        return path.delete();
+    }
+
+    /**
+     * 删除文件或递归删除目录
+     * 递归删除目录下的所有文件及子目录下所有文件
+     */
+    public static boolean rm(String path) throws Exception {
+        return rm(getFile(path));
+    }
+
+
+    // -------------------------------- S --------------------------------
+
+//    public static String splicingPath(String... paths) {
+//        StringBuilder result = new StringBuilder();
+//        for (int i = 0; i < paths.length; i++) {
+//            if (i == 0) {
+//                if ("/".equals(paths[0].charAt(paths.length - 1) + "")) {
+//                    String substring = paths[0].substring(0, paths[0].length() - 2);
+//                    result.append(substring);
+//                } else {
+//                    result.append(paths[0]);
+//                }
+//            } else {
+//                String[] split = paths[i].split("/");
+//
+//                for (String s : split) {
+//                    if (s != null && !"".equals(s)) {
+//                        result.append("/").append(s);
+//                    }
+//                }
+//            }
+//        }
+//        return result.toString();
+//    }
+    // -------------------------------- T --------------------------------
+    // -------------------------------- U --------------------------------
+    // -------------------------------- V --------------------------------
+    // -------------------------------- W --------------------------------
+
+    /**
+     * 将 web 文件保存到本地文件
+     */
+    public static void writeMultipartFileToLocalPath(MultipartFile multipartFile, String localPath) throws IOException {
+        writeInputStreamToLocalPath(multipartFile.getInputStream(), localPath);
+    }
+
+    /**
+     * 将输入流保存为本地文件
+     */
+    public static void writeInputStreamToLocalPath(InputStream inputStream, String localPath) throws IOException {
+        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
+        byte[] data = new byte[1024];
+        int dataLength;
+        File file = new File(localPath);
+        createParentDirectory(file);
+        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file, false));
+        while ((dataLength = bufferedInputStream.read(data)) != -1) {
+            bufferedOutputStream.write(data, 0, dataLength);
+        }
+        bufferedOutputStream.close();
+        bufferedInputStream.close();
+    }
+
+
+}

+ 3 - 0
simulation-resource-common/src/main/resources/bootstrap.yml

@@ -12,3 +12,6 @@ spring:
         server-addr: 10.15.12.70:8848
         namespace: 3698bfc2-a612-487a-b2a2-aaad16cd9d9d
         file-extension: yaml
+server:
+  tomcat:
+    uri-encoding: utf-8

+ 24 - 14
simulation-resource-scheduler/pom.xml

@@ -71,32 +71,42 @@
         </dependency>
         <!-- nacos - 结束 -->
 
-        <!-- web 服务 -->
+        <!-- api-common -->
+        <dependency>
+            <groupId>com.css</groupId>
+            <artifactId>api-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- 基础 -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-loadbalancer</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
-        <!-- 参数校验 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-validation</artifactId>
         </dependency>
-        <!-- lombok -->
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-
-        <!-- redis -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-redis</artifactId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
         </dependency>
-        <!-- api-common -->
         <dependency>
-            <groupId>com.css</groupId>
-            <artifactId>api-common</artifactId>
-            <version>${project.version}</version>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
         </dependency>
 
     </dependencies>

+ 2 - 2
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/SimulationResourceSchedulerApplication.java

@@ -2,11 +2,11 @@ package com.css.simulation.resource.scheduler;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.cloud.openfeign.EnableFeignClients;
 
 
 @SpringBootApplication
-@EnableScheduling
+@EnableFeignClients
 public class SimulationResourceSchedulerApplication {
 
     public static void main(String[] args) {

+ 22 - 0
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/configuration/feign/FeignConfiguration.java

@@ -0,0 +1,22 @@
+package com.css.simulation.resource.scheduler.configuration.feign;
+
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 转发 token
+ */
+@Configuration
+public class FeignConfiguration implements RequestInterceptor {
+    @Override
+    public void apply(RequestTemplate requestTemplate) {
+        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        HttpServletRequest request = attributes.getRequest();
+        requestTemplate.header("Authorization", request.getHeader("Authorization"));
+    }
+}

+ 15 - 0
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/feign/DemoService.java

@@ -0,0 +1,15 @@
+package com.css.simulation.resource.scheduler.feign;
+
+import com.css.simulation.resource.scheduler.configuration.feign.FeignConfiguration;
+import com.css.simulation.resource.scheduler.feign.fallback.DemoServiceFallback;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Component
+@FeignClient(value = "simulation-resource-common", fallback = DemoServiceFallback.class, configuration = FeignConfiguration.class)
+public interface DemoService {
+
+    @RequestMapping("/hello")
+    String hello();
+}

+ 10 - 0
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/feign/fallback/DemoServiceFallback.java

@@ -0,0 +1,10 @@
+package com.css.simulation.resource.scheduler.feign.fallback;
+
+import com.css.simulation.resource.scheduler.feign.DemoService;
+
+public class DemoServiceFallback implements DemoService {
+    @Override
+    public String hello() {
+        return "服务错误!";
+    }
+}