网传,微软更新了Microsoft服务协议。根据该协议,如果美国政府对微软下达禁令,微软可能无法继续支持Windows服务,并且不承担因此引发的任何后果,只会尽最大努力避免影响。该事件引发网友热议。
8月10日上午,微软方面对此回应称,近日某些个别社交媒体对微软服务条款全球性更新的谣言,不符合事实。我们为中国用户提供服务的承诺坚定不移。
笔者随即去阅读了这份争议很大对服务协议,其中确实有“对于因超出微软合理控制范围的情况(例如,劳资纠纷、不可抗力、战争或恐怖主义行为、恶意破坏、意外事故或遵守任何适用法律或政府命令)而导致微软无法履行或延迟履行其义务,微软对此不承担任何责任或义务。微软将尽最大努力降低这些事件的影响,并履行未受影响的义务”等文字表述。
事实上,不仅仅是微软,很多产品的用户协议中都有对不可抗力相关的说明,这也是一种通用条款。因此,大家大可不必担心。
我们大胆的假设下微软如果真的”断供“ 对于我们会有多大对影响呢?我们有没有可替代对方案?
微软的业务分为云和桌面操作系统以及办公软件这三大块,至于移动端,咳咳,咱就不提了。
首先,云计算这一块,国内几乎被阿里云、腾讯云等国内巨头占据了大量对市场份额,2018年IDC 中国云计算市场份额报告中,微软Azure 只占5%,而阿里云占比45.5%、腾讯云占比10.3%。这一块断供对我们影响不大。
但是,如果微软在操作系统这一块对我们实施断供,那么会怎么样,我们来看一组数据,根据 statcounter 机构数据,截至 2019 年 11 月,全球操作系统市场上,Windows 占据了 77.21%的市场份额,OS X 占据了 16.79%的市场份额,Linux 只占据约 1.79%的市场份额。可见微软在桌面端的市场份额和影响力。
同时,微软在office 办公软件的市场份额也非常高,如果这一块断供,受影响最大对将是企业客户。
可能有人会说了微软断供,我们有没有替代方案?事实上,在过去和现在,很多国家在过去都曾尝试努力摆脱对微软对依赖,我们来看看:
韩国政府宣布计划将政府及公共机构的操作系统替换为基于Linux的开源操作系统,将于2026年完成。而隔壁的朝鲜早就开始使用自主研发了红星操作系统。
2020年5月,德国慕尼黑政府宣布将放弃Windows系统,逐步开始使用Linux。
2018年,据俄罗斯《消息报》报道,俄罗斯国防部决定将所有办公电脑操作系统改为自主研发的Astra Linux系统。
2020年1月14日,微软正式停止Windows 7、Windows Server 2008等操作系统的更新和支持服务,全球数以亿万计的用户失去了官方支持,而中国用户在其中占比最大,他们的系统将在无防护状态下运行。我们今天在一些场合,例如医院看到医生使用的操作系统还是windows xp, 甚至笔者见过最牛逼对是某电信公司装的操作系统还是windows 98,为什么政府部门不愿升级系统,去采购windows 10 这样的操作系统,因为不安全,也正是这个原因直到 2017 年底,才允许微软与中国电科合资公司修改后发布的「Windows 10神州网信政府版」进入采购目录。Windows 10 神州网信政府版是在 Win10 基础上,根据中国法律法规,针对中国专业领域的需求,定制开发的一个操作系统版本。
因为无法实现自主可控,对于系统的控制权不在我们自己手上,这也是很多国家在去微软化的最大原因。中国工程院院士倪光南就曾表示信息安全问题是个“定时炸弹”,现在很多事件,像乌克兰停电,就是受到攻击以后整个瘫痪了。所以核心技术如果不掌握,我们可能会遭到供应链给人“卡脖子”,还有安全被人“卡脖子”,实际就造成了像棱镜门事件,或者像乌克兰停电,或者伊朗核设施被人攻击破坏这种情况。
同时最近一段时间,随着美国对中国对打压,尤其是对华为的打压,我们国内逐渐意识到了实现技术自主和去美化有多么重要,但是事实上去微软化的路程是非常艰辛和急需要耐心的。
上面说对德国慕尼黑政府宣布将放弃Windows系统,事实上,早在2003 年,受微软终止支持 Windows NT 4.0 的影响,慕尼黑决定抛弃Windows,而使用Linux,但是在2017年最终还是又开始回归了 Windows。这是为啥?因为 Linux 虽然安全可靠、可控,但是生态建设不如windows,普及性和易用性不如Windows,像专业的Photoshop和一些工业软件无法在Linux上使用。
而在国内,倪光南院士曾在公开场合中表示,目前国内一些重要的部门已经率先开启了用国产Linux系统替代国外系统的过程。另外国家税务总局就采购了中兴新支点操作系统,由此可以看出在替换Windows这方面,国家已经有所行动了。
如果Windows真的断供,将是国产软件的重大机遇。
国内已经有不少基于Linux内核研发的操作系统产品,据笔者了解到,以武汉深之度科技有限公司为首的一批国内做操作系统的厂商组建的统信软件,正在打造“中国操作系统创新生态”,目标就是为了解决我国操作系统受制于人的心腹之患。目前来看笔者体验后UOS 和开源的deepin 非常相似,但是UOS会更稳定些,对于普通用户做了些权限限制,比如不能使用root,总体使用上感觉虽然和windows 还存在一定对差距,例如没有原生的微信以及专业对工业级软件,但是简单的办公是没有问题的,其通过Wine 实现的各种windows 平台软件也可以运行,但是体验稍差,生态方面还需要持续建设,目前统信UOS 还在不断在适配各种国产软件,我们目前可以看到例如网易云音乐、wps办公软件、百度网盘、搜狗百度和讯飞输入法等软件的影子,从UOS的适配名单中笔者还看到了大量的国产软件开始适配系统和国产CPU。同时UOS的界面非常的漂亮,有点集windows和mac 的所有有点一样。
对于程序员而言,各种IDE全家桶都是原生的,例如JetBrains全家桶、vscode等大量开源软件,可以说对于程序员而言,使用Linux 是最没有成本和最舒服的。
同时在游戏方面还有steam上各种原生的Linux 游戏,例如巫师3、Dota2、GTA等游戏,体验完全不比windows 下差。
另外悄悄告诉你们,这篇文章笔者就是在manjaro kde 下完成的。现在的Linux 的体验已经不比windows 差了,甚至windows在很多方面有抄袭(借鉴)的意思,比如windows 10 的多桌面。
几年前,我们讨论的是去IOE、即去IBM、Oroce、EMC,现在,我们讨论的是如何实现硬件自主和系统自主,相信在未来,我们一定可以使用上国内的操作系统,但是请你相信,微软是不会放弃中国这么一块巨大的市场的。所以完全不用担心使用不了Windows,这是对于普通人而言,而对于国家而言,自主可控就显得无比重要了。我们不得不承认的一件事情就是在这一块我们还有很长的路要走。任重而道远,我们需要更多的实干家来不断完善生态,而不是打着国产操作系统的牌子行骗或者只是演讲台上的PPT。
如果真有那么一天,你会用国产操作系统吗?欢迎评论区留言。
]]>本文主要针对如何使用积分扩展点以及如何实现与有赞云独立的数据库进行整合进行简单的介绍,本案例中用到的数据库仅为测试使用,且只是为了演示如何使用,不对具体的业务逻辑做具体的实现
1.首先,打开clone 下来的工程,根据如图所示的youzanyun-demo-dal
位置添加对应的实体类、Mapper、Mapper.xml文件
我这里简单贴下我的代码
对应的mapper UserSourceMapper
1 | @Mapper |
dataobject 中的usersource 下的UserSource
1 | public class UserSource { |
reources 下的mapper 如下
1 | <?xml version="1.0" encoding="UTF-8" ?> |
里面对应的数据库表,会在创建数据库时说明,接下来,我们在有赞云控制台的应用管理-配置管理-应用变量中新增如下配置
键 | 值 | 说明 |
---|---|---|
mybatis.mapperLocations | classpath:mybatis/mapper/*.xml | mapper文件路径 |
mybatis.typeAliasesPackage | com.youzan.cloud.youzanyun.demo.dal.dao | dao包路径 |
mybatis.typeAliasesPackage | com.youzan.cloud.youzanyun.demo.dal.dataobject | 实体类路径 |
druid.datasource.url | jdbc:mysql://10.60.164.192:3306/test?characterEncoding=utf-8 | 数据连接地址 |
druid.datasource.password | password | 密码 |
druid.datasource.username | root | 用户名 |
druid.datasource.driverClassName | com.mysql.jdbc.Driver | 驱动 |
然后我们返回工程,我们在如下位置新建一个 IncreasePointsExtPointDemoImpl
积分扩展点实现类,当然你放在自己建的目录中也可以
代码如下
1 | @Slf4j |
接下来,我们需要去数据库配置数据库,在应用管理中的组件管理,新增一个mysql
然后点管理,可以看到你的数据库信息,包括IP 端口 用户名和密码
点击管理控制台,登录phpmyadmin
比如我这里创建的数据库
1 | CREATE TABLE `user_source` ( |
然后在里面插入一条数据
1 | INSERT INTO user_source (account_id, account_type, amount, description, event_type , biz_vlue, operator_name, extra_info) VALUES ('17563168', 'YouZanAccount', 10, '1', 100 , 'null', '13148484985', 'null') |
我们将编写好的代码push 到服务器,然后在业务配置-配置管理中的会员中心后端扩展中开启对应的扩展点。因为是测试,不需要配置业务标识
然后在控制台点击发布,在应用管理-发布管理,点击发布,选择服务端发布
发布成功后,我们在对应的微商城中的客户管理里面给上面插入的客户给积分(注意,这个用户的数据我已经提前插入到数据库中,不然是无法更新的
如果发现没有成功,建议在扩展点打一些日志,然后在运维管理-日志管理中查看对应的日志信息,如下所示可以看到已经成功进入扩展点并打了日志
我们可以在数据库中执行
1 | SELECT * FROM user_source; |
可以看到积分已经变成3000了,表示整合mybatis 对数据库进行更新成功了
那么我们知道怎么去实现增加积分,我们也可以照葫芦画瓢的去实现查询和消耗等扩展点
1.报错
1 | 2020-04-22 07:25:14.032 ERROR 31 --- [DubboServerHandler-10.62.180.70:7200-thread-2] wsc-pc-scrm-0a5b1aad-1587511513395-472276 y.c.y.d.b.IncreasePointsExtPointDemoImpl : 增加用户积分异常 {} |
解决,确认你的mybatis.mapperLocations 对应的路径是否正确
]]>首先,配置maven
1 | <dependencies> |
然后我们在application.properties 中进行配置
1 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource |
接下来我们创建一个User 类
1 | public class User { |
然后创建一个UserDao 类
1 | @Repository |
接下来创建一个UserService 类
1 | @Service |
最后是UserController类
1 | @RestController |
我们运行程序,然后访问127.0.0.1:8080/user 我们看到IDE 控制台输出了如下内容
访问数据库,我们查询后结果如下
这是传统Dao 方式的整合,接下来,我们讲下使用Mybatis 整合
首先,在pom.xml 中增加
1 | <dependency> |
然后创建一个Mapper 文件夹,在该文件夹下创建一个UserMapper 接口
1 | @Mapper |
接下来,在resource下创建一个Mapper 文件夹,然后在文件夹中创建一个UserMapper.xml
1 | <?xml version="1.0" encoding="UTF-8" ?> |
然后对之前的UserService 类进行改造
1 | @Service |
然后我们在application.properties中添加mybatis 的配置
1 | mybatis.typeAliasesPackage=com.example.demo.Mapper |
最后,我们修改下UserController
1 | @RestController |
运行程序,我们访问结果如下
查询数据库
整个工程的目录结构如下
]]>那么本文就针对创建电子卡券的这个流程进行讲解如何去使用扩展点实现这一功能。
首先,要使用扩展点,你必须具备以下条件:
这里假设你已经创建了自用型容器,我们从首页进入到该容器中,将项目克隆到本地
切换到git 仓库信息,复制仓库地址,然后在克隆的时候填写username 和password,username就是你注册平的手机号,password 就是Gittoken
克隆后先不要着急 import 项目,我们先配置下Maven的setting.xml文件,你可以复制我下面的,我这里使用的maven 版本是apache-maven-3.6.3
1 | <?xml version="1.0" encoding="UTF-8"?> |
然后打开idea,导入项目并下载对应的jar包,整个项目大概是这样的
上图是创建应用后通过 git clone 下来的工程结构,应用名称为 youzanyun-demo,默认生成有六个 module。
项目根包名:com.youzan.cloud.youzanyun.demo。
接下来按图例说明一下:
youzanyun-demo-api:接口声明 XXService.java、DTO 封装等,一般在这个模块里不会去依赖其他模块和第三方依赖;
youzanyun-demo-biz:服务实现模块,除了在该模块里写 XXServiceImpl.java 外,最主要的还会在这里编写业务扩展点实现类和消息扩展点实现类;
youzanyun-demo-dal:如果你的应用中用到了数据库,需要在这个模块里去写 dao、mapper 等,应用框架默认支持 druid 和 mybatis;
youzanyun-demo-deploy:这个模块是用来打包的,执行 mvn package 后的最终 jar 包生成模块,所以生成后不需要去改动里面的内容,改动后可能会导致发布失败;
youzanyun-demo-web:项目的一些 web 相关的类放在这个模块里,如 XXController.java,以及一些静态资源(js、css、页面等等);
youzanyun-demo-ui:前端扩展点定制需要在该目录下实现。 h5-extension,H5定制目录;mp-extension,小程序定制目录,创建应用后默认不会有这个目录,通过开发者工具导入项目之后会自动生成。
按照说明我们要实现对应的扩展点,需要在如下目录中去创建对应的后端业务扩展点,也就是youzanyun-demo-biz\src\main\java\com.youzan.cloud.youzan.demo.biz,注意不要去修改包名称,否则可能无法加载到对应的Bean
接下来,我们开始创建扩展点,这里我演示下创建电子卡券扩展点,首先我们创建一个 CreateTicketExtImplDemo 的类,然后这个类的基本结构如下
1 | @Slf4j |
说下上面的class
那么,我们接下来只需要在这个方法里面写上具体的业务逻辑,然后将结果返回给有赞云就行,有赞云提供了丰富的扩展点接口,你可以参考文档 https://doc.youzanyun.com/doc#/content/EXT/0-1
以创建电子卡券接口为了,我们需要用到2个接口
那么对应的业务逻辑基本如下:
最终代码如下,仅供参考,实际请根据业务需要实现
1 | package com.youzan.cloud.youzanyun.demo.biz; |
注意上述代码中创建token 部分与你直接调用API接口所使用的Token 创建方式并不一样,需要特别注意
1 | // 创建Token |
然后我们将实现好的业务代码push 到git仓库去,这样在开发环境下的业务配置-路由配置-交付-后端流程中,我们就可以看到我们实现的扩展点,我们将他开启
这里的业务标识,我们可以不用管,但是在实际的生产环境中如果你需要对特定类型的商品实现扩展点,那么你需要配置。
不过这里有个注意点创建电子卡券扩展点与下单中的电子卡券自定义交付扩展点会冲突,如果你开启了这个扩展点建议先关闭,否则可能看不到具体的效果
开启后,我们切换到应用管理-发布管理,我们点击发布,选择服务端,然后填写发布说明进行发布
最终发布的版本会在列表显示
接下来,我们可以在对应的授权测试店铺进行测试,如何判断店铺是否授权呢?我们在应用概况的店铺授权信息中点击新增/查看测试店铺就可以看到了,在这个店铺去创建一个电子卡券类型的商品,然后下单测试
当你创建完订单后会自动生成对应的电子卡券的卡券凭证,这里面就包括了券码和统一核销码
好了,以上就是整个扩展点的使用说明
]]>1 | <dependency> |
然后创建一个Book 类
1 | package com.example.demo; |
然后创建一个BookController 控制器
1 | package com.example.demo; |
接下里在resource 下的template 中新建一个books.html
1 | <!DOCTYPE html> |
在application.properties中添加如下内容
1 | spring.thymeleaf.cache=false |
访问结果如下
]]>任何先进技术的产生都不是凭空出现的,SpringBoot 也不例外,SpringBoot 是基于Spring 的基础上产生的。众所周知,Spring 是一个轻量级的容器,在Java EE 项目中得到广泛使用,但是Spring
其复杂、繁琐和臃肿的XML配置方式配置使得开发人员在实际使用过程中变得非常痛苦,尤其是与其他第三方工具进行整合时,比如Mybatis等就更会使得配置文件变得异常复杂和重复,比如我们来看一段Spring的配置
上图是一段配置数据库以及事务管理和Mybatis 的配置,我们发现仅仅是配置文件就非常的多,当然这还不是最复杂的。在这种基础上,SpringBoot 诞生了。
SpringBoot 的出现给开发者带来了新的自动化配置解决方案,使得开发者能够基于 SpringBoot 快速创建基于 Spring 生产级的独立应用程序, SpringBoot 中对一些常用的第三方库提供了默认的自动化配置方案,使得开发者只需要很少的 Spring 配置就能运行完整的 JavaEE 应用。由于其拥有了开箱即用的特性以及服务监控方案同时自带web服务器且与Spring的另一个主流的Spring Cloud 等服务治理框架以及kubernetes 等技术的融合使得开发人员可以快速的实现微服务以及服务的治理、熔断等,最重要的是你可以完全不需要配置XML,真的是太爽了。
那么,如何入门SpringBoot 呢?本文将带你了解
首先,我们创建一个SpringBoot工程,创建SpringBoot的方法有很多,这里以IDEA 企业版为例,我们选择 Spring initalizr 然后创建一个工程
创建完工程之后,我们打开pom.xml,我们可以看到这段配置
1 | <parent> |
spring-boot-starter-parent 是一种特殊的 starter,它提供了一些 maven 默认配置 ,同时还提供了dependency-management ,可以便开发者在引入其他依赖时不必输入版本号,方便依赖管理。
SpringBoot 提供的starter 非常多,这些 Starter 要为第三方库提供自动配置,假如我们要配置一个web项目,则可以在maven 中加入
1 | <dependency> |
在项目的入口我们可以看到一个DemoApplication,这是整个SpringBoot的入口
1 | package com.example.demo; |
其中@SpringBootApplication 注解等于如下注解,表示开启自动配置以及自动扫包
1 | @EnableAutoConfiguration |
其中ComponentScan 会扫描@Service、@Repository、@Component、@Controller、@RestController以及带@Configuration 注解的类,但是我们为了更方便,通常都是直接在入口加上@SpringBootApplication
在IDE中,我们运行DemoApplication 这个class 就可以运行SpringBoot 了,此时终端会出现如下信息,我们可以看到 (v2.2.6.RELEASE) 版本号以及Tomcat的端口
但是此时我们去访问127.0.0.1:8080,会出现404的提醒
我们可以在项目下新建一个 HelloController
1 | @RestController |
此时,我们去访问可以看到如下内容
当然,更多的时候我们写完一个应用,是需要放到服务器上去运行的,这个时候我们需要把应用进行打包,要打包应用,我们需要在pom.xml中配置
1 | <build> |
当然,使用idea 创建的SpringBoot 这些都给我们安排的妥妥的,我们只需要在终端输入如下命令就可以将整个项目进行打包
1 | mvn package |
然后我们在终端执行
1 | java -jar target/demo-0.0.1-SNAPSHOT.jar |
就可以运行打包好的项目,如下所示
当SpringBoot 程序启动之后,我们会看到SpringBoot 的Logo
但是通常情况下,企业会将其替换成自己的公司Logo,那么如何定制属于自己的企业Logo 呢?
首先,我们要把文件转成TXT文本形式的字体,比如在 http://www.network-science.de/ascii/ 设置,比如我们设置一个SpringDemo的字体
然后在项目的resource目录下新建一个banner.txt的文件,将生成的文字复制粘贴进去即可
然后我们重新运行程序就会发现默认的Logo 被替换了
如果要关闭也很简单,只需要在main函数中,设置
1 | SpringApplicationBuilder builder = new SpringApplicationBuilder(DemoApplication.class); |
在SpringBoot 中,我们可以在application.properties 中对web 容器进行配置,如下所示
1 | server.address=127.0.0.1 # 配置地址 |
在idea 中,会对配置项进行智能提示,非常方便
我们还可以在该文件中配置证书
1 | server.ssl.key-store= #配置秘钥文件名称 |
SpringBoot 中的application.properties配置文件可以出现在如下4个位置
开发者也可以自定义这个文件的名称,只需要在运行时加上spring.config.name=xxx即可
1 | jar -jar xxx.jar --spring.config.name=xxx |
也可以知道配置文件所在路径
1 | jar -jar xxx.jar --spring.config.location=classpath:/ |
SpringBoot 的配置文件最终都会被加载到Environment中,我们可以通过@Value 注解以及EnvironmentAware 接口来讲数据注入到属性上,例如application.properties中的内容如下
1 | book.name=西游记 |
Book 类的内容如下
1 | @Component |
其中ConfigurationProperties 注解中的prefix 属性描述了要加载配置文件的前缀对应的控制器类如下
1 | @RestController |
我们执行后访问可以看到如下内容
除此之外,还支持YAML 配置,我们将application.properties中的内容删除或注释,然后在resource中新建一个application.yml 文件,内容如下,重新运行程序得到的结果与上面的一样。
1 | book: |
SpringApplicationBuilder builder = new SpringApplicationBuilder(DemoApplication.class);
builder.application().setAdditionalProfiles(“prod”);
builder.run(args);
或者在项目启动时候加上`--spring.profiles.active=prod`
]]>首先,还是介绍下环境
我们先使用idea 创建一个maven工程,工程名称叫com.ssm,然后在pom.xml中加入以下jar包,可以看到所需要的jar包还是很多的
1 | <dependencies> |
然后我们编写配置文件,在mian-java 这个目录上点击右键创建一个文件夹,然后选择resource,然后在resource 下创建db.properties 文件,内容如下
1 | jdbc.driver=com.mysql.jdbc.Driver |
其对应的数据库创建方式以及数据插入如下
1 | mysql> create database mybatis_db; |
然后还是在resource 目录下创建一个applicationContext.xml文件,内容如下
1 | <?xml version="1.0" encoding="UTF-8"?> |
这个配置文件中主要是定义了数据库的驱动以及连接池、事务管理器等,在最后配置了Mybatis 的工厂,制定其核心配置文件为mybatis-config.xml,并且使用typeAliases 创建一个别名,关于别名,你可以参考官网文档 https://mybatis.org/mybatis-3/zh/configuration.html#typeAliases
1 | <?xml version="1.0" encoding="UTF-8"?> |
然后我们开始整合,我们先看下使用传统的DAO 方式如何整合,采用传统DAO 方式整合,我们需要编写DAO 接口以及实现类,并且需要向DAO实现类注入SqlSessionFactory,然后通过方法体通过SqlSessionFactory 创建SqlSession。具体怎么做呢?
首先,我们创建一个User.java 的用户类,并生成get和set方法以及tostring方法
1 | package com.ssm; |
然后我们创建一个UserMappler.xml,编写一个根据用户id查询用户的select 语句
1 | <?xml version="1.0" encoding="UTF-8"?> |
接着我们在Mybatis-config.xml中创建一个映射文件
1 | <mappers> |
接着我们创建一个UserDao.java,我们创建一个findUserById 的接口
1 | package com.ssm; |
我们需要在applicationContext.xml 中定义一个bean,其id 为userDao,并指向clas路径,同时定义一个property,引用sqlSessionFactory,
其表示将sqlSessionFactory对象注入该bean 的实例化对象中
1 | <bean id="userDao" class="com.ssm.UserDaoImpl"> |
然后我们需要实现UserDao,我们创建一个UserDaoImpl.java文件,内如下
1 | package com.ssm; |
接着,我们创建一个测试类
1 | package com.ssm; |
执行结果如下
以上是使用传统Dao方式来进行整合,但是我们会发现采用这种方法实现整合会出现大量冗余代码,为此,我们可以使用Mybatis 提供的Mapper 接口进行实现
MapperFactoryBean 是Mybatis-Spring 提供的一个用于根据Mapper 接口生成Mapper 对象的类,这个类在Spring 配置时候可以配置一下参数
了解了基本的配置后,我们就开始使用Mapper 接口的方式进行整合了
首先,我们创建一个UserMapper.java,内容如下
1 | package com.ssm; |
同时,创建一个UserMapper.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
仔细看你会发现和传统Dao 方式中我们定义接口其实一模一样,不过,接下来可就不一样了,我们需要在spring的配置文件中创建一个id为userMapper 的bean,代码如下
1 | <!-- Mapper代理开发(基于MapperFactoryBean)--> |
这段配置是用来定义Mapper代理开发,也就是基于MapperFactoryBean的配置,然后我们在测试类中进行测试,你会发现我们并没有写UserMapper 的实现类UserMapperImpl,这是与传统DAO方式的区别
1 | @Test |
执行代码
接下里我们看下给予MapperScannerConfigUre 的整合,在实际的开发过程中,Dao 层会包含很多的接口,如果我们每一个接口都要在Spring中配置对应的Bean,那么这个工作量是相当大的,因此mybatis-spring提供了一种自动扫描的兴衰来配置mybatis中的映射器,即可采用MapperScannerConfigure 类
只需要在spring配置文件中定义如下配置即可,我们将spring配置文件中的传统Dao 和基于MapperFactoryBean 的bean 注释掉,增加如下配置
1 | <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> |
其中
然后我们再次执行对应的测试类,发现一样的效果。你会发现通过这样整合,这种是不是特别简单呢?
]]>在传统的JDBC 实现中,我们需要把查询过程写在java 类中,这样非常不便于后期维护,而使用Mybatis 则可以将查询语句配置在配置文件中,只需要维护好映射关系即可, 下面我们就来一起看雪如何去使用Mybatis吧。
首先,我们创建一个mybatis_db 的数据库,然后创建一个表 t_user,在这个表中我们插入几条数据,如下所示:
1 | mysql> create database mybatis_db; |
我们创建一个maven工程,并配置pom.xml 下载mybatis 和mysql-connect-java 的jar包,目前mybatis 的最新版本是3.5.4
1 | <dependency> |
整个工程的目录如下
接下来,我们在 idea 的resource 中创建一个mybatis-config.xml 的配置文件,内容如下,具体不需要过多解释就是配置JDBC相关的参数以及通过mappers 定义一个mybatis 的映射文件
1 | <?xml version="1.0" encoding="UTF-8"?> |
接下里我们创建对于的User类,并生成get和set以及toString 方法
1 | package com.mybatis; |
配置UserMapper.xml
接下里,我们创建映射文件UserMapper.xml 然后需要制定一个namespace就是 UserMapper,接着写一个select 语句,定义id和参数类型以及resultType,resultMap是指描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
1 | <?xml version="1.0" encoding="UTF-8"?> |
然后我们创建一个测试类,根据id来查询用户
1 | package com.mybatis; |
如果我们希望进行模糊查询,则在UserMapper.xml 中定义
1 | <select id="findUserByName" parameterType="String" resultType="com.mybatisdemo.User"> |
然后在测试类中新建一个方法进行测试
1 |
|
如图所示
接下来我们测试下添加新用户,首先我们在UserMapper.xml 中定义一个insert元素
1 | <insert id="addUser" parameterType="com.mybatisdemo.User" > |
然后来写测试接口
1 | @Test |
如下所示
接下来测试更新
1 | <update id="updateUserInfo" parameterType="com.mybatisdemo.User"> |
然后写个测试类
1 | @Test |
执行后如下所示
最后,我们测试下删除功能
1 | <delete id="deleteUser" parameterType="com.mybatisdemo.User" > |
测试类如下
@Test public void deleteUser() throws Exception { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); int rows = sqlSession.delete("deleteUser",1); if (rows >0){ System.out.println("Success delete "+ rows +" data!"); }else{ System.out.println("delete data fail!"); } sqlSession.commit(); sqlSession.close(); }
执行结果如下
]]>Spring 通过一个名为spring-tx-4.3.6-RELEASE 的JAR包来管理事务,在这个JAR包中的org.Springframework.transaction 包中包含了三个接口文件:
接下来我们将通过实例的方式来讲解如何使用注解的方式来通过Spring 进行事务的处理,手续我们在maven的pom.xml 中增加事务的JAR包
1 | <dependency> |
我们首先准备一个数据库
1 | CREATE TABLE IF NOT EXISTS `user`( |
然后向数据库中写入一些数据,包括了用户名、密码和积分,如下所示
1 | MariaDB [spring_db]> select * from user; |
我们要做的事情就是把张三的积分转给李四
我们需要创建一个 User 类,如下
1 | package com.SpringDemo; |
然后创建一个接口 UserDao
1 | package com.SpringDemo; |
在UserDao 接口中我们定义了一个transfer 的方法,它包含了三个参数分别是outUser、inUser、jifen
接来下我们定义实现类 UserDAOImpl
1 | package com.SpringDemo; |
接下来我们定义一个applicationContext.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
Spring 的事务管理方式有2种,一种是传统的编程序事务管理,即通过代码来管理事务的开始、执行和异常以及回滚,一种是声明式管理,即通过配置文件的方式,原理是通过AOP技术实现,我们在实际开发过程中推荐使用声明式事务管理,效率会大大提升,因为只需要通过配置即可。
在该接口中我们我们重写transfer的方法,更新数据库将inUser 的积分进行增加,而对应的outUser 积分要进行减少,但是在这里我们要模拟系统运行的一些突然性问题。之后我们加了一个@Transactionl 注解,并设置了propagation、Isolation、readOnly 三个参数
1 | @Override |
注解 @Transactional 的参数含义如下
属性名 | 说明 |
---|---|
name | 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器。 |
propagation | 事务的传播行为,默认值为 REQUIRED。 |
isolation | 事务的隔离度也可以叫隔离级别,默认值采用 DEFAULT。 |
timeout | 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。 |
read-only | 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。 |
rollback-for | 用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。 |
no-rollback- for | 抛出 no-rollback-for 指定的异常类型,不回滚事务。 |
@Transactional 注解也可以添加到类级别上。当把@Transactional 注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。
isolcation 除了 DEFAULT,还有其他属性,我们可以在Isolation 这个类中看到相对于的定位
1 | public enum Isolation { |
Propagation 的属性如下
1 | public enum Propagation { |
此外使用@Transactional 必须保证是在public 级别的方法中使用,@Transactional 只能应用到 public 方法才有效,这是因为在使用 Spring AOP 代理时,Spring 在调用 TransactionInterceptor 在目标方法执行前后进行拦截之前,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的的 intercept 方法或 JdkDynamicAopProxy 的 invoke 方法会间接调用 AbstractFallbackTransactionAttributeSource(Spring 通过这个类获取 @Transactional 注解的事务属性配置属性信息)的 computeTransactionAttribute 方法。
接下来我们创建一个测试类来进行测试
1 | package com.SpringDemo; |
我们执行上述程序,可以发现报错了,程序报
1 | Exception in thread "main" java.lang.ArithmeticException: / by zero |
如图所示
此时,我们查看数据库中的数据没有发生任何变化
1 | MariaDB [spring_db]> select * from user; |
而当我们把 int i =1/0; 注释掉再次执行就会发现程序执行没有报错了,并且数据发生了变化
1 | MariaDB [spring_db]> select * from user; |
好了,以上就是关于Spring的事务管理介绍。
]]>进入有赞什么感受呢:
其实我觉得电脑这玩意就是一个工具,我没有什么信仰,对于我来说是mac 还是 Windows 其实都一样,以前买这台mac 是因为上上家公司购买 macbook 办公有补贴,所以就买了,用了4年,算下来也是不亏的。于是开开心心的卖了。因为这台mac 在我录制视频剪辑的时候会很卡,正好现在的公司又给配了一台2019款的mac,所以我这台mac其实就可以下岗了。如果闲置着越往后越贬值了不如趁着还值几个钱卖了搞个台式机还可以用个六七年不成问题
卖了之后直接就在老板那配个Windows台式机扔家里,其实自从微软推出了Windows 10 我感觉 Windows 也是越来越好用了,而 mac 主要胜在系统的流畅性以及item2等工具非常适合开发,但是 Windows 其实也可以,比如我现在使用vscode +hexo+git+markdown 写文档,写完直接 vscode 一键提交,完全不用切换窗口。毕竟不论是 mac 还是Windows 都只是个工具而已。
因此,卖掉后我直接自己装了一台Windows 台式机,本来是打算选择京东自营的,但是从京东看整套配件价格在6280,如下所示
配件 | 型号 | 京东价格 |
---|---|---|
cpu | AMD 锐龙7 3700X 处理器 (r7)7nm 8核16线程 3.6GHz 65W AM4接口 盒装CPU | 2249 |
主板 | 微星(MSI)B450M MORTAR MAX迫击炮 电竞电脑主板 支持3700X/3600X/3600/2600 CPU(AMD B450/Socket AM4) | 739 |
内存 | 金士顿(Kingston) DDR4 3200 16GB(8G×2)套装 台式机内存条 骇客神条 Fury雷电系列 | 689 |
ssd 硬盘 | 三星(SAMSUNG)250GB SSD固态硬盘 M.2接口(NVMe协议) 970 EVO Plus(MZ-V7S250B) | 529 |
显卡 | 影驰 GTX1660Super/GTX1660TI 6G GDDR6 台式电脑游戏显卡 GTX1660Super大将6G 高频版 | 1599 |
机箱 | 先马(SAMA)黑洞7 中塔主动静音台式电脑主机箱 支持ATX主板/宽体五金/标配3风扇4面静音棉/背线/独立电源仓 | 209 |
电源 | 长城(GreatWall)额定500W HOPE-6000DS 电源 (70cm超长背板走线/三年质保/台系电容/12cm静音风扇/宽幅) | 249 |
总价 | 6263 |
结果我发现线下配还便宜200多,但是可能是因为我比较懂硬件的配置,没有被坑,今天跟我在一个地方装机的女生,是个主播,我就看到老板给他写的配置,那真的是给小白写的。CPU 就直接写I5,具体是几代不提的,所以如果你不懂配置,不建议去逛电脑城,老板最喜欢的就是这种,他会把一些难卖的产品或者对于他来说有赚头的产品卖给你而不是你想要的产品。
很多人会说京东买的售后会好些,其实我觉得线下线上都一样。另外我觉得很多人喜欢用鲁大师跑分,手机也跑分,我觉得真的没必要在乎这些。这玩意骗骗小白而已,真把他当回事就有点过了,其实现在不管你怎么配,只要硬件是新款的性能都说完全够用的,除非你是发烧友或者是专业级的用来处理视频渲染,当然都会搞这个了肯定多多少少对硬件有一定了解了。小白而言其实主流配置就可以。最多一套5000完全够用了。
这台电脑我给他定的使用年限是6年。
测试下磁盘速度如下,还是可以的,我也不怎么玩游戏其实250G对于我来说够用了
]]>Spring JDBC 模块主要包括core、dataSource、object、support四个包
我们了解了这些模块的功能,接来下我们看看怎么去配置JDBC,请看下面的xml文件
1 | <?xml version="1.0" encoding="UTF-8"?> |
在上述xml 文件中的beans
中定义了三个bean
,分别是dataSource、jdbcTemplate。
其中dataSource中的4个属性分别对应的是
driverClassName,它是数据库的驱动
url 数据库的访问地址
username 数据库的用户名
password 数据库的密码
在使用传统的JDBC操作数据库时,这些参数我们也是要配置的。
下面我们通过实例的方式来讲解如何通过JDBC来对数据库进行操作,我们需要进行以下准备工作
1.配置maven的pom.xml 下载所需要的jar包
1 | <dependency> |
2.需要有一个可以反问的数据库,比如我的数据库设置密码为root
1 | mysqladmin -u root password root |
3.创建一个spring_db 的表
1 | MariaDB [(none)]> create database spring_db; |
1 | @Test |
进入数据库,我们可以看到该表已经被创建出来了
1 | MariaDB [(none)]> use spring_db; |
下面,我们通过jdbc 来实现增删改查操作,首先,我们要创建一个类,名字为User,这个User 类中包含了用户的id、用户名和密码信息,并设置其set和get属性
1 | package com.ssm.jdbc; |
然后我们创建一个UserDao 接口,该接口定义了添加、更新、删除、根据ID查询和查询所有用户的方法
1 | package com.ssm.jdbc; |
接下来,我们来对UserDao的接口进行实现,在这个方法中我们对具体的增删改查逻辑进行设置,直接看代码吧
1 | package com.ssm.jdbc; |
然后我们在jdbc.xml 中加入bean,加入UserDao
1 | <!-- 定义id为userDao的Bean --> |
好了,一切准备就绪,我们接来下通过测试类来测试下具体的增删改查。
首先来测试下添加用户方法,如图下所示
1 | @Test |
更新用户
1 | @Test |
删除用户
1 | @Test |
查询用户信息,包括了根据ID查询和查询所有
1 | @Test |
1936年被首次发现,在反山王墓中发现了几千件精美的玉器,含有璧、琮、钺、璜、冠形器、三叉形玉器、玉镯、玉管、玉珠、玉坠、柱形玉器、锥形玉器、玉带及环等,其中在反山12号墓出土的玉琮,是新石器时代良渚文化的玉琮之首,故称“玉琮王”,据《周礼·春官·大宗伯》记载:“以苍璧礼天、黄琮礼地。” 琮是用来祭祀地神的,具有通灵的功能。
随后在几代人考古学家的发掘探索下发现了良渚古城遗址。包括城墙、宫殿、水利系统等,也就是说在五千年以前良渚这个地方就已经孕育出了一个国家。当时的水坝遗址鉴定比传说中的大禹治水故事的通认年代还早数百年至千年。这种水利系统很可能是距今为止最早的水利工程,良渚先民们通过草裹泥来砌大坝治理水。
2019年良渚申遗成功,至此良渚文化已经成为世界历史中绕不过去的话题。
趁着疫情期间公园免费参观,在寒风之中我和老婆一起过去参观一番,虽然是疫情而且还下着小雨,但是游园的人还是蛮多的,进了公园后,如果不了解良渚的历史,你可能会发现这个公园真的没那么的好玩,因为进去之后需要凭借你的想象力来还原良渚先民们是如何在这里生活和工作的。
去年在把房子买在了良渚,距离遗址公园也蛮近的,等房子交付后可以没事就进来晃晃,现在这个季节公园里面的油菜花开的还不错。
]]>AOP 即面向切面编程,也可以叫做面向方向编程,AOP不是一个新东西,它是OOP,即面向对象编程的一种补充,在当前已经成为一种成熟的编程方式。
在学习AOP 之前,我们先了解下为啥我们要使用AOP?
那么,在传统的业务处理代码中,比如你要操作数据库,会进行事务的处理或者打印一些日志。虽然通过OOP 也可以实现,比如通过继承或组合的方式来达到代码的复用,但是如果实现某些功能,比如日志记录,相同的代码会分散到各个方法中,如果后面要想关闭某个功能或进行修改就必须要修改所有的方法,非常的不方便。
那么为了解决为了解决这个问题,AOP的思想随之产生。它采取了横向抽取机制。将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向提取机制的方式。是采用传统的AOP方式下无法办到的。因为传统的面向对象思想只能实现父子关系的纵向重用。
在AOP思想中,通过aspect(切面)可以分别在不同的类的方法中加入,例如事务日志权限和异常处理等功能。
使用切面这种横向方式。能够使开发人员在编写业务逻辑时专注于核心业务逻辑,而不用过度的关注与其他业务逻辑的实现。这样可以提高开发效率,同时还增强了代码的可维护性。
目前主流的AOP 框架有2个,分别是spring aop 和aspectJ,前者是纯Java 实现的,不需要专门的编译过程和类加载器,在运行期间可以通过代理的方式向目标内植入增强的代码。而AspectJ是一个基于Java语言的AOP框架。在Spring 2.0 开始,引入了对AspectJ 的支持,并提供了一个专门的编译器在编译时提供横向代码的植入。
在了解AOP之前,首先要了解一下它的专业术语。这些术语包括Aspect、Joinpiont、Pointcut、Advice、Target Object、Proxy 和Weaving,对于这些专业术语具体的解释如下:
使用AspectJ 实现AOP 的方式有
XML 声明
这种方式是通过XML文件来定义切面、切入点以及通知等,所有的切面、切入点和通知都必须定义在<aop:config>
元素中,在<beans>
元素中可以包含多个<aop:config>
元素,一个<aop:config>
中又可以包含子元素和属性,其子元素包含<aop:pointcut
、<aop:advisor
、<aop:aspect>
,在配置时,需要严格按照顺序来定义,在<aop:aspect>
下,同样包含属性和多个子元素,通过使用<aop:aspect>
元素以及其子元素 可以在XML中配置切面、切入点和通知。如下所示
1 | <?xml version="1.0" encoding="UTF-8"?> |
但是 XML 的配置过于复杂,因为日常开发过程中,我们更倾向于使用注解的方式来进行AOP的开发
为了在应用中使用@AspectJ支持,Spring需要添加三个库:
因此,我们需要配置maven,如下所示
1 | <dependency> |
新建一个app.xml ,我们需要在Spring配置文件中做如下配置:
1 | <?xml version="1.0" encoding="UTF-8"?> |
然后,我们创建一个UserDao 的接口,如下所示
1 | package com.ssm.aspectj; |
将 UserDao 实例化,并加上注解@Repository(“userDao”),方便后续进行调用具体的方法
1 | package com.ssm.aspectj; |
定义一个切面类,在该类中编写各种通知
1 | package com.ssm.aspectj.xml; |
srping 的通知包括五种通知工作:
通知 | 描述 |
---|---|
前置通知 | 在一个方法执行之前,执行通知。 |
后置通知 | 在一个方法执行之后,不考虑其结果,执行通知。 |
返回后通知 | 在一个方法执行之后,只有在方法成功完成时,才能执行通知。 |
抛出异常后通知 | 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。 |
环绕通知 | 在建议方法调用之前和之后,执行通知。 |
在上述代码中,其中 @Pointcut(“execution(* com.ssm.aspectj..(..))”) 表示定义切入点,使用注解@Pointcut 后面的execution(* com.ssm.aspectj..(..)) 表示匹配所有目标类的所有方法。 第一个代表返回类型,第二个代表方法名,而..代表任意入参的方法,他的格式如下
语法:execution(修饰符 返回值 包.类.方法(参数) throws 异常)
最后编写个测试类从ClassPathXmlApplicationContext 读取xml 文件,然后调用getBean 获取userDao并执行addUser方法。
1 | package com.ssm.aspectj; |
结果如下
]]>常用的注解有
声明bean的注解
@Component 组件,没有明确的角色
@Service 在业务逻辑层使用(service层)
@Repository 在数据访问层使用(dao层)
@Controller 在展现层使用,控制器的声明(C)
注入bean的注解
@Autowired:由Spring提供
@Inject:由JSR-330提供
@Resource:由JSR-250提供
首先,创建一个userDao
1 | package com.springdemo; |
然后创建userDao 的实现类UserDaoImpl
1 | package com.springdemo; |
创建userService
1 | package com.springdemo; |
创建userService 的实现类UserServiceImpl
1 | package com.springdemo; |
创建UserController
1 | package com.springdemo; |
Resource 如果报错,需要在pom.xml 中添加javax.annotation
1 | <dependency> |
创建一个beans.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
如果context 报错,确认beans 中的xmlns和xsi 信息是否正确
创建AnnotationAssembleTest
1 | package com.springdemo; |
执行结果
1 | userDao.save |
spring bean 的作用域有如下几种:
以上五种作用域中,request、session和global session三种作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的Spring ApplicationContext环境。
下面简单介绍下2种
当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。
applicationContext.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
ScopeTest.java
1 | package com.springdemo; |
使用scope 指定作用域为 prototype
1 | <bean id="scope" class="com.springdemo.Scope" scope="prototype"/> |
当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。
代码
1 | package com.springdemo; |
首先需要准备2个仓库,
比如我的公共仓库就是 awen.github.io 而私有仓库你自己取名字,我这里叫 deploy_blog,然后把本地的hexo 环境中的文件全部上传到私有仓库去
1 | ssh-keygen -t rsa -b 4096 -f ~/.ssh/github-actions-deploy |
在Settings->SSH and GPG keys添加刚刚生成的公钥,名称随意。
在私有仓库的Settings->Secrets里添加刚刚生成的私钥,名称为 ACTION_DEPLOY_KEY。
在hexo 的站点配置文件下的deploy 中配置repo 为你博客公共仓库的git地址
1 | deploy: |
在私有仓库的Actions选项卡下点击新建workflow,编写如下配置。
1 | name: Deploy Blog |
你也可以在本地的.github 目录下新建一个workflows 目录,在里面新建一个yml 文件内容如上,然后将文件push 到github 上去就会自动触发编译了。
编译过程中如果有错误,在GitHub的actions 中可以看到一个叉,发布成功的是一个绿色的勾
发布失败的可以点进去看下是哪一个步骤出错了,然后对应的修改即可,比如我这里是deploy 这步错了
点击展开,可以看到,根据报错调整你的workflows 文件即可
]]>现在很多企业级的项目都是基于 spring 框架开发的,而这两年很火的微服务概念就有基于 springboot springcloud 等框架,spring 框架解决企业应用的复杂性和耦合性,对于一个Java 程序员来说,要想学习 springboot 和 springcloud,掌握 spring 的基础用法是一件必须做的事情。那么本文就带领大家一起来理解下 spring 的基本概念以及通过一些案例来快速配置 spring,从而理解 spring 的 IoC 和 DI 概念。
学习 Springboot 和 Springcloud 要不要跳过 spring?我的建议是不要,应该先学习 spring 和 spring mvc,然后进阶去学习 Spring其他框架,会更便于你理解。
Spring 是一个以 IoC (英文 Inversion of Control,控制反转)和 AOP(Aspect Oriented Programming)为内核的框架,那么啥是 IoC?AOP 又是个什么鬼?
什么是 IoC
IoC 是 spring 的基础,通过 IoC 可以实现控制,在学 Java 基础的时候我们知道调用 new 关键词来构造一个方法创建对象,而在 Spring 中创建对象就是用 IoC。spring 中的 IoC 方式对象的生命周期管理由Spring 框架提供的 IoC 容器来管理,我们可以直接从 IoC 容器中获取对象,控制权从应用程序交给了 IoC 容器。
什么是 DI
而 DI(Dependency Inject,依赖注入)与 IoC 其实含义是一样的,DI 就是对象的属性,已经被注入好相关的 value,直接使用即可。所谓的依赖注入就是由IoC 容器在运行期间动态的将某种依赖关系注入到对象之中。
什么是 AOP
而AOP 是面向切面编程,它是通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术,AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。
我相信你对于上面的话每一个字你都能看懂,但是连在一起你就不知道是什么意思了,没关系,我们继续往下看。
在我们学习 Java 面向对象的时候,我们都知道,如果你写的代码出现重复了可以将重复的代码做如下操作:
抽取成类的方式我们称之为纵向抽取,我们可以通过继承的方式实现纵向抽取。但是在负载的业务场景下即使抽取成类还是会出现重复的代码,因为一些逻辑(开始、结束、提交事务)依附在我们业务类的方法逻辑中!
而AOP的理念则是将分散在各个业务逻辑代码中相同的代码通过横向切割的方式抽取到一个独立的模块中!
使用 Ioc/DI 的优势是啥
spring 框架不断的升级,目前最新版本已经更新到了 5.2.5 了。但是在本文中我们使用的是4.3.6 来讲解,为了更好的创建一个 spring 项目我们使用的工具有下面:
同时由于 spring 的 jar 包 都在国外服务器,下载速度慢,所以我们使用阿里云的仓库进行加速
打开maven的配置文件(windows机器一般在maven安装目录的conf/settings.xml),在标签中添加mirror子节点插入如下代码就可以使用阿里云的镜像加速下载 jar 包了:
1 | <mirror> |
使用 idea 创建一个 maven 项目
并在 pom.xml 的dependencies中添加如下内容
1 |
|
其中
spring 的核心容器
spring 框架提供了两个最基本最重要的包 org.springframework.beans.factory和org.springframework.context。前者的主要接口是 BeanFactory,后者的主要接口是 ApplicationFactory。
IoC 框架的主要组件有 Beans、配置文件 applicationcontext.xml、Beanfactory 接口和相关类、ApplicationContext 接口和相关类。
Beans 是项目中为业务提供功能的 Bean,就是容器要管理的 Bean,也就是我们场景的 JavaBean、Java 类。
在 Spring 中 Bean 的管理是基于配置文件配置的,如下所示:
1 | <?xml version="1.0" encoding="UTF-8"?> |
配置文件的名称可以是 applicationcontext.xml,也可以是其他,通常我们习惯使用 applicationcontext。
如上所示,在配置文件中xml 标签内的内容是指将定义xml 所遵循的规范。
Spring 要取得该 Bean 类,是根据bean标签中的 id、class 和 property name 和 ref 找到实例对象,从而获取对象的相关属性和值。通常多个 bean 包含在 beans 标签内,而 property 是 bean 对应的子元素。
BeanFactory 使用工厂涉及模式,负责读取 Bean 的配置文件,管理对象的生命周期和依赖关系,包括创建、加载和维护等。
org.springframework.beans.Factory.BeanFactory 是 BeanFactory 的顶级实现类。它会根据配置文件中的定义装载 Bean。Beanfactory 的常用方法有:
ApplicationContext 接口提供了高级功能的容器,基本与BeanFactory 一致,不同之处是:
ApplicationContext 接口实现类有:
上面我们说了依赖注入和控制反转是对同一件事件的不同说明,依赖注入是在使用 spring 框架创建对象时,动态的将其所依赖的对象注入 Bean 组件中,一般通过量子方式
我们通过具体的案例来讲解
在 idea maven 项目中的 src 目录下建立如下目录结构
首先,创建一个 UserDao 接口,定义一个 login()方法
1 | package org.example; |
然后创建一个 UserDao 接口的实现类UserDaoImpl
1 | package org.example; |
在src 目录下创建一个 applicationContext.xml 文件的 beans 标签下配置
1 | <bean id="UserDao" class="org.example.UserDaoImpl"></bean> |
然后创建一个IoC,如下所示
1 | package org.example; |
执行后如下所示,我们可以看到通过 Spring 加载配置文件就可以操作就可以调用 userDao 的 login()方法。
接下来演示 DI
首先,我们创建UserService接口
1 | package org.example; |
然后创建一个UserServiceImpl 实现类并在类中调用 userDao 的 login()
1 | package org.example; |
然后在 applicationContext.xml 中配置property name 设置为
1 | <bean id="userService" class="org.example.UserServiceImpl"> |
最后我们创建一个 DI.java,代码如下所示
1 | package org.example; |
执行 DI,如下所示,我们可以看到Spring 通过userService实现类中的user.login()方法调用了 userDao 的 login()方法。
]]>本文版权归属 CSDN,作者 阿文
2020年3月12日,美团云正式对外发布公告,称因业务调整,美团公有云将于2020年5月31日0:00起,停止对用户的服务与支持,并回收资源。资源回收后将无法找回数据。这也是美团云在内部放弃公有云后两年,正式披露停服时间。
美团云是美团于2013年推出的公有云计算服务平台,成立至今,在华南、华北等多地建设了数据中心,并相继上线了云主机、存储、网络等产品。依托美团在O2O、餐饮、酒店、旅游等行业的经验,美团云还推出了餐饮云、酒店云、交通云等标准化行业解决方案。2015年,美团云正式独立运营,成立北京三快云计算有限公司。
除了美团云之前,在前几年各大巨头都纷纷推出公有云服务,例如滴滴云、百度云、京东云、金山云、华为云、网易云等等,各家推出的产品形态基本一致,都包含了云服务、数据库、对象存储、CDN、云硬盘等等。但是相比较阿里云、AWS、腾讯云等头部云计算厂商而言,这些企业进军公有云市场都比较晚。
据 IDC 最新发布的《中国公有云服务市场(2019上半年)跟踪》报告显示,2019上半年中国公有云服务整体市场规模达到54.2亿美元,其中IaaS市场增速稳健,同比增长72.2%,PaaS市场增速有所回落,同比增长92.6%。
因此笔者认为,在未来公有云市场或将迎来一波大转型,一些三四线公有云厂商或关闭或转型为内部用户服务。
对于三四线的中小型公有云厂商而言,他们所能够获得的用户并不多,因此投入的人力和物力也可想而知。因此在未来,这些厂商最终会关闭公有云服务或转型为内部用户服务以及私有云方向。
而目前公有云IaaS市场来看,阿里、腾讯、中国电信、AWS、华为位居前五,占据总体75.3%的市场份额。
阿里云,调研机构Canalys近日发布了2019年第四季度中国公有云服务市场报告称阿里云在2019年四季度中国公有云市场阿里云排名第一,阿里云通过其强大的生态和运营能力以及多样化的产品,阿里在中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本都有相应的产品和服务,阿里云持续助力互联网行业业务系统上云,不断深耕零售、政府和金融三大行业云化转型。阿里云每年都会举办一次规模巨大的“云栖大会”。
从 2009 年阿里巴巴收购万网到并合并到阿里云旗下,阿里云已经成为全球领先的云计算及人工智能科技公司。服务着制造、金融、政务、交通、医疗、电信、能源等众多领域的领军企业,包括中国联通、12306、中石化、中石油、飞利浦、华大基因等大型企业客户,以及微博等明星互联网公司。在双11全球狂欢节、12306春运购票等极富挑战的应用场景中,阿里云始终保持着良好的运行纪录。
腾讯云借助腾讯集团其在游戏和视频领域的优势以及微信小程序等强大的生态转化能力优势,积极拓展产业互联网的发展机遇。同时腾讯云的产品形态也丰富多样、
AWS凭借其国际市场的领先地位,继续保持在中国企业出海市场的领先优势。AWS 作为云计算的先行者和领导者制定了各种标准。
华为云近几年驶入发展快车道,无论是从组织扩张、市场运营还是行业拓展上都表现突出。
百度云正逐步融合百度集团的生态体系,在不断丰富云服务综合能力的同时,持续增强视频、金融等细分行业的精耕细作。在2019ABC INSPIRE 百度云智峰会上,百度副总裁、百度智能云总经理尹世明宣布,“百度云”品牌全面升级为“百度智能云”。而从 IDC 发布的报告上,我们可以看到百度在PaaS市场表现仍然亮眼,其加速将AI底层技术和应用能力向云输入,刺激了百度云在该市场的长足增长。
事实上,随着疫情的影响,中国云计算服务商反应迅速,为政府、企业提供了云端计算能力、数字化系统、人工智能等服务,做出了突出贡献。受疫情影响政府和企业上云意愿加强,大部分未上云的企业正在评估上云路径,在未来一段时间内云计算服务商将获得更多新客户。而对于这些新客户如何选择适合自己的云平台呢?
笔者认为,应该从企业的自身发展阶段以及各家云服务商给出的优惠力度和云厂商自身的产品性能等多个方面综合评估:
首先,企业可根据自身的预算多考察几家,包括头部企业和二三线云服务商,通过价格、产品形态和性能、稳定性等几个方面对比选择适合自己的平台。
第二,在选择云服务商时要重点考察下其运营能力和研发能力以及产品的完整性,可以通过阅读云厂商的官网文档分析对比出来,一个好的产品其文档应该是完整的详实的,从侧面也能看出来该云厂商的投入力度和研发能力。
第三,考察一个服务商的研发能力还有一个途径就是看其产品的迭代能力,可以考察其产品版本是否紧随开源产品的版本迭代,研发能力强的服务商其推出的产品版本或都较新,而同时研发能力强的企业通常在一些开源领域都会有所建树会积极投身和参与开源领域的产品迭代中。
第四,从售后流程和售后服务的态度来考察,当你遇到一些问题时是否能够快速的获得解决,这就包括上面说的文档的详实程度以及售后的服务水平。如何判断呢?可以通过考察官网文档以及问题的解决时间和质量上来考察。通常来说中小型客户如果选择使用大的服务商时一般所获得的支持力度会比较弱。因此不妨尝试使用一些二线优秀的服务商。
引用
1.IDC: 2019上半年中国公有云市场——硝烟四起,群雄逐鹿 https://www.idc.com/getdoc.jsp?containerId=prCHC45634819
]]>Prometheus是最初在SoundCloud上构建的开源系统监视和警报工具包 。自2012年成立以来,许多公司和组织都采用了Prometheus,这个项目发展到今天,已经全面接管了 Kubernetes 项目的整套监控体系。
Prometheus 项目与 Kubernetes 项目一样,也来自于 Google 的 Borg 体系,它的原型系统,叫作 BorgMon,是一个几乎与 Borg 同时诞生的内部监控系统。
Prometheus非常适合记录任何纯数字时间序列。它既适合以机器为中心的监视,也适合监视高度动态的面向服务的体系结构。在微服务世界中,它对多维数据收集和查询的支持是一种特别的优势。
Prometheus的设计旨在提高可靠性,使其成为中断期间要使用的系统,从而使您能够快速诊断问题。每个Prometheus服务器都是独立的,而不依赖于网络存储或其他远程服务。当基础结构的其他部分损坏时,您可以依靠它,而无需建立广泛的基础结构来使用它。
普罗米修斯重视可靠性。即使在故障情况下,也始终可以查看有关系统的可用统计信息。但是如果您需要100%的准确性(例如按请求计费),则Prometheus并不是一个很好的选择,因为所收集的数据可能不会足够详细和完整。在这种情况下,最好使用其他系统来收集和分析计费数据,并使用Prometheus进行其余的监视。
下图是 Prometheus 和它的组件的整体架构:
从图中可看到包含以下主要组件:
Prometheus的主要特点是:
Prometheus包含多个组件,其中有许多是可选的,例如:
直接去GitHub 下载最新的版本
官网网站 https://prometheus.io/
下载地址 https://github.com/prometheus/prometheus/releases
下载后解压并进入到目录,执行
1 | [root@k8s prometheus-2.15.0.linux-amd64]# ls |
启动后程序会输出一些日志,默认监听的端口是9090,使用的是prometheus目录下的prometheus.yaml 配置文件,程序启动时首选会启动prometheus,然后启动TSDB(时序数据库)
1 | level=info ts=2019-12-24T06:34:56.601Z caller=main.go:294 msg="no time or size retention was set so using the default time retention" duration=15d |
此时通过浏览器访问,可以看到如下界面,这就是prometheus 的控制台
prometheus.yml 是prometheus 的配置文件,您可以使用如下命令来指定配置文件启动 prometheus
1 | prometheus --config.file=prometheus.yml |
它的默认配置如下
1 | # cat prometheus.yml |
包括了
其中global是一些常规的全局配置,这里只列出了两个参数:
scrape_configs指定prometheus要监控的目标,在scrape_config 中每个监控目标是一个 job,但job的类型有很多种。可以是最简单的static_config,即静态地指定每一个目标,例如上面的:
1 | - job_name: prometheus |
默认的配置文件scrape_configs 定义了一个job 对 prometheus 自身进行监控。您可以访问ip:9090/metrics 来访问 prometheus 自身的监控数据
我们用浏览器访问http://host:9090/metrics
,即可看到一个instance向外暴露的监控指标。除了注释外,其它每一行都是一个监控指标项,大部分指标形如:
1 | go_info{version="go1.10.3"} 1 |
这里go_info
即为度量指标名称,version
为这个度量指标的标签,go1.10.3
为这个度量指标version标签的值,1
为这个度量指标当前采样的值,一个度量指标的标签可以有0个或多个标签。这就是上面说到的监控指标数据模型。
可以看到有些度量指标的形式如下:
1 | go_memstats_frees_total 131961 |
按prometheus官方建议的规范,以_total
为后缀的度量指标一般类型是counter计数器类型。
有些度量指标的形式如下:
1 | go_memstats_gc_sys_bytes 213408 |
这种度量指标一般类型是gauge测量器类型。
有些度量指标的形式如下:
1 | prometheus_http_response_size_bytes_bucket{handler="/metrics",le="100"} 0prometheus_http_response_size_bytes_bucket{handler="/metrics",le="1000"} 0prometheus_http_response_size_bytes_bucket{handler="/metrics",le="10000"} 46prometheus_http_response_size_bytes_bucket{handler="/metrics",le="100000"} 46prometheus_http_response_size_bytes_bucket{handler="/metrics",le="1e+06"} 46prometheus_http_response_size_bytes_bucket{handler="/metrics",le="1e+07"} 46prometheus_http_response_size_bytes_bucket{handler="/metrics",le="1e+08"} 46prometheus_http_response_size_bytes_bucket{handler="/metrics",le="1e+09"} 46prometheus_http_response_size_bytes_bucket{handler="/metrics",le="+Inf"} 46prometheus_http_response_size_bytes_sum{handler="/metrics"} 234233prometheus_http_response_size_bytes_count{handler="/metrics"} 46 |
这种就是histogram柱状图类型。
还有的形式如下:
1 | go_gc_duration_seconds{quantile="0"} 7.3318e-05go_gc_duration_seconds{quantile="0.25"} 0.000118693go_gc_duration_seconds{quantile="0.5"} 0.000236845go_gc_duration_seconds{quantile="0.75"} 0.000337872go_gc_duration_seconds{quantile="1"} 0.000707002go_gc_duration_seconds_sum 0.003731953go_gc_duration_seconds_count 14 |
这种就是summary总结类型。
更多关于配置相关的说明,可以阅读官网文档
就Prometheus而言,pull拉取采样点的端点服务称之为instance。多个这样pull拉取采样点的instance, 则构成了一个job。
例如, 一个被称作api-server的任务有四个相同的实例。
1 | job: api-server instance 1:1.2.3.4:5670 instance 2:1.2.3.4:5671 instance 3:5.6.7.8:5670 instance 4:5.6.7.8:5671 |
当Prometheus拉取一个目标, 会自动地把两个标签添加到度量名称的标签列表中,分别是:
job: 目标所属的配置任务名称api-server。 instance: 采样点所在服务: host:port 如果以上两个标签二者之一存在于采样点中,这个取决于honor_labels配置选项。
对于每个采样点所在服务instance,Prometheus都会存储以下的度量指标采样点:
up度量指标对服务健康的监控是非常有用的。
Prometheus从根本上存储的所有数据都是时间序列: 具有时间戳的数据流只属于单个度量指标和该度量指标下的多个标签维度。除了存储时间序列数据外,Prometheus也可以利用查询表达式存储5分钟的返回结果中的时间序列数据
每一个时间序列数据由metric度量指标名称和它的标签labels键值对集合唯一确定。
这个metric度量指标名称指定监控目标系统的测量特征(如:http_requests_total
- 接收http请求的总计数). metric度量指标命名ASCII字母、数字、下划线和冒号,他必须配正则表达式[a-zA-Z_:][a-zA-Z0-9_:]*
。
标签开启了Prometheus的多维数据模型:对于相同的度量名称,通过不同标签列表的结合, 会形成特定的度量维度实例。(例如:所有包含度量名称为/api/tracks
的http请求,打上method=POST
的标签,则形成了具体的http请求)。这个查询语言在这些度量和标签列表的基础上进行过滤和聚合。改变任何度量上的任何标签值,则会形成新的时间序列图
标签label名称可以包含ASCII字母、数字和下划线。它们必须匹配正则表达式[a-zA-Z_][a-zA-Z0-9_]*
。带有_
下划线的标签名称被保留内部使用。
标签labels值包含任意的Unicode码。
有序的采样值形成了实际的时间序列数据列表。每个采样值包括:
‘‘小结:指定度量名称和度量指标下的相关标签值,则确定了所关心的目标数据,随着时间推移形成一个个点,在图表上实时绘制动态变化的线条’’
表示一个度量指标和一组键值对标签,需要使用以下符号:
[metric name]{[label name]=[label value], …}
例如,度量指标名称是api_http_requests_total
, 标签为method="POST"
, handler="/messages"
的示例如下所示:
api_http_requests_total{method=”POST”, handler=”/messages”}
这些命名和OpenTSDB使用方法是一样的
Prometheus 提供了四个核心的metrics类型。这四种类型目前仅在客户库和wire协议中区分。Prometheus服务还没有充分利用这些类型。不久的将来就会发生改变。
counter 是一个累计度量指标,它是一个只能递增的数值。计数器主要用于统计服务的请求数、任务完成数和错误出现的次数等等。计数器是一个递增的值。反例:统计goroutines的数量。
gauge是一个度量指标,它表示一个既可以递增, 又可以递减的值。
测量器主要测量类似于温度、当前内存使用量等,也可以统计当前服务运行随时增加或者减少的Goroutines数量
histogram,是柱状图,在Prometheus系统中的查询语言中,有三种作用:
度量指标名称: [basename]
的柱状图, 上面三类的作用度量指标名称
小结:所以如果定义一个度量类型为Histogram,则Prometheus系统会自动生成三个对应的指标
使用histogram_quantile()函数, 计算直方图或者是直方图聚合计算的分位数阈值。 一个直方图计算Apdex值也是合适的, 当在buckets上操作时,记住直方图是累计的。
类似histogram柱状图,summary是采样点分位图统计,(通常的使用场景:请求持续时间和响应大小)。 它也有三种作用:
带有度量指标的[basename]
的summary
在抓取时间序列数据展示。
[basename]{分位数="[φ]"}
[basename]_sum
, 是指所有观察值的总和[basename]_count
, 是指已观察到的事件计数值在prometheus的世界里70%的场景并不需要专门写埋点逻辑代码,因为已经有现成的各类exporter了,只要找到合适的exporter,启动exporter就直接暴露出一个符合prometheus规范的服务端点了。
exporter列表参见这里,另外官方git仓库里也有一些exporter。
举例,在某个宿主机上运行node_exporter后,以Centos为例,安装
1 | # curl -Lo /etc/yum.repos.d/_copr_ibotty-prometheus-exporters.repo https://copr.fedorainfracloud.org/coprs/ibotty/prometheus-exporters/repo/epel-7/ibotty-prometheus-exporters-epel-7.repo |
然后执行
1 | node_exporter |
如图所示
用浏览器访问http://${host_ip}:9100/metrics
即可看到node_exporter暴露出的这个宿主机各类监控指标数据
然后在prometheus的配置文件里加入以下一段:
1 | scrape_configs: |
然后在prometheus的web管理控制台里就可以查询到相应的监控指标了。在http://${HOST}:9090/graph
界面里输入go_memstats_alloc_bytes{instance="${host_ip}:9100"}
点击Execute
按钮即可。
将 ${host_ip} 替换成你的IP
如图
在控制台中,切换到Graph 可以看到对应的监控图标,在图标列中可以显示对应job 的监控指标
假如你的监控指标很特殊,需要自己写埋点上报逻辑代码,也是比较简单的。已经有各个语言的Client Libraries了,照着示例写就可以了。
]]>