关于项目中的面试题

Maven的生命周期

mvn clean:清理编译的项目
mvn compile:编译项目
mvn test:测试项目(运行测试类)
mvn package:负责将我们的项目打包
mvn install:将这个项目安装到仓库中

Jar包冲突怎么解决?

1、我们可以借助Maven Helper插件中的Dependency Analyzer分析冲突的jar包,然后在对应标红版本的jar包上面点击execlude,就可以将该jar包排除出去。
2、手动在pom.xml中使用标签去排除冲突的jar包
介绍一下springboot
Spring Boot 是Spring项目中的一个子工程,其实人们把Spring Boot 称为搭建程序的脚手架。其最主要作用就是帮我们快速的构建庞大的spring项目,并且尽可能的减少一切xml配置,做到开箱即用,迅速上手,让我们关注与业务而非配置。其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。用我的话来理解,就是 Spring Boot 其实不是什么新的框架,它默认配置了很多框架的使用方式,就像 Maven 整合了所有的 Jar 包,Spring Boot 整合了所有的框架。
好处:搭建项目快,省去了大量的xml配置文件,内嵌tomcat容器,不需要再将项目打包进行部署到tomcat。

知道springboot的装配原理么?

@EnableAutoConfiguration作用就是从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。这些功能配置类要生效的话,会去classpath中找是否有该类的依赖类(也就是pom.xml必须有对应功能的jar包才行)并且配置类里面注入了默认属性值类,功能类可以引用并赋默认值。生成功能类的原则是自定义优先,没有自定义时才会使用自动装配类。

什么是微服务?

微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。

那你说一下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的真实性。验证通过之后才会访问到我们的微服务。这就是我们项目当中微服务具体使用的一些场景以及它的组件。

Redis是什么?

redis是一个高性能的key-value数据库,它是完全开源免费的,而且redis是一个NOSQL类型数据库,是为了解决高并发、高扩展,大数据存储等一系列的问题而产生的数据库解决方案,是一个非关系型的数据库

redis缓存

redis作为缓存的作用就是减少对数据库的访问压力,当我们访问一个数据的时候,首先我们从redis中查看是否有该数据,如果没有,则从数据库中读取,将从数据库中读取的数据存放到缓存中,下次再访问同样的数据,还是先判断redis中是否存在该数据,如果有,则从缓存中读取,不访问数据库了。
针对上面出现的问题:
当我们后台数据库中内容修改之后,因为缓存中的内容没有修改,我们访问的时候都是先访问缓存,所以即使数据库中的内容修改了,但是页面的显示还是不会改变的。因为缓存没有更新,所以这就涉及到缓存同步的问题:即数据库修改了内容与缓存中对应的内容同步。
缓存同步的原理:就是将redis中的key进行删除,下次访问的时候,redis中没有改数据,则从DB进行查询,再次更新到redis中。
我们可以写一个缓存同步的服务:

缓存穿透

缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。

缓存雪崩

缓存雪崩,是指在某一个时间段,缓存集中过期失效。
产生雪崩的原因之一,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。

缓存击穿

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上
凿开了一个洞。

Spring常用注解

Spring常用注解包括了SpringMVC的注解,SpringMVC是Spring的子项目
声明bean的注解
@Controller 标注控制层组件
@Service 标注业务层组件
@Respostory 标注数据访问组件
@Component 标注@Controller、@Service、@Respostory以外的其他组件
注入Bean的注解
@Autowired 按类型注入,注入的属性必须提供set方法
注意:@Resource按名称注入,属于J2EE范畴,不属于Spring框架,@Autowired属于Spring框架
@Qualifier 与@Autowired配合使用
接口或父类可能存在多个实现类或子类的实例,因此通过@Qualifier来指定名称的实例注入

springboot常用注解

springboot注解:
@Service: 注解在类上,表示这是一个业务层bean
@Controller:注解在类上,表示这是一个控制层bean
@Repository: 注解在类上,表示这是一个数据访问层bean
@Component: 注解在类上,表示通用bean ,value不写默认就是类名首字母小写
@Autowired:按类型注入.默认属性required= true;当不能确定 Spring

@Configuration:注解在类上,表示这是一个IOC容器,相当于spring的配置文件,java配置的方式。 IOC容器的配置类一般与 @Bean 注解配合使用,用 @Configuration 注解类等价与 XML 中配置 beans,用@Bean 注解方法等价于 XML 中配置 bean。
@Bean: 注解在方法上,声明当前方法返回一个Bean
@Scope:注解在类上,描述spring容器如何创建Bean实例。
(1)singleton: 表示在spring容器中的单例,通过spring容器获得该bean时总是返回唯一的实例
(2)prototype:表示每次获得bean都会生成一个新的对象
(3)request:表示在一次http请求内有效(只适用于web应用)
(4)session:表示在一个用户会话内有效(只适用于web应用)
(5)globalSession:表示在全局会话内有效(只适用于web应用)
在多数情况,我们只会使用singleton和prototype两种scope,如果未指定scope属性,默认为singleton
@Value:注解在变量上,从配置文件中读取。
例如:@Value(value = “#{message}”)
@ConfigurationProperties 赋值,将注解转换成对象。给对象赋值。车险项目:HttpClientSetting类
@Profile:注解在方法类上在不同情况下选择实例化不同的Bean特定环境下生效!!!!!!!!!!!!!!!!!
@SpringBootApplication:@SpringBootApplication=@ComponentScan+@Configuration+@EnableAutoConfiguration:约定优于配置
@EnableAutoConfiguration启用 Spring 应用程序上下文的自动配置,试图猜测和配置您可能需要的bean。自动配置类通常采用基于你的classpath 和已经定义的 beans 对象进行应用。被 @EnableAutoConfiguration 注解的类所在的包有特定的意义,并且作为默认配置使用。通常推荐将 @EnableAutoConfiguration 配置在 root 包下,这样所有的子包、类都可以被查找到。
@RestController @RestController 是一个结合了 @ResponseBody 和 @Controller 的注解
@Responsebody 注解表示该方法的返回的结果直接写入 HTTP 响应正文(ResponseBody)中,一般在异步获取数据时使用,通常是在使用 @RequestMapping 后,返回值通常解析为跳转路径,加上@Responsebody 后返回结果不会被解析为跳转路径,而是直接写入HTTP 响应正文中。

为什么使用redis?

刚刚也说了mysql的一个并发问题,这个我也通过资料了解过,mysql数据库表单数据上线为352w条吧,大概是这个样子吧,因为我们使用的分布式系统嘛,这个表单的数据量很容易突破上线,就算到时候搭建集群或者主从配置,读写分离,当高并发的情况下还是会发生并发问题,主要还是mysql的IO读写瓶颈这个问题无法突破,因为它无论是存在表里或者是存在数据库里的数据,最终都是要写入磁盘,然后通过数据库客户端来进行读取,所以,为了解决这个问题,只有把数据缓存到内存中,才能加快读取速度,避免IO瓶颈问题。

redis连接及使用

Redis呢共有16个db,索引值四0-15,如无选择默认选择db0,redis 官方提供的客户端连接工具是 jedis,但是使用繁琐,我们在项目中是通过 spring 提供的 springDataRedis,对 jedis 进行二次封装,使用便捷。首先 pom 文件中引入 spring-data-redis 的依赖 ,在 spring 配置文件中,配置 JedisPoolConfig,配置 redis 连接池的参数信息;配置 RedisTemplate,由 spring 封装,连接操作 redis 的工具类;在代码中注入 RedisTemplate,通过 redisTemplate.boundsOpsXxx()方法,操作指定数据类型数据的 api就可以了。

但是呢,这里有个问题就是在操作redis的时候如果是在系统中直接操作redis的话,那首先从架构设计这方面来看是不合理的,因为系统是分布式的嘛,直接在系统上操作会产生系统之间的耦合和依赖,另一方面呢就是数据同步这块,如果说后台数据库的数据发生改变,前端又是直接从redis中读取的数据,那这样就有问题了,因为读取到的还是老的数据。所以我们就使用了RabbitMQ消息中间件。利用RabbitMQ进行了系统之间的异步通信,而且一并实现了redis跟数据库的数据同步问题。

Redis中遇到的问题

缓存雪崩:缓存雪崩就是同一时刻服务器重启或者一大波请求key失效,导致服务器宕机,也是是所谓的雪崩。
缓存穿透:就是先去redis使用key进行查询,redis中不存在,然后去数据库查找,如果一大波请求,会导致服务器宕机。这就是所谓的穿透。解决的话互斥锁排队分布式项目我使用的是分布式锁,就是key获取value值为空时,锁上,从数据库中load数据后在释放,若其他线程获取锁失败的话,就等待一段时间。

Redis两种持久化方式:

redis还有两种持久化方式,一个是RDB,这也是redis默认的持久化方式,这种方式是以快照的方式存储数据,在固定的时间段内如果有多少变化,那么就会生成快照存储到磁盘上,redis 在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的。对于 RDB 方式,redis 会单独创建一个子进程来进行持久化,而主进程是不会进行任何 IO 操作的,这样就确保了 redis 极高的性能。 这种方式的优点呢就是快,但是如果没等到持久化开始redis宕机了,那么就会造成数据丢失
还有一种是AOF,是即时性的持久化方式,是将 redis 执行过的所有写指令记录下来,在下次 redis 重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。AOF的方式会导致性能下降
两种方式可以同时开启,当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。
我们项目中使用的持久化方式就是默认的RDB,因为我们存储的数据首先来说不是很重要的数据,如果丢失了,还可以从数据库加载到,主要用的就是性能这块
redis怎么做到和mysql数据库数据同步?
读取数据的时候先从redis里面查,若没有,再去数据库查,同时写到redis里面,并且要设置失效时间。存数据的时候要具体情况具体分析,可以选择同时插到数据库和redis(要是存放到redis中,最好设置失效时间),也可以选择直接插到数据库里面,少考虑一些问题,添加内容的,把对应的redis里的数据的删除掉.第一个人查的时候从数据库里查询,把数据放到的缓存中,第二个人访问就可以直接从缓存中访问数据了

项目中哪一块用到redis了?

Redis实现的单点登录,登录之后生成token,将用户的信息保存到奥redis中并设置过期时间为30分钟(模仿session过期时间),然后返回登录成功,把token保存到cookie中,在其他服务发送请求的时候就携带token,接收到token之后进行解析出用户信息,先查询redis是否存在,不存在则跳转到登录页面,如果存在的话重新调整用户信息的过期时间为30分钟,并返回到要处理的业务页面。

什么是RabbitMQ?

RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

RabbitMQ的五种消息模式

模式1:简单模式(Simple / HelloWorld 单生产单消费)
简单的发送与接收,没有特别的处理。
模式2:工作模式(Work单发送多接收)
一个生产者端,多个消费者端。示例中为了保证消息发送的可靠性,不丢失消息,使消息持久化了。同时为了防止接收端在处理消息时down掉,只有在消息处理完成后才发送消息确认。
模式3:发布、订阅模式(Publish/Subscribe)
使用场景:发布、订阅模式,生产者端发送消息,多个消费者同时接收所有的消息。
模式4:路由模式(Routing)
生产者按routing key发送消息,不同的消费者端按不同的routing key接收消息。
模式5:通配符(或主题)模式(Topics ,按topic发送接收)
生产者端不只按固定的routing key发送消息,而是按字符串“匹配”发送,消费者端同样如此。
与之前的路由模式相比,它将信息的传输类型的key更加细化,以“key1.key2.keyN…”的模式来指定信息传输的key的大类型和大类型下面的小类型,让消费者端可以更加精细的确认自己想要获取的信息类型。而在消费者端,不用精确的指定具体到哪一个大类型下的小类型的key,而是可以使用类似正则表达式(但与正则表达式规则完全不同)的通配符在指定一定范围或符合某一个字符串匹配规则的key,来获取想要的信息。“通配符交换机”(Topic Exchange)将路由键和某模式进行匹配。此时队列需要绑定在一个模式上。符号“#”匹配一个或多个词,符号“*”仅匹配一个词。

RabbitMQ消息发送失败解决方案?在使用RabbitMQ的时候有没有遇到过什么问题?

第一种用数据库或者redis配合着解决:
怎么配合呢咱们这边不是发送的酒店的ID么,在发送之前把ID记录在数据库里面去,然后设置一个状态字段,0代表这个消息发送中,然后监听端进行消费,消费成功后把这个字段在改为1.然后就是几种突发情况,第一种情况比如说突然断电了然后我的消息首先是记录在数据库里面了,然后他的那个状态是不是为0啊,然后我们有一个用quartz写的定时器,每隔5分钟会去数据库跑批(批处理)然后把状态为0的数据,再重新发送一遍消息,直到消费成功为止.
第二种解决:ACK确认字符
在发送消息的时候设置提交的方式,改成手动提交的方式,在后台改成commit状态改成手动方式,如果发送成功的话,然后commit手动提交方式。

说一下spring?

Spring 是一个开源框架,为简化企业级应用开发而生
Spring可以实现java模块化开发,贯穿表现层,业务层,逻辑层,实现了各个层之间的解耦合关系
Spring 是一个 IOC 和 AOP 容器框架

Spring 容器的核心:

控制反转(IOC):传统的java 开发模式中,当需要一个对象时,我们会自己使用 new 或者 getInstance 等直接或者间接调用构造方法创建一个对象。
而在spring 开发模式中,spring 容器使用了工厂模式为我们创建了所需要的对象,不需要我们自己创建了,直接调用spring 提供的对象就可以了,这是控制反转的思想
面向切面编程(AOP):在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事务管理,记录日志等公用操作处理的过程就是面向切面编程的思想。
AOP 底层是动态代理,如果是接口采用JDK 动态代理,如果是类采用CGLIB 方式实现动态代理。
依赖注入(DI):Spring 使用 JavaBean 对象的 set 方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程,就是依赖注入的思想

Spring中的事务

注解式事务和声明式事务
注解式事务只需在spring配置文件配置一个事务管理器并注入数据源,然后开启事务,在需要加事务的方法上加@Transactional这个注解就可以了。
声明式事务是结合springAOP来实现的,切点一般是扫描service层实现类,通过方法名匹配配置传播特性,决定哪些方法上加事务,哪些不需要事物。
springboot常用注解

说一下springmvc执行流程?

用户向服务器发送请求,请求被Springmvc的核心控制器DispatcherServlet捕获,DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象,最后以HandlerExecutionChain对象的形式返,DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter,提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller),Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象,根据返回的ModelAndView,调用ViewResolver进行解析返回给DispatcherServlet一个View,经过渲染之后响应给用户。

说一下Mybatis

Mybatis 框架也是一个持久层框架,我们目前做的这个项目就是用的这个框架,我觉他相对于以前的hibernate来说比较简单,把sql语句写在配置文件里,解除了代码和sql语句的耦合度,写一些复杂的查询比较灵活.

Mybatis 和 Hibernate 的区别

Hibernate一个是全封装,mybatis是半封装,使用hibernate做单表查询操作的时候比较简单(因为hibernate是针对对象进行操作的),但是多表查询起来就比较繁琐了,比如说5张表10张表做关联查询,就算是有SQLquery那后续的维护工作也比较麻烦,还有就是Hibernate在Sql优化上执行效率上会远低于MyBatis(因为hibernate会把表中所有的字段查询出来,比较消耗性能)我们以前在做传统项目方面用过hibernate,但是现在基本上都在用mybatis.

Mybatis缓存?

mybatis一级缓存是SqlSession级别的缓存,默认支持一级缓存,不需要在配置文件去配置。
mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存:

{}和${}的区别?

这两个符号一般是在使用Mybatis编写底层SQL语句时使用,#就是一个占位符,具体的使用是#{id},而 是 一 个 原 样 输 出 的 标 识 , 是 是一个原样输出的标识,是 {value},我在项目里一直是使用#,因为这样可以防止Sql注入,安全性高。

1.阿里短信

为什么使用/优点:
阿里云平台比较稳定,到达率高
怎么用:
首先呢需要企业注册一个阿里云,里面找到短信微信服务,申请自己的模板和签名等信息;下载短信服务提供的SDK,通过SDK提供的工具类,和自己对应的参数配置,访问短信服务商网关,进行短信发送;因为短信服务与系统业务联系不高,所以我们单独开发了一个短息微服务,通过RabbitMQ进行消息通讯,这样既与系统进行了解耦,也提高了短信服务的复用率;当用户点击发送验证码的时候,通过RabbitMQ向短信服务发送消息,短信服务会将配置的模板id,手机号自动向用户发送短信验证码;用户点击注册按钮时,我们会在redis中通过手机号获取对应的验证码, 然后与用户输入的验证码进行比较,如果一致就返回消息,提示成功,如果不成功提示验证码错误。(遇到的问题验证码过期):刚刚也说了redis中验证码存储的时候,存到话我们使用String的key:key:value****来进行存储,通过expire设置生命周期,最长保存时间设置成5分钟,超过自动移除,如果用户不断申请验证码,首先用手机号去redis中查询如果缓存中存在验证码,则提示验证码已发送,请注意查收;

2.什么是单体架构,分布式架构,微服务架构

单体架构:
传统架构。集所有功能于一身构建一个项目,不可分开部署
缺点:当业务增长到一定程度 单体应用就不足以支撑业务需求
分布式架构:
分布式结构就是将一个完整的系统,按照业务功能,拆分成一个个独立的子系统,部署在不同服务器。
优点:降低了系统之间的耦合性 服务的复用性提高
微服务架构:
又称微服务架构,是一种分布式的系统。就是将一个单体架构的应用按业务划分为一个个独立运行的程 序即服务,它们之间通过 HTTP 协议进行通信,可以采用不同的编程语言,使用不同的存储技术,自动化部署减少人为控制,降低出错概率。服务数量越多,管理起来越复杂,因此采用集中化管理。微服务和分布式差不多 但是 微服务可以部署在一个服务器上
微服务架构优点:
①每一个服务高内聚 低耦合 代码好理解
②每一个服务只做一件事 开发效率提高
③可以用不同语言开发 基于接口编程
④易于与第三方集成
微服务架构缺点:
①分布式系统的模块划分和工作分工复杂
②多服务运维难度,随着服务的增加,运维的压力也在增大
③服务间通信成本
④数据一致性

3.项目时什么电商模式,电商模式还有什么:

1 B2C模式 企业—个人 唯品会
2 B2B模式 企业—企业 阿里巴巴
3 O2O模式 线上—线下 美团,饿了么
4 B2B2C模式 企业—企业—个人 京东,天猫
5 C2C模式 个人—个人 咸鱼,瓜子二手车
.这个前后端分离的项目,会不会产生跨域,怎么解决
会产生
跨域是因为浏览器得同源策略 协议 域名端口号不同都会产生跨域
解决:项目中是通过Spring注解解决跨域的 @CrossOrigin,也可以使用nginx反向代理,httpClient,网关

5.微信支付遇到什么问题了

post编码问题。当组装好数据后,需要通过POST的形式向微信服务器发送数据。可是,问题来了,微信的数据封装的完全正确,key也设置正确了,在官方的验证工具上验证出来也是正确的,可是,微信总是提示签名错误。这个问题出现在post请求的编码问题上,遇到这个问题的情况是,在封装数据的时候,xml里面加入了中文,然后每次请求就会报错,可是如果中文去掉,下单成功。最后才发现,原来POST的时候,没有设置编码,设置成为UTF8之后就没事了。可是,返回的签名错误,也真心难排查啊

6.主键自增的情况下,怎么直接查询最后一条数据

先查询id的最大值,然后再查询id为此值的数据
SELECT * FROM menu WHERE menuId = (SELECT MAX(m.menuId) FROM menu m)

根据主键id倒序排序,查询第一条数据
SELECT * FROM menu m ORDER BY m.menuId DESC LIMIT 2;
7.MyBatisPlus
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性:
无侵入:只做增强,不做改变,引入后不会对现有工程产生影响
损耗小:启动就会自动注入基本CURD,性能基本无损耗,直接面向对象操作
CRUD操作很强:内置通用Mapper,通用Service,仅仅通过少量配置即可实现单表大部分CRUD操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
8.limit查询优化方法(offset偏移量)
offset偏移量较小:

需求:查询第10条数据之后(包含第10条)的10条数据
原始:
代码示例:
select * from user limit 10,10; 不包含第10条
select * from user limit 9,10; 包含第10条 因为索引是从0开始
优化:使用子查询
代码示例:
SELECT * FROM menu WHERE menuId >=(SELECT menuId FROM menu ORDER BY menuId LIMIT 10,1)LIMIT 10;
offset偏移量较大:测试优化后sql执行速度只有前者的1/3。可以预计offset越大,后者越优

需求:查询第10000条数据之后的10条数据
原始:
select * from user limit 10000,10;
优化:使用子查询
代码示例:
SELECT * FROM menu WHERE menuId >=(SELECT menuId FROM menu ORDER BY menuId LIMIT 10000,1)LIMIT 10;
通过以上对比,得出mysql limit查询语句优化经验: 使用limit语句时,当数据量偏移量较小时可以直接使用limit,当数据量偏移量较大时,可以适当的使用子查询来做相关的性能优化。
工作中怎么查看日志
在linux中,tomcat文件夹中有log的文件,可以使用tail查看文本的结尾,head查看文件的开头

tail -n200 info.log //查看info.log文件结尾200行
head -n200 info.log //查看info.log文件开头200行
平常会在Controller层定义全局变量吗?
不会,因为Controller是默认单例模式,高并发下全局变量会出现线程安全问题
解决:
①将全局变量都变成局部变量,通过方法参数传递
②使用ThreadLocal,为多线程并发提供了新思路
③在类上加@Scope(“session”) 把这个Bean的范围设置成session,表示这个Bean是会话级别的
④将控制器的作用域从单例改为原型,即在spring配置文件Controller中声明 scope=“prototype”,每次都创建新的controller

11.HashMap的底层原理

1、 原理
HashMap底层是通过数组和链表联合实现的,当我们创建一个HashMap时,会先创建一个数组,当我们使用put方法存数据时,先根据key和hashcode()方法计算出hash值,然后用这个哈希值确定出在数组中的位置,再把value值放进去,如果这个位置本来没放东西,就会直接放进去,如果之前有,就会生成一个链表,把新放入的值放在头部,当用get()方法取值的时候,会先根据key的hashCode()方法计算出hash值,确定位置,再根据equals方法从该位置上的链表中取出该value值

11.2 默认大小,及为什么

默认大小:HashMap默认初始化容量为16,数组的索引就是0-15
默认初始容量为什么是16:这个并没有明文说明,因为一定要设置一个2的n次幂作为初始值,在效率和内存上做权衡,不能太大,又不能太小,所以就用了2的4次幂 16

11.3 扩容大小及为什么

什么时候扩容:当HashMap空间使用达到0.75之后会进行扩容,每次扩容翻倍,新建数组,将元素拷贝到新数组中
为什么是以2倍的形式扩容:HashMap的初始化容量是2的n次幂,扩容也是以2倍的形式进行扩容,是因为容量也是2的n次幂,这样可以使元素均匀的分布在HashMap中的数组上,减少Hash碰撞,避免形成链表的结构,使得查询的效率降低

12.有没有遇到过Hash碰撞,怎么处理的

暂时没有遇到过,但是了解过,Hash碰撞就是两个对象的Hash值一样的时候,就会发生hash碰撞
解决:
1.开放地址法:当发生地址冲突时,按照某种方法继续探测哈希表中的其他存储单元,直到找到空位
2.再哈希法
3.链地址法(拉链法)

13.cookies和session的区别

cookie数据是以文本格式存放在客户的浏览器上,session数据放在服务器上。
cookie不是很安全,考虑到安全应当使用session。

cookie不安全的表现形式:
cookie欺骗
cookie截获
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,而session则存储与服务端,浏览器对其没有限制。

14.引用数据类型有哪些

类 接口 数组

15.MySQL优化方案

  1. 使用支持mysql主从复制的版本
  2. 在使用MySQL时使用索引
  3. 优化sql语句
  4. 优化MySQL服务,修改MY.INI文件,根据服务器配置缓存的大小
  5. 根据服务器配置索引的缓存
  6. 使用视图,将冗余字段放在一张表里
  7. 使用第三方技术mycat,对数据库拆分,水平拆分和垂直拆分,我们用的水平拆分
  8. 设置表内存放数据上限,同时通过mycat配置读写分离

16. 什么是多线程?他怎么解决高并发?

线程就是可执行的代码段,线程要服务于进程,一个进程有好多个线程,main方法就是主线程,多个线程同时执行就是多线程,线程池就是把准备好的线程放到线程池里,如果处理请求需要调用线程的时候,就从线程池里去调用,用完以后再放回到线程池里,这样就防止高并发节省资源,我们目前开发中没有涉及到过多线程,其实我个人理解用多线程无非是为了提高代码的执行效率提高客户的体验,解决高并发,但是项目里如果多线程使用的多的话,后期的代码维护这一块也不怎么好维护,我们现在在解决这些高并发都是建议使用中间件来解决,redis啦,activeMQ啦
ThreadLocal和Synchonized都用于解决多线程并发访问但是ThreadLocal与synchronized有本质的区别: synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal是为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。

17. 说下nginx?

Nginx 是一个高性能的HTTP和反向代理web服务器
我们在项目中使用Nginx主要是用它来做反向代理服务器。我们将所有的请求都通过80端口,然后让nginx监听80端口,然后具体由nginx看是路由到哪一个服务。
正向代理和反向代理的区别?
正向代理类似一个跳板机,代理访问外部资源
比如我们国内访问谷歌,直接访问访问不到,我们可以通过一个正向代理服务器,请求发到代理服,代理服务器能够访问谷歌,这样由代理去谷歌取到返回数据,再返回给我们,这样我们就能访问谷歌了
正向代理的用途:
  (1)访问原来无法访问的资源,如google
(2)可以做缓存,加速访问资源
  (3)对客户端访问授权,上网进行认证
  (4)代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息
反向代理(Reverse Proxy)实际运行方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器

反向代理的作用:

(1)保证内网的安全,阻止web攻击,大型网站,通常将反向代理作为公网访问地址,Web服务器是内网
(2)负载均衡,通过反向代理服务器来优化网站的负载
正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端.
反向代理即是服务端代理, 代理服务端, 客户端不知道实际提供服务的服务端

Nginx负载均衡? Nginx负载均衡的策略有

1.轮询方式是Nginx负载默认的方式,顾名思义,所有请求都按照时间顺序分配到不同的服务上,如果服务Down掉,可以自动剔除
2.指定每个服务的权重比例,weight和访问比率成正比,通常用于后端服务机器性能不统一,将性能好的分配权重高来发挥服务器最大性能
3.每个请求都根据访问ip的hash结果分配,经过这样的处理,每个访客固定访问一个后端服务
4.将请求分配到连接数最少的服务上。
5.按后端服务器的响应时间来分配请求,响应时间短的优先分配。

18.Java里常见的数据结构都有哪些以及特征

数组
数组是最常用的数据结构,数组的特点是长度固定,可以用下标索引,并且所有的 元素的类型都是一致的。
列表
列表和数组很相似,只不过它的大小可以改变。列表一般都是通过一个固定大小的 数组来实现的,并且会在需要的时候自动调整大小。列表里可以包含重复的元素。
集合
集合和列表很相似,不过它不能放重复的元素
堆栈
堆栈只允许对最后插入的元素进行操作,也就是先进后出。如果你移除了栈顶的元素,那么你可以操作倒数第二个元素,依次类推。这里边常用的方法有peek()返回不删除栈顶元素,push()向栈里添加元素, pop()返回并删除栈顶元素。
队列
队列和堆栈有些相似,不同之处在于在队列里第一个插入的元素也是第一个被删除 的元素,就是先进先出。常用的方法有peek()返回头部元素,offer()向尾部添加元素, poll() 移除并返回头部元素
链表
链表是一种由多个节点组成的数据结构,并且每个节点包含有数据以及指向下一个节点的引用,在双向链表里,还会有一个指向前一个节点的引用。例如,可以用单向链表和 双向链表来实现堆栈和队列,因为链表的两端都是可以进行插入和删除的动作的。当然,也 会有在链表的中间频繁插入和删除节点的场景。

19:Nginx介绍下?

Nginx介绍下:
Nginx 是一个高性能的 HTTP 和反向代理服务器,具有反向代理和负载均衡以及动静分离等功能。
我先来说说反向代理功能吧
反向代理是指以代理服务器来接受用户的请求,然后将请求,分发给内部网络上的服务器,并将从服务器上得到的结果返回给用户,此时代理服务器对外就表现为一个反向代理服务器。 反向代理总结就一句话就是:代理端代理的是服务端。
反向代理的话,只需要配置对应的server模块就行了,里面配置上server_name和对应监听的端口,然后在配置location路径转发规则就行,当然也可以配置代理静态资源。
再来说说负载均衡吧,负载均衡即是代理服务器将接收的请求均衡的分发到各服务器中,负载均衡主要解决网络拥塞问题,提高服务器响应速度,服务就近提供,达到更好的访问质量,减少后台服务器大并发压力,同时还可以保证服务端的高可用。常用的nginx的负载均衡策略有轮训、权重、iphash、最少连接数,默认的策略就是轮训

spring中都用了哪些设计模式?

代理模式:AOP采用jdk和cglib
单例模式:spring创建bean默认采用单例模式
工厂模式:beanFactory就是工厂模式的体现
模板模式:redisTemplates,jdbcTemplates

你可能感兴趣的:(java)