首页 文章 精选 留言 我的

精选列表

搜索[AI教育],共10000篇文章
优秀的个人博客,低调大师

【熵增教育】SpringBoot的配置外部化——熵增学院

在前面的课程中,我们给大家分享过SpringBoot精妙的启动配置,主要阐述的是spring的IoC容器在SpringBoot中的加载过程,并与传统项目中Spring的IoC容器加载过程进行了一个对比.我们在开发的过程中,除了IoC容器的配置之外,当然还有许多其他的配置,诸如数据库的链接信息,端口,以及项目的内部使用的一些个性化信息等.那SpringBoot是如何管理这些配置呢?我今天呢,就从以下这三个方面来给大家分享一下SpringBoot是如何管理配置信息的. 配置文件和属性获取 配置文件的名字、目录和优先级 传统的properties与YAML 1.配置文件和属性获 1.1 传统配置文件的值获取与SpringBoot中的值获取 在传统的项目里,我们的配置信息一般都写在配置文件中,然后关于spring需要的信息,我们就在spring的xml文件里引用,大略如下所示: classpath下的config里创建一个jdbc.properties jdbc.driverClassName=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/testdb?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true jdbc.username=develop jdbc.password=&dT$BvYdOlH4*m9G 然后在我们的application.xml里引入我们需要的这个数据源: <?xmlversion="1.0"encoding="UTF-8"?> <beansxmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <context:property-placeholderlocation="classpath:config/jdbc.properties"/> <beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"> <propertyname="driverClassName"value="${jdbc.driverClassName}"/> <propertyname="url"value="${jdbc.url}"/> <propertyname="username"value="${jdbc.username}"/> <propertyname="password"value="${jdbc.password}"/> </bean> ......其他配置 </beans> 当然除了spring的数据源信息之外,我们往往也会有一些其他的信息,比如项目返回给前端的一些报错信息等,此时我们通常的做法是使用java的原生方法去加载。如以下所示: 在classpath的config下有个webreslt.properties 0=SUCCESS 100000=参数有误 100001=AppKey不能为空 100002=Signature不能为空 100003=参数列表(paramMap)不能为空 100004=secret不能包含在参数列表中 100005=参数签名不合法 100006=手机号不能为空 100007=验证码不能为空 100008=邮件内容不能为空 100009=收件人不能为空 100010=邮件主题不能为空 200000=应用无权限 200001=应用未注册 300000=Api异常 300001=短信发送失败 300002=短信验证失败 300003=邮件发送失败 300004=短信发送超过最大条数限制 获取值的方法如下: packagecom.ailu.paas.common.utils; importorg.apache.commons.lang3.StringUtils; importjava.util.Locale; importjava.util.ResourceBundle; publicclassPropertyFileReader{ publicstaticStringgetItem(Stringkey){ returngetItem(key,""); } publicstaticStringgetItem(Stringkey,StringdefaultValue){ ResourceBundlerb=ResourceBundle.getBundle("config/webresult"); Stringvalue=""; try{ value=newString(rb.getString(key).getBytes("ISO-8859-1"),"UTF-8"); }catch(Exceptione){ e.printStackTrace(); } if(StringUtils.isEmpty(value)){ value=defaultValue; } returnvalue.trim(); } } 然后在其他的地方,我们就可以直接使用以下这样的方式去获取属性文件中的值了. Stringvalue=PropertyFileReader.getItem(key); 而在SpringBoot中呢,我们则可以使用@Component+@Value这两个组合,来快速的读取配置文件中的值, 仍然是在classpath下,我们在配置文件里写上如下配置: name="Lianmengtu" 然后我们创建一个java类,并加上@Component和@Value,如下所示: packagetop.lianmengtu.testprofile.common; importlombok.Getter; importlombok.Setter; importorg.springframework.beans.factory.annotation.Value; importorg.springframework.stereotype.Component; @Component @Getter @Setter publicclassTestProperty{ @Value("${name}") privateStringname; } 其中@Component是为了把TestProperty作为组件放入到Spring的IoC容器中,而@Value("${name}")则是为了从配置文件中取值,${name}中的name即是配置文件中的key.然后我们就可以在其他地方通过注入直接使用了: @Autowired privateTestPropertytestProperty; publicvoidtest(){ System.out.println(testProperty.getName()); } 1.2 随机值的绑定 在某些场景下,我们可能需要在项目的配置中添加一些随机值,并且这些值在我们项目启动后就自动的初始化,而SpringBoot就考虑到了这种情况,于是给我们准备了一些工具,方便我们的使用.使用情况如下: #随机字符串 secret=${random.value} #随机数 setup=${random.int} #0-10之间的随机数 range-int=${random.int[0,10]} #生成uuid uuid=${random.uuid} 获取方式和其他的属性相同,如下所示: packagetop.lianmengtu.testprofile.common; importlombok.Getter; importlombok.Setter; importorg.springframework.beans.factory.annotation.Value; importorg.springframework.stereotype.Component; @Component @Getter @Setter publicclassTestProperty{ @Value("${secret}") privateStringsecret; @Value("${setup}") privateIntegersetup; @Value("${range-int}") privateIntegerrangeInt; @Value("${uuid}") privateStringuuid; } 1.3 变量的引用与占位符 有些时候我们会在配置项中引用另一项的值,当然,是以变量的形式进行引用.如下所示: protocal=http:// domain=${protocal}ask.lianmengtu.top 这里我们看到,在springBoot中使用的变量占位符是${key}.这时候就有一个问题,因为我们现在大多数的开发环境都是maven,我们都知道maven也是支持变量占位的,我们可以在打包不同环境的时候可以激活不同的profile,然后对变量值进行替换,而我们往常在使用Maven的时候,用的变量占位符正好是${key},那此时,我们该怎么办呢?SpringBoot是不是不支持Maven的变量占位呢?我们必须要二选其一吗? 当然不是.SpringBoot也考虑到了这个问题,因此给maven占位提供了另外一个符号即@key@,如下所示: protocal=http:// domain=${protocal}ask.lianmengtu.top username=@username@ password=@password@ 然后我们就可以在我们的pom里这么写了,而当我们激活某一个profile的时候,相应的maven变量就会被替换了 <profiles> <profile> <id>dev</id> <properties> <username>dev</username> <password>dev123</password> </properties> </profile> <profile> <id>test</id> <properties> <username>test</username> <password>test123</password> </properties> </profile> </profiles> 2. yml与properties SpringBoot是除了支持properties这种方式之外,它也支持YAML这种方式,并且因为yml结构清晰,又可以继承,所以使用yml这种方式的人也越来越多了.而我就是这么对yml路转粉的. 2.1 yml结构化 yml的第一个好处是结构化,这与properties是明显的差别.这里放上两份同样的配置文件来个视觉对比,首先是properties environments.dev.url= environments.dev.name=DeveloperSetup environments.prod.url= environments.prod.name=MyCoolApp my.servers[0]=dev.example.com my.servers[1]=another.example.com 对比yml environments: dev: url:http://dev.example.com name:DeveloperSetup prod: url:http://another.example.com name:MyCoolApp my: servers: -dev.example.com -another.example.com 这里只是举个例子,所以可能这两三行大家看起来没什么感觉,但要知道在实际的项目中,我们的配置可能包含各种各样的信息,数据库的,缓存的,第三方平台的等等,那时候,如果我们还用properties,那么看着将会非常头大. 2.2 yml的继承 在我们使用配置文件的时候,尤其是分环境使用的时候,常常会碰到这么一个问题: 大多数的项目配置都一样,只有少数的不一样,此时,如果是使用properties,那么我们就只能每个文件各写一份,而在yml里,我们就不用,我们只需要将通用的那部分写到application-common.yml里,然后少量不同的,我们在分环境进行描述,application-dev.yml,application-prod.yml里,这样我们只需要激活一份文件,剩下的就会自动的进行继承和使用了,具体方式如下: application.yml app: name:"lianmengtu" country:"China" username:"melon" password:"melon123" application-dev.yml: app: username:"jacobdev" password:"dev123456" application-prod.yml app: username:"LMTprod" password:"prod456" 这样当我们在启动时,激活不同的配置时,username和password会不同,但name和country则是从默认的yml中继承过来的. 2.3 指定配置文件的名字和地址 刚刚我们提到过多种环境,配置文件之所以要区分环境,就是因为有些信息是需要保密的,无法公开.而SpringBoot则允许从外部,通过命令行的形式,对配置文件进行指定,当然也可以指定变量. 2.3.1 指定配置文件的名字 我们可以使用--spring.config.name=xxx 这样的参数形式指定配置文件的名字: $java-jarmyproject.jar--spring.config.name=myproject 2.3.2 配置指定目录下的配置文件 我们可以使用--spring.config.location=xxxxx这样的参数形式来配置指定目录下的配置文件,如下文则指定了classpath下的config目录下的test.yml java-jarmyproject.jar--spring.config.location=classpath:/config/test.yml 当然从1.x转过来的人可能更喜欢指定目录,这里要特别说明一下,如果--spring.config.location是以目录结尾的,则必须加/ 如下所示: java-jarmyproject.jar--spring.config.location=classpath:/config/ 2.3.3 配置的优先级 在我们没有明确指定文件名字的时候,springBoot会按着以下顺序进行考虑 当前目录下的config目录里的application.properties 当前目录下的application.properties classpath下的config目录下的application.properties classpath下的application.properties 当然除了这些之外,命令行也是可以传参数的,并且命令行参数的优先级是最高的. 3. 一些比较复杂的配置 使用@Value()来进行属性注入有些时候会显得比较笨重,尤其是使用多个配置或者我们的配置项是呈垂直结构化的数据时,更是这样.SpringBoot提供了另外一种方法来处理这类比较复杂的数据.这就是我们要说的@ConfigurationProperties. 首先我们有这样一个配置文件: app: name:"lianmengtu" enabled:false security: username:"jacob" password:"jacob123" roles: -USER -ADMIN 我们看到在这个配置文件里,app下有name属性,有enabled属性,其中较为特殊的是security,因为他还包含了些其他的属性,包括username,包括password,还有一个类型为String的roles集合,那么此时,我们可以对应的写成下面这个属性类 packagetop.lianmengtu.testprofile.common; importorg.springframework.boot.context.properties.ConfigurationProperties; importorg.springframework.stereotype.Component; importjava.util.ArrayList; importjava.util.Collections; importjava.util.List; @ConfigurationProperties("app") publicclassComplexProperty{ privateStringname; privatebooleanenabled; privatefinalSecuritysecurity=newSecurity(); publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicbooleanisEnabled(){ returnenabled; } publicvoidsetEnabled(booleanenabled){ this.enabled=enabled; } publicSecuritygetSecurity(){ returnsecurity; } publicstaticclassSecurity{ privateStringusername; privateStringpassword; privateList<String>roles=newArrayList<>(Collections.singleton("USER")); publicStringgetUsername(){ returnusername; } publicvoidsetUsername(Stringusername){ this.username=username; } publicStringgetPassword(){ returnpassword; } publicvoidsetPassword(Stringpassword){ this.password=password; } publicList<String>getRoles(){ returnroles; } publicvoidsetRoles(List<String>roles){ this.roles=roles; } } } 之后,我们可以在我们的service层引用它: packagetop.lianmengtu.testprofile.service.impl; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.stereotype.Service; importtop.lianmengtu.testprofile.common.ComplexProperty; importjava.util.List; @Service publicclassPropertyService{ privatefinalComplexPropertycomplexProperty; @Autowired publicPropertyService(ComplexPropertycomplexProperty){ this.complexProperty=complexProperty; } publicStringname(){ returncomplexProperty.getName(); } publicbooleanenabled(){ returncomplexProperty.isEnabled(); } publicStringuserName(){ returncomplexProperty.getSecurity().getUsername(); } publicStringpassword(){ returncomplexProperty.getSecurity().getPassword(); } publicStringroles(){ StringBufferroles=newStringBuffer(); List<String>roleArray=complexProperty.getSecurity().getRoles(); roleArray.forEach(role->{ roles.append(role).append("----"); }); returnroles.toString(); } } 这里的构造函数注入,我们也可以换成相应的@Autowried注入.为了使这个配置生效,我们需要在Application上加上@EnableConfigurationProperties(ComplexProperty.class) packagetop.lianmengtu.testprofile; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; importorg.springframework.boot.context.properties.EnableConfigurationProperties; importtop.lianmengtu.testprofile.common.ComplexProperty; @SpringBootApplication @EnableConfigurationProperties(ComplexProperty.class) publicclassApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(Application.class,args); } } 刚刚举的那种类型可以说是比较复杂的一个类型了,除了那种内嵌的形式之外,如果说我们只想得到内嵌类里面的属性或者说只有内嵌类里面有属性,则我们可以写成以下这种形式,其他的地方都不用变.这种形式我们称之为relaxed binding @ConfigurationProperties("app.security") publicclassComplexProperty{ privateStringusername; privateStringpassword; privateList<String>roles; publicStringgetUsername(){ returnusername; } publicvoidsetUsername(Stringusername){ this.username=username; } publicStringgetPassword(){ returnpassword; } publicvoidsetPassword(Stringpassword){ this.password=password; } publicList<String>getRoles(){ returnroles; } publicvoidsetRoles(List<String>roles){ this.roles=roles; } } 并且也支持map类型,配置文件如下所示,其中key可以有两种指定方式,一种是"[/key]",一种是/key: app: name:"lianmengtu" enabled:false security: username:"jacob" password:"jacob123" roles: -USER -ADMIN work: "[/position]":"CEO" "[/company]":"bat" /address:"BeiJing" 而我们的配置类则如下所示: packagetop.lianmengtu.testprofile.common; importorg.springframework.boot.context.properties.ConfigurationProperties; importjava.util.List; importjava.util.Map; @ConfigurationProperties("app.security") publicclassComplexProperty{ privateStringusername; privateStringpassword; privateList<String>roles; privateMap<String,String>work; publicStringgetUsername(){ returnusername; } publicvoidsetUsername(Stringusername){ this.username=username; } publicStringgetPassword(){ returnpassword; } publicvoidsetPassword(Stringpassword){ this.password=password; } publicList<String>getRoles(){ returnroles; } publicvoidsetRoles(List<String>roles){ this.roles=roles; } publicMap<String,String>getWork(){ returnwork; } publicvoidsetWork(Map<String,String>work){ this.work=work; } } 这两种方式都是Ok的, 总结 今天的内容,其实到这里就已经结束了,在使用配置文件的过程中,我们还碰到了一些问题,首先,我们在使用这种配置方式,无论是@Component+@Value还是后来的@ConfigurationProperties这两种方式,他都是在进入spring的时候进行初始化的,这也就意味着,如果我们没有从Spring的容器中去取我们的属性容器的话,那么我们的属性值是没有办法注入的,这一点希望大家能够注意,其次,今天只是讲了主要的几种方式,还有一些像复杂类型的属性合并,以及属性验证,这些希望大家可以研究一下,如果有不明白的,欢迎大家在论坛上提出来,我们可以一起探讨.以下是@ConfigurationProperties和@Value的一些对比: Feature @ConfigurationProperties @Value Relaxed binding Yes No Meta-data support Yes No SpELevaluation No Yes 转载请注明出处:联盟兔

优秀的个人博客,低调大师

PlayEdu v1.0-beta.6 发布,视频教育解决方案

官网:https://playedu.xyz PlayEdu 是基于 SpringBoot3 + Java17 + React18 开发的企业内部培训系统。它专注于提供私有化部署方案,包括视频,图片等资源的内网部署。目前主要支持有本地视频上传播放、学员邮箱登录、无限级部门、无限级资源分类、学员在线学习等主要功能。 更新 优化MinIO配置 优化图形验证码 优化学员删除的关联数据删除 优化 dockerfile 新增:禁止拖拽播放配置 源代码 https://gitee.com/playeduxyz/playedu https://github.com/playedu/playedu 页面展示

优秀的个人博客,低调大师

PlayEdu v1.0-beta.5 发布,视频教育解决方案

官网:https://playedu.xyz PlayEdu 是基于 SpringBoot3 + Java17 + React18 开发的企业内部培训系统。它专注于提供私有化部署方案,包括视频,图片等资源的内网部署。目前主要支持有本地视频上传播放、学员邮箱登录、无限级部门、无限级资源分类、学员在线学习等主要功能。 更新 学员注册增加课程分类筛选 线上课-学员列表增加学员所属部门、邮箱字段的显示 线上课-学员列表显示可以观看该线上课的所有学员 修复学员的多部门查询bug 优化学员学习进度的展示(前后台保持统一) 修复后台部门的文案显示溢出 优化视频播放页面样式和交互 源代码 https://gitee.com/playeduxyz/playedu https://github.com/playedu/playedu 页面展示

优秀的个人博客,低调大师

uexam v3.8.0 发布,在线教育学习考试系统

学之思简介: 学之思开源考试系统是一款 java + vue 的前后端分离的考试系统。主要优点是开发、部署简单快捷、界面设计友好、代码结构清晰。支持 web 端和微信小程序,能覆盖到 pc 机和手机等设备。 支持多种部署方式:集成部署、前后端分离部署、docker 部署。 本次更新内容: 1. 升级前端node版本至16,兼容v12-v16版本 2. 升级element ui框架版本 3. 修复微信小程序兼容问题 4. 修复部分系统登录失败问题 5. 接口、教程文档更新 学生端功能: 模块 介绍 登录 用户名、密码 注册 年级、用户名、密码 任务中心 管理员发布的年级任务,每个学生只能做一次 考试 题干支持文本、图片、数学公式、表格等,学生答题支持:文本 固定试卷 可重复练习、自行批改的试卷 时段试卷 在时间限制内,可重复练习、自行批改的试卷 考试记录 查看答卷记录和试卷信息 错题本 答错题目会自动进入错题本,显示题目基本信息 个人信息 显示学生个人资料 更新信息 修改个人资料、头像 个人动态 显示用户最近的个人动态 消息中心 用于接收管理员发送的消息 管理端功能: 模块 介绍 登录 用户名、密码 主页 试卷总数、题目总数、用户活跃度、题目月数量 学生列表 显示系统所有的学生,新增、修改、删除、禁用 管理员列表 显示系统所有的管理员,新增、修改、删除、禁用 学科列表 学科查询、修改、删除 学科创编 创建学科 试卷列表 试卷查询、修改、删除 试卷创编 创建的试卷为时段试卷、固定试卷、任务试卷 题目列表 题目查询、修改、删除 题目创建 题目支持单选题、多选题、判断题、填空题、简答题,题干支持文本、图片、表格、数学公式 任务列表 任务查询、修改、删除 消息列表 显示已发送的消息,消息已读人数等信息 消息发送 发送消息给多个用户 用户日志 显示所有用户日志 个人资料 显示管理员用户名、真实姓名 时间线 显示管理员创建时间 修改资料 修改姓名、手机号 小程序功能: 模块 介绍 登录 用户登录登出功能,登录会自动绑定微信账号,登出会解绑 注册 年级、用户名、密码 任务中心 管理员发布的年级任务,每个学生只能做一次 考试 题干支持文本、图片、数学公式、表格等,学生答题支持:文本 固定试卷 可重复练习、自行批改的试卷 时段试卷 在时间限制内,可重复练习、自行批改的试卷 考试记录 查看答卷记录和试卷信息 错题本 答错题目会自动进入错题本,显示题目基本信息 个人信息 显示学生个人资料 更新信息 修改个人资料、头像 个人动态 显示用户最近的个人动态 消息中心 用于接收管理员发送的消息

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册