目录
入门部分
1.Spring Boot 简介
2.微服务
3.环境准备
4.Maven配置
5.IDEA配置
6.修改Banner
7.使用IDEA创建一个项目
8.添加Banner文件
9.创建Controller类
10.一个方法映射多个URL地址
11.窄化请求
12.其他创建方式
13.其他运行方式
讲原理部分
1、从POM文件讲原理
2、启动器
3、主程序类,主入口类
4、自动配置原理
参数传递
1.get方式Url传参:
2.get方式Url传参:
3.get方式Url传参:
4.POST方式传递数据
5.POST传递字符串文本
6.@requestbody接收参数
SwaggerAPI框架
1.添加依赖
2.Swagger配置
3.使用注解
4.Webjars的使用
springboot-配置文件的使用
1、配置文件的使用
2、切换配置文件
1、多配置文件
2、单配置文件[分块]
3、激活指定profile
4、配置文件加载位置
springboot-配置文件详解
1.YML是什么
2.YML语法
字面量
对象、Map
数组
springboot-配置文件的注入
1、单值注入
2、批量注入
3、两种注入的区别
4、注入值的数据校验
springboot-其他配置文件
1、@PropertySource
2、@ImportResource
3、@Bean
4、配置文件占位符
入门部分
1.Spring Boot 简介
简化Spring应用开发的一个框架;
整个Spring技术栈的一个大整合;
J2EE开发的一站式解决方案;
spring官网
2.微服务
2014,martin fowler
微服务:架构风格(服务微化)
一个应用应该是一组小型服务;可以通过HTTP的方式进行互通;
单体应用:ALL IN ONE
微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元;
3.环境准备
SpringBoot2.0环境约束
- jdk1.8+;java version 1.8.0_112
- maven 3.3+;Apache Maven 3.5.4
- A favorite text editor or IDE:IntelliJ IDEA 2018.2.6
- SpringBoot 2.1.1.RELEASE
4.Maven配置
给$M2_HOME\conf\settings.xml配置文件t添加如下内容
- 在之间添加如下内容
- 作用:国内maven仓库镜像[众所周知的原因国内不能很好的访问maven中央仓库]
- 在之间添加如下内容
- 作用:指定项目编译运行使用的JDK版本
5.IDEA配置
整合Maven进来
6.修改Banner
1 2 3 4 5 6 7 8 9 10 | ${AnsiColor.BLUE} _______ _______ ______ | || || | |____ || ___|| _ | ____| || |___ | | | | | ______|| ___|| |_| | | |_____ | |___ | | |_______||_______||______| -----版本号-----${spring-boot.version} |
文字Banner可以从这个网站生成[有很多种字体样式可以选择]
//patorjk.com/software/taag
${AnsiColor.BLUE} 表示Banner文字的颜色
${spring-boot.version} 当前使用的SpringBoot版本
7.使用IDEA创建一个项目
- 目录结构说明
- src/main/java: Java代码的目录
- src/main/resources: 资源目录
- src/test/java: 测试代码的目录
- src/test/resources: 测试资源目录
- POM文件说明
8.添加Banner文件
${AnsiColor.BLUE} _______ _______ ______ | || || | |____ || ___|| _ | ____| || |___ | | | | | ______|| ___|| |_| | | |_____ | |___ | | |_______||_______||______| -----版本号-----${spring-boot.version}在resources目录下创建banner.txt文件,添加以下内容
可以更换成你自己的banner
9.创建Controller类
- 文件模板修改
直接右上角运行
访问//localhost:8080/hello
- 注解的方式还有一种,和上面的效果一样
如果这个类下面的所有方法都是加了@ResponseBody注解,我们可以把@Controller和@ResponseBody去掉,仅使用@RestController注解
package com.example.demo.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloWorld { @RequestMapping[value = "/hello", method = RequestMethod.GET] public String hello[] { return "hello SpringBoot"; } }
- 还可以简化
如果我们使用的是@RequestMapping的GET请求可以简化使用@GetMapping注解
package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloWorld { @GetMapping["/hello"] public String hello[] { return "hello SpringBoot"; } }注解说明:
@RestController: 处理http请求:等同于@Controller+@ResponseBody @RequestMapping: value = "访问的路由" method = 请求方法 @GetMapping:以GET方式请求 相当于对@RequestMapping配置的缩写
10.一个方法映射多个URL地址
package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloWorld { @GetMapping[{"/hello", "/hi"}] //注意这里的{} public String hello[] { return "hello SpringBoot"; } }//localhost:8080/hello
//localhost:8080/hi
11.窄化请求
package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping["/user"]//这个地址就叫做窄化请求 public class HelloWorld { @GetMapping["/hello"] public String hello[] { return "hello SpringBoot"; } }
类和方法都有value时,访问的地址是类上的地址拼接上方法上的地址。
//localhost:8080/user/hello
12.其他创建方式
- SPRING INITIALIZR:通过IDEA或者STS工具创建INITIALIZR项目(上面所写的项目创建就是这样)
- 创建Maven项目手动添加依赖
- 通过//start.spring.io/生成定制项目
下面我们演示,创建Maven项目手动添加依赖
手动添加依赖
启动类需要自己手动编写,类名叫什么无所谓,但是必须添加一个注解叫@SpringBootApplication,然后在写一个main方法,
然后再编写一下他的控制器类,跟之前我们写的一样
启动,启动完成后会扫描的类
下面我们演示,通过//start.spring.io/生成定制项目
最后会下载一个ZIP包,我们可以解压到桌面然后通过IDEA导入这个项目
选择刚才解压的文件夹,一直下一步就行了
然后跟之前一样分开写类也可以跟下面一样写一起。
13.其他运行方式
- 在IDE中直接运行
- 发布Jar包运行
在pom/xml文件引用插件
org.springframework.boot spring-boot-maven-plugin导入这个maven插件,利用idea打包,
生成的jar包,可以使用java -jar xxx.jar启动
Spring Boot 使用嵌入式的Tomcat无需再配置Tomcat
讲原理部分
1、从POM文件讲原理
org.springframework.boot spring-boot-starter-parent 2.1.1.RELEASE父项目
spring-boot-starter-parent他的父项目是:
org.springframework.boot spring-boot-dependencies 2.1.1.RELEASE ../../spring-boot-dependencies这是真正管理Spring Boot应用里面所依赖的版本
Spring Boot的版本仲裁中心;
以后我们导入依赖默认是不需要写版本;
(没有在dependencies里面管理的依赖自然需要声明版本号)
太多了就放两张图感受一下就行啦。
2、启动器
org.springframework.boot spring-boot-starter-web我们去他的官网看一下
spring-boot-starter-web:
spring-boot-starter:spring-boot场景启动器,帮我们导入了web模块正常运行所依赖的组件;
点击进去可以看到帮我们引入很多web相关的依赖
Spring Boot将所有的功能场景都抽取出来,做成一个个的starters(启动器),只需要在项目里面引入这些starter相关场景的所有依赖都会导入进来,要用什么功能就导入什么场景的启动器
3、主程序类,主入口类
@SpringBootApplication public class DemoApplication { public static void main[String[] args] { SpringApplication.run[DemoApplication.class, args]; } }@SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;
点进去这个注解可以看到下面的源码
@Target[ElementType.TYPE] @Retention[RetentionPolicy.RUNTIME] @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan[excludeFilters = { @Filter[type = FilterType.CUSTOM, classes = TypeExcludeFilter.class], @Filter[type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class] }] public @interface SpringBootApplication {- @SpringBootConfiguration: Spring Boot的配置类,标注在某个类上,表示这是一个Spring Boot的配置类
- @Configuration: 配置类上来标注这个注解,配置类也是容器中的一个组件@Component
- @EnableAutoConfiguration:开启自动配置功能
点击@SpringBootConfiguration可以看到下面的源码,这是SpringBoot的底层的注解叫@Configuration,之前我们在使用Spring的时候会出现大量的XML文件,后来在使用SpringBoot之后推荐我们使用类+注解的形式来使用配置,就再也不会出现大量的XML文件了,所以某些类要是做配置类必须加上@Configuration来标注他是配置类
点击@EnableAutoConfiguration可以看到下面的源码
- 将主配置类(@SpringBootApplication标注的类 )的所在包及下面所有子包里面的所有组件都可以扫描到Spring容器;
下面我们做个试验
可以看到在启动类和控制器类在不同的包下面,那么我们在访问控制器类发现找不到了
所以我们一般会把启动类放在外层
- 调用了SpringFactoriesLoader.loadFactoryNames[EnableAutoConfiguration.class,classLoader];
- Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作;
- 以前我们需要自己配置的东西,自动配置类都帮我们;
- 有了自动配置类,免去了我们手动编写配置注入功能组件等的工作;
- J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-1.5.9.RELEASE.jar;
4、自动配置原理
1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
2)、@EnableAutoConfiguration 作用:
-
利用EnableAutoConfigurationImportSelector给容器中导入一些组件?
-
可以查看selectImports[]方法的内容;
-
List configurations = getCandidateConfigurations[annotationMetadata, attributes];获取候选的配置
将类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中
精髓:
1)、SpringBoot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;
xxxxAutoConfigurartion:自动配置类[给容器中添加组件]; xxxxProperties:封装配置文件中相关属性;参数传递
参数传递可以说是服务端和外界沟通的主要方式
本段内容包括:
1.get方式Url传参:
package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping["/hello/{name}"] public String hello[@PathVariable["name"] String name] { // 最后一个name是形参name,名字可以随意,但是前两个要保持一致 return "hello " + name; } }@PathVariable 路径传参,可以在路径上拼接参数的
- 访问://localhost:8080/hello/jenrey
2.get方式Url传参:
package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping["/hello"] public String hello[@RequestParam["name"] String name] { System.out.println["获取到的name是:" + name]; return "hello " + name; } }@RequestParam
如果请求参数的名字跟方法中的形参名字一致可以省略@RequestParam[name]
- 访问://localhost:8080/hello?name=jenrey
如果请求参数的名字跟方法中的形参名字一致可以省略@RequestParam[name],如下
package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping["/hello"] public String hello[String name] { System.out.println["获取到的name是:" + name]; return "hello " + name; } }3.get方式Url传参:
package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping["/hello"] public String hello[@RequestParam[value = "name", defaultValue = "admin"] String n] { System.out.println["获取到的name是:" + n]; return "hello " + n; } }@RequestParam+默认参数
package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping["/hello"] public String hello[@RequestParam[value = "name", required = false] String n] { System.out.println["获取到的name是:" + n]; return "hello " + n; } }注意:如果没有指定默认值,并且没有传递参数将会报错
Required String parameter 'name' is not present:name参数没有提供
- 解决方案
- 1.defaultValue = xxx:使用默认值
- 2.required = false:标注参数是非必须的
4.POST方式传递数据
package com.example.demo.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { Logger log = LoggerFactory.getLogger[HelloController.class]; @PostMapping["/hello"] public String add[@RequestParam["name"] String name, @RequestParam["age"] Integer age] { log.info[name + " " + age]; log.info[age.getClass[].getSimpleName[]]; //打印age的类型,可以自动帮我们转的 return "name:" + name + "\nage:" + age; } }因为POST请求不好通过浏览器模拟,所以我们使用Postman软件来实现
5.POST传递字符串文本
package com.example.demo.controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @RestController public class HelloController { @PostMapping["/postString"] public String postString[HttpServletRequest request] { ServletInputStream is = null; StringBuilder sb = null; try { is = request.getInputStream[]; //所有请求体中的内容会封装到request上。 sb = new StringBuilder[]; byte[] buf = new byte[1024]; int len = 0; while [[len = is.read[buf]] != -1] { sb.append[new String[buf, 0, len]]; } System.out.println[sb.toString[]]; return sb.toString[]; } catch [IOException e] { e.printStackTrace[]; } finally { try { if [is != null] { is.close[]; } } catch [IOException e] { e.printStackTrace[]; } } return sb.toString[]; } }通过HttpServletRequest获取输入流
6.@requestbody接收参数
- @requestbody可以接收GET或POST请求中的参数
- 把json作为参数传递,要用【RequestBody】
- 附带着说一下使用postman方式设置content-type为application/json方式测试后台接口
下面是User的pojo类
package com.example.demo.pojo; public class User { private String username; private String age; public String getUsername[] { return username; } public void setUsername[String username] { this.username = username; } public String getAge[] { return age; } public void setAge[String age] { this.age = age; } } package com.example.demo.controller; import com.example.demo.pojo.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { Logger log = LoggerFactory.getLogger[HelloController.class]; @PostMapping["/user"] public String user[@RequestBody User user] { log.info[user.toString[]]; return null; } }SwaggerAPI框架
为了方便上面的API接口调试,我们可以使用:
- Postman:模拟POST请求
- Swagger:描述和测试API接口
1.添加依赖
io.springfox springfox-swagger2 2.9.2 io.springfox springfox-swagger-ui 2.9.2 org.projectlombok lombok 1.18.4 provided2.Swagger配置
yml配置文件
swagger: title: SpringBoot学习 description: SpringBoot快速入门 version: 1.0.0 name: jenrey url: //jenrey.csdn.net email:新建一个config包,下面新建一个SwaggerConfig.java文件,内容如下
package com.example.demo.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration //配置类必须要加这个注解 @EnableWebMvc //必须加上 @EnableSwagger2 //必须加上 @ConfigurationProperties[prefix = "swagger"] //把yml里面的基本信息导入到我们的配置类中,并制定前缀 @Data //因为我们是API接口文档它必须要扫描控制器层,而控制器这些类在哪个包下面我们必须指定一下,通过一个组件扫描指定一下控制器所在的包 @ComponentScan[basePackages = {"com.example.demo.controller"}] public class SwaggerConfig { private String title; //下面这些值我们直接在配置文件里面去写 private String description; private String version; private String name; private String url; private String email; @Bean //用注解的方式创建的Bean,生成的Bean是放到容器里面了,生成一个docker,docker要配置一个API的基本信息info public Docket customDocket[] { return new Docket[DocumentationType.SWAGGER_2].apiInfo[apiInfo[]]; } private ApiInfo apiInfo[] { Contact contact = new Contact[name, url, email]; //然后基本信息里面有个联系人,需要联系人的姓名,url地址,邮箱 return new ApiInfoBuilder[] //返回一个ApiInfoBuilder .title[title] .description[description] .contact[contact] .version[version] .build[]; //是用创建者方式调用build方法,帮我们返回一个ApiInfo给它放到容器里面 } }新建一个WebMvcConfig.java文件,写入下面代码
package com.example.demo.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration class WebMvcConfig implements WebMvcConfigurer { public void addResourceHandlers[ResourceHandlerRegistry registry] { registry.addResourceHandler["swagger-ui.html"] .addResourceLocations["classpath:/META-INF/resources/"]; registry.addResourceHandler["/webjars/**"] .addResourceLocations["classpath:/META-INF/resources/webjars/"]; } }上面两个写好了之后就可以使用Swagger注解了,比如我们写一个控制类,来测试一下Swagger
3.使用注解
package com.example.demo.controller; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @Api[value = "用户模块的控制器"]//注释这个类是干嘛的,我们使用Swagger下面的@Api注解 public class HelloSwagger { Logger log = LoggerFactory.getLogger[HelloSwagger.class]; @GetMapping["/hello"] @ApiOperation[value = "测试Swagger"] //描述接口作用的 /* @ApiImplicitParams[ {@ApiImplicitParam[],@ApiImplicitParam[]} ] //有多参数用这个 */ public String hello[] { return "hello SpringBoot-Swagger"; } }在控制器API上添加接口描述的注解
然后我们运行一下SpringBoot
输入上述的地址可以看到是Swagger的描述信息
//localhost:8080/v2/api-docs
//localhost:8080/swagger-ui.html
Swagger的具体用法,请参照B站Swagger视频
4.Webjars的使用
其实就是把我们常用的一些,像jquery,BootStrap等组件都有Webjars的引入方式
官网://www.webjars.org/
把下面的配置写的pom中其实就是在我们的项目中添加了jquery
org.webjars jquery 3.3.1-1通过jar包的方式引入了jQuery
再浏览器中可以通过如下地址访问到
//localhost:8080/webjars/jquery/3.3.1-1/jquery.js
地址说明:/webjars/jquery/3.3.1-1/jquery.js
对应上面的 webjars/ artifactId/version/文件名
可以到项目中的jar包中具体查看。
所以我们通过这样的一个路径就可以请求到JQ了,是一种通过jar包来引入的方式,并不是向之前一样从官网或者其他地方下载一个JQ添加到我们的项目工程资源路径下。现在根本不需要了,直接引入jar包
springboot-配置文件的使用
1、配置文件的使用
#修改端口号 server.port=8081 #端口号后需额外添加字符 server.servlet.context-path=/demo修改配置方式1:src\main\resources\application.properties**
- 访问://localhost:8081/demo/hello
修改配置方式2:src\main\resources\application.yml
server: port: 8081 servlet: context-path: /zed个人比较喜欢yml
2、切换配置文件
1、多配置文件
src\main\resources\application-dev.yml
server: port: 8081src\main\resources\application-prod.yml
server: port: 8080src\main\resources\application.yml
- 根据active:来切换配置文件
注意active后面写那个就是激活那个配置文件
2、单配置文件[分块]
server: port: 8081 spring: profiles: prod --- server: port: 8080 spring: profiles: dev --- spring: profiles: active: prod
- 在单一文件中,可用连续三个连字号()区分多个文件。
- 根据active:来切换配置文件
spring profiles是配置块的名称。
3、激活指定profile
1、在配置文件中指定 spring.profiles.active=dev
2、命令行:
java -jar ***.jar spring.profiles.active=dev
可以直接在测试的时候,配置传入命令行参数
3、虚拟机参数,在IDEA或Eclipse中的run configuration中可以进行配置
-Dspring.profiles.active=dev
4、配置文件加载位置
springboot 启动后扫描以下位置的application.properties或者application.yml文件,
作为Spring boot的默认配置文件
file:./config/ | 项目目录下的config |
file:./ | 项目目录下 |
classpath:/config/ | resources目录下的config |
classpath:/ | resources目录下 |
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
我们还可以通过spring.config.location来改变默认的配置文件位置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;
指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
java -jar ***.jar spring.config.location=E:/application.yml
从spring的运行日志中可以看到:
Loaded config file 'file:./config/application.yml' [file:./config/application.yml] Loaded config file 'file:./application.yml' [file:./application.yml] Loaded config file 'file:/C:/Users/Administrator/Desktop/demo3/target/classes/config/application.yml' [classpath:/config/application.yml] Loaded config file 'file:/C:/Users/Administrator/Desktop/demo3/target/classes/application.yml' [classpath:/application.yml]配置文件的加载顺序:
- ./config/application.yml 项目目录下的config目录下的配置文件
- ./application.yml 项目目录下的配置文件
- classpath:/config/application.yml 资源路径下的config 目录下的配置文件
- classpath:/application.yml 资源路径下的配配置文件
总结:
- 先加载的优先级最高,后面的优先级低。
- 后面的配置文件中如果有不同的配置项,也会读取进来。
springboot-配置文件详解
1.YML是什么
SpringBoot使用一个全局的配置文件,配置文件名是固定的;
- application.properties
- application.yml
配置文件的作用:修改SpringBoot自动配置的默认值;
YAML(YAML Aint Markup Language)
YAML A Markup Language:是一个标记语言
YAML isnt Markup Language:不是一个标记语言
标记语言:
以前的配置文件;大多都使用的是xxx.xml文件;
YAML:以数据为中心,比json、xml等更适合做配置文件;
- YAML:配置例子
- XML:配置例子
2.YML语法
k:[空格]v:表示一对键值对(空格必须有);
以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
server: port: 8081 path: /hello属性和值也是大小写敏感;
字面量
普通的值(数字,字符串,布尔)
k: v 字面量直接来写
字符串默认不用加上单引号或者双引号; "":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思 name: "zhangsan \n lisi":输出;zhangsan 换行 lisi '':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据 name: zhangsan \n lisi:输出;zhangsan \n lisi总结:
对于字串的值,直接写和加上单引号的效果是一样,字串的内容原样输出,如果要使用特殊的字符的功能,需要加上双引号,比如说:\n如果是再双引号中的就作为换行了。
对象、Map
(属性和值)(键值对):
k: v:在下一行来写对象的属性和值的关系;注意缩进
对象还是k: v的方式
friends: lastName: zhangsan age: 20行内写法:
friends: {lastName: zhangsan, age: 18}数组
(List、Set):
用 - 值表示数组中的一个元素
pets: - cat - dog - pig行内写法
pets: [cat, dog, pig]springboot-配置文件的注入
1、单值注入
使用@Value注解注入单个属性的值
- yml配置文件
- java代码
${key} :来引用属性文件中key对应的值
2、批量注入
使用@ConfigurationProperties注解批量注入配置文件中的多个值
- yml配置文件
@Data是一个lomlok插件,免去了getter/setter和toString这些繁琐的东西
在POM文件的节点中间添加
org.projectlombok lombok 1.18.4 provided- 新建一个Person的Pojo类,代码如下
- 新建一个Dog的Pojo类,代码如下
使用@ConfigurationProperties注解必须同时添加@Component将当前的配置类放入IOC容器中
在编写yml文件的时候没有出现属性提示:
我们可以导入配置文件处理器,以后编写配置就有提示了
org.springframework.boot spring-boot-configuration-processor true发现变成了下面的灰色
我们重新启动IDEA,点击一下 隐藏通知 就行啦。
- 测试代码
- 控制台的输出
javaBean:
- 将配置文件中配置的每一个属性的值,映射到这个组件中
- @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
- prefix = person:配置文件中哪个下面的所有属性进行一一映射
- 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能;
- @Data是一个插件,,免去了getter/setter和toString这些繁琐的东西
3、两种注入的区别
@Value获取值和@ConfigurationProperties获取值的区别
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL: #{} | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
松散语法绑定:last_name = last-name = lastName 他们取的值都是相同的
配置文件yml还是properties他们都能获取到值;
总结:
- 如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
- 如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
4、注入值的数据校验
@ConfigurationProperties[prefix = "person"] @Component @Data @Validated //数据校验 public class Person { @Email[message = "用户名必须是一个正确的邮箱格式"] private String lastName; @Max[value = 200,message = "年龄不能超过200岁"] @Min[value = 0,message = "年龄必须大于0岁"] private Integer age; private Boolean boss; private Date birth; private Map maps; private List lists; private Dog dog; }经过刚才的测试得出,两个注解不能同时作用在一个属性上。
springboot-其他配置文件
1、@PropertySource
@PropertySource[value = {"classpath:person.properties"}] @Component @ConfigurationProperties[prefix = "person"] public class Person { // lastName必须是邮箱格式 // @Email // @Value["${person.last-name}"] private String lastName; // @Value["#{11*2}"] private Integer age; // @Value["true"] private Boolean boss;@PropertySource:加载指定的配置文件;
请注意 [字串,bool,时间,列表可以注入],map不能注入,
简单的数据类型Spring注入数据后进行了类型转换
断点查看可以知道注入的数据
person.lastName= person.age=18 person.boss=false person.birth=2017/12/12 person.lists=lisi,zhaoliu People[lastName=, age=18, pets=null, boss=false, birth=Tue Dec 12 00:00:00 CST 2017, lists=[[lisi, zhaoliu]]]IDEA设置*.properties文件的默认编码
Settings
>Editor
>File Encoding
>Properties Files[*.properties]
>Default encoding for properties files:UTF-8
>OK
2、@ImportResource
@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
想让Spring的配置文件生效,@ImportResource标注在一个配置类上
@ImportResource[locations = {"classpath:beans.xml"}] @SpringBootApplication public class SpringbootApplication { public static void main[String[] args] { SpringApplication.run[SpringbootApplication.class, args]; } }- Spring的配置文件
- 测试
3、@Bean
SpringBoot推荐使用全注解的方式给容器中添加组件
1、配置类@Configuration> Spring配置文件
2、使用@Bean给容器中添加组件
/** * @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件 * 在配置文件中用标签添加组件 */ @Configuration public class MyAppConfig { // 将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名 @Bean public HelloService helloService02[]{ System.out.println["配置类@Bean给容器中添加组件了..."]; return new HelloService[]; } }测试:
@Test public void testHelloService[] { boolean b = ioc.containsBean["helloService02"]; System.out.println[b]; // true }输出:配置类@Bean给容器中添加组件了 同时返回true
4、配置文件占位符
- 随机数
- 占位符获取之前配置的值
person.last-name=张三${random.uuid} person.age=${random.int} person.birth=2017/12/15 person.boss=false person.maps.k1=v1 person.maps.k2=14 person.lists=a,b,c # 没有取到:后面是默认值 person.dog.name=${person.hello:hello}_dog person.dog.age=15如果没有可以使用的:指定默认值
Linux下vim的配置,原文地址://blog.csdn.net/luckytanggu/article/details/52045357
一、安装vundle
- 1
- 1
默认安装在/.vim/bundle/vundle下;
安装v undle
$ git clone //github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim- 1
- 1
默认安装在/.vim/bundle/vundle下;
安装vundle
$ git clone //github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim- 1
- 1
默认安装在/.vim/bundle/vundle下;
安装vundle
$ git clone //github.com/V二、创建vimrc(vim的配置文件)
可以直接克隆我的vim配置文件到你的本地
git clone :Tangugo/vim.git
把.vimrc配置文件拷贝到~/目录下
cp vim/.vimrc ~/
注:前面带点.的文件是隐藏文件,需ls -la才能查看到
vim配置文件一般分为以下四部分:
- 加载vim的相关插件[vim插件大全]
- vim的常规设置
- vim插件的设置
- 键盘中一些键的功能重新映射其他键或组合键上[例如Esc退出插入模式映射到jj组合键]
三、安装插件让.vimrc配置文件生效
按以下步骤操作
vim
:PluginInstall
安装插件需要一定的时间,跟网速有关,喝杯茶等待
四、Vim 自动补全插件 YouCompleteMe 安装与配置a
可以参考//howiefh.github.io/2015/05/22/vim-install-youcompleteme-plugin/
1、安装
确保Vim版本至少是7.3.584,并且支持python2脚本
cd ~/.vim/bundle/YouCompleteMe
./install.py
需要支持C语言的话
./install.py clang-completer
2、拷贝配置文件
cp third_party/ycmd/cpp/ycm/.ycm_extra_conf.py ~/
3、修改配置文件,在flags部分后添加如下内容:
-isystem,
/usr/include,
在.vimrc中设定 YouCompleteMe配置[第二部克隆vimrc文件,该vimrc已指定了]
let g:ycm_global_ycm_extra_conf = ~/.ycm_extra_conf.py
五、安装完后我的补全遇到如下问题:
在写代码时,每当输入.就提示ConnectionError错误提示[如输入:os.],到/tmp/ycm_temp目录下查看日志文件,提示如下错误:
Traceback [most recent call last]:
File "/home/zhu/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/JediHTTP/jedihttp.py", line 23, in
from waitress import serve
ImportError: No module named waitress
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
发现报错源,顺藤摸瓜,于是到PyPi[几乎所有Python的第三方库在此处都能找到]查找waitress模块,下载安装后,完美解决了代码补全出现的问题
waitress安装:
tar -zxvf waitress-1.0a2.tar.gz
cd waitress-1.0a2
python setup.py install # 注:非root用户需在命令前加上sudo
安装完后vim就变得无比强大绚丽了,看截图
以下是我的vimrc配置文件
" ************* Vundle 配置 ****************
filetype off " 侦测文件类型
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin[]
" Vundle.vim : vim的一个非常好用的插件管理器
Bundle 'gmarik/Vundle.vim'
" 更酷的启动界面
"Bundle 'mhinz/vim-startify'
" 协作编程
"Bundle 'FredKSchott/CoVim'
" 代码补全
Bundle 'Valloric/YouCompleteMe'
Bundle 'SirVer/ultisnips'
Bundle 'honza/vim-snippets'
Bundle 'YanhaoMo/snippets'
" Python代码补全
"Bundle 'Pydiction'
" 符号自动补全
Bundle 'Raimondi/delimitMate'
" 文件搜索
Bundle 'kien/ctrlp.vim'
Bundle 'Shougo/unite.vim'
Bundle 'scrooloose/nerdtree'
Bundle 'vim-scripts/mru.vim'
" 静态语法检查
Bundle 'scrooloose/syntastic'
" 代码浏览
Bundle 'majutsushi/tagbar'
" git支持
Bundle 'tpope/vim-fugitive'
Bundle 'airblade/vim-gitgutter'
" 美化主题
Bundle 'tomasr/molokai'
Bundle 'morhetz/gruvbox'
Bundle 'kien/rainbow_parentheses.vim'
Bundle 'bling/vim-airline'
"Bundle 'vim-airline-themes'
Bundle 'nathanaelkane/vim-indent-guides'
Bundle 'solarized'
Bundle 'jpo/vim-railscasts-theme'
"Bundle 'altercation/vim-colors-solarized.git'
"Bundle 'fholgado/minibufexpl.vim'
" 代码bug追踪
Bundle 'ZenCoding.vim'
" 编辑增强
" 多光标操作
Bundle 'terryma/vim-multiple-cursors'
" 成对符号编辑
Bundle 'tpope/vim-surround'
Bundle 'tpope/vim-unimpaired'
" 快速注释
Bundle 'scrooloose/nerdcommenter'
" 自动对齐
Bundle 'godlygeek/tabular'
" 快速移动
Bundle 'Lokaltog/vim-easymotion'
" 代码块对齐用
Bundle 'Yggdroot/indentLine'
" 增强状态栏
Bundle 'rstatusline'
" tmux支持
Bundle 'benmills/vimux'
" c/c++
Bundle 'vim-scripts/a.vim'
Bundle 'vim-scripts/c.vim'
" org-mode
Bundle 'jceb/vim-orgmode'
Bundle 'tpope/vim-speeddating'
" markdown
Bundle 'plasticboy/vim-markdown'
" 可以通过浏览器实时预览,但是要安装额外依赖,详见官网
"Bundle 'suan/vim-instant-markdown'
" 网页开发
Bundle 'mattn/emmet-vim'
" pyhon
Bundle 'klen/python-mode'
"Bundle 'python-imports.vim'
" js
Bundle 'coolwanglu/vim.js'
" golang
"Bundle 'fatih/vim-go'
" 用ack代替grep搜索
Bundle 'mileszs/ack.vim'
"bundle 'vimwiki/vimwiki'
"Bundle 'vim-scripts/bufexplorer.zip'
"Bundle 'terryma/vim-smooth-scroll'
call vundle#end[]
filetype plugin on " 载入文件类型插件
filetype indent on " 为特定文件类型载入相关缩进文件
" *************** gvim配置 ***************
if has["gui_running"]
let $LANG='en' "设置gvim菜单栏始终显示为英文
set langmenu=en
source $VIMRUNTIME/delmenu.vim
source $VIMRUNTIME/menu.vim
"set guifont=DejaVu\ Sans\ Mono\ for\ Powerline\ Book\ 10
set guifont=Source\ Code\ Pro\ for\ Powerline\ Regular\ 10
set guioptions-=e
set guioptions-=m
set guioptions-=T
set guioptions-=L
set guioptions-=r
set guioptions-=B
set guioptions-=0
set go=
winpos 1000 0
"set lines=100 columns=150 " 开启时的窗口默认大小
endif
" *************** vim常用的基本设置 ***************
set nocompatible " 不使用vi的键盘模式,而是vim自己的
"syntax enable " 开启语法高亮功能
syntax on " 语法高亮支持
set nu " 显示行号
set rnu " 显示相对行号
set wrap " 当一行文字很长时换行
"set nowrap " 当一行文字很长时取消换行
set showmatch " 当光标移动到一个括号时高亮显示对应的另一个括号
set showcmd " 回显输入的命令
set showmode " 显示当前的模式
set clipboard+=unnamed " 关联系统的剪贴板
set ruler " 在编辑过程中右下角显示光标的行列信息
set nocp " 让Vim工作在不兼容模式下
set shortmess=atI " 启动时不显示捐助乌干达儿童的提示
set so=6 " 上下滚行时空余6行
set autoindent " 自动套用上一行的缩进方式
set smartindent " 智能缩进
set mouse=a " 开启鼠标支持
set laststatus=2 " 总是显示状态行
set backspace=indent,eol,start " 对退格键提供更好的支持
set ts=4 " 设置tab长度为4
set sts=4 " 设置制表符宽度
set shiftwidth=4 " 设置缩进空格数
set expandtab " 用空格代替tab键
set smarttab " 更加智能的tab键
set hid " 当buffer被丢弃时隐藏它
set encoding=utf-8 " 默认使用utf-8编码格式
set fileencodings=utf-8,cp936,gb18030,big5,euc-kr,latin1 " 自动判断编码时 依次尝试一下编码
set ffs=unix,dos,mac " 设置文件类型
set hlsearch " 高亮搜索内容
set ignorecase " 搜索模式里忽略大小写
set smartcase " 如果搜索字符串里包含大写字母,则禁用 ignorecase
set incsearch " 显示搜索的动态匹配效果
set lazyredraw " 解决某些类型的文件由于syntax导致vim反应过慢的问题
set ttyfast " 平滑地变化
set cc=80 " 第80字符处显示分隔符
set foldmethod=indent " 折叠方式
set nofoldenable " 不自动折叠
set foldcolumn=1 " 在行号前空出一列的宽度
set t_Co=256 " 设置256真彩色
set history=1000 " 设置历史记录条数
"set autoread " 当文件在外部被修改时自动载入
"set cindent " 使用c语言的缩进格式
"set whichwrap+=,h,l " 允许backspace和光标键跨越行边界
"set cmdheight=2 " 显示两行命令行
set list lcs=tab:\\ ,trail: " 显示tab键为,并且显示每行结尾的空格为''
" 一些备用字符:
" 格式化状态行显示的内容
set statusline=[%t]\ %y\ %m%=%{&fileencoding}\ [%{&ff}]\ [%l,\ %c]\ [%L]\ [%p%%]
" 打开一个文件自动定位到上一次退出的位置
if has["autocmd"]
au BufReadPost * if line["'\""] > 1 && line["'\""] %.html &"
exec "!firefox %.html &"
endif
endfunc
" C,C++的调试
map :call Rungdb[]
func! Rungdb[]
exec "w"
exec "!g++ % -g -o % /dev/null 2>&1"
" elseif &filetype == 'perl'
" exec "!astyle --style=gnu --suffix=none %"
" elseif &filetype == 'py'||&filetype == 'python'
" exec "r !autopep8 -i --aggressive %"
" elseif &filetype == 'java'
" exec "!astyle --style=java --suffix=none %"
" elseif &filetype == 'jsp'
" exec "!astyle --style=gnu --suffix=none %"
" elseif &filetype == 'xml'
" exec "!astyle --style=gnu --suffix=none %"
" else
" exec "normal gg=G"
" return
" endif
" exec "e! %"
"endfunc
" 更新cscope文件
map :!cscope -Rbq
im :!cscope -Rbq
" 修改的键盘映射
nmap '
" 当按下\+Enter时取消搜索高亮
map :noh
" Unite插件配置
map b :Unite -winheight=10 buffer
map r :MRU
map f :NERDTreeToggle
" Tagbar插件配置
let g:tagbar_autoclose=1
map t :TagbarToggle
" 设置文件类型辅助
map s :setfiletype
" 更方便的窗口间跳转
map j j
map k k
map l l
map h h
map j
map k
map l
map h
" vimux插件配置
map e :VimuxPromptCommand
map x :VimuxCloseRunner
map vl :VimuxRunLastCommand
map vi :VimuxInspectRunner
" 更方便的页滚动
map
map
map ,,j [easymotion-w]
map ,,k [easymotion-b]
map ,,s [easymotion-s]
"********** 新建.c,.h,.sh,.java文件,自动插入文件头 **********
autocmd BufNewFile *.cpp,*.[ch],*.sh,*.rb,*.java,*.py exec ":call SetHead[]"
"" 定义函数SetHead,自动插入文件头
func! SetHead[]
if &filetype == 'sh'
call setline[1,"\#!/bin/bash"]
call append[line["."], ""]
elseif &filetype == 'python'
call setline[1,"#!/usr/bin/env python"]
call append[line["."],"# -*- coding=utf-8 -*-"]
call append[line["."]+1, ""]
elseif &filetype == 'ruby'
call setline[1,"#!/usr/bin/env ruby"]
call append[line["."],"# encoding: utf-8"]
call append[line["."]+1, ""]
" elseif &filetype == 'mkd'
" call setline[1,""]
else
call setline[1, "/*************************************************************************"]
call append[line["."], " > File Name: ".expand["%"]]
call append[line["."]+1, " > Author: "]
call append[line["."]+2, " > Mail: "]
call append[line["."]+3, " > Created Time: ".strftime["%c"]]
call append[line["."]+4, " ************************************************************************/"]
call append[line["."]+5, ""]
endif
if expand["%:e"] == 'cpp'
call append[line["."]+6, "#include"]
call append[line["."]+7, "using namespace std;"]
call append[line["."]+8, ""]
endif
if &filetype == 'c'
call append[line["."]+6, "#include"]
call append[line["."]+7, ""]
endif
if expand["%:e"] == 'h'
call append[line["."]+6, "#ifndef _".toupper[expand["%:r"]]."_H"]
call append[line["."]+7, "#define _".toupper[expand["%:r"]]."_H"]
call append[line["."]+8, "#endif"]
endif
if &filetype == 'java'
call append[line["."]+6,"public class ".expand["%:r"]]
call append[line["."]+7,""]
endif
" 新建文件后,自动定位到文件末尾
endfunc
autocmd BufNewFile * normal G
" ********* 实用设置 *********
if has["autocmd"]
autocmd BufReadPost *
\ if line["'\""] > 0 && line["'\""]