SSM相关
讲下 springmvc 框架的工作流程
1、用户向服务器发送请求,请求被 SpringMVC 的前端控制器 DispatcherServlet 截获。
2、DispatcherServlet 对请求的 URL(统一资源定位符)进行解析,得到 URI(请求资源标识符),然后根据该 URI,调用 HandlerMapping 获得该 Handler 配置的所有相关的对象,包括 Handler 对象以及 Handler 对象对应的拦截器,这些对象都会被封装到一个 HandlerExecutionChain 对象当中返回。
3、DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter。HandlerAdapter 的设计符合面向对象中的单一职责原则,代码结构清晰,便于维护,最为重要的是,代码的可复制性高。HandlerAdapter 会被用于处理多种 Handler,调用 Handler 实际处理请求的方法。
4、提取请求中的模型数据,开始执行 Handler(Controller)。在填充 Handler 的入参过程中,根据配置,spring 将帮助做一些额外的工作
消息转换:将请求的消息,如 json、xml 等数据转换成一个对象,将对象转换为指定的响应信息。数据转换:对请求消息进行数据转换,如 String 转换成 Integer、Double 等。
数据格式化:对请求的消息进行数据格式化,如将字符串转换为格式化数字或格式化日期等。
数据验证:验证数据的有效性如长度、格式等,验证结果存储到 BindingResult 或 Error 中。
5、Handler 执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象,ModelAndView 对象中应该包含视图名或视图模型。
6 、 根 据 返 回 的 ModelAndView 对 象 , 选 择 一 个 合 适 的 ViewResolver( 视 图 解 析 器 ) 返 回 给DispatcherServlet。
7、ViewResolver 结合 Model 和 View 来渲染视图。
8、将视图渲染结果返回给客户端。
以上 8 个步骤,DispatcherServlet、HandlerMapping、HandlerAdapter 和 ViewResolver 等对象协同工作,完成 SpringMVC 请求—>响应的整个工作流程,这些对象完成的工作对于开发者来说都是不可见的,开发者并不需要关心这些对象是如何工作的,开发者,只需要在 Handler(Controller)当中完成对请求的业务处理。
图片怎么上传
前端使用 angularJS 异步上传,后端使用 springmvc 的 MultipartFile 类型来接收,放
到分布式图片服务器中,服务器返回图片路径把路径返回页面回显图片
微服务和 SOA 有什么区别?
如果一句话来谈 SOA 和微服务的区别,即微服务不再强调传统 SOA 架构里面比较重的 ESB企业服务总线,同时 SOA 的思想进入到单个业务系统内部实现真正的组件化。
说的更直白一点就是微服务被拆分的粒度更小
spring 框架 AOP 执行原理简单说下?还有就是 AOP 在事务管理方面是怎么实现的?
Spring AOP 使用的动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理。JDK 动态代理通过反 射来接 收被代 理的类, 并且要 求被代 理的类 必须实 现一个 接口。 JDK 动态 代理的 核心 是InvocationHandler 接口和 Proxy 类。如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用 CGLIB 做动态代理的。
AOP 在事务管理方面,Spring 使用 AOP 来完成声明式的事务管理有 annotation 和 xml 两种形式。开发中,方便代码编写,很多时候都是在 spring 配置文件中配置事务管理器并开启事务控制注解。在业务类或业务类方法中添加@Transactional 实现事务控制。
Spring 分布式事务如何处理的
回答:
第一种方案:可靠消息最终一致性,需要业务系统结合 MQ 消息中间件实现,在实现过程中需要保证消息的成功发送及成功消费。即需要通过业务系统控制 MQ 的消息状态
第二种方案:TCC 补偿性,分为三个阶段 TRYING-CONFIRMING-CANCELING。每个阶段做不同的处理。
TRYING 阶段主要是对业务系统进行检测及资源预留CONFIRMING 阶段是做业务提交,通过 TRYING 阶段执行成功后,再执行该阶段。默认如果 TRYING阶段执行成功,CONFIRMING 就一定能成功。
CANCELING 阶段是回对业务做回滚,在 TRYING 阶段中,如果存在分支事务 TRYING 失败,则需要调用 CANCELING 将已预留的资源进行释放。
Springboot 用过没,跟我说说,他的特点?
Springboot 是从无数企业实战开发中总结出来的一个更加精炼的框架,使得开发更加简单,能使用寥寥数行代码,完成一系列任务。
1) Springboot 解决那些问题
a) 编码更简单
i. Spring 框架由于超重量级的 XML,annotation 配置,使得系统变得很笨重,难以维护
ii. Springboot 采用约点大于配置的方法,直接引入依赖,即可实现代码的开发
b) 配置更简单
Xml 文件使用 javaConfig 代替,XML 中 bean 的创建,使用@bean 代替后可以直接注入。配置文件变少很多,就是 application.yml
c) 部署更简单
d) 监控更简单
Spring-boot-start-actuator:
可以查看属性配置
线程工作状态
环境变量
JVM 性能监控
支付部分
支付接口是怎么做的?
调用微信的支付接口,参考微信提供的 api
使用了微信的统一下单接口和查询支付状态接口
每个接口需要的参数放入到 map 中使用微信提供的 sdk 转成 XML 字符串,httpClient远程提交参数和接收结果。
项目业务面试问题
哪些情况用到 activeMq
商品上架后更新 solr 索引库、更新静态页、发送短信
秒杀的时候,只有最后一件物品,该怎么去抢或者分配?
秒杀商品的库存都会放到 redis 中,在客户下单时就减库存,减完库存会判断库存是否为大于 0,如果小于 0,表示库存不足,刚才减去的数量再恢复,整个过程使用 redis的 watch 锁
solr 和 lucene 的区别
solr 是 Apache 的用于实现全文检索的开源项目,是一个 war 包,直接可以放入tomcat 服务器中配置一下就可以使用,而 Lucene 是全文检索的底层技术,solr 是在Lucene 的基础上开发的 solr
solr 怎么设置搜索结果排名靠前(得分)?
设置 boots 值
你项目对于订单是怎么处理的,假如一个客户在下订单的时候没有购买怎么办,对于顾客在购买商品的时候你们怎么处理你们的库存?
订单表中设置了一个过期时间,每天会有定时任务来扫描订单表数据,如果到达预订的
过期时间没有付款就会取消此订单交易。
关于库存的设计是这样的:
普通商品在发货时才去更新库存,如果库存不足商家会马上补货
秒杀的商品会在客户下单时就减库存,如果在规定时间(半个小时)没有付款,会取消
此订单把库存还原
插入商品的话,要求级联插入几张表,你们当时是怎么实现的?
三张表 商品表、商品描述表、sku 表,他们的关系是一对一对多,三张表使用了组合类 表现他们的关系,在页面使用 angularjs 双向绑定了组合类
redis 存储格式的选择
redis 支持的数据结构总共有 5 种:hash、value、list、set、zset,其中项目中用到最多是 hash
商品表中的数据是哪里来的不知道
商品表的数据是在商家管理后台中由商家录入的。数据分别录入到商品表、商品描述表和商品项表
当初设计项目时预计的访问量计划是多少
访问量计划是 3000 至 5000
店主申请开店是从哪里申请的,所需要的信息都有哪些
商家申请开店在商家管理后台申请入驻的。在运营商管理后台审核通过后,方可登陆系统完成后续操作,例如:录入商品信息等。所需要的信息可以参考:注册页面学习。需要信息有:商家登录名、密码、店铺名称、公司名称、公司电话、联系人、联系人电话、营业执照号、税务登记号、组织机构代码证、法人代表信息、开户行信息等。
模板表的设计思想
模板表设计主要是为了商品表与品牌表、规格表进行数据关联。方便商品录入时,选择对应的品牌和规格数据。
简单介绍一下你的这个项目以及项目中涉及到的技术框架以及使用场景以及你主要负责项目中的哪一块?
项目介绍时,先整体介绍是什么项目,项目主要是做啥的。例如:XXX 电商项目,是一个 B2B2C 综合电商平台。由三个系统组成,包含:运营商管理后台、商家管理后台、网站前台。运营商平台主要负责基础数据维护、商家审核、商品审核等。商家管理后台主要负责商家入驻、商品录入/修改、商品上下架等。网站前台主要负责商品销售。包含:网站首页、商品搜索、商品详情展示、购物车、订单、支付、用户中心等模块。
再介绍自己在项目中做的功能模块。例如:运营商管理后台的品牌、规格数据录入,已经商品管理后台商品录入功能。同时,实现了网站前台系统中的商品搜索、购物车等功能模块。
然后介绍里面使用的技术:例如:dubbo 分布式框架、ssm、angularjs、solr、redis、freemarker、activeMQ、微信扫码支付等等。最好是结合技术讲解项目功能点如何实现。
秒杀系统中如何防止超售?如何避免脚本进行恶意刷单?
防止超售解决方案:将存库从 MySQL 前移到 Redis 中,所有的写操作放到内存中,由于 Redis 中不存在锁故不会出现互相等待,并且由于 Redis 的写性能和读性能都远高于 MySQL,这就解决了高并发下的性能问题。然后通过队列等异步手段,将变化的数据异步写入到 DB 中。当达到库存阀值的时候就不在消费队列,并关闭购买功能。
避免脚本恶意刷单:采用 IP 级别的限流,即针对某一个 IP,限制单位时间内发起请求数量。
单点登录你们是自己编写的还是使用通用的 CAS?
项目使用通用的 CAS 框架。
如果一个用户的 token 被其他用户劫持了,怎样解决这个安全问题。
a、在存储的时候把 token 进行对称加密存储,用时解开。
b、将请求 URL、时间戳、token 三者进行合并加盐签名,服务端校验有效性。
c.HTTPS 对 URL 进行加密
项目部署上线后,运营商管理,商品审核等后台流量问题?
回答:
先询问流量是指哪方面?流量分为三种,一种是商家流量,另一种是用户流量,第三种运营商流量。
解决方案:
这三种流量对系统运行造成很大压力,随着项目上线时间增长,压力会越来越大,因此我们要减轻系统访问压力 ,就需要做一系列优化措施。
具体优化如下:
数据层面的优化:
从数据库层面做优化,比如:索引,缓存,集群,读写分离,主从复制,分表,分库。
从数据库设计层面的优化:比如减少表关联,加入冗余字段
从缓存方面优化:比如 redis 实现数据缓存,减轻数据库压力
从搜索上进行优化:比如查找索引库
项目层面的优化:
采用面向服务的分布式架构:分担服务器压力 ,提高项目并发量
比如 dubbox+zookeeper 分布式架构
采用分布式文件系统实现海量文件存储:如采用 fastdfs 实现海量图片存储,提高文件的访问速度。
采用 mq 使用服务进一步解藕:同步索引库,同步静态资源,短信发送服务器层面的优化
集群思想的使用:tomcat,zookeeper,redis,mysql 等
Tomcat 异步通信的使用,tomcat 连接池配置
秒杀和团购业务实现思路
回答:
将商品数量查询出存入到 redis 中,所有用户下单后,减掉 redis 中的数量
如果并发量很大时,还要考虑高并发问题,所以可以加入 mq 消息中间件处理抢单问题,再结合 redis
实现库存减少操作。高并发方面还可以考虑 CDN,Nginx 负载均衡等
你们项目中使用的安全框架是什么?
使用 springSecurity,校验用户登录和用户权限!
项目中使用到的应用服务器是什么?
Tomcat+nginx
讲一下每台服务器的集群数量:
项目中一共 15 台项目服务,那么为了每一台高可用一主一备,但首页项目高并发设为四台服务器,则一共 32 台项目服务器,再加 redis 集群用了 3 台,为了每一台高可用一主一备一共 6 台,fastdfs 一个 trackerServer 一个 storageServer 搭建集群一共 6 台,solr 集群 7 台服务器,nginx 为了高可用一主一备一共 2 台,mysql 数据库集群 3 台!activemq 消息中间件高可用 2 台;
共计:58 台服务器!
1:你在项目开发中碰到过哪些重大且棘手的问题
场景一:需求不明确困境
在项目开发中,项目采用迭代开发,开发需求不是很明确,对于项目开发初期来说非常困难,进度非常慢,有时开发的出的产品结果往往不能令老板满意,或者是甲方满意,项目还需要不停的迭代,修改。
比如说:
在开发品优购项目的时候,客户定位是一个综合性的商务平台,可以实现在线第三方商家对接,实现商品的销售但是并没有明确的需求,因此开发全凭借电商的项目经验来实现里面的相关的业务,后期慢慢迭代。
场景二:使用 cas 单独登录不能很好实现想要的效果
场景三: solr 高亮不能显示的问题
前台使用 angularJS 加载搜索结果,但是发现高亮不能展示。
问题原因:
angularJS 底层使用 ajax,异步加载高亮信息返回给页面后,页面没有刷新,就直接显示返回的数据。此时会把所有的数据作为普通的文本数据进行加载。因此就没有高亮的效果。
解决方案:
使用 angularJS 过滤器过滤文本数据,此时 angularJS 过滤器把 html 文本数据解析为浏览器能识别的 html 标签。高亮就能展示了。
场景四:Nginx 静态页面服务跳转到购物车跨域问题
在 Nginx 中部署了静态页面,添加购物车时必须从静态页面跳转到购物车系统,实现购物车添加操作。
由于在静态页面中使用 angularJS 实现的跳转,发现跳转到购物车系统完全没有问题,但是并不能跳转回到购物车系统页面。
问题分析:
从静态详情系统跳转到购物车系统,会存在跨域问题,因此不能进行回调函数的数据传递。所以在回调函数中的页面跳转就不能实现。
解决方案:
使用 angularJS 跨域调用及 springmvc 跨域配置,解决问题。
场景五:activeMQ 存在运行时间长了以后,收不到消息的现象时间长了就会出现,卡死,新的数据不能从队列接听到。只能重启程序。
解决方案:
1)不要频繁的建立和关闭连接
JMS 使用长连接方式,一个程序,只要和 JMS 服务器保持一个连接就可以了,不要频繁的建立和关闭连接。频繁的建立和关闭连接,对程序的性能影响还是很大的。这一点和 jdbc 还是不太一样的。
2)Connection 的 start()和 stop()方法代价很高
JMS 的 Connection 的 start()和 stop()方法代价很高,不能经常调用。我们试用的时候,写了个 jms 的 connection pool,每次将 connection 取出 pool 时调用 start()方法,归还时调用 stop()方法,然而后来用 jprofiler发现,一般的 cpu 时间都耗在了这两个方法上。
3)start()后才能收消息
Connection 的 start()方法调用后,才能收到 jms 消息。如果不调用这个方法,能发出消息,但是一直收不到消息。不知道其它的 jms 服务器也是这样。
4)显式关闭 Session
如果忘记了最后关闭 Connection 或 Session 对象,都会导致内存泄漏。这个在我测试的时候也发现了。本来以为关闭了 Connection,由这个Connection 生成的 Session 也会被自动关闭,结果并非如此,Session 并没有关闭,导致内存泄漏。所以一定要显式的关闭 Connection 和 Session。
5)对 Session 做对象池
对 Session 做对象池,而不是 Connection。Session 也是昂贵的对象,每次使用都新建和关闭,代价也非常高。而且后来我们发现,原来 Connection是线程安全的,而 Session 不是,所以后来改成了对 Session 做对象池,而只保留一个Connection。
6) 集群
ActiveMQ 有强大而灵活的集群功能,但是使用起来还是会有很多陷阱
场景六:activeMQ 存在发生消息太大,造成消息接收不成功
多个线程从 activeMQ 中取消息,随着业务的扩大,该机器占用的网络带宽越来越高。
仔细分析发现,mq 入队时并没有异常高的网络流量,仅仅在出队时会产生很高的网络流量。
最终发现是 spring 的 jmsTemplate 与 activemq 的 prefetch 机制配合导致的问题。
研究源码发现 jmsTemplate 实现机制是:每次调用 receive()时都会创建一个新的 consumer 对象,用完即销毁。
正常情况下仅仅会浪费重复创建 consumer 的资源代价,并不至于产生正常情况十倍百倍的网络流量。但是 activeMQ 有一个提高性能的机制 prefetch,此时就会有严重的问题。
prefetch 机制:
每次 consumer 连接至 MQ 时,MQ 预先存放许多 message 到消费者(前提是 MQ 中存在大量消息),预先存 放 message 的数量取决于 prefetchSize(默认为 1000)。此机制的目的很显然,是想让客户端代码用一个 consumer 反复进行 receive 操作,这样能够大量提高出队性能。此机制与 jmsTemplate 配合时就会产生严重的问题,每次 jmsTemplate.receive(),都会产生 1000个消息的网络流量, 但是因为 jmsTemplae 并不会重用 consumer,导致后面 999 个消息都被废弃。反复 jmsTemplate.receive()时,表面上看 不出任何问题,其实网络带宽会造成大量的浪费。
解决方案:
1、若坚持使用 jmsTemplate,需要设置 prefetch 值为 1,相当于禁用了 activeMQ 的 prefetch 机制,此时感觉最健壮, 就算多线程,反复调用 jmsTemplate.receive()也不会有任何问题。但是会有资源浪费,因为要反复创建 consumer 并频繁与服务器进 行数据通信,但在性能要求不高的应用中也不算什么问题。
2、不使用 jmsTemplate,手工创建一个 consumer,并单线程反复使用它来 receive(),此时可以充分利用 prefetch 机制。配合多线程的方式每个线程拥有自己的一个 consumer,此时能够充分发挥 MQ在大吞吐量时的速度优势。
切记避免多线程使用一个 consumer 造成的消息混乱。大吞吐量的应用推荐使用方案 2,能够充分利用prefetch 机制提高系 MQ 的吞吐性能。
商品的价格变化后,如何同步 redis 中数以百万计的购物车数据。
解决方案:
购物车只存储商品 id,到购物车结算页面将会从新查询购物车数据,因此就不会涉及购物车商品价格同步的问题。
系统中的钱是如何保证安全的。
在当前互联网系统中钱的安全是头等大事,如何保证钱的安全可以从以下 2 个方面来思考:
1)钱计算方面
在系统中必须是浮点数计算类型存储钱的额度,否则计算机在计算时可能会损失精度。
2)事务处理方面
在当前环境下,高并发访问,多线程,多核心处理下,很容易出现数据一致性问题,此时必须使用事务进行控制,访问交易出现安全性的问题,那么在分布式系统中,存在分布式事务问题,可以有很多解决方案:
使用 jpa 可以解决
使用 tcc 框架可以解决等等。
订单中的事物是如何保证一致性的。
使用分布式事务来进行控制,保证数据最终结果的一致性。
当商品库存数量不足时,如何保证不会超卖。
当库存数量不足时,必须保证库存不能被减为负数,如果不加以控制,库存被减为小于等于 0 的数,那么这就叫做超卖。
那么如何防止超卖的现象发生呢?
场景一: 如果系统并发要求不是很高
那么此时库存就可以存储在数据库中,数据库中加锁控制库存的超卖现象。
场景二:系统的并发量很大
如果系统并发量很大,那么就不能再使用数据库来进行减库存操作了,因为数据库加锁操作本身是以损失数据库的性能来进行控制数据库数据的一致性的。
但是当并发量很大的时候,将会导致数据库排队,发生阻塞。因此必须使用一个高效的 nosql 数据库服务器来进行减库存。
此时可以使用 redis 服务器来存储库存,redis 是一个内存版的数据库,查询效率相当的高,可以使用watch 来监控减库存的操作,一旦发现库存被减为 0,立马停止售卖操作。
你们系统的商品模块和订单模块的数据库是怎么设计的
商品模块设计:
商品模块一共 8 张表,整个核心就是模板表。采用模板表为核心的设计方法,来构造商品数据。订单设计:
订单涉及的表有:
1) 收货人地址
2) 订单信息
3) 订单明细订单关系描述:
系统中商家活动策划以及上报相关业务流程。
品优购系统中有以下活动:
1) 秒杀活动
a) 后台设置秒杀商品
b) 设置秒杀开启时间,定时任务,开启秒杀
c) 秒杀减库存(秒杀时间结束,库存卖完,活动结束)
2) 促销活动
3) 团购活动
4) 今日推荐
以上活动销售记录,统计,使用图形化报表进行统计,可以查看销售情况。
11,涉及到积分积累和兑换商品等业务是怎么设计的
积分累计有 2 大块:
积分累计:
根据用户购买的商品的价格不同,没有购买一定价格的商品,获取一定的积分。积分商城:
积分商城是用户可以使用积分商品换取商品的区域。
介绍下电商项目,你觉得那些是亮点?
这个项目是为 xxx 开发的 b2b2c 类型综合购物平台,主要以销售家用电器,电子产品为主要的电子商城网站。
项目的亮点是:
1) 项目采用面向服务分布式架构(使用 dubbo,zookeeper)
a) 解耦
b) 提高项目并发能力
c) 分担服务器压力
2) 项目中使用 activeMQ 对项目进一步解耦
a) 提高项目并发能力
b) 提高任务处理速度
3) 使用微信支付,支付宝支付(自己总结)
4) 使用阿里大于发生短信
5) 使用第三方分布式文件系统存储海量文件
6) Nginx 部署静态页面实现动静分离
购物车功能做了吗,实现原理说一下?
购物车设计示意图:
你们的项目上线了吗?这么大的项目怎么没上线?
项目上线问题回答:
1) 项目没有上线
可以是项目没有上线之前,你离职了,这个一个创业型的公司,或者此项目是给甲方做的项目,你没有参与上线。以此来回避这个问题
2) 项目上线
项目已经上线了
上线环境:
a) Centos7
b) Mysql
c) Jdk8
d) Tomcat8
关于上线,那么面试官一定会问您,上线遇到什么问题没有?因此必须把项目中遇到的问题准备 2 个。
订单怎么实现的,你们这个功能怎么这么简单?
订单实现:
从购物车系统跳转到订单页面,选择默认收货地址
选择支付方式
购物清单展示
提交订单
订单业务处理:
一个商家一个订单,不同的仓库发送的货品也是属于不同的订单。因此会产出不同的订单号。
订单处理:根据支付的状态进行不同的处理
1) 在线支付
a) 支付未成功—从新发起支付
b) 支付超时---订单关闭
2) 货到付款