原 荐 SpringBoot 2.0 系列0

SpringBoot 2.0 系列004 --启动实战之配置文件

配置文件

配置文件加载流程

很多文档包括官方文档说SB的默认配置文件是application开头的文件,那么是为什么呢?

  • 我们先看下流程图

由上述流程我们发现,在执行SpringApplication的run方法中的prepareEnvironment子方法时,触发ConfigFileApplicationListener类中的 load方法,完成配置文件的加载

  • ConfigFileApplicationListener分析
public void load() {
  this.profiles = Collections.asLifoQueue(new LinkedList<Profile>());
  this.processedProfiles = new LinkedList<>();
  this.activatedProfiles = false;
  this.loaded = new LinkedHashMap<>();
  // 核心初始化方法  负责初始化 profile (spring.profiles.active) 
  // 如果没有则使用默认的AbstractEnvironment类中的(spring.profiles.default)default(可以是application-default名称的,也可以起不加)
  initializeProfiles();
  // 不为空时 循环加载  初始化了  理论上不会为空
  while (!this.profiles.isEmpty()) {
    Profile profile = this.profiles.poll();
    // 第二步 此方法加载 文件的前缀 active 以及后缀  和路径 
    load(profile, this::getPositiveProfileFilter,
         addToLoaded(MutablePropertySources::addLast, false));
    this.processedProfiles.add(profile);
  }
  // 默认加载的
  load(null, this::getNegativeProfileFilter,
       addToLoaded(MutablePropertySources::addFirst, true));
  addLoadedPropertySources();
  • 接 上边标注第二步的位置
private void load(Profile profile, DocumentFilterFactory filterFactory,
				DocumentConsumer consumer) {
            // getSearch 如果你配置了spring.config.location 路径  则使用此处路径
            // 否则是用默认的 ConfigFileApplicationListener.DEFAULT_SEARCH_LOCATIONS
            // 即 private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
			getSearchLocations().forEach((location) -> {
				boolean isFolder = location.endsWith("/");
				// getSearchNames 是你配置文件的名称 ,如果配置了spring.config.name 则使用配置的这个名字
				// 否则使用默认的 private static final String DEFAULT_NAMES = "application";
				// 这就是默认是application这个名字的原因
				Set<String> names = (isFolder ? getSearchNames() : NO_SEARCH_NAMES);
				names.forEach(
				       
                        // 第三步  location是路径  name是文件名 profile则是-defalut部分或者其他-dev之类的
						(name) -> load(location, name, profile, filterFactory, consumer));
			});
		}
  • 接上边标注第三步
private void load(String location, String name, Profile profile,
				DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
    
            // 这里需要注意的是propertySourceLoaders 此处是在new loader的时候初始化的,即我们流程中的addPropertySources一步
               				        //底层使用的是META-INF/spring.factories
               				        /** org.springframework.boot.env.PropertySourceLoader=\
                                          org.springframework.boot.env.PropertiesPropertySourceLoader,\
                                          org.springframework.boot.env.YamlPropertySourceLoader
                                       */
           // 这也就是 文件后缀支持 yml,yaml,properties,xml的原因
           // 没有名字的情况
			if (!StringUtils.hasText(name)) {
				for (PropertySourceLoader loader : this.propertySourceLoaders) {
					if (canLoadFileExtension(loader, location)) {
						load(loader, location, profile,
								filterFactory.getDocumentFilter(profile), consumer);
					}
				}
			}
			// 带后缀名的情况
			for (PropertySourceLoader loader : this.propertySourceLoaders) {
				for (String fileExtension : loader.getFileExtensions()) {
					String prefix = location + name;
					fileExtension = "." + fileExtension;
					// 第四步 通过后缀名方式加载
					loadForFileExtension(loader, prefix, fileExtension, profile,
							filterFactory, consumer);
				}
			}
		}
  • 接第四步
private void loadForFileExtension(PropertySourceLoader loader, String prefix,
				String fileExtension, Profile profile,
				DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
			DocumentFilter defaultFilter = filterFactory.getDocumentFilter(null);
			DocumentFilter profileFilter = filterFactory.getDocumentFilter(profile);
			// 前边说的 -default和-dev部分
			if (profile != null) {
				// Try profile-specific file & profile section in profile file (gh-340)
				// prefix 是路径名+文件名
				// fileExtension是.yml这种
				// profile 则是第一步initializeProfiles 是this.profiles注入的
				String profileSpecificFile = prefix + "-" + profile + fileExtension;
				// 各处执行装载 扫描不同路径下是否有对应配置文件
				load(loader, profileSpecificFile, profile, defaultFilter, consumer);
				load(loader, profileSpecificFile, profile, profileFilter, consumer);
				// Try profile specific sections in files we've already processed
				for (Profile processedProfile : this.processedProfiles) {
					if (processedProfile != null) {
						String previouslyLoaded = prefix + "-" + processedProfile
								+ fileExtension;
						load(loader, previouslyLoaded, profile, profileFilter, consumer);
					}
				}
			}
			// Also try the profile-specific section (if any) of the normal file
			//// 各处执行装载 扫描不同路径下是否有对应配置文件
			// 第五步
			load(loader, prefix + fileExtension, profile, profileFilter, consumer);
		}
  • 接 第五步

第三步和第四步都会执行下面的方法

private void load(PropertySourceLoader loader, String location, Profile profile,
				DocumentFilter filter, DocumentConsumer consumer) {
			try {
				Resource resource = this.resourceLoader.getResource(location);
				String description = getDescription(location, resource);
				if (profile != null) {
					description = description + " for profile " + profile;
				}
				if (resource == null || !resource.exists()) {
					this.logger.trace("Skipped missing config " + description);
					return;
				}
				if (!StringUtils.hasText(
						StringUtils.getFilenameExtension(resource.getFilename()))) {
					this.logger.trace("Skipped empty config extension " + description);
					return;
				}
				String name = "applicationConfig: [" + location + "]";
				// 转换成docment对象 
				List<Document> documents = loadDocuments(loader, name, resource);
				if (CollectionUtils.isEmpty(documents)) {
					this.logger.trace("Skipped unloaded config " + description);
					return;
				}
				List<Document> loaded = new ArrayList<>();
				for (Document document : documents) {
				    // 文档Filter
					if (filter.match(document)) {
						maybeActivateProfiles(document.getActiveProfiles());
						addProfiles(document.getIncludeProfiles());
						loaded.add(document);
					}
				}
				Collections.reverse(loaded);
				if (!loaded.isEmpty()) {
				    // consumer对象来自 addToLoaded方法 目的是装载到PropertySources中
					loaded.forEach((document) -> consumer.accept(profile, document));
					
					// 开启debug后 打印出这句话 表示文件被加载完毕。 
					this.logger.debug("Loaded config file " + description);
				}
			}
			catch (Exception ex) {
				throw new IllegalStateException("Failed to load property "
						+ "source from location '" + location + "'", ex);
			}
		}

配置文件使用

由上述分析可知,默认的配置文件名为application(-{profile}).yml/xml/yaml/properties,且默认支持项目的resources路径

问题1 怎么使用名称不是application的文件?

根据流程分析可知,文件默认完整名称是由spring.config.name和spring.profiles.default两条属性控制。由此可知,在启动前注入此属性即可。

  • 目标 ,修改默认application为ricky01 ,defalut默认bgt01
  • 在resources新建如下几个文件及内容

默认端口是8010 其他是8011,8012,8013,

  • 注入 spring.config.name和spring.profiles.default属性

主要有如下3种方式

/**
     *   测试自定义加载文件的方式 01  通过启动设置参数
     *  --spring.config.name=ricky01 --spring.profiles.default=bgt01
     * @param args
     */
    public static void main01(String[] args) throws InterruptedException {
        SpringApplication application = new SpringApplication(SpringBootApplication01.class);
        application.run(args);
    }

    /**
     *   测试自定义加载文件的方式 01  通过启动设置参数
     *  设置环境变量
     * @param args
     */
    public static void main02(String[] args) throws InterruptedException {
        System.setProperty("spring.config.name", "ricky01");
        System.setProperty("spring.profiles.default", "bgt02");
        SpringApplication application = new SpringApplication(SpringBootApplication01.class);
        application.run(args);
    }

    /**
     *   测试自定义加载文件的方式 01  通过启动设置参数
     *  设置传入参数
     * @param args
     */
    public static void main(String[] args) throws InterruptedException {
        args=new String[2];
        args[0]="--spring.config.name=ricky01";
        args[1]="--spring.profiles.default=bgt03";
        SpringApplication application = new SpringApplication(SpringBootApplication01.class);
        application.run(args);
    }
  • 结果

公用ricky01.yml中的contextpath,服务端口却是各自定义的。以下是bgt03时的启动日志

.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.1.RELEASE)

2018-05-16 13:40:25.165  INFO 24984 --- [           main] com.ricky.SpringBootApplication01        : Starting SpringBootApplication01 on jsb-bgt with PID 24984 (D:\work\ideawork\SpringBootLearn\chapter04\target\classes started by zdwljs in D:\work\ideawork\SpringBootLearn)
2018-05-16 13:40:25.169  INFO 24984 --- [           main] com.ricky.SpringBootApplication01        : No active profile set, falling back to default profiles: bgt03
2018-05-16 13:40:25.263  INFO 24984 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@3e92efc3: startup date [Wed May 16 13:40:25 CST 2018]; root of context hierarchy
2018-05-16 13:40:28.721  INFO 24984 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8013 (http)
2018-05-16 13:40:28.756  INFO 24984 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2018-05-16 13:40:28.757  INFO 24984 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.29
2018-05-16 13:40:28.770  INFO 24984 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [D:\Program Files\Java\jdk1.8.0_161\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;d:\work\Git\cmd;C:\Program Files (x86)\MySQL\MySQL Server 5.5\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Users\zdwljs\AppData\Local\Microsoft\WindowsApps;D:\Program Files\Java\jdk1.8.0_161\bin;;.]
2018-05-16 13:40:28.924  INFO 24984 --- [ost-startStop-1] o.a.c.c.C.[.[localhost].[/ricky01]       : Initializing Spring embedded WebApplicationContext
2018-05-16 13:40:28.924  INFO 24984 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3672 ms
2018-05-16 13:40:29.149  INFO 24984 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2018-05-16 13:40:29.155  INFO 24984 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-05-16 13:40:29.155  INFO 24984 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-05-16 13:40:29.155  INFO 24984 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-05-16 13:40:29.155  INFO 24984 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2018-05-16 13:40:29.371  INFO 24984 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-05-16 13:40:29.783  INFO 24984 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@3e92efc3: startup date [Wed May 16 13:40:25 CST 2018]; root of context hierarchy
2018-05-16 13:40:29.905  INFO 24984 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2018-05-16 13:40:29.907  INFO 24984 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-05-16 13:40:29.947  INFO 24984 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-05-16 13:40:29.947  INFO 24984 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-05-16 13:40:30.183  INFO 24984 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-05-16 13:40:30.245  INFO 24984 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8013 (http) with context path '/ricky01'
2018-05-16 13:40:30.251  INFO 24984 --- [           main] com.ricky.SpringBootApplication01        : Started SpringBootApplication01 in 5.845 seconds (JVM running for 6.639)

问题2 怎么使用外部配置文件加载 方便统一管理

比如我们放在D:\work\ricky\config目录下管理

  • 目标 使用d盘config目录下的文件,如下
  • 第一步 在d盘新建上述文件 默认端口是8020 bgt01端口则是8021
  • 第二步 更改加载路径,如下

这里 只罗列一种方式 其他的和上面修改apllication方式一样

public static void main(String[] args) throws InterruptedException {
        args=new String[3];
        args[0]="--spring.config.location=file:d:/work/ricky/config/";
        args[1]="--spring.config.name=ricky02";
        args[2]="--spring.profiles.default=bgt01";
        SpringApplication application = new SpringApplication(SpringBootApplication02.class);
        application.run(args);
    }
  • 结果
.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.1.RELEASE)

2018-05-16 14:09:21.111  INFO 19708 --- [           main] com.ricky.SpringBootApplication02        : Starting SpringBootApplication02 on jsb-bgt with PID 19708 (D:\work\ideawork\SpringBootLearn\chapter04\target\classes started by zdwljs in D:\work\ideawork\SpringBootLearn)
2018-05-16 14:09:21.118  INFO 19708 --- [           main] com.ricky.SpringBootApplication02        : No active profile set, falling back to default profiles: bgt01
2018-05-16 14:09:21.221  INFO 19708 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1ab06251: startup date [Wed May 16 14:09:21 CST 2018]; root of context hierarchy
2018-05-16 14:09:24.122  INFO 19708 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8021 (http)
2018-05-16 14:09:24.187  INFO 19708 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2018-05-16 14:09:24.187  INFO 19708 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.29
2018-05-16 14:09:24.208  INFO 19708 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [D:\Program Files\Java\jdk1.8.0_161\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;d:\work\Git\cmd;C:\Program Files (x86)\MySQL\MySQL Server 5.5\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Users\zdwljs\AppData\Local\Microsoft\WindowsApps;D:\Program Files\Java\jdk1.8.0_161\bin;;.]
2018-05-16 14:09:24.427  INFO 19708 --- [ost-startStop-1] o.a.c.c.C.[.[localhost].[/ricky02]       : Initializing Spring embedded WebApplicationContext
2018-05-16 14:09:24.429  INFO 19708 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3225 ms
2018-05-16 14:09:24.748  INFO 19708 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2018-05-16 14:09:24.756  INFO 19708 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-05-16 14:09:24.757  INFO 19708 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-05-16 14:09:24.757  INFO 19708 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-05-16 14:09:24.758  INFO 19708 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2018-05-16 14:09:24.980  INFO 19708 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-05-16 14:09:25.424  INFO 19708 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1ab06251: startup date [Wed May 16 14:09:21 CST 2018]; root of context hierarchy
2018-05-16 14:09:25.583  INFO 19708 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2018-05-16 14:09:25.586  INFO 19708 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-05-16 14:09:25.672  INFO 19708 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-05-16 14:09:25.672  INFO 19708 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-05-16 14:09:25.989  INFO 19708 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-05-16 14:09:26.185  INFO 19708 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8021 (http) with context path '/ricky02'
2018-05-16 14:09:26.191  INFO 19708 --- [           main] com.ricky.SpringBootApplication02        : Started SpringBootApplication02 in 13.196 seconds (JVM running for 14.36)

这里实现的只是外部的,如果你还是需要在项目中则可以修改location=classpath:/XXX/

演示项目地址,欢迎fork和star

码云:SpringBootLearn

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

go语言制作的zip压缩程序

package main import ( "archive/zip" "bytes" "fmt" "io/ioutil" "os" "path/f...

2555
来自专栏CaiRui

Shell中的$..

$0 这个程式的执行名字 $n 这个程式的第n个参数值,n=1..9 $* 这个程式的所有参数,此选项参数可超过9个。 $# 这个程式的参数个数 $$ 这个程式...

3189
来自专栏C/C++基础

Linux命令(39)——du命令

(1)文件大小与占用磁盘空间大小的区别。 文件大小(又名 apparent size)是文件自身实际大小,与占用磁盘空间大小(又名 occupied spa...

661
来自专栏Java Edge

操作系统之文件管理概述1 文件和文件系统3 目录管理4 文 件 共 享5 文件保护5.1.1 访问矩阵的实现6 文件物理结构(重点)2文件存储空间管理(重点)

28210
来自专栏Golang语言社区

Golang语言社区--go语言执行cmd命令关机、重启等

大家好,我是Golang语言社区主编彬哥,这篇给大家带来关于Go语言操作cmd命令执行windows平台的相关操作

64919
来自专栏码匠的流水账

storm drpc实例

492
来自专栏kwcode

System.Runtime.InteropServices.COMException (0x800A03EC): 无法访问文件

System.Runtime.InteropServices.COMException (0x800A03EC): 无法访问文件。请尝试下列方法之一:

632
来自专栏杂烩

Eclipse下Hadoop的MapReduce开发之单Map编写

    先说下业务需求吧,有个系统日志文件,记录系统的运行信息,其中包含DEBUG、INFO、WARN、ERROR四个级别的日志,现在想要看到所有WARN级别的...

653
来自专栏菩提树下的杨过

mongodb 速成笔记

以下环境为mac osx + jdk 1.8 + mongodb v3.2.3 一、安装 brew安装方式是mac下最简单的方式 brew update bre...

1955
来自专栏SpringSpace.cn

RHEL 4.7 (64bit) 环境安装 GCC 4.6 测试记录 (更新至gcc-4.6.1)

Red Hat Enterprise Linux AS release 4 (Nahant Update 7)

1202

扫码关注云+社区