java面试看这一篇就够了

由于最近比较忙,项目赶的比较紧所以一直没有更新整理面试题,这次抽了些时间把答应大家的面试题整理出来了感谢各位小伙伴们的支持,你们的支持是我分享的动力,希望在以后的日子里咱们共同学习进步。如果感觉不错就多多分享、收藏、关注。篇幅有点长建议先收藏。

                                                                   Jason

springboot相关面试话术

1、什么是springboot

SpringBoot是Spring项目中的一个子工程,其实人们把Spring Boot 称为搭建程序的脚手架。其最主要作用就是帮我们快速的构建庞大的spring项目,并且尽可能的减少一切xml配置,做到开箱即用,迅速上手,让我们关注与业务而非配置。

2、为什么要用springboot

Spring Boot 优点非常多,如:一、独立运行Spring Boot而且内嵌了各种servlet容器,Tomcat、Jetty等,现在不再需要打成war包部署到容器中,Spring Boot只要打成一个可执行的jar包就能独立运行,所有的依赖包都在一个jar包内。二、简化配置spring-boot-starter-web启动器自动依赖其他组件,简少了maven的配置。三、自动配置Spring Boot能根据当前类路径下的类、jar包来自动配置bean,如添加一个spring-boot-starter-web启动器就能拥有web的功能,无需其他配置。四、无代码生成和XML配置Spring Boot配置过程中无代码生成,也无需XML配置文件就能完成所有配置工作,这一切都是借助于条件注解完成的,这也是Spring4.x的核心功能之一。五、应用监控Spring Boot提供一系列端点可以监控服务及应用,做健康检测

3、springboot有哪些优点

减少开发,测试时间和努力。使用 JavaCong 有助于避免使用 XML。避免大量的 Maven 导入和各种版本冲突。通过提供默认值快速开始开发。没有单独的 Web 服务器需要。这意味着你不再需要启动 Tomcat,Glasssh或其他任何东西。需要更少的配置 因为没有 web.xml 文件。只需添加用@ Conguration 注释的类,然后添加用@Bean 注释的方法,Spring 将自动加载对象并像以前一样对其进行管理。您甚至可以将@Autowired 添加到 bean 方法中,以使 Spring 自动装入需要的依赖关系中。基于环境的配置 使用这些属性,您可以将您正在使用的环境传递到应用程序:-Dspring.proles.active = {enviornment}。在加载主应用程序属性文件后,Spring 将在(application{environment} .properties)中加载后续的应用程序属性文件。application.yml

spring.active.profile=dev

application-dev.yml

application-test.yml

application-prod.yml

4、Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下3 个注解:@SpringBootConguration:组合了 @Conguration 注解,实现配置文件的功能。@EnableAutoConguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能:@SpringBootApplication(exclude = { DataSourceAutoConguration.class })。@ComponentScan:Spring组件扫描,从当前类所在的包以及子包扫描,之外的包扫描不到,所以我们在开发的时候,所有的类都在主类的子包下

5、springboot项目有哪几种运行方式

打包用命令或者放到容器中运行用 Maven/Gradle 插件运行直接执行 main 方法运行6、如何理解springboot中的starters?

Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成Spring及其他技术,而不需要到处找示例代码和依赖包。如你想使用Spring JPA访问数据库,只要加入springboot-starter-data-jpa启动器依赖就能使用了。Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。

7、springboot自动配置原理

这个就得从springboot项目的核心注解@SpringbootApplication说起了,这个注解包含了三个注解,其中一个是@EnableAutoConfiguration注解,这个注解主要是开启自动配置的,这个注解会"猜"你将如何配置 spring,前提是你已经添加 了 jar 依赖项,比如项目中引入了 spring-boot-starter-web ,这个包里已经添加 Tomcat 和 SpringMVC,这个注解节就会自动假设您在开发一个 web 应用程序并添加相应的 spring 配置,springboot默认有一个spring-boot-autoconfigure包,大多数常用的第三方的配置都自动集成了,像redis、es等,这里边有一个META-INF/spring.factories文件,这里边定义了所有需要加载的bean的全路径,spring会根据反射的原理,创建这些对象,放到IOC容器中,加载时需要的参数,通过JavaConfig的方式加载配置文件中的参数然后创建了对应的对象,这就是自动配置的原理

2

springcloud相关面试话术

1、什么是Springcloud

Spring Cloud 是一系列框架的集合,它利用 Spring Boot 的开发便利性简化 了分布式系统的开发,比如服务发现、服务网关、服务路由、链路追踪等。他的设计目的是为 了简化 Spring 应用的搭建和开发过程。该框架遵循“约定大于配置”原则,采用特定的方 式进行配置,从而使开发者不用定义大量的 XML 配置。Spring Cloud 并不重复造轮子,而是将市 面上开发得比较好的模块集成进去,进行封装,从而减少了各模块的开发成本。换句话说:Spring Cloud 提供了构建分布式系统所需的“全家桶”。核心组件:Eureka、Ribbon、Feign、 Hystrix、Zuul.

为什么要使用这个呢?因为之前的嗯项目架构都是集中式的。这就会导致一个问题在项目当中出现任何一个小问题都会让整个项目不能使用。修改完之后需要让整个项目全量更新,所以基于传统架构的这种方式,我们在这个项目当中把,架构调整了一下,采用了微服务的架构。那使用了微服务架构之后,在整体的分配任务上呀,还有扩展性上来讲,比以前的开发以及这个效率上都有很显著的提高。

我介绍一下spring cloud里边儿的一些组件吧,我们项目当中使用的。首先就是它的注册中心Eureka。所有的微服务。都需要连接Eureka去进行管理。它里边儿会有心跳协议,会知道每个微服务具体的一个在线状态。以及给其他调用微服务的这些去提供一些这这个微服务的基本信息

接着就是这个远程调用feign,它提供了微服务之间的远程调用的一个组件,它是基于HTTP的。然后,远程调用这个组件集成了负载均衡ribbon。它可以有效的分辨出当前注册中心当中这个为服务有多少实例,会根据内部的算法去均衡的域访问这些实例,它的算法有轮询还有随机,这个算法我们也可以自定义,它默认的算法呢是轮循去访问

接着就是。熔断器hystrix。那他这个组件儿在我们项目当中用的时候,就是在远程调用时。如果任何一个微服务响应超时或者发生异常,熔断器就会介入,把当前请求切断。然后去执行我们的回调方法,返回回调方法当中的数据。这样的话会保证我们微服务当中的请求链路不会卡死,而且,这样的话不会让用户在前台一直在等着。会有一个非常好的用户体验。

接着就是我们的网关。Zuul。网关在我们项目当中充当的地位就是一个所有请求的入口。所有请求进来之后,首先通过网关有网关,根据路径儿去解析,然后转发到对应的微服务上,当然这个网关还充当了一个功能,就是一个鉴权功能,我们项目当中,登陆了之后,会给用户颁发一个token。用户在访问的时候,这个token会携带在请求头当中,经过我们网关时,网关会拦截取出token。验证token的真实性。验证通过之后才会访问到我们的微服务。这就是我们项目当中微服务具体使用的一些场景以及它的组件。

2、服务注册和服务发现是什么意思,springcloud是如何实现的

在微服务项目中,我们通常会用到服务之间的相互调用,我们通常在属性文件中进行所有的需要请求的微服务的地址端口等信息。随着越来越多的 服务开发和部署,添加和修改这些属性变得更加复杂。有些服务可能会下架,而某些位置可 能会发生变化。手动更改属性可能会产生问题。Eureka 提供了服务注册和服务发现的功能,服务注册是让所有微服务将自己的信息注册到注册中心,服务发现是让微服务可以拉取注册中心里的服务列表,方便结合feign进行远程调用,由于所有服务都在 Eureka 服务器上注册并通过调用 Eureka 服务器完成查找, 因此无需处理服务地点的任何更改和处理。

3、负载均衡的意义是什么

我觉得负载均衡的主要意义就是,避免单一应用由于并发等原因,导致应用宕机从而导致系统整体无法使用,多负载同时工作,可以很好的解决高并发的问题,实现服务的高可用。

在我们项目中,服务的接入层由nginx管理,用户请求经过nginx之后,根据相应的域名,转发到对应的服务器去,由于nginx只负责请求转发,没有业务逻辑处理,所以效率上非常高。

nginx支持的负载均衡策略有很多,我们在nginx.conf中配置upstream模块即可。

首先是轮训,默认的就是这种方式

第二种权重的方式,就是根据服务器的性能,配置较大的权重,nginx就会分配更多的请求

第三种是iphash的方式,nginx会根据请求的ip地址,今夕那个hash运算,然后分配相应的服务器,后续来自同一ip的请求都会分配到这个服务器上

第四种是最少连接数,把请求转发给连接数较少的后端服务器

还有就是可以根据响应时间和url hash来做处理,我们项目中配置的是权重的方式。

在我们项目的微服务架构中,feign和zuul都集成了ribbon的的功能,它是负责在微服务之间相互调用的时候,帮我们实现负载均衡的功能,我们在将微服务注册到注册中心时,如果服务名称一致,就默认为一个集群,在进行远程调用或者路由转发的时候,都可以均衡的访问响应的服务器,ribbon的负载均衡机制有轮训和随机,默认是轮训,当然也可以自定义负载均衡的策略。

4、hystrix介绍

hystrix在微服务架构中充当熔断器的功能,它提供了资源隔离、限流、熔断、降级、运维监控等功能,

在微服务架构中通常会有多个微服务之间相互调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。

熔断器的原理很简单,如同电力过载保护器。它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,直接执行回调方法,返回回调方法中的友好数据或者缓存数据,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费 CPU时间去等到长时间的超时产生。熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经、修正,应用程序会再次尝试调用操作。

当 Hystrix Command 请求后端服务失败数量超过一定比例(默认 50%),断路器会切换到开路状态(Open)。这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认 5 秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况,如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix 的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力。

5、Eureka和ZooKeeper都可以提供服务注册与发现的功能,请说说两个的区别

1、ZooKeeper保证的是CP,就是一致性和容错,Eureka保证的是AP,就是可用性和容错。

ZooKeeper在选举期间注册服务瘫痪,虽然服务最终会恢复,但是选举期间不可用的,只有等到选举结束之后,所有数据同步之后才能使用。

Eureka各个节点是平等关系,只要有一台Eureka就可以保证服务可用,而查询到的数据并不是最新的,自我保护机制会导致Eureka不再从注册列表移除因长时间没收到心跳而应该过期的服务。Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点(高可用),当网络稳定时,当前实例新的注册信息会被同步到其他节点中(最终一致性)

Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像ZooKeeper一样使得整个注册系统瘫痪

2、ZooKeeper有Leader和Follower角色,Eureka各个节点平等

3、ZooKeeper采用过半数存活原则,Eureka采用自我保护机制解决分区问题

4、Eureka本质上是一个微服务的一个模块,而ZooKeeper是一个进程,需要单独安装

3

ElasticSearch相关面试话术

1、介绍一下ElasticSearch,以及在项目中的应用

Java开发的基于lucene分布式全文搜索引擎。基于restful Web接口。在检索领域相当优秀,在我们项目中主要是负责检索商品信息。商品信息构成是比较复杂的,并且数据量巨大,至少会有几十万,如果使用mysql做检索,效率会非常低,并且对mysql造成很大的压力。

在使用过程中主要需要做几件事:

1、Es服务的安装,中文分词器使用IK分词器,这个主要是运维负责;

2、在项目中集成springDataElasticSearch框架,用来操作ES;

3、创建实体类,标注了一个Document注解,这个注解里声明了这个索引库的名称以及它的类型,还有他的分片儿信息,还有他的副本信息。在这个类中创建所有跟商品相关的字段。同样会有一些注解去标识他的数据类型,他的比如说id字段会有一个id注解,其他字段用@Field注解标注在es中存储的数据类型,是否进行分词等,有些字段也可以不加任何注解,es会根据存储的数据去判断字段在es中存储的类型。等其他的字段都建好之后,然后又新添加了一个统一的搜索字段,我们给它定义的名称叫all,我们会把经常搜索的数据全部定义到这个字段里。比方说商品标题、副标题、品牌等;

4、初始全量数据导入

使用springboot测试类实现导入,分批从mysql中取出,组装数据到,保存到es中

5、修改、新增、删除等增量数据导入

使用rabbitMQ实现,商品上下架的时候发送Mq消息,搜索微服务以及静态页面微服务实现ES数据的同步和静态页面的数据同步操作

6、使用es实现搜索

使用all进行分词查询,搜索时,按照matchQuery做的,这个方法的做法是会把输入的关键词分词之后,然后去匹配,匹配的规则我们设置的是and的方式匹配,就是分词之后每个词条都匹配才算匹配,我们在项目里设置了个all字段,会把所有可能被分词的字段都会放到这个里边,只对这一个字段设置分词,关键字搜索的时候,都会去匹配这个字段,使用规格参数聚合实现商品搜索规格参数的渲染使用分类和品牌聚合实现商品分类和品牌查询的渲染使用布尔查询实现规格参数、品牌、分类的过滤实现分页、排序等需求2、为什么使用Es?

因为在我们商城中的数据,将来会非常多,所以采用以往的模糊查询,模糊查询前置配置,会放弃索引,导致商品查询是全表扫面,在百万级别的数据库中,效率非常低下,而我们使用ES做一个全文索引,我们将经常查询的商品的某些字段,比如说商品名,描述、价格还有id这些字段我们放入我们索引库里,es内部有个倒排索引的机制,普通的索引的原理是通过id寻找数据,而倒排索引是通过数据寻找id,它的大概原理是把需要分词的数据通过ik分词器分词之后,记录出每个词条对应的文档id,在进行搜索的时候,将搜索关键字分词之后,找到每个词条的文档id,然后在进行通过id搜索操作,大大提高了全文检索的效率,这也是在全文检索方面最常用的技术。

3、 什么是桶(bucket)?什么是度量(metrics)?

桶,是按照某种方式对数据进行分组,每一组数据在ES中称为一个桶,例如我们根据国籍对人划分,可以得到中国桶、英国桶,日本桶……或者我们按照年龄段对人进行划分:010,1020,2030,3040等。分桶的方式有很多,比如按日期阶梯分组、按数值阶梯分组、按词条内容分组、按数值和日期范围分组等。

度量,分组完成以后,我们一般会对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等,这些在ES中称为度量。度量有求平均值、求最大最小值、求百分比、求和等。

4、es内部存储的存储结构

es内部默认就是分布式的存储结构,每当创建一个索引库的时候,我们需要指定当前索引库的分片数和副本数,分片数就是把数据分布式的存放在分片上,所有分片的数据加起来就是整个索引库的数据量,分片数越多,数据存放的越分散,搜索的时候,es会检索每个分片的伤的数据一起返回。副本数是指在数据进入索引库的时候,同时需要备份的数量,如果副本数量越多,那么需要消耗的存储空间就会越多,过多的话会造成空间浪费,一般生产中使用的时候都用的默认的配置,就是5个分片,2个副本。

4

页面静态化相关面试话术

首先说说为什么要进行页面静态化

从搜索这里可以看出,搜索列表展示的是固定30条数据,搜索的访问量已经很巨大了,那么详情页面的访问量是30倍的搜索量,如果放在整个百万级的用户量上来说,这个访问量是很巨大的,所以我们就不能每次访问详情页面的时候,都去服务端请求数据再展示

其次是这个详情页面来说,不会经常频繁的变动,所以每次去服务端取的数据基本都是一致的,所以我们就得想办法去解决如何快速的响应这么高的访问量

我们项目中服务端的请求和前端的请求,都是通过nginx做的反向代理,那么我们在项目中的方案是基于两个点去解决的,首先呢是结合模版引擎技术,用户在首次访问某个数据的详情页的时候,我们使用thymeleaf给生成静态页面,响应给用户,同时放到指定的nginx代理的目录下,那么用户在第二次访问这个数据详情页是,通过nginx中的配置,nginx首先会去该目录下查看是否有这个数据静态页面存在,如果存在的话,直接就访问静态html文件了,如果不存在,才会放行到我们微服务里去请求数据。

然后在线上的时候,会结合CDN技术,同时指向nginx代理的静态页面的路径,进一步提高用户的访问速度。

在生成静态页面的同时会造成一个问题,就是数据库的数据修改之后,需要同步到静态页面中去,这里我们采用的是rabbitmq做的异步处理,在数据库数据修改之后,通过mq发送消息,静态化的微服务收到消息之后,会重新生成一遍html页面,这样就会跟数据库的数据同步了

5

rabbitmq相关面试话术

1、介绍一下rabbitmq

RabbitMQ是Erlang语言开发的基于AMQP的一款消息中间件,核心思想是生产者不会将消息直接发送给队列,消息在发送给客户端时先发送给交换机,然后由交换机转发给对应的队列。对路由(Routing),负载均衡(Load balance)、数据持久化都有很好的支持。

它里边有5种数据传递方式

第一种是简单模型,一个生产者,一个队列,一个消费者,队列只能被一个消费者监听,所以生产者将消息发给队列之后,只能有一个消费者收到消息

第二种是工作模型,一个生产者,一个队列,多个消费者,队列可以被多个消费者监听,但是生产者将消息发给队列之后,还是只能有一个消费者接收到消息

后边三种都叫订阅模型,这三种里边引入了交换机的概念,具体的区分是根据交换机的类型区分的,在这三种模式种,生产者把消息发送给交换机,交换机不负责存储消息,由交换机发送给指定的队列,消费者监听队列消费消息。

首先是fanout类型,这种叫广播模式,生产者将消息发送给交换机,交换机会将消息转发给所有绑定到到当前交换机的队列中,对应监听队列的消费者都能收到消息,但是,如果没有队列绑定到这个交换机,消息会被mq丢弃。

接着是direct类型,这种叫定向模式,也叫路由模式,这种模式中,队列在绑定交换机的时候,同时指定了自己的routing key,可以理解为一个路由标示,生产者在发送消息给交换机的时候,同时指定要发送给的routing key,这时候,交换机就会根据这个routing key来定向的发送给对应的队列,对应监听该routing key的队列的消费者就能收到消息,但是如果交换机没有找到对应的routing key,消息会被丢弃。

最后是topic模式,这种叫通配符模式,队列在绑定交换机的时候,同时指定了自己的routing key,生产者在发送消息给交换机的时候,同时指定要发送给的routing key 的通配符,一般这个routing key是由多个单词用.的方式隔开的,通配符中,#号可以匹配一个或者多个单词,*号只能匹配一个单词,例如生产者指定的通配符为a.#,可以匹配到的routing key有:a.b、a.b.c等,如果是a.*的话,只能匹配a.b或者是a.c这样的routing key。每个队列绑定到交换机的时候可以定义多个routing key,交换机会跟据指定的通配符,发送到匹配通配符的routing key 对应的队列中,对应的消费者就可以收到消息了,但是,如果没有符合通配符的routing key ,消息会被丢弃

当然,在生产中使用的时候,为了避免mq宕掉等造成消息丢失的问题,我们都会配置持久化措施,在rabbitmq里,需要将交换机持和队列和消息持久化,这样消息就会被持久化到磁盘中,不会因为突发的断电等情况导致消息丢失

2、如何保证消息确定消息发送成功,并且被消费成功,有什么保障措施

解析:这里不用背,这里的问法会有很多中,这道题中问了两部分第一部分是确保发送成功,还可以被问成:消息发送失败了怎么办,或者如何保证消息可靠传输第二部分是确保消费成功,还可以被问成:消息消费时,发生异常了,消息已经被消费了,怎么办等

首先,需要确保消息被发送成功,rabbitmq中提供了事物和confirm的机制,事物的话,就类似于数据库的事物,开启,执行,提交,如果过程中发生任何异常,就会触发回滚机制,我们可以在回滚中加入一些逻辑处理,重新发送或者日志记录,同时配置生产者确认的机制,就是在消息发送之后,该消息会被指定唯一的ID,如果有消息成功被交换机转发到队列之后,mq会给生产者发送ack确认,如果没有队列接收消息,那么会发送错误回执消息给生产者,生产者可以尝试重试发送,或者日志记录。通过这些可以看出,mq会增加一些保障性措施,必然会导致性能有一些下降,如果要保证消息的严格一致性,那么可以配置这些,如果消息不重要,或者允许有丢失的情况,那么可以不用配置,这样的话能提升mq的性能。

其次就是,消息确保发送成功之后,还要确保消息被消费成功,因为在消费者端,如果消息消费时发生异常,又没有做一些处理,那么消息就会丢失,这种情况,可以采取两种方式解决

第一种就是消费端配置手动ACK确认机制,消息被消费完成的时候,手动确认告诉mq消费成功,mq才会删除消息,如果消息被接收了,但是mq没有收到ack确认,那么消息在mq中会变为unacked状态,我们可以通过项目日志或者mq面板监控,当消费者断开连接之后,消息会重新回到队列中,消费者重新连接之后,会再次收到消息。

第二种就是可以结合数据库解决,生产者端发送成功之后,可以在数据库中存储发送的消息和发送时间,并标记状态为未消费状态,消费者端消费完成之后,标记mysql中数据的状态为已经消费。消费者端通过定时任务去数据库跑批检索超时未被消费的消息并重新发送,这种方式可以很好的解决消费失败的问题,但是增加了生产者和消费者之间的耦合度,以及会造成消息重复消费的问题,我们可以在保证消息发送成功的基础上,将上述逻辑放在消费者端,生产者正常发送消息,消费者在收到消息之后,存储到myqsl中,标记状态为未消费,同时ack通知mq确认,然后再消费消息,消息消费成功之后,改变mysql状态为已消费,消费端同时配置定时任务跑批检索数据库,定时重新执行超时未消费的消息。

以上的解决办法都是需要根据实际的业务需求来的,如果消息需要保证强一致性,不能出现任何差错,那么就需要按照前面说的添加对应的配置

我们项目中的mq主要用于数据同步使用的,mysql数据发生变化之后,需要同步到es索引库以及静态化页面中,这里我们配置了生产者确认模式,和消费者手动ack确认机制。

3、如何保证消息不被重复消费

我们可以在生产者端,发送消息时,数据的变动部分,进行md5加密处理,同时配置上一个唯一id,每次发送的数据的唯一id是递增的,相当于版本号的功能,在消费者端,收到消息之后,首先去数据库匹配一下md5值如果数据库中记录的当前记录已经被消费,那么就不进行消费,如果发现数据库没有记录当前消息,或者记录的状态没有被消费,那么才会重新消费该消息

4、RabbitMQ 宕机了怎么处理

RabbitMQ 提供了持久化的机制,将内存中的消息持久化到硬盘上,即使重启 RabbitMQ,消息也不会丢失。持久化队列和非持久化队列的区别是,持久化队列会被保存在磁盘中,固定并持久的存储,当 Rabbit 服务重启后,该队列会保持原来的状态在RabbitMQ 中被管理,而非持久化队列不会被保存在磁盘中,Rabbit 服务重启后队列就会消失。非持久化比持久化的优势就是,由于非持久化不需要保存在磁盘中,所以使用速度就比持久化队列快。即是非持久化的性能要高于持久化。而持久化的优点就是消息会一直存在,不会随服务的重启或服务器的宕机而消失。使用的时候需要根据实际需求来判断具体如何使用。

6

认证授权相关面试话术

1、你给我说一下授权认证(登陆注册)的逻辑

这块来说就比较简单了,我们提供的注册功能有用户名密码注册,手机号注册,微信登陆绑定注册功能

用户名密码注册登陆我们系统规定的是用户名不得重复,注册的时候,会去做一下重复校验,向后台提交注册信息的时候,密码都会经过md5加密传输,到后台会首先用加密工具生成32位的盐值,然后把用户名通过md5加密之后,用户名的md5和密码的md5和盐值结合之后,生成md5值,然后一起存入数据库,用户登录的时候,按照首先根据用户名去数据库查找用户,找出来用户之后,根据相同的逻辑计算加密之后的密码和数据库的密码对比,对比一致则登陆成功手机号注册登陆(推荐使用,方便快捷)这里用到了阿里的短信服务功能,注册的时候,手机号码校验通过之后,向用户手机发送验证码,后台将验证码和手机号对应关系存入redis,用户提交注册之后,验证码跟redis中对比即可微信登陆绑定系统用户注册这里结合微信登陆使用的,微信登陆之后,如果发现对应openid没有绑定系统用户,需要提示用户去绑定,然后才能注册常识:微信开发,有两个平台,微信开放平台,主要用于app端以及web端扫码登录等开发,app中,微信登陆,微信支付,微信分享等微信公众平台,主要用于微信网页开发,公众号开发,公众号中网页登陆,微信分享,微信支付等微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret。申请微信登录且通过审核后,可开始接入流程。就是你的网站要想实现微信扫码登陆功能首先要在微信备案通过,它才会给你个AppID和AppSecret。1、用户点击网站微信登陆图标。2、网站带上AppID和回调域名参数请求微信OAuth2.0授权登陆。3、第二步通过后,微信返回二维码供用户扫码。4、用户扫码确定授权。5、微信带上code参数回调java后端回调地址。6、java后端获取到code后,在带上带上AppID和AppSecret和code再去调微信接口获取access_token。7、获取access_token后就可以解析用户的一些基本信息,比如:微信用户头像、用户名、性别、城市等一些基本参数。因为是app登陆,需要用到微信开放平台的接入功能,微信登陆采用的auth2.0的验证机制,在开放平台里注册了账号并通过企业认证,获取了AppID 和 AppSecret之后,第一步我们的服务器先获取code,传给移动端,移动端跟微信交互,用户确认授权之后,然后移动端请求我们后台获取用户信息,我们后台会先去用code获取access_token,然后在通过access_token获取用户信息,同时会返回用户的openId,我们会根据这个openId去我们的数据库查,是否已经获取过用户信息,如果获取过用户信息,看一下最后获取时间,因为每3天更新一次,所以这里会看一下是否需要重新获取如果没有获取过用户信息,会通过access_token获取用户信息,提示绑定系统用户,access_token失效时间为2个小时,因为微信有接口请求次数限制,2小时之内不会再去请求微信的access_token微信app登陆web端微信扫码登录因为我们系统是微服务架构,所以这里使用jwt实现了单点登录,因为平台有很多,有web端、管理端,还有一个清结算平台,实现单点登录会更方便用户使用,登录之后,给用户颁发了一个token令牌,每次请求的时候,都会在请求头里携带这个token,经过我们的网关的时候,会对这个token做一个权限认证,认证通过,然后才能请求到我们的微服务具体的接口

2、说一下jwt

微服务集群中的每个服务,对外提供的都是Rest风格的接口。而Rest风格的一个最重要的规范就是:服务的无状态性,即:

服务端不保存任何客户端请求者信息客户端的每次请求必须具备自描述信息,通过这些信息识别客户端身份,一般这里就是token登陆令牌这样做的话,会有很多好处,比如

客户端请求不依赖服务端的信息,任何多次请求不需要必须访问到同一台服务服务端的集群和状态对客户端透明服务端可以任意的迁移和伸缩减小服务端存储压力我们项目中也是采用的无状态登陆,使用token作为身份认证的令牌,这个token就是使用jwt生成的,jwt类型的token分为三部分,头部,载荷,签名,头部存储一些识别信息,载荷存储一些用户的基本字段,我们存储的是id的username,签名是通过头部和载荷外加RAS非对称加密生成的

3、说一下auth2.0机制

其实就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。

令牌(token)与密码(password)的作用是一样的,都可以进入系统,但是还是有一些差异的。

(1)令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。

(2)令牌可以被数据所有者撤销,会立即失效。以上例而言,屋主可以随时取消快递员的令牌。密码一般不允许被他人撤销。

(3)令牌有权限范围(scope),比如只能进小区的二号门。对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。

有了这些设计,保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。这就是 OAuth 2.0 的优点。

注意,只要知道了令牌,就能进入系统。系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。这也是为什么令牌的有效期,一般都设置得很短的原因。

具体来说,auth2.0一共分成四种授权类型

第一种是授权码模式,这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。比如A应用想要获取B应用的用户数据,A会首先访问B的授权页面,用户点击确认授权之后,B会请求A配置的回调地址,同时附带上授权码code,A可以通过这个code向B申请登录令牌access_token,获取到登录令牌之后,然后就可以向B应用请求用户信息数据了。最常见的就是微信登陆等第三方登录都用的这种方式。

还有就是隐藏式、密码式、客户端凭证等三种模式,我这边就是大概了解了一下,实际没有使用过。

7

nginx相关面试话术

1、介绍一下nginx

Nginx 是一个高性能的 HTTP 和反向代理服务器,具有反向代理和负载均衡以及动静分离等功能

我先来说说反向代理功能吧

反向代理是指以代理服务器来接受用户的请求,然后将请求,分发给内部网络上的服务器,并将从服务器上得到的结果返回给用户,此时代理服务器对外就表现为一个反向代理服务器。反向代理总结就一句话就是:代理端代理的是服务端。

反向代理的话,只需要配置对应的server模块就行了,里面配置上server_name和对应监听的端口,然后在配置location路径转发规则就行,当然也可以配置代理静态资源

再来说说负载均衡吧,负载均衡即是代理服务器将接收的请求均衡的分发到各服务器中,负载均衡主要解决网络拥塞问题,提高服务器响应速度,服务就近提供,达到更好的访问质量,减少后台服务器大并发压力,同时还可以保证服务端的高可用。常用的nginx的负载均衡策略有轮训、权重、iphash、最少连接数,默认的策略就是轮训

负载均衡这里需要配置upstream模块,在upstream中配置好当前的负载均衡规则,然后配置好每个server对应的ip端口即可,在server模块配置的转发规则就时向这个upstream上转发就行了

2、nginx如何处理http请求

Nginx这块的处理时结合多进程机制和异步机制 ,异步机制使用的是异步非阻塞方式

首先呢是多进程机制

服务器每当收到一个客户端请求时,就有服务器主进程 ( master process )生成一个 子进程( worker process )出来和客户端建立连接进行交互,直到连接断开,该子进程就结束了。

使用进程的好处是各个进程之间相互独立,不需要加锁,减少了使用锁对性能造成影响,同时降低编程的复杂度,降低开发成本。接着呢就是采用独立的进程,可以让进程互相之间不会影响 ,如果一个进程发生异常退出时,其它进程正常工作, master 进程则很快启动新的 worker 进程,确保服务不会中断,从而将风险降到最低。缺点是操作系统生成一个子进程需要进行 内存复制等操作,在资源和时间上会产生一定的开销。当有大量请求时,会导致系统性能下降

还有就是异步非阻塞机制

每个工作进程 使用 异步非阻塞方式 ,可以处理多个客户端请求 。

当某个工作进程接收到客户端的请求以后,调用 IO 进行处理,如果不能立即得到结果,就去 处理其他请求 (这就是非阻塞 );而 客户端 在此期间也 无需等待响应 ,可以去处理其他事情(这就是异步 )。

当 IO 返回时,就会通知此工作进程 ;该进程得到通知,暂时挂起 当前处理的事务去响应客户端请求 。

3、nginx常用命令

启动:nginx

当我们修改配置了之后,重启:nginx -s reload

停止nginx:nginx -s stop

4、什么是动静分离,为什么要动静分离

这个我理解的来说就是把前端静态资源和后台请求分离开,主要就是为了提升静态资源的访问速度,一般前后端分离的项目用的居多,分离之后,我们可以把静态资源放入cdn中去,可以实现用户的就近访问,同时还提供了更大的带宽。

5、如何保证nginx高可用

因为nginx是我们所有项目的入口,必须要保证nginx的高可用,这里一般都用的nginx集群,并同时加入了keepalive来做的双机热备处理,通过请求一个vip(virtual ip:虚拟ip)来达到请求真实IP地址的功能,而VIP能够在一台机器发生故障时候,自动漂移到另外一台机器上,从来达到了高可用的功能

8

前端相关面试话术

1、介绍下VUE(如果分开问你的话,就分开说)

vue呢在我的理解中,就是一个轻量级的前端js框架,最重要的就是它的MVVM思想,就是model和view之间可以通过view-model监听来进行数据到视图之间,以及视图到数据的双向绑定操作,我们在写前端代码的过程中,不需要关注任何dom操作,比jQuery方便很多

vue常用的指令都有v-for ,v-if,v-show等,绑定事件用v-on,可以省略为@符号,绑定属性用v-bind,可以省略为冒号,

还有就是vue的生命周期,常用的基本上就是created这个钩子函数,在vue组件创建之后,就会调用它,我们都在这里去服务端初始化数据,有的时候看需求了,如果需要页面大致框架渲染出来之后,再加载数据的话,就用mounted这个钩子函数里加载就行了,它相当于原生js里的onload方法

另外的话,就是基本上开发的时候,都用的是组件开发,经常的话会涉及到组件之间的传递数据以及传方法,传数据的话就使用动态绑定属性的方式,子组件中定义props就可以接收了,但是子组件无法直接修改父组件中数据模型的值,只能通过调用父级方法来修改,这就需要父组件给子组件传方法,通过@符号,自定义属性名就可以把父级中的方法传递给子组件,子组件调用的时候,使用$emit就可以调用这个方法

另外一般vue项目都是通过npm管理的,npm呢就相当于与前端的maven,主要是帮助我们管理js依赖的,我们在想要添加js依赖的时候,比如axios,可以通过npm install -g exios命令来下载就行了,也不需要我们从网上手动下载了,另外结合webpack打包的工具,在开发以及部署的时候方便很多了,不过这些都是我们专门的前端工程师来做的,用vue的脚手架搭建框架,以及配置路由等等,我们实际去写的时候,都是往里边填代码,我这边平时就是好琢磨,就研究了一下,现在来说,简单的框架搭建,以及npm管理来说,都不是问题。

2、说说你了解过的UI框架

符合vue风格的MVVM思想的,最常见的就是elementUI,还有Vuetify、iview等

符合jQuery风格的手动dom元素操作的,有bootstrap、layUI以及跟早的easyUI等

还有现在非常火的移动端的开发框架,Flutter,它是google公司推出的开源免费的移动端的UI框架

3、jquery元素选择器都有哪些

$("#id")$(".clazz")$("标签名")

9

工作流相关面试话术

1、工作流话术

工作流这块儿。嗯,实际在工作中使用的时候,activiti用的居多,当然还有一些其他的工作流引擎,嗯,在网上看了也大概看了一下,其他的像JBPM以及workflow等用的情况来讲不是很多,所以说activity目前来讲用的比较多的,它最新的版本是5.0,那他在用的时候在数据库里边儿需要,嗯,有23张表,然后在23张表里边儿会记录着所有的这些工作都是相关流程相关所有的数据。

在用的时候呢,首先就是要配置它的23张表,在数据库先创建了一下这些表。然后呢,去加载activity的配置文件。这里加载那会有两种方式,嗯,我在写这个demo的时候,而写的是用spring去加载他的一个xml配置文件,这配置文件里边儿,他就跟spring去整合其他的一些框架的时候是一样的,这个xml里边儿配置了一些这个它的的一个核心的引擎的管理器ProcessEngineConfiguration,还有一些它的数据库连接啊等等。然后给他放到了spring的配置文件中。

然后就是需要去定义一个流程。这里呢,我使用的是一个eclipse的插件,通过画流程图的方式去定义了一个简单的理由请假的流程。然后生成了一个zip的压缩包。

接下来呢,需要把这个流程部署到Activity中。通过processEngine获取到Deployment部署的类,定义一个流程名称,然后将这个压缩包,部署到activity中。这时会返回一个流程id

然后需要去启动流程实例。流程部署好了呢,如果说实际有人去发起一个请假流程,这时候需要去启动一个新的流程实例,每个流程实例会有一个独立的id。这个流程上还可以设计一些流程变量。可以是全局的,也可以是局部的。这些变量会在整个流程当中。根据它的性质去向下传递。它后台会有一个taskservice会去数据库检索待处理的任务。然后去处理就就行。处理完成之后,嗯,后边儿这个流程示例会继续向下一个节点去进行。下一个节点收到任务之后,同样通过taskservice去处理。最终直到这个任务被执行完。

总结来看呢,这个activity通过代码的方式简化了实际工作当中一些流程性的问题。当然它这里边儿还会有一些复杂的流程。包括,如何去呃多人同时处理任务呀,以及一些复杂的节点等等,大致这就是我了解的activity工作流。

10

spring相关面试话术

1、介绍一下spring

关于Spring的话,我们平时做项目一直都在用,不管是使用ssh还是使用ssm,都可以整合。Spring里面主要的就三点,也就是核心思想,IOC控制反转,DI依赖注入,AOP切面编程

我先来说说IOC吧,IOC就是spring里的控制反转,把类的控制权呢交给spring来管理,我们在使用的时候,在spring的配置文件中,配置好bean标签,以及类的全路径,如果有参数,然后在配置上相应的参数。这样的话,spring就会给我们通过反射的机制实例化这个类,同时放到spring容器当中去。

我们在使用的时候,需要结合DI依赖注入使用,把我们想使用的类注入到需要的地方就可以,依赖注入的方式有构造器注入、getset注入还有注解注入。我们现在都使用@autowired或者@Resource注解的方式注入。

然后就是AOP切面编程,他可以在不改变源代码的情况下对代码功能的一个增强。我们在配置文件中配置好切点,然后去实现切面的逻辑就可以实现代码增强,这个代码增强,包括在切点的执行前,执行中,执行后都可以进行增强逻辑处理,不用改变源代码,这块我们项目中一般用于权限认证、日志、事务处理这几个地方。

2、AOP的实现原理

这块呢,我看过spring的源码,底层就是动态代理来实现的,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了 ,目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理:

JDK 动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler 接口和 Proxy 类,InvocationHandler 通过 invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy 利用InvocationHandler 动态创建一个符合接口的的实例,生成目标类的代理对象。如果代理类没有实现 InvocationHandler 接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现 AOP。CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。不过在我们的业务场景中没有代理过final的类,基本上都代理的controller层实现权限以及日志,还有就是service层实现事务统一管理3、详细介绍下IOC容器

Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext

BeanFactory 是基础类型的 IoC 容器,提供了完整的 IoC 服务支持。简单来说,BeanFactory 就是一个管理 Bean 的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。

ApplicationContext 是 BeanFactory 的子接口,也被称为应用上下文。它不仅提供了 BeanFactory 的所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等方面的良好支持。

他俩的主要区别在于,如果 Bean 的某一个属性没有注入,则使用 BeanFacotry 加载后,在第一次调用 getBean() 方法时会抛出异常,但是呢ApplicationContext 会在初始化时自检,这样有利于检查所依赖的属性是否注入。

因此,在实际开发中,通常都选择使用 ApplicationContext

4、@Autowired 和 @Resource的区别

@Autowired 默认是按照类型注入的,如果这个类型没找到,会根据名称去注入,如果在用的时候需要指定名称,可以加注解@Qualifier("指定名称的类")

@Resource注解也可以从容器中注入bean,默认是按照名称注入的,如果这个名称的没找到,就会按照类型去找,也可以在注解里直接指定名称@Resource(name="类的名称")

5、springbean的生命周期

生命周期这块无非就是从创建到销毁的过程

spring容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。

而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。

整体来说就4个步骤:实例化bean,属性赋值,初始化bean,销毁bean

首先就是实例化bean,容器通过获取BeanDefinition对象中的信息进行实例化然后呢就是属性赋值,利用依赖注入完成 Bean 中所有属性值的配置注入接着就是初始化bean,如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。最后就是销毁bean,和init-method一样,通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑6、springbean的作用域

Spring 容器中的 bean 可以分为 5 个范围:

(1)singleton:单例模式,使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 默认的作用域。controller、service、dao层基本都是singleton的

(2)prototype:原型模式,每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。

(3)request:在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Request 内有效。

(4)session:在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效。

(5)global-session:全局作用域,在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。

7、事务的传播特性

解读:事务的传播特性发生在事务方法与非事物方法之间相互调用的时候,在事务管理过程中,传播行为可以控制是否需要创建事务以及如何创建事务

java面试看这一篇就够了_第1张图片

8、事务的隔离级别

Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。真正的数据库层的事务提交和回滚是通过 binlog实现的。隔离级别有四种

Read uncommitted (读未提交):读未提交,允许另外一个事务可以看到这个事务未提交的数据,最低级别,任何情况都无法保证。Read committed (读已提交):保证一个事务修改的数据提交后才能被另一事务读取,而且能看到该事务对已有记录的更新,可避免脏读的发生。Repeatable read (可重复读):保证一个事务修改的数据提交后才能被另一事务读取,但是不能看到该事务对已有记录的更新,可避免脏读、不可重复读的发生。Serializable (串行化):一个事务在执行的过程中完全看不到其他事务对数据库所做的更新,可避免脏读、不可重复读、幻读的发生。9、spring中都用了哪些设计模式

(1)工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;

(2)单例模式:Bean默认为单例模式。

(3)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;

(4)模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。

(5)观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。

10、spring中如何处理bean在线程并发时线程安全问题

在一般情况下,只有无状态的 Bean 才可以在多线程环境下共享,在 Spring 中,绝大部分 Bean 都可以声明为 singleton 作用域,因为 Spring 对一些 Bean 中非线程安全状态采用 ThreadLocal 进行处理,解决线程安全问题。

ThreadLocal 和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而 ThreadLocal 采用了“空间换时间”的方式。

ThreadLocal 会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal 提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进 ThreadLocal。

我们项目中的拦截器里就有这样的逻辑,在我们微服务中,网关进行登录以及鉴权操作,具体的微服务中需要用到token去解析用户信息,我们就在拦截器的preHandler里定义了threadlocal,通过token解析出user的信息,后续controller以及service使用的时候,直接从threadlocal中取出用户信息的,在拦截器的afterCompletion方法中清理threadlocal中的变量,避免变量堆积消耗内存

11

springMVC相关面试话术

话术

1、介绍一下springMVC

springmvc是一个视图层框架,通过MVC模型让我们很方便的接收和处理请求和响应。我给你说说他里边的几个核心组件吧

它的核心控制器是DispatcherServlet,他的作用是接收用户请求,然后给用户反馈结果。它的作用相当于一个转发器或中央处理器,控制整个流程的执行,对各个组件进行统一调度,以降低组件之间的耦合性,有利于组件之间的拓展

接着就是处理器映射器(HandlerMapping):他的作用是根据请求的URL路径,通过注解或者XML配置,寻找匹配的处理器信息

还有就是处理器适配器(HandlerAdapter):他的作用是根据映射器处理器找到的处理器信息,按照特定执行链路规则执行相关的处理器,返回ModelAndView

最后是视图解析器(ViewResolver):他就是进行解析操作,通过ModelAndView对象中的View信息将逻辑视图名解析成真正的视图View返回给用户

接下来我给你说下springmvc的执行流程吧

2、springMVC的执行流程

(1)用户发送请求至前端控制器 DispatcherServlet;

(2) DispatcherServlet 收到请求后,调用 HandlerMapping 处理器映射器,请求获取 Handle;

(3)处理器映射器根据请求 url 找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet;

(4)DispatcherServlet 调用 HandlerAdapter 处理器适配器;

(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);

(6)Handler 执行完成返回 ModelAndView;

(7) HandlerAdapter 将 Handler 执 行 结 果 ModelAndView 返 回 给DispatcherServlet;

(8)DispatcherServlet 将 ModelAndView 传给 ViewResolver 视图解析器进行解析;

(9)ViewResolver 解析后返回具体 View;

(10)DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中)

(11)DispatcherServlet 响应用户。

3、springMVC接收前台参数的几种方式

1、如果传递参数的时候,通过ur1拼接的方式,直接拿对象接收即可,或者string、 int2、如果传递参数的时候,传到后台的是js对象,那么必须使用对象接收,并且加@requestBody,使用requestBody之后,传递的参数至少要有一个,并且所有传的参数都要在后台对象里存在3、get的请求方式,所有的参数接收都使用普通对象或者string、int4、在用form表单提交的时候,所有的参数接收都使用普通对象或者string、int4、springMVC中的常用注解

@RequestMapping:指定类或者方法的请求路径,可以使用method字段指定请求方式

@GetMapping、@PostMapping:规定了请求方式的方法的请求路径

@RequestParam:接收单一参数的

@PathVariable:用于从路径中接收参数的

@CookieValue:用于从cookie中接收参数的

@RequestBody:用于接收js对象的,将js对象转换为Java对象

@ResponseBody:返回json格式数据

@RestController:用在类上,等于@Controller+@ResourceBody两个注解的和,一般在前后端分离的项目中只写接口时经常使用,标明整个类都返回json格式的数据

等等

5、spring如何整合springMVC

简单的说 springMVC在ssm中整合 就是 在 web.xml 里边配置springMVC的核心控制器:DispatcherServlet; 它就是对指定后缀进行拦截;然后在springMVC.xml里边配置扫描器,可以扫描到带@controller注解的这些类,现在用springMVC都是基与注解式开发, 像@service,@Repository @Requestmapping,@responsebody 啦这些注解标签 等等 都是开发时用的,每个注解标签都有自己的作用;它还配置一个视图解析器,主要就是对处理之后的跳转进行统一配置,有页面的路径前缀和文件后缀 ,如果有上传相关的设置,还需要配置上multpart的一些配置,比如单个文件最大的大小,以及最大请求的大小,大致就是这些

12

mybatis相关面试话术

1、介绍一下mybatis,说一下它的优点和缺点是什么?

Mybatis是一个半ORM(对象关系映射)的持久层框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程,使用时直接编写原生态sql。

优点:

1:基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML 里,解除sql与程序代码的耦合,便于统一管理,提供XML标签,支持编写动态SQL语句,并可重用;

2:很好的与各种数据库兼容;

3:提供映射标签,支持对象与数据库的ORM字段关系映射,提供对象关系映射标签,支持对象关系组件维护。

4:与JDBC相比,消除了JDBC大量冗余的代码,不需要手动开关连接,能够与Spring很好的集成

缺点:

1:SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求;

2:SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库;

2、MyBatis与Hibernate有哪些不同?

首先Hibernate是一个完全面向对象的持久层框架,mybatis是一个半自动化的持久层框架。

开发方面:hibernate开发中,sql语句已经被封装,直接可以使用,加快系统开发, Mybatis 属于半自动化,sql需要手工完成,稍微繁琐,但是如果对于庞大复杂的系统项目来说,复杂的sql语句较多,选择hibernate 就不是一个好方案。

sql优化方面:Hibernate 自动生成sql,有些语句较为繁琐,会多消耗一些性能, Mybatis 手动编写sql,可以避免不需要的查询,提高系统性能;

对象管理方面:Hibernate 是完整的对象-关系映射的框架,开发工程中,无需过多关注底层实现,只要去管理对象即可;Mybatis 需要自行管理 映射关系。

缓存方面:Hibernate的二级缓存配置在SessionFactory生成的配置文件中进行详细配置,然后再在具体的表-对象映射中配置是那种缓存,MyBatis的二级缓存配置都是在每个具体的表-对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。

总之:Mybatis 小巧、方便、高效、简单、直接、半自动化;Hibernate 强大、方便、高效、复杂、间接、全自动化

3、#{}和${}的区别是什么?

#{}是预编译处理,${}是字符串替换。

Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;

Mybatis在处理${}时,就是把${}替换成变量的值。

使用#{}可以有效的防止SQL注入,提高系统安全性。

4、当实体类中的属性名和表中的字段名不一样 ,怎么办 ?

第一种方法:通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致;

第二种方法:通过来映射字段名和实体类属性名的一一对应的关系;

第三种方法:在实体类通过@Column注解也可以实现;

5、通常一个Xml映射文件,都会写一个Dao接口与之对应,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

Dao接口即Mapper接口。接口的全限名,就是映射文件中的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;接口方法内的参数,就是传递给sql的参数。

Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MapperStatement。在Mybatis中,每一个