• 基于SpringCloud微服务的Hdfs分布式大数据实现的企业网盘系统


    目录
    1 绪 论 5
    1.1 研究的背景及意义 5
    1.1.1 选题的背景 5
    1.1.2 国内外研究现状 6
    1.1.3 研究的意义 7
    1.2 系统目标 7
    2 需求分析 8
    2.1 功能需求 8
    2.1.1 子系统说明 8
    2.1.2 功能需求描述 9
    2.2 非功能需求 10
    2.2.1 外部接口需求 10
    2.2.2 性能需求 10
    2.2.3 其它需求 11
    3 总体设计 12
    3.1 运行环境 12
    3.2 基本处理流程 12
    3.3 模块结构 13
    3.4 外部接口 15
    3.4.1 软件接口 15
    3.4.2 硬件接口 15
    3.4.3 通讯接口 15
    3.4.3 其他接口 15
    3.5 内部接口 15
    SpringCloud将SpringBoot工程搭建的服务,注册到Eureka注册中心,服务间通过Feign进行http方式调用,最后将上层服务在网关暴露出去。 15
    4 数据库设计 16
    4.1 概念结构设计 16
    4.1.1 设计思路 16
    概念结构设计指的就是开发人员在项目开发前,对数据结构进行设计,这是需求分析中所得到东西进行抽象化的结果。本系统主要实体如下: 16
    (1) 用户:用户主键(pk)、用户名、头像、密码、salt值、邮箱、手机号码、类型、状态、部门ID(fk)、添加时间。 16
    (2) 部门:部门主键(pk)、父部门编号、部门名、删除标记。 16
    (3) 角色:角色主键(pk)、角色名、注释、添加时间。 16
    (4) 菜单:菜单主键(pk)、父菜单ID、菜单名称、菜单URL、授权、类型、菜单图标、排序、版本号。 16
    (5) 文件:文件ID(pk)、父文件ID、原版文件名、文件名、文件路径、文件大小、文件类型、是否可在线查看、是否邮箱、创建者、创建时间、修改者、添加时间、版本号、下载数量。 16
    (6) 网盘:网盘ID(pk)、企业名字、企业ID(fk)、是否有效、创建者、添加时间。 16
    (7) 分享:ID(pk)、用户主键(fk)、用户名、被分享用户ID(fk)、被分享用户名、文件名、过期时间、是否有效、创建时间、创建者、修改时间、修改人、版本号。 16
    (8) 数据字典:字典id(pk)、字典名称、 字典类型、字典码、 字典值、 排序、备注、删除标记、创建时间、创建者、修改时间、修改者、版本号。 16
    (9) 系统日志:日志id(pk)、用户名、用户操作、请求方法、请求参数、执行时长(毫秒)、IP地址、创建时间、创建者。 16
    (10) 文件上传:id(pk)、URL地址、创建时间、创建者。 16
    (11) 定时任务:任务id(pk)、SpringBean名称、方法名称、参数、cron表达式、任务状态、注释、添加时间。 16
    (12) 定时任务日志:任务日志id(pk)、任务id(fk)、SpringBean名称、方法名、参数、任务运行状态、失败信息、耗时(毫秒)、创建时间。 16
    (13) 网络磁盘文件关联实体:id(pk)、网络磁盘id(fk)、文件id(fk)、添加时间、创建者。 16
    (14) 用户文件管理实体:id(pk)、用户编号(fk)、文件主键(fk)、新增时间、创建者。 16
    4.1.2 E-R图 17
    4.1.3 数据库总表 17
    表名 17
    功能 17
    系统配置信息表 17
    存储系统所有的配置信息 17
    部门表 17
    存储企业所有部门信息 17
    通知公告表 17
    存储系统所有通知公告信息 17
    网盘表 17
    存储企业所有网盘信息 17
    系统日志表 17
    存储系统所有日志信息 17
    菜单表 17
    存储系统所有菜单信息 17
    OSS上传文件表 18
    存储系统所有通过OSS上传文件信息 18
    角色表 18
    存储系统角色相关信息 18
    角色部门表 18
    存储系统所有角色和部门关联信息 18
    角色菜单表 18
    存储系统所有角色和菜单关联信息 18
    用户表 18
    存储系统用户相关信息 18
    用户角色表 18
    存储系统所有用户和角色关联信息 18
    定时任务表 18
    存储系统所有定时任务信息 18
    定时任务日志表 18
    存储系统所有定时任务运行的日志信息 18
    用户文件表 18
    存储系统所有用户关联的文件信息 18
    文件表 18
    存储系统所有文件相关信息 18
    网盘文件表 18
    存储系统所有网盘关联文件的信息 18
    关注用户表 18
    存储所有已关注和被关注的信息 18
    分享表 18
    存储所有已分享和收到的分享信息 18
    4.2 逻辑结构设计 18
    4.2.1 设计思路 18
    逻辑结构设计是通过需求分析,得到抽象数据设计局部视图,然后将多个E-R图进行集成,得到总的E-R图,最后将ER图向关系模型进行转换,在将转换的结果向数据模型转换。企业网盘系统的E-R图则是由管理员,系统管理员,部门,角色,菜单,公告,网盘等个实体的属性以及各个实体类型之间的联系这三个方面组成。 18
    4.2.2 逻辑模型 19
    4.3 物理结构设计 24
    4.3.1 存取方式 24
    4.3.2 存储结构 24
    5 界面设计 25
    5.1 界面关系图 25
    5.2 界面设计成果 26
    5.2.1 主界面 26
    5.2.2 前台子界面 28
    5.2.3 后台子界面 29
    6 详细设计 31
    6.1 系统主要功能模块介绍 31
    6.1.1 前台主要功能模块介绍 31
    6.1.2 后台主要功能模块介绍 31
    6.2 后台登录模块设计 32
    6.2.1 后台登录模块算法描述 32
    6.2.2 后台登陆模块程序流程图 33
    6.2.3 后台登陆模块关键类说明 33
    6.3 用户管理模块设计 33
    6.3.1 用户管理模块算法描述 33
    6.3.2 用户管理模块程序流程图 34
    6.3.3 用户管理模块关键类说明 34
    6.4部门管理模块设 34
    6.4.1 部门管理模块算法描述 34
    6.4.2 部门管理模块程序流程图 35
    6.4.3 部门管理模块关键类说明 35
    6.5角色管理模块设计 35
    6.5.1 角色管理模块算法描述 35
    6.5.2 角色管理模块程序流程图 36
    6.5.3 角色管理模块关键类说明 36
    6.6网盘管理模块设计 36
    6.6.1 网盘管理模块算法描述 36
    6.6.2 网盘管理模块程序流程图 37
    6.6.3 网盘管理模块关键类说明 37
    6.7系统菜单管理模块设计 37
    6.7.1 系统菜单管理模块算法描述 37
    6.7.2 系统菜单管理模块程序流程图 38
    6.7.3 系统菜单管理模块关键类说明 38
    6.8前台登录模块设计 38
    6.8.1 前台登录模块算法描述 38
    6.8.2 前台登录模块程序流程图 39
    6.8.3 前台登录模块关键类说明 39
    7 编码 40
    7.1 代码实现与核心算法 40
    7.1.1 前台系统 40
    7.1.2 后台系统 41
    7.2 代码优化分析 42
    7.2.1 前端代码优化分析 42
    7.2.2 后端代码优化分析 43
    8 测试 44
    8.1 测试方案设计 44
    8.1.1 测试策略 44
    8.1.2 测试进度安排 44
    8.1.3 测试资源 44
    8.1.4 关键测试点 44
    8.2 测试用例构建 45
    8.2.1 测试用例编写约定 45
    8.2.2 测试用例设计 45
    8.2.3 关键测试用例 45
    8.2.4 测试用例维护 53
    9 总结与展望 54
    9.1 设计工作总结 54
    9.2 未来工作展望 54
    参考文献 56
    附录 软件使用说明书 58
    附录 主要源代码 60
    2 需求分析
    2.1 功能需求
    2.1.1 子系统说明
    根据本次的设计需求分析,本次企业级网盘系统的开发与完成主要分为前端和后端二大部分,前台主要为企业用户服务的,企业的员工可以管理自己的网盘,如果自己有比较好的资源文件可以加入到企业共享网盘,这样企业每个用户都有权限下载、在线查看文件,除此之外,也可以把自己的资源文件通过用户分享或者链接分享的方式发送给用户。系统后台用户可以对系统角色进行编辑和分配,控制用户的管理权限,管理企业共享网盘里面的资源文件等,具体模块功能如下:
    前台:
    (1)用户登录,本系统用户可以通过账号登录,短信登录,还可以通过QQ扫码登录,如果用户忘记了密码,验证通过后,可以找回密码。
    (2)个人中心,用户可以修改自己的信息,绑定扫描登录的QQ号。
    (3)系统通知,后台管理员通过后台系统发布系统通知,然后通知会通过推送的方式发送给前台用户。
    (4)网盘管理,每个用户系统会分配一个网盘给他,用户可以在分配的网盘里面创建文件夹,上传各种格式的文件,文件下载,文件重命名,文件复制,文件删除。除此之外,用户可以在线浏览文档,图片和视频等多媒体资源。
    (5)企业内部资源查询,用户可以把自己个人好的资源加入到企业内部共享网盘,例如,自己总结的或者看到的优秀的技术文档,或者一些有技术含量的开源项目、开发工具等。在上方的输入框可以通过输入关键词对资源进行模糊查询。
    (6)分享管理,用户可以把自己一些好的资源分享给企业其他用户,可以通过搜索相关的用户,然后将资源分享给他,也可以通过生成一个code,然后拼接一个url进行分享。
    (7)关注用户,自己感兴趣的一些用户可以进行关注,当关注的用户发布他们的资源,关注他的用户可以在动态里面看见。
    后台:
    (1)用户登录,这里提供了多种登录的方式,如账号登录,扫码登录,短信登录,方便用户登录网盘系统。
    (2)首页数据大盘,系统管理员可以通过可视化的界面查看企业内部用户使用该系统的活跃折线图,资源下载排行榜,资源受欢迎程度排行榜。
    (3)用户管理,本次毕设系统面向两类用户人群,一类是前台用户,管理员可以通过导入Excel的方式批量添加用户,也可以一条一条添加,而后台用户只能单条添加。管理员可以对用户信息分别进行编辑,删除操作。
    (4)部门管理,企业刚开始使用系统时,需要将企业部门相关信息完善,后台提供了非常
    友好的界面和操作方便管理员录入。
    (5)角色管理,系统超级管理员可以添加多个角色,然后分别给角色分配权限,该权限包过系统后台菜单的权限和部门之间的数据权限,保存之后即可生效。
    (6)企业共享网盘资源管理,后台管理员可以管理企业内部用户上传在共享网盘上的资源,可以将一些劣质的,对企业无关的资料进行清除。
    (7)系统管理,管理员可以动态的增加,删除,修改菜单,给菜单分配对应的权限,这样设置的好处是可以将不同的菜单功能面向不同的用户人群;在该模块下的定时任务配置管理界面中,用户可以配置Corn表达式,来定时触发需要执行的代码。系统管理员在日志管理里面查看所有的系统日志,如果系统监控一些奇怪的请求,系统会及时将相关异常信息通过邮件发送给管理员。
    (8)其他管理,系统对后台所有提供的接口生成一个在线接口文档,对系统开发人员,和系统以后的维护有重要的意义。
    (9)系统监控,在该模块下有服务器监控,Sql监控,Hadoop监控,SpringCloud微服务注册中心监控。

    2.1.2 功能需求描述
    经过对企业网盘的需求分析,我们最终决定本次毕业设计系统采用SpringCloud,首先需要将所有的服务启动,然后注册到服务注册中心,服务之间可以互相调用,访问的协议是Http。最后引入API Gateway作为轻量级网关,该网关处理分发前端的请求,通过JSON数据返回给前端。为了保证该系统信息的保密性,访问该系统所有的用户都需要进行权限校验,只有校验成功的用户才可以成功跳转到系统主界面。然后在拦截器里面根据用户ID去用户角色表和用户菜单表查出用户可以访问的菜单权限和数据权限,从而给用户展示不同的界面,系统角色功能如下:
    (1)企业普通员
    该用户通过前台系统登陆后,进入系统首页,首页会有个图表展示,登陆用户可以清楚知道自己网盘里面的文件数和分享的文件数,右侧也会有个企业员工分享排行榜,然后用户可以分别操作网盘,分享,资源库,关注用户,个人信息修改,系统通知这几个模块。在我的网盘管理模块中,用户可以通过用户或链接的方式将自己的资源分享给其他的用户,也可以将文件发布到企业共享网盘里面。只要是在企业里面的员工都有权限查看企业的共享网盘,可以在线查看共享网盘里面的文件,下载到自己本地。

    (2)管理员
    用户通过后台入口登陆后台系统,系统通过账号自动检测用户的类型,管理员登陆后,会根据管理员所拥有的菜单权限和部门数据权限控制用户所能看到的后台界面和查询数据的范围。管理员可以添加前台用户,然后给用户分配部门和所拥有的角色,另外还有网盘管理模块的权限,在网盘管理这个模块中,本文转载自http://www.biyezuopin.vip/onews.asp?id=14712,管理员可以查看企业共享网盘里面所有的资源文件,并有权修改文件信息,规范网盘。

    (3)超级管理员
    系统超级管理员默认账号是admin,密码是asdf123。超级管理员登录系统后,管理员,如果是超级管理员,会跳过过滤器的校验。除此之外,超级管理员可以添加系统后台用户类型,动态配置后台菜单和对应页面按钮的权限,添加系统角色类型,添加企业部门相关信息。除了管理员有的功能外,超级管理员有权查看系统相关的日志,定时任务,公告管理,数据库监控,Hadoop分布式存储集群监控,微服务监控。

    //网关权限(Token)验证
    @Component
    public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
        @Autowired
        private TokenService tokenService;
        public static final String USER_KEY = "userId";
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response,  
    Object handler) throws Exception {
            Login annotation;
            if (handler instanceof HandlerMethod) {
                annotation = ((HandlerMethod) handler).getMethodAnnotation(Login.class);
            } else {
                return true;
            }
            if (annotation == null) {
                return true;
            }
            //从header中获取token
            String token = request.getHeader("token");
            //如果header中不存在token,则从参数中获取token
            if (StringUtils.isBlank(token)) {
                token = request.getParameter("token");
            }
            //token为空
            if (StringUtils.isBlank(token)) {
                throw new BizException("token不能为空");
            }
            //查询token信息
            SysUserEntity userEntity = tokenService.queryByToken(token);
            if (userEntity == null) {
                throw new BizException("token失效,请重新登录");
            }
            //设置userId到request里,后续根据userId,获取用户信息
            request.setAttribute(USER_KEY, userEntity.getUserId());
            return true;
        }
    }
    
    /**
     * 有@LoginUser注解的方法参数,注入当前登录用户
     */
    @Component
    public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
        @Autowired
        private IUserService userService;
    
        @Override
        public boolean supportsParameter(MethodParameter parameter) {
            return parameter.getParameterType().isAssignableFrom(SysUserEntity.class) && 
    parameter.hasParameterAnnotation(LoginUser.class);
        }
    
        @Override
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer 
    container,NativeWebRequest request, WebDataBinderFactory factory) throws 
    Exception {
            //获取用户ID
            Object userId = request.getAttribute(AuthorizationInterceptor.USER_KEY, 
    RequestAttributes.SCOPE_REQUEST);
            if(userId == null){
                return null;
            }
            //获取用户信息
            return userService.getUserByUserId(userId.toString());
        }
    }
    
    /**
     * TokenService的实现
     */
    @Service("tokenService")
    public class TokenServiceImpl implements TokenService {
        @Autowired
        private RedisUtil redisUtil;
        @Autowired
        private IUserService userService;
        private final static int EXPIRE = 3600 * 6;//6小时过期
        @Override
        public String createToken(long userId) {
            //生成token
            String token = generateToken();
            SysUserEntity userEntity = userService.getUserByUserId(String.valueOf(userId));
            if (StringUtils.isEmpty(token) || userEntity == null) {
                throw new BizException("token生成失败!");
            }
            redisUtil.setObject(token, userEntity, EXPIRE);
            return token;
        }
    
        @Override
        public void cleanToken(String token) {
            redisUtil.delete(token);
        }
    
        @Override
        public SysUserEntity queryByToken(String token) {
            return (SysUserEntity) redisUtil.get(token);
        }
    
        private String generateToken() {
            return UUID.randomUUID().toString().replace("-", "");
        }
    
        //生成短信验证码
        private int generateCapatcha(){
            Random random = new Random();
            int max = 999999;// 最大值
            int min = 100000;// 最小值
            int code = random.nextInt(max);// 随机生成
            if(code < min){// 低于6位数,加上最小值,补上
                code = code + min;
            }
            return code;
        }
    
        @Override
        public String createCaptcha(String mobile) {
            String key = RedisKeys.getCapatchaKey(mobile);
            Object result = redisUtil.get(key);
            if (result == null){
                String capathca = String.valueOf(generateCapatcha());
                redisUtil.setObject(key, capathca, 60);
                return capathca;
            }
            return result.toString();
        }
    
        @Override
        public boolean checkCaptcha(String mobile, String captcha) {
            String key = RedisKeys.getCapatchaKey(mobile);
            Object result = redisUtil.get(key);
            if (result == null){
               return false;
            }
            return result.toString().equals(captcha);
        }
    }
    
    
    /**
     * 企业网盘SpringCloud服务调用
     */
    @FeignClient(name = "service", url = "http://localhost:9000")
    public interface IDiskService {
    
        /**
         * 获取企业网盘资源
         */
        @RequestMapping(value = "/front/app/listDisk")
        List<FileEntity> listDisk(@RequestParam("deptId") String deptId,
                                  @RequestParam("diskId") String diskId,
                                  @RequestParam("fileName") String fileName,
                                  @RequestParam("page") Integer page,
                                  @RequestParam("limit") Integer limit);
    
        /**
         * 获取总页数
         */
        @RequestMapping(value = "/front/app/listDiskTotal")
        int listDiskTotal(@RequestParam("deptId") String deptId,
                          @RequestParam("diskId") String diskId,
                          @RequestParam("fileName") String fileName);
    
        /**
         * 获取企业网盘目录类型
         */
        @RequestMapping(value = "/front/app/listDiskDirType")
        List<DiskDirVo> listDiskDirType(@RequestParam("userId") String userId,
                                        @RequestParam("deptId") String deptId);
    
    
    /**
    * 异常处理器
    */
    @RestControllerAdvice
    public class BizExceptionHandler {
       private Logger logger = LoggerFactory.getLogger(getClass());
       //处理自定义异常
       @ExceptionHandler(BizException.class)
       public R handleBizException(BizException e){
          R r = new R();
          r.put("code", e.getCode());
          r.put("msg", e.getMessage());
          return r;
       }
    
       @ExceptionHandler(DuplicateKeyException.class)
       public R handleDuplicateKeyException(DuplicateKeyException e){
          logger.error(e.getMessage(), e);
          return R.error("数据库中已存在该记录");
       }
    
       @ExceptionHandler(Exception.class)
       public R handleException(Exception e){
          logger.error(e.getMessage(), e);
          return R.error();
       }
    }
    
    /**
     * 连接Hadoop
    */
    public class HdfsConn {
        private FileSystem fileSystem = null;
        private Configuration configuration = null;
        private static final String serverUrl = "hdfs://60.205.212.196:9000/";
        private static final String HADOOP_HOME = "E:\\hadoop-2.8.3";
        //创建单例
        private static class SingletonHolder{
            private static final HdfsConn INSTANCE = new HdfsConn();
        }
    
        //初始化
        private HdfsConn(){
            try {
                configuration = new Configuration();
                configuration.set("fs.defaultFS", serverUrl);
                /*System.setProperty("HADOOP_USER_NAME", "hdfs");*/
                System.setProperty("HADOOP_USER_NAME", "root");
                System.setProperty("hadoop.home.dir", HADOOP_HOME);
                configuration.set("dfs.permissions", "false");
                fileSystem = FileSystem.get(configuration);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static FileSystem getFileSystem() {
            return SingletonHolder.INSTANCE.fileSystem;
        }
    
        public static Configuration getConfiguration() {
            return SingletonHolder.INSTANCE.configuration;
        }
    
        public static void main(String[] args) throws Exception{
            String dir = "/cxx/aa";
            FileSystem fs = getFileSystem();
            if (!fs.exists(new Path(dir))) {
                fs.mkdirs(new Path(dir));
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    Windows与网络基础-4-安装GNS3软件环境
    关于ntp时间源的优先级问题
    热修复技术可谓是百花齐放
    集中签约 深算院YashanDB关键行业商用提速
    探索Java设计模式:桥接模式
    php7使用openssl_encrypt函数进行AES加密
    【题目推荐2】
    【javaEE】网络编程套接字
    Mysql 用户权限设置 细分数据库、表操作
    氨基NH2/羧酸COOH/马来酰亚胺MAL修饰CdTe/CdS量子点
  • 原文地址:https://blog.csdn.net/newlw/article/details/126701326