是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使
开发人员不再需要定义样板化的配置。
不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭
建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性
等问题得到了很好的解决。
SpringBoot所具备的特征有:
可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
内嵌Tomcat或Jetty等Servlet容器;
提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
尽可能自动配置Spring容器;
提供准备好的特性,如指标、健康检查和外部化配置;
绝对没有代码生成,不需要XML配置。
Spring框架特点是:轻代码、重配置
SpringBoot特点是:约定大于配置,主要功能是:
自动配置
依赖管理
手动配置 ---> 自动配置
自动配置是用Java实现的
在spring-boot-autoconfigure包下保存大量的自动配置类
类名都保存 meta-INFO/spring.factotiries文件下
自动配置类生效需要一定条件,如@ConditionalOnClass,引入某些类时(导入了对应的框架依赖)
自动配置类是什么时候导入内存的
启动类上的注解:@SpringBootApplication
包含三个注解:
@ComponentScan 包的扫描
@SpringBootConfiguration 定义配置类
@EnableAutoConfiguration 启动自动配置(将自动配置类加载到内存)
怎么加载类到内存中? Class.forName("完整类名")
@EnableAutoConfiguration --> AutoConfigurationimportSelector --> loadFactoryNames --->
loadSpringFactories --> classLoader.getResources("meta-INF/spring.factories")
springboot和springmvc是一样的吗1. springMvc属于一个企业WEB开发的MVC框架,涵盖面包括前端视图开发、文件配置、后台接
口逻辑开发等,XML、config等配置相对比较繁琐复杂;
2. springBoot框架相对于springMvc框架来说,更专注于开发微服务后台接口,不开发前端视图,
同时遵循默认优于配置,简化了插件配置流程,不需要配置xml,相对springmvc,大大简化了配置
流程;
mq消息丢失了怎么办.针对 生产者到交换机 confirm 机制 确定生产者将消息投递到交换机
针对 交换机到队列 return 机制 交换机发送消息到队列失败会执行回调
针对 队列到消费者 消息没发 --> 消息持久化
消息发了,不知道是否被消费 ---> 手动确认 ack
fastDFS的实现过程两大组件是什么FastDFS服务端有两个角色:跟踪器(tracker)和存储节点(storage)。跟踪器主要做调度工
作,按照存储架构将文件进行分组存储,以及访问对应组内文件,生成文件id等工作。Tracker
server在内存中记录分组和Storage server的状态等信息,不记录文件索引信息,占用的内存量很
少。另外,客户端(应用)和Storage server
storage负责完成文件管理的所有功能,包括存储、同步和提供存取接口。
spring和springboot区别?spring是一个一站式的轻量级的java开发框架,核心是控制反转(IOC)和面向切面(AOP
),针对于开发的WEB层(springMvc)、业务层(Ioc)、持久层(jdbcTemplate)等都提供了多种配置解
决方案;
springBoot框架相对于springMvc框架来说,更专注于开发微服务后台接口,不开发前端视
图,同时遵循默认优于配置,简化了插件配置流程,不需要配置xml,相对springmvc,大大简化了
配置流程;
spring事物怎么实现的?在Service层的方法上配置
分为两种:
编程式事务
编写Java代码,实现启动事务、提交事务或回滚事务
编程麻烦、代码侵入性高,不推荐
声明式事务
通过配置+注解实现
代码简洁,侵入性低,推荐
声明式事务
1)在spring配置文件中添加事务管理的配置
2) 在需要事务的Service方法上添加注解:
@Transactional
String 和StringBuilder,StringBuffer 的区别?String : final修饰,String类的方法都是返回new String。即对String对象的任何改变都不影响到原对象,对字符串的修改 *** 作都会生成新的对象。
StringBuffer : 对字符串的 *** 作的方法都加了synchronized,保证线程安全。
StringBuilder : 不保证线程安全,在方法体内需要进行字符串的修改 *** 作,可以new StringBuilder对象,调用StringBuilder对象的append、replace、delete等方法修改字符串。
首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String
对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
String:适用于少量的字符串 *** 作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量 *** 作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量 *** 作的情况**
重载( Overload)和重写( override)的区别。重载的方法能否根据返回类型进行区分?重写发生于子类和父类,重载是在一个类中
重写返回值类型,方法名,参数列表要完全相同;重载和返回值类型无关,方法名相同,参数列表不同
重写子类中方法的访问修饰符访问范围不能比父类低;重载和访问修饰符无关
作用不同,重写是子类改写父类的方法;重载是新增方法,让方法调用方便
堆区:专门用来保存对象的实例(new 创建的对象和数组),实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在Stack中)
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到 *** 作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身.
3.一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
栈区:对象实例在Heap 中分配好以后,需要在Stack中保存一个4字节的Heap内存地址,用来定位该对象实例在Heap 中的位置,便于找到该对象实例。
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、 *** 作指令区(存放 *** 作指令)。
4.由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.
静态区/方法区:
1.方法区又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
3.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
synchronized属于jvm层面,是java的关键字,lock是API层面,是java5以后的一个接口
synchronized底层主要是monitorenter和monitorexit
monitorenter(底层是通过monitor对象来完成,其实wait /notify等方法也依赖于monitor对象,所以只有在同步块或方法中才能调wait/notify等方法
synchronized是可重入锁
1:作用位置不同
synchronized修饰普通方法,默认的锁对象是当前对象,synchronized修饰静态方法,默认的锁对象是当前类的class对象,比如User.class,synchronized修饰代码块,自己设置锁对象
lock只能给代码块加锁
2:获取锁和释放锁的机制不同
synchronized无需手动获取锁和释放锁,代码执行完自动释放锁,发生异常会自动释放锁,不会发生死锁
lock需要自己加锁和释放锁,如lock()和unlock(),如果忘记unlock(),就会发生死锁,所以,一般在finally里面使用unlock()
3:等待是否可中断
synchronized不可中断,除非抛出异常或者正常执行完成
ReentranLock可中断
1:设置超时方法tryLock(long timeout,TimeUnit unit)
2:lockInterruptibly()放入代码块中,调用interrupt()方法可中断
4:加锁是否公平
synchronized默认非公平锁
ReentranLock两者都可以,默认是非公平锁,构造方法可以传入boolean值,true为公平锁,false为非公平锁
5:锁绑定多个条件Condition(一个ReentrantLock对象可以同时绑定多个对象)
synchronized没有condition这个说法(synchronized使用Object对象本身的wait 、notify、notifyAll调度机制,而Lock可以使用Condition进行线程之间的调度)
ReentrantLock用来实现分组唤醒需要唤醒的线程们,可以精确唤醒,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。
(比如用A线程唤醒B线程,B线程执行完唤醒C线程,这种交替,精确唤醒)
讲下请求头中的content-length
对于http的请求返回结果要进行内容的长度校验主要有两种方式,二者互斥使用
1.客户端在http头(head)加Connection:keep-alive时,服务器的response是Transfer-Encoding:chunked的形式,通知页面数据是否接收完毕,例如长连接或者程序运行中可以动态的输出内容,例如一些运算比较复杂且需要用户及时的得到最新结果,那就采用chunked编码将内容分块输出。
2.除了如1所述之外的情况一般都是可以获取到Content-Length的。
在HTTP协议中,Content-Length用于描述HTTP消息实体的传输长度the transfer-length of the message-body。在HTTP协议中,消息实体长度和消息实体的传输长度是有区别,比如说gzip压缩下,消息实体长度是压缩前的长度,消息实体的传输长度是gzip压缩后的长度。
在具体的HTTP交互中,客户端是如何获取消息长度的呢,主要基于以下几个规则:
响应为1xx,204,304相应或者head请求,则直接忽视掉消息实体内容。
如果有Transfer-Encoding,则优先采用Transfer-Encoding里面的方法来找到对应的长度。比如说Chunked模式。
“如果head中有Content-Length,那么这个Content-Length既表示实体长度,又表示传输长度。如果实体长度和传输长度不相等(比如说设置了Transfer-Encoding),那么则不能设置Content-Length。如果设置了Transfer-Encoding,那么Content-Length将被忽视”。这句话翻译的优点饶,其实关键就一点:有了Transfer-Encoding,则不能有Content-Length。
Range传输。不关注,没详细看了:)
通过服务器关闭连接能确定消息的传输长度。(请求端不能通过关闭连接来指明请求消息体的结束,因为这样可以让服务器没有机会继续给予响应)。这种情况主要对应为短连接,即非keep-alive模式。
HTTP1.1必须支持chunk模式。因为当不确定消息长度的时候,可以通过chunk机制来处理这种情况。
在包含消息内容的header中,如果有content-length字段,那么该字段对应的值必须完全和消息主题里面的长度匹配。
“The entity-length of a message is the length of the message-body before any transfer-codings have been applied”
也就是有chunk就不能有content-length 。
其实后面几条几乎可以忽视,简单总结后如下:
1、Content-Length如果存在并且有效的话,则必须和消息内容的传输长度完全一致。(经过测试,如果过短则会截断,过长则会导致超时。)
2、如果存在Transfer-Encoding(重点是chunked),则在header中不能有Content-Length,有也会被忽视。
3、如果采用短连接,则直接可以通过服务器关闭连接来确定消息的传输长度。(这个很容易懂)
结合HTTP协议其他的特点,比如说Http1.1之前的不支持keep alive。那么可以得出以下结论:
1、在Http 1.0及之前版本中,content-length字段可有可无。
数据库的默认隔离级别,什么是可重复读?数据库怎么实现可重复读?@Transactional注解的属性isolation
值:
Isolation.DEFAULT 默认,和数据库隔离级别一致
Isolation.Readuncommitted 读未提交
Isolation.Readcommitted 读已提交
Isolation.Repeatableread 可重复读
Isolation.Serializable 串行化
事务传播性的配置
@Transactional注解的属性propagation
值:
PROPAGATION_REQUIRED
如果存在一个事务,则支持当前事务。如果没有事务则开启事务,这是默认选项。
如果外部方法和内部方法都是这种,内部方法的事务会加入外部方法的事务,形成
一个整体事务,一旦任何方法出现异常,所有方法都会回滚。
PROPAGATION_SUPPORTS
如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。
PROPAGATION_MANDATORY
如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
PROPAGATION_REQUIRES_NEW
总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
如果方法设置该类型,方法就在新的事务中执行,和其它方法没有联系。
(注意:上下级方法需要在两个类中)
PROPAGATION_NOT_SUPPORTED
总是非事务地执行,并挂起任何存在的事务。
PROPAGATION_NEVER
总是非事务地执行,如果存在一个活动事务,则抛出异常
PROPAGATION_NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务,则按
PROPAGATION_REQUIRED 执行
A)使用DELETE JOIN语句删除重复的行
B)使用中间表删除重复的行
以下显示了使用中间表删除重复行的步骤:
创建一个新表,其结构与要删除重复行的原始表相同。
将原始表中的不同行插入到直接表中。
删除原始表和重命名立即表的原始表。
C)使用ROW_NUMBER() 函数删除重复的行
请注意,ROW_NUMBER()自MySQL版本8.02起,功能已得到支持,因此您应在使用功能之前检查您的MySQL版本。
以下语句使用ROW_NUMBER()函数为每行分配一个顺序整数。如果电子邮件重复,则行号将大于1。
groupby用过吗?讲一下havinghaving 条件
对分组后的结果进行筛选
group by 列 having 条件
where和having的区别
where是分组前进行筛选
having是分组前进行筛选
where --> group by --> having
主键有什么作用?保证实体的完整性加快数据库的 *** 作速度在表中添加记录时,DBMS会自动检查记录的主键值,不允许该值与其他值重复 讲一下事务的ACID?
原子性(Atomic)
一个事务的多个 *** 作作为一个整体不可分割,要么全部执行,要么全部失败
一致性(Consistency)
数据在事务执行前和执行后处于一致状态(正确)
隔离性(Isolation)
系统的多个事务需要相互隔离,互相不影响
永久性(Duration)
一旦事务提交,对数据库的修改是永久的
讲一下微服务和分布式的区别?分布式的核心就一个字:拆。只要是将一个项目拆分成了多个模块,并将这些模块分开部署,那就算是分布式。
如何拆呢?有两种方式:水平拆分,或垂直拆分(也称为“横向拆分”和“垂直拆分”),具体如下:
水平拆分:根据“分层”的思想进行拆分。例如,可以将一个项目根据“三层架构”拆分成 表示层(jsp+servlet)、业务逻辑层(service)和数据访问层(dao),然后再分开部署:把表示层部署在服务器A上,把service和dao层部署在服务器B上,然后服务器A和服务器B之间通过dubbo等RPC进行进行整合
垂直拆分:根据业务进行拆分。例如,可以根据业务逻辑,将“电商项目”拆分成“订单项目”、“用户项目”和“秒杀项目”。显然这三个拆分后的项目,仍然可以作为独立的项目使用。像这种拆分的方法,就成为垂直拆分。
微服务可以理解为一种非常细粒度的垂直拆分。例如,以上“订单项目”本来就是垂直拆分后的子项目,但实际上“订单项目”还能进一步拆分为“购物项目”、“结算项目”和“售后项目”
Eureka和Nacos有什么区别? Eureka只能做注册中心吗?1、ACP原则
nacos支持AP(可用性 | 分区容错性) 和 CP(一致性 | 分区容错性)两种
eureka只支持 AP (可用性 | 分区容错性)
2、配置中心
nacos有自己的配置中心,提供管理界面
eureka需要配合config实现配置中心,且不提供管理界面
3、连接方式
nacos支持动态刷新,在控制器(controller)上加 @RefreshScope 注解即可,采用Netty连接,是长连接
eureka本身不支持动态刷新,需要配合MQ完成动态刷新,且是短连接,是定时发送
4、应对高并发
nacos没有使用synchronized和加锁,而是使用copyOnWrite思想
nacos这个更新注册表内存方法里,为了防止读写并发冲突,大量采用了copyOnWrite思想,防止读写并发冲突,具体做法就是把原内存结构复制一份, *** 作完后再替换进真正的注册表内存中去。
eureka方式读写并发冲突用的是注册表的多级缓存结构,只读缓存,读写缓存,内存注册表,各级缓存之间定时同步,缓存都存在Eureka Server中,客户端的感知和及时性不如nacos。
网关(Gateway)又称网间连接器、协议转换器。网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关的结构也和路由器类似,不同的是互连层。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。在使用不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。与网桥只是简单地传达信息不同,网关对收到的信息要重新打包,以适应目的系统的需求。同时,网关也可以提供过滤和安全功能。大多数网关运行在OSI 7层协议的顶层--应用层。
客户端发送请求给Gateway网关,网关将请求发送给处理器映射(HandlerMapping)
网关通过路由的匹配,将请求发送给Web处理器处理,请求就需要经过一系列过滤器
过滤器分为“pre"前置和”post"后置两种,前置过滤器实现鉴权作用,后置过滤实现性能统计或日志收集
通过过滤器就到达需要的服务
Feign旨在是编写Java Http客户端变得更加容易。
之前使用Ribbon+RestTemplate时,利用RESTTemplate请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,有偶遇对于服务依赖的调用可能不止一处,往往一个借口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务借口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon是,自动封装服务调用客户端的开发量。
@RestContorller和@Controller什么区别?知识点:@RestController注解相当于@ResponseBody + @Controller合在一起的作用。
1) 如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。
2) 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。
如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。
3)如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。
@ReponseBody是什么?@responseBody注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。
注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到 *** 作方法的入参中。
Linux 上解压过zip包吗?怎么解压?1)对于zip linux下提供了zip和unzip程序,zip是压缩程序,unzip是解压程序。它们的参数选项很多,这里只做简单介绍,举例说明一下其用法:
# zip all.zip *.jpg 这条命令是将所有.jpg的文件压缩成一个zip包
# unzip all.zip
这条命令是将all.zip中的所有文件解压出来
2)对于.rar要在linux下处理.rar文件,需要安装RAR for Linux,可以从网上下载,但要记住,RAR for Linux 不是免费的;可从http://www.rarsoft.com/download.htm下载RAR 3。60 for Linux ,然后安装:
# tar -xzpvf rarlinux-3.2.0.tar.gz
# cd rar
# make
这样就安装好了,安装后就有了rar和unrar这两个程序,rar是压缩程序,unrar是解压程序。它们的参数选项很多,举例说明一下其用法:
# rar a all *.jpg
这条命令是将所有.jpg的文件压缩成一个rar包,名为all.rar,该程序会将.rar 扩展名将自动附加到包名后。
# unrar e all.rar
这条命令是将all.rar中的所有文件解压出来
Redis用来做什么?Redis是一个高性能的内存数据库,以key-value方式存储数据,可以作为缓存使用。
为什么使用缓存?
高并发
MySQL的连接数存在瓶颈,连接过大可能导致MySQL宕机
解决方法:
部署多个MySQL服务,主从复制
部署缓存,承担一部分的并发
高性能
基于内存,内存IO效率远远高于磁盘
Redis的特点:
性能高(读的速度是110000次/s,写的速度是81000次/s,单机redis支撑万级并发)
支持多种存储类型
丰富的特性(发布订阅、事务、过期策略等)
支持持久化
单线程 (避免上下文切换,线程同步问题)
为什么不用MongoDB,它也是基于内存的?首先 Redis 完全符合上面我们说的几个特征,而且还是基于内存、可持久化的数据库,并且是非常友好的 Key-Value 键值对的方式存储。
而 MongoDB 数据库作为非结构化的文件数据库,其功能和特性并不能支持大多数的缓存数据的存放,只会徒劳增加成本。
MongoDB 的更多使用方式还是存储一些大文件之类的数据,不是专注于去实现一些缓存数据的存储。
Redis 就不一样了,他本身就是应运而生的,除了做缓存数据库虽然还能去实现消息队列之类的功能,但是那都是一些附属价值;Redis 最核心的价值还是缓存数据库,多种数据结构、丰富的 API 使 Redis 在目前环境中还暂时找不到太多对手。
Redis里 用什么数据类型存储商品信息? list ribbon负载均衡策略我们编写的java文件都是保存着业务逻辑代码。java编译器将 .java 文件编译成扩展名为 .class 的文件。.class 文件中保存着java转换后,虚拟机将要执行的指令。当需要某个类的时候,java虚拟机会加载 .class 文件,并创建对应的class对象,将class文件加载到虚拟机的内存,这个过程被称为类的加载。
线程池中,达到核心线程数后,添加一个线程会怎么样?
线程池创建线程需要获取mainlock这个全局锁,会影响并发效率,所以使用阻塞队列把第一步创建核心线程与第三步创建最大线程隔离开来,起一个缓冲的作用。
引入阻塞队列,是为了在执行execute()方法时,尽可能的避免获取全局锁。
反射的作用?1、获得Class对象
使用Class类的forName静态方法
(1)Class class1=Class.forName(“Reflect.Student”);// 会加载类,则Student类中的静态代码块也会被加载。
直接获取某一个对象的class
(2)Class class2=Reflect.Student.class;//不会加载类,也没有生成对象
调用某个对象的getClass()方法
(3)Student s1=new Student();
Class class3=s1.getClass();//既加载类,也生成了对象,(Object类有一个getClass方法)
2、判断是否为某个类的实例
用instanceof关键字来判断是否为某个类的实例
3、创建实例
使用Class对象的newInstance()方法来创建Class对象对应类的实例。
先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。
4、获取方法
getDeclaredMethods()
5、获取构造器信息
getDeclaredMethods()
getMethods()
getMethod()
6、获取类的成员变量(字段)信息
getFiled: 访问公有的成员变量
getDeclaredField:所有已声明的成员变量。但不能得到其父类的成员变量
getFileds和getDeclaredFields用法
7、调用方法
invoke()
8、利用反射创建数组
Array.newInstance()
反射的缺点:
使用反射基本上是一种解释 *** 作,用于字段和方法接入时要远慢于直接代码。因此Java反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)