暂时未有相关云产品技术能力~
目录一.springboot的概念1.什么是springboot?二.使用springboot进行开发的优势springboot的设计原则是什么,使用springboot进行开发具有怎样的优势?(M)三.手把手搭建一个springboot项目 ①创建项目并选择依赖 ②设置热部署(部分代码改动不需要手动重新run即可生效)四.springboot配置文件1.前提须知2.两种配置文件及对比3.springboot默认扫描配置文件的位置4.详解properties文件1.语法规则2.优先级3.自定义配置以及配置信息的读取五.springboot日志详解1.日志的概念(包括框架)2.日志的作用3.日志的级别4.日志的创建及打印5.lombok补充6.linux打印日志一.springboot的概念1.什么是springboot?springboot与spring相同,都是一种矿建,但是springboot是基于spring框架进行开发的脚手架,对spring框架进行部分优化,从而提高项目开发的效率。二.使用springboot进行开发的优势springboot的设计原则是什么,使用springboot进行开发具有怎样的优势?(M)springboot的设计原则:约定大于配置其优越的设计原则使其具有超越springframework的优点:①相比于springframework必须通过配置大量的xml文件来运行程序,springboot内部约定好了很多默认的配置,并提供不同的配置文件允许用户定制自定义的配置项②springboot内部约定好了众多第三方框架的配置路径(主要包括各种框架的配置信息),可以在项目启动时加载各种配置信息,实现第三方框架的快速配置③springboot内部集成了了web容器,无需配置其他的web容器④springboot具有更多的监控指标,能更好的了解项目运行的情况三.手把手搭建一个springboot项目 ①创建项目并选择依赖 ②设置热部署(部分代码改动不需要手动重新run即可生效)③禁用JMX:因为如果不对其进行排除会导致在项目启动时报错,虽然这个报错不影响我们项目的实现,但是规范化起见,我们还是加上 ④禁用tomcat,取而代之undertow(非必须选项,换是因为undertow的效率略高于tomcat)⑤修改编码集四.springboot配置文件1.前提须知受益于springboot的设计原则:springboot会约定好(配置好)许多默认的配置,在springboot项目启动时加载,也就是说即使用户不进行任何的配置,该springboot项目也会默认加载一些配置项,同时springboot提供给用户配置文件,允许用户进行定制化的项目配置2.两种配置文件及对比SpringBoot 默认使用以下 2 种全局的配置文件,其文件名是固定的application.propertiesapplication.yml其中,application.yml 是一种使用 YAML 语言编写的文件,它与 application.properties 一样,可以在 Spring Boot 启动时被自动读取,修改 Spring Boot 自动配置的默认值。二者功能类似,都能完成Spring Boot配置(例如指定Tomcat端口,配置mybatis等),但是Properties的优先级要高于YAML。3.springboot默认扫描配置文件的位置springboot项目在运行时,会默认扫描以下路径,查找配置文件并对项目进行定制化的配置file:./config/file:./config/*/file:./classpath:/config/classpath:/注:file: 指当前项目根目录;classpath: 指当前项目的类路径,即 resources 目录。以上所有位置的配置文件都会被加载,且它们优先级依次降低,序号越小优先级越高。其次,位于相同位置的 application.properties 的优先级高于 application.yml。所有位置的文件都会被加载,高优先级配置会覆盖低优先级配置,形成互补配置,即:存在相同的配置内容时,高优先级的内容会覆盖低优先级的内容;存在不同的配置内容时,高优先级和低优先级的配置内容取并集。4.详解properties文件1.语法规则key=value ,一般value不加双引号或者单引号2.优先级不同的文件位置,配置文件的优先级也有所不同file:./config/file:./classpath:/config/classpath:/由上到下优先级逐渐降低3.自定义配置以及配置信息的读取通过@Value读取配置文件中的信息配置文件中:spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8spring.datasource.name=rootspring.datasource.password=abc123 @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.name}") private String name; @Value("${spring.datasource.password}") private String password;通过@ConfigurationProperties(prefix = "”)获取配置类中自定义的对象配置文件中:# 创建自定义对象user.username=zhangsanuser.userId=1user.list[0]=1user.list[1]=2user.map.1=hhh类中:@ConfigurationProperties(prefix = "user")public class User { private String username; private int userId; private List<Integer>list; private Hashtable<Integer,String>map; //使用init方法判断 @PostConstruct public void init(){ System.out.println(username+userId+list+map); }五.springboot日志详解1.日志的概念(包括框架)日志在程序运行时打印在控制台上的信息:日志框架 常见的日志框架如:log4j、logback、slf4j、jdk-logging、commons-logging......但是这些框架在使用中一旦涉及日志框架的转化,十分不方便,因此slf4j应运而生,slf4j用于日志框架的桥接,引入slf4j之后,日志的使用也比较简单了:只需要引入某个具体日志框架的依赖包+slf4j的依赖包,统一使用slf4j的配置类和方法。2.日志的作用发现和定位问题记录用户的登录信息,进行大数据分析记录系统的操作信息,方便数据的恢复和定位操作者记录程序的执行时间,方便以后优化程序3.日志的级别 所有项目默认的日志打印级别是info(只打印info即其以上的日志级别)日志的级别由上到下级别逐渐变高,我们可以通过设置配置文件来修改项目的日志打印级别 # 当前项目日志的打印级别是debuglogging.level.root=debug# 设置具体某个包下的日志打印级别logging.level.com.ljl.springmvc_adv.controller.loginController=info4.日志的创建及打印使用方式如下:package com.example.demo.Controller; @Controller@ResponseBodypublic class LoggerController { // 1. 得到日志对象 private Logger logger = LoggerFactory.getLogger(LoggerController.class); // 2. 打印日志 @RequestMapping("/logger") public String logger(){ logger.trace("日志级别: trace"); logger.debug("日志级别: degue"); logger.info("日志级别: info"); logger.warn("日志级别: warn"); logger.error("日志级别: error"); return "logger"; }}在默认的配置下,一般只打印info及以上级别的日志@Slf4j@Componentpublic class LoggerTest { public static void main(String[] args) { log.debug("这是debug级别的日志......"); log.info("这是info级别的日志......"); log.warn("这是warn级别的日志......"); log.error("这是error级别的日志......"); }}5.lombok补充大家思考一个问题:为什么加入@Data注解之后,为什么很多方法为什么即使不写也会自动生成呢?我们不妨对比一下编译前后的文件类我们在所写的文件中的文件类是这样的:@Data@Repository//注入到容器@ConfigurationProperties(prefix = "user")public class User { private String username; private int userId; private List<Integer>list; private Hashtable<Integer,String>map; //使用init方法判断 @PostConstruct public void init(){ System.out.println(username+userId+list+map); } }编译后:package com.example.springboot_study.test; import java.util.Hashtable;import java.util.List;import javax.annotation.PostConstruct;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Repository; @Repository@ConfigurationProperties( prefix = "user")public class User { private String username; private int userId; private List<Integer> list; private Hashtable<Integer, String> map; @PostConstruct public void init() { System.out.println(this.username + this.userId + this.list + this.map); } public User() { } public String getUsername() { return this.username; } public int getUserId() { return this.userId; } public List<Integer> getList() { return this.list; } public Hashtable<Integer, String> getMap() { return this.map; } public void setUsername(final String username) { this.username = username; } public void setUserId(final int userId) { this.userId = userId; } public void setList(final List<Integer> list) { this.list = list; } public void setMap(final Hashtable<Integer, String> map) { this.map = map; } public boolean equals(final Object o) { if (o == this) { return true; } else if (!(o instanceof User)) { return false; } else { User other = (User)o; if (!other.canEqual(this)) { return false; } else if (this.getUserId() != other.getUserId()) { return false; } else { label49: { Object this$username = this.getUsername(); Object other$username = other.getUsername(); if (this$username == null) { if (other$username == null) { break label49; } } else if (this$username.equals(other$username)) { break label49; } return false; } Object this$list = this.getList(); Object other$list = other.getList(); if (this$list == null) { if (other$list != null) { return false; } } else if (!this$list.equals(other$list)) { return false; } Object this$map = this.getMap(); Object other$map = other.getMap(); if (this$map == null) { if (other$map != null) { return false; } } else if (!this$map.equals(other$map)) { return false; } return true; } } } protected boolean canEqual(final Object other) { return other instanceof User; } public int hashCode() { int PRIME = true; int result = 1; result = result * 59 + this.getUserId(); Object $username = this.getUsername(); result = result * 59 + ($username == null ? 43 : $username.hashCode()); Object $list = this.getList(); result = result * 59 + ($list == null ? 43 : $list.hashCode()); Object $map = this.getMap(); result = result * 59 + ($map == null ? 43 : $map.hashCode()); return result; } public String toString() { return "User(username=" + this.getUsername() + ", userId=" + this.getUserId() + ", list=" + this.getList() + ", map=" + this.getMap() + ")"; }}通过这些对比,我们可以得出以下的结论:lombok会在编译期将自己注解作用的代码加入类中,从而使注解生效。6.linux打印日志
一.redis的概念Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。在redis官网中对redis的描述是这样的(Redis is an open source (BSD licensed), in-memory data structure store used as a database, cache, message broker, and streaming engine. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. Redis has built-in replication, Lua scripting, LRU eviction, transactions, and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.)我们可以提取其中的关键点:redis是基于opensource,遵守BSD协议,使用c语言编写的key-value形式存储数据,存储在内存中的数据库,并且redis支持持久化的数据储存二.redis的作用和优势我们知道当前市场中主流的数据库是MySQL,我们思考以下几个问题:redis 和MySQL有怎样的关系?MySQL在当前市场的局限在哪?redis相对于MySQL具有怎样的优势?我们对比一下MySQL和redis:在高并发的市场环境下,MySQL对数据的处理逐步进入瓶颈期,它无法在及时处理巨量的数据,在某些应用场景无法满足用户的需求,redis相对于MySQL,首先从硬件方面进行对比:MySQ的数据存储在硬盘中,而redis中的数据存储在内存中,因此,redis对于数据的读取具有更快的速度,从存储结构上来看,redis使用key-value的形式存储数据,查询数据具有更高的效率;从数据库类型来看,与MySQL的关系型数据库(RDBMS)不同,redis是NOSQL类型的数据库。通过两者的对比,我们对redis的作用和优势进行概括性描述:redis作用1.redis提供分布式缓存技术,是挡在mysql之前的带刀护卫(减少MySQL处理数据的压力)(当请求发送给数据库时,在请求到达MySQL之前会先到达redis,在redis中查询数据是否存在,如果在redis中存在就直接返回,不通过MySQL,redis中不存在则去MySQL中查询,在MySQL中查询成功后返回数据,同时将数据也加载到redis中,下一次的请求直接在redis中获取数据)2.redis支持内存存储和持久化(RDB+AOF),redis支持异步将内部中的数据写到硬盘上,同时不影响继续服务(当redis发生断电等异常情况,从硬盘中加载数据,不再通过MySQL)。3.提供高可用的架构搭配,如单机,主从,哨兵,集群等等4.为缓存穿透、击穿和雪崩提供解决方案5.提供分布式锁6.队列Reids提供list和set操作,这使得Redis能作为一个很好的消息队列平台来使用。我们常通过Reids的队列功能做购买限制。比如到节假日或者推广期间,进行一些活动,对用户购买行为进行限制,限制今天只能购买几次商品或者一段时间内只能购买一次。也比较适合适用。7.排行榜+点赞在互联网应用中,有各种各样的排行榜,如电商网站的月度销量排行榜、社交APP的礼物排行榜、小程序的投票排行榜等等。Redis提供的zset数据类型能够快速实现这些复杂的排行榜。比如小说网站对小说进行排名,根据排名,将排名靠前的小说推荐给用户 redis的优势:性能极高 -Redis能读的速度是110000次/秒,写的速度是81000次/秒Redis数据类型丰富,不仅仅支持简单的key-value类型的数据,同时还提供list,zset,set,hash等数据结构的存储Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用Redis支持数据的备份,即master-slave模式的数据备份生成dump.rpb文件(可以在配置文件中改) 默认生成在redis.conf同级目录三.redis7新特性四.redis的使用我们在此处所说的redis的使用是Linux环境下的使用4.1redis的安装1.redis的安装需要在64位的centos运行环境,因此使用以下指令,测试我们centos的环境getconf LONG_BIT 结果返回32就代表32位,返回64就代表64位2.redis需要在安装依赖于gcc的编译环境,我们使用以下指令进行测试: gcc -v 查看gcc版本yum -y install gcc-c++ 安装c++库环境.3.将此前下载的redis-7.0.11.tar.gz(当然你下载的可能是其他版本)直接拖入到Linux中的/opt文件夹中(一般放入/opt文件夹,该文件夹是自定义文件夹)是,之后解压文件夹tar -zxvf redis-7.0.11.tar.gz /opt目录下解压在解压文件夹之后会生成这样一个redis-7.0.11这样一个文件目录: 在解压之后进入文件目录内:cd redis-7.0.11安装redismake && make install 进入默认的安装目录内并且查看与redis相关的文件cd /usr/local/bin #进入安装的默认文件夹ll #查看当前目录下的文件及目录能观察到以下与redis相关的文件结果:4.重新切回到redis -7.0.11这个文件目录下,创建myredis 的文件目录,并将redis-7.0.11的文件目录下的redis.conf这个文件复制到myredis的文件目录下(因为我们要对配置文件进行修改,所以最好要对原来的配置文件进行保存)mkdir /myredis #在redis-7.0.11目录下创建myredis的文件目录cp redis.conf /myredis/redis7.conf #将默认的配置文件复制过去5.对复制的配置文件进行修改:在底行模式下使用/+关键字的方式进行对配置文件的特定内容进行搜索,锁定到特定内容之后将该内容进行修改:示例:vim /myredis/redis7.conf // linux在vim中搜索词 esc + /搜索词 + enter6.修改redis.conf配置文件,改完后确保生效,一定要记得重启redis服务器1.默认daemonize no 改为 daemonize yes2.默认protected-mode yes 改为 protected-mode no3.默认bind 127.0.0.1 改为 直接注释掉(默认bind 127.0.0.1只能本机访问)或改成本机IP地址,否则影响远程IP连接4.添加redis密码 改为 requirepass 你自己设置的密码7.启动redis服务器和客户端redis-server /root/opt/redis-7.0.11/myredis/redis7.conf #启动服务为什么要从根目录开始使用呢?因为如果我们从当前目录开始使用可能会报找不到文件或者目录的错误(亲测)ps -ef | grep redis | grep -v grep #测试是否启动成功测试结果:8.连接服务redis-cli -a 设置的密码 -p 6379 ping 测试 得到 pong执行第一行的 redis 有一个warning警告 下面指令可以不展示警告redis-cli -a 设置的密码 -p 6379 2>/dev/null4.2redis的使用(永远的helloworld)输入以下的代码:set k1 helloWorldOKget k1"helloWorld"4.3redis的关闭关闭服务Linux redis 里: shutdown 直接关闭 单实例远程关闭 : redis-cli -a 密码 shutdown多实例远程关闭,指定端口号关闭: redis-cli -p 6379 shutdown4.4redis的卸载卸载redisls -l /usr/local/bin/redis-* 查看所以redis文件rm -rf /usr/local/bin/redis-* 删除全部文件
编辑这道题看起来hin简单,但思想还是很巧妙滴在我们解决这道问题之前,我们首先要了解什么是异或运算异或,英文为exclusive OR,缩写成xor [1] 异或(xor)是一个数学运算符。它应用于逻辑运算。异或的数学符号为“⊕”,计算机符号为“xor”。其运算法则为:a⊕b = (¬a ∧ b) ∨ (a ∧¬b)如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。异或也叫半加运算,其运算法则相当于不带进位的二进制加法:二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以异或常被认作不进位加法。看到这儿大家是不是已经有点蒙圈了,异或运算简单来说就是相同运算为0,不同运算为1,比如:0^1=1,0^0=0,1^1=0.......而在当前问题中,存在两个相同的数,两个相同的数字进行异或运算结果为0,而任何其他数字与0进行异或运算都等于其本身而解决问题的真正关键在于异或运算满足交换律、和结合律,即编辑 在满足交换律和结合律的前提下,那我们就能将相同的数字相邻到一块儿,(1^01=1^1^0)进而求出最后单独存在的数字。代码如下:public class HomingWork { public static void main(String[] args) { int[]arr={4,1,2,1,2}; System.out.println(find(arr)); } public static int find(int[]arr){ int num=arr[0]; for (int i = 1; i < arr.length ; i++) { num^=arr[i];//进行异或运算 } return num; }
2023年05月