记一次-JS-偶发性加载失败的经历

临时提交,资料整理完成后,再完善

August 17, 2019 · 1 min · jiezi

SpringBoot注入数据的方式

关于注入数据说明1.不通过配置文件注入数据通过@Value将外部的值动态注入到Bean中,使用的情况有:注入普通字符串注入操作系统属性注入表达式结果注入其他Bean属性:注入Student对象的属性name注入文件资源注入URL资源辅助代码package com.hannpang.model;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;@Component(value = “st”)//对student进行实例化操作public class Student { @Value(“悟空”) private String name; public String getName() { return name; } public void setName(String name) { this.name = name; }}测试@Value的代码package com.hannpang.model;import org.springframework.beans.factory.annotation.Value;import org.springframework.core.io.Resource;import org.springframework.stereotype.Component;@Componentpublic class SimpleObject { @Value(“注入普通字符串”) private String normal; //关于属性的KEY可以查看System类说明 @Value("#{systemProperties[‘java.version’]}")//–>使用了SpEL表达式 private String systemPropertiesName; // 注入操作系统属性 @Value("#{T(java.lang.Math).random()80}")//获取随机数 private double randomNumber; //注入表达式结果 @Value("#{1+2}") private double sum; //注入表达式结果 1+2的求和 @Value(“classpath:os.yaml”) private Resource resourceFile; // 注入文件资源 @Value(“http://www.baidu.com”) private Resource testUrl; // 注入URL资源 @Value("#{st.name}") private String studentName; //省略getter和setter方法 @Override public String toString() { return “SimpleObject{” + “normal=’” + normal + ‘'’ + “, systemPropertiesName=’” + systemPropertiesName + ‘'’ + “, randomNumber=” + randomNumber + “, sum=” + sum + “, resourceFile=” + resourceFile + “, testUrl=” + testUrl + “, studentName=’” + studentName + ‘'’ + ‘}’; }}Spring的测试代码package com.hannpang;import com.hannpang.model.SimpleObject;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTestpublic class Demo04BootApplicationTests { @Autowired private SimpleObject so; @Test public void contextLoads() { System.out.println(so); }}运行结果为:SimpleObject{normal=‘注入普通字符串’, systemPropertiesName=‘1.8.0_172’, randomNumber=56.631954541947266, sum=3.0, resourceFile=class path resource [os.yaml], testUrl=URL [http://www.baidu.com], studentName=‘悟空’}2.通过配置文件注入数据通过@Value将外部配置文件的值动态注入到Bean中。配置文件主要有两类:application.properties、application.yaml application.properties在spring boot启动时默认加载此文件自定义属性文件。自定义属性文件通过@PropertySource加载。@PropertySource可以同时加载多个文件,也可以加载单个文件。如果相同第一个属性文件和第二属性文件存在相同key,则最后一个属性文件里的key启作用。加载文件的路径也可以配置变量,如下文的${anotherfile.configinject},此值定义在第一个属性文件config.properties在application.properties中加入如下测试代码app.name=一步教育在resources下面新建第一个属性文件config.properties内容如下book.name=西游记anotherfile.configinject=system在resources下面新建第二个属性文件config_system.properties内容如下我的目的是想system的值使用第一个属性文件中定义的值book.name.author=吴承恩下面通过@Value(“${app.name}”)语法将属性文件的值注入bean属性值,详细代码见:package com.hannpang.test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.PropertySource;import org.springframework.core.env.Environment;import org.springframework.stereotype.Component;@Component@PropertySource(value = {“classpath:config.properties”,“classpath:config_${anotherfile.configinject}.properties”})public class LoadPropsTest { @Value("${app.name}") private String appName; // 这里的值来自application.properties,spring boot启动时默认加载此文件 @Value("${book.name}") private String bookName; // 注入第一个配置外部文件属性 @Value("${book.name.author}") private String author; // 注入第二个配置外部文件属性 @Autowired private Environment env; // 注入环境变量对象,存储注入的属性值 //省略getter和setter方法 public void setAuthor(String author) { this.author = author; } @Override public String toString(){ StringBuilder sb = new StringBuilder(); sb.append(“bookName=”).append(bookName).append("\r\n") .append(“author=”).append(author).append("\r\n") .append(“appName=”).append(appName).append("\r\n") .append(“env=”).append(env).append("\r\n") // 从eniroment中获取属性值 .append(“env=”).append(env.getProperty(“book.name.author”)).append("\r\n"); return sb.toString(); }}测试代码package com.hannpang;import com.hannpang.model.SimpleObject;import com.hannpang.test.LoadPropsTest;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTestpublic class Demo04BootApplicationTests { @Autowired private LoadPropsTest lpt; @Test public void loadPropertiesTest() { System.out.println(lpt); }}运行结果为:bookName=西游记author=吴承恩appName=一步教育env=StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[ConfigurationPropertySourcesPropertySource {name=‘configurationProperties’}, MapPropertySource {name=‘Inlined Test Properties’}, MapPropertySource {name=‘systemProperties’}, OriginAwareSystemEnvironmentPropertySource {name=‘systemEnvironment’}, RandomValuePropertySource {name=‘random’}, OriginTrackedMapPropertySource {name=‘applicationConfig: [classpath:/application.properties]’}, ResourcePropertySource {name=‘class path resource [config_system.properties]’}, ResourcePropertySource {name=‘class path resource [config.properties]’}]}env=吴承恩3. #{…}和${…}的区别演示A.${…}的用法{}里面的内容必须符合SpEL表达式,通过@Value(“${app.name}”)可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,则会报错。可以通过赋予默认值解决这个问题,如@Value("${app.name:胖先森}")部分代码// 如果属性文件没有app.name,则会报错// @Value("${app.name}")// private String name;// 使用app.name设置值,如果不存在则使用默认值@Value("${app.name:胖先森}")private String name;B.#{…}的用法部分代码直接演示// SpEL:调用字符串Hello World的concat方法@Value("#{‘Hello World’.concat(’!’)}")private String helloWorld;// SpEL: 调用字符串的getBytes方法,然后调用length属性@Value("#{‘Hello World’.bytes.length}")private String helloWorldbytes;C.#{…}和${…}混合使用${…}和#{…}可以混合使用,如下文代码执行顺序:通过${server.name}从属性文件中获取值并进行替换,然后就变成了 执行SpEL表达式{‘server1,server2,server3’.split(‘,’)}。// SpEL: 传入一个字符串,根据",“切分后插入列表中, #{}和${}配置使用(注意单引号,注意不能反过来${}在外面,#{}在里面)@Value(”#{’${server.name}’.split(’,’)}")private List<String> servers;在上文中在#{}外面,${}在里面可以执行成功,那么反过来是否可以呢${}在外面,#{}在里面,如代码// SpEL: 注意不能反过来${}在外面,#{}在里面,这个会执行失败@Value("${#{‘HelloWorld’.concat(’’)}}")private List<String> servers2;答案是不能。因为spring执行${}是时机要早于#{}。在本例中,Spring会尝试从属性中查找#{‘HelloWorld’.concat(‘’)},那么肯定找到,由上文已知如果找不到,然后报错。所以${}在外面,#{}在里面是非法操作D.用法总结#{…} 用于执行SpEl表达式,并将内容赋值给属性${…} 主要用于加载外部属性文件中的值#{…} 和&dollar;{…} 可以混合使用,但是必须#{}外面,&dollar;{}在里面4.@Value获取值和@ConfigurationProperties获取值比较 @ConfigurationProperties@Value功能批量注入配置文件中的属性一个个指定松散绑定(松散语法)支持不支持SpEL不支持支持JSR303数据校验支持不支持复杂类型封装支持不支持配置文件yml还是properties他们都能获取到值;如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;关于数据校验的部分代码@Component@ConfigurationProperties(prefix = “person”)@Validatedpublic class Person { //lastName必须是邮箱格式 @Email private String lastName;5. @ImportResource引入配置文件不推荐的使用方式Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上@ImportResource(locations = {“classpath:beans.xml”})导入Spring的配置文件让其生效编写配置文件信息<?xml version=“1.0” encoding=“UTF-8”?><beans xmlns=“http://www.springframework.org/schema/beans" xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id=“helloService” class=“com.hanpang.springboot.service.HelloService”></bean></beans>大概了解就好,我们基本上不使用这种方式6.@Configuration注解SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式1、配置类@Configuration作用于类上,相当于一个xml配置文件2、使用@Bean给容器中添加组件,作用于方法上/* * @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件 * * 在配置文件中用<bean><bean/>标签添加组件 * <bean id=“helloService” class=“com.hanpang.springboot.service.HelloService”></bean> /@Configurationpublic class MyAppConfig { //将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名 @Bean public HelloService helloService02(){ System.out.println(“配置类@Bean给容器中添加组件了…”); return new HelloService(); }}使用Bean注入太麻烦,我们更加喜欢使用扫描的方式import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration; import com.wx.dao.IUserDao;import com.wx.dao.UserDaoImpl; //通过该注解来表明该类是一个Spring的配置,相当于一个传统的ApplicationContext.xml@Configuration//相当于配置文件里面的<context:component-scan/>标签,扫描这些包下面的类的注解@ComponentScan(basePackages=“com.hanpang.dao,com.hanpang.service”)public class SpringConfig { // 通过该注解来表明是一个Bean对象,相当于xml中的<bean> //bean的id值默认是方法名userDao / @Bean public HelloService helloService02(){ System.out.println(“配置类@Bean给容器中添加组件了…”); return new HelloService(); } */}附录随机数${random.value}、${random.int}、${random.long}${random.int(10)}、${random.int[1024,65536]} ...

December 23, 2018 · 2 min · jiezi

YAML语法简易入门

YAML 语法个人感觉这篇文档属于"搬运工"性质可以查看官方或者其他的博客资料,会有一大堆的内容YAML语言的设计参考了JSON,XML和SDL等语言。YAML 强调以数据为中心,简洁易读,编写简单。有意思的命名:AML全称是”YAML Ain’t a Markup Language”(YAML不是一种置标语言)的递归缩写。 在开发的这种语言时,YAML 的意思其实是:”Yet Another Markup Language”(仍是一种置标语言)。语法特点大小写敏感通过缩进表示层级关系禁止使用tab缩进,只能使用空格键 (个人感觉这条最重要)缩进的空格数目不重要,只要相同层级左对齐即可使用#表示注释支持的数据结构对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)纯量(scalars):单个的、不可再分的值双引号和单引号的区分双引号"":不会转义字符串里面的特殊字符,特殊字符作为本身想表示的意思。name: “123\n123”—————————输出: 123 换行 123如果不加引号将会转义特殊字符,当成字符串处理值的写法1.字符串使用”或”“或不使用引号value0: ‘hello World!‘value1: “hello World!“value2: hello World!2.布尔值true或false表示。3.数字12 #整数 014 # 八进制整数 0xC #十六进制整数 13.4 #浮点数 1.2e+34 #指数 .inf空值 #无穷大4.空值null或~表示5.日期使用 iso-8601 标准表示日期date: 2018-01-01t16:59:43.10-05:00在springboot中yaml文件的时间格式 date: yyyy/MM/dd HH:mm:ss6.强制类型转换(了解)YAML 允许使用个感叹号!,强制转换数据类型,单叹号通常是自定义类型,双叹号是内置类型。money: !!str123date: !Booleantrue内置类型列表!!int # 整数类型 !!float # 浮点类型 !!bool # 布尔类型 !!str # 字符串类型 !!binary # 也是字符串类型 !!timestamp # 日期时间类型 !!null # 空值 !!set # 集合 !!omap,!!pairs # 键值列表或对象列表!!seq # 序列,也是列表 !!map # 键值表7.对象(重点)Map(属性和值)(键值对)的形式: key:(空格)v :表示一堆键值对,空格不可省略。car: color: red brand: BMW一行写法car:{color: red,brand: BMW}相当于JSON格式:{“color”:“red”,“brand”:“BMW”}8.数组一组连词线开头的行,构成一个数组。brand: - audi - bmw - ferrari一行写法brand: [audi,bmw,ferrari]相当于JSON[“auri”,“bmw”,“ferrari”]9.文本块|:使用|标注的文本内容缩进表示的块,可以保留块中已有的回车换行value: | hello world!输出结果:hello 换行 world!+表示保留文字块末尾的换行,-表示删除字符串末尾的换行。value: |hellovalue: |-hellovalue: |+hello输出:hello\n hello hello\n\n(有多少个回车就有多少个\n)注意 “|” 与 文本之间须另起一行>:使用 > 标注的文本内容缩进表示的块,将块中回车替换为空格,最终连接成一行value: > helloworld!输出:hello 空格 world!注意 “>” 与 文本之间的空格10.锚点与引用使用 & 定义数据锚点(即要复制的数据),使用 * 引用锚点数据(即数据的复制目的地)name: &a yamlbook: abooks: - java - a - python输出book: yaml 输出books:[java,yaml,python]注意引用部分不能追加内容配置文件注入数据/* * 将配置文件中配置的每一个属性的值,映射到这个组件中 * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定; * prefix = “person”:配置文件中哪个下面的所有属性进行一一映射 * * 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能; * */@Component //实例化@ConfigurationProperties(prefix = “person”)//yaml或者properties的前缀public class Person { private String name; private Integer age; private Boolean flag; private Date birthday; private Map<String,Object> maps; private List<Object> tempList; private Dog dog; //省略getter和setter以及toString方法我们可以导入配置文件处理器,以后编写配置就有提示了,@ConfigurationPropertiesIDE会提示打开在线的帮助文档,配置依赖如下:<!–导入配置文件处理器,配置文件进行绑定就会有提示–><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional></dependency>application.yaml文件person: name: 胖先森 age: 18 flag: false birthday: 2018/12/19 20:21:22 #Spring Boot中时间格式 maps: {bookName: “西游记”,author: ‘吴承恩’} tempList: - 红楼梦 - 三国演义 - 水浒传 dog: dogName: 大黄 dogAge: 4在test中进行测试如下@RunWith(SpringRunner.class)@SpringBootTestpublic class Demo03BootApplicationTests { @Autowired private Person p1; @Test public void contextLoads() { System.out.println(p1); }}输出结果为:Person{name=‘胖先森’, age=18, flag=false, birthday=Wed Dec 19 20:21:22 CST 2018, maps={bookName=西游记, author=吴承恩}, tempList=[红楼梦, 三国演义, 水浒传], dog=Dog{dogName=‘大黄’, dogAge=4}}application.properties文件person123.name=刘备person123.age=20person123.birthday=2018/12/19 20:21:22person123.maps.bookName=水浒传person123.maps.author=罗贯中person123.temp-list=一步教育,步步为赢person123.dog.dogName=小白person123.dog.dogAge=5java代码修改前缀@Component //实例化@ConfigurationProperties(prefix = “person123”)//yaml或者properties的前缀public class Person { private String name; private Integer age; private Boolean flag; private Date birthday; private Map<String,Object> maps; private List<Object> tempList; private Dog dog; //省略getter和setter以及toString方法在test中进行测试如下@RunWith(SpringRunner.class)@SpringBootTestpublic class Demo03BootApplicationTests { @Autowired private Person p1; @Test public void contextLoads() { System.out.println(p1); }}输出结果为:Person{name=‘����’, age=20, flag=null, birthday=Wed Dec 19 20:21:22 CST 2018, maps={bookName=ˮ䰴�, author=�޹���}, tempList=[һ������, ����ΪӮ], dog=Dog{dogName=‘��’, dogAge=5}}属性文件中文乱码问题 ...

December 19, 2018 · 2 min · jiezi