论面试的基本功java项目面试

一.首先出来面试管会让你自我介绍和介绍自己的项目. 

   你好,我叫xx,从毕业出来一致在xx上班,从事java开发相关工作这段时间我接触的框架ssh,ssm,开发工具eslipse,myeslipse接触的数据库Mysql,Oracle.非关系型数据库Redis.

下面介绍项目:我最近做的项目是一个网上商城的项目,采用的ssm框架,管理工具用的maven,采用的是分布式部署dubbo+zookeeper,这个项目分几个子系统模块:前台 后台 登录 cms(内容详情) product(商品详情) solr(搜索) buyer(购物车订单),具体的还有(会员系统 日志管理可以不说)等,-------注意简洁别啰嗦

 我负责的模块:随便写  前提你得说的出来.

二.技术点:

 1.分布式部署 dubbo+zookeeper 

  为什么用dubbo; dubbo是一个开源的分布式框架

   答:dubbo基于tcp协议高效的

第一步:使用前线搭建一个注册中心.一般推荐使用zookeeper.
第二步:有了注册中心,就可以发布服务在配置文件dubbo-privider.那个配置文件中暴漏,数据有ip端口号,将 服务发送给注册中心.
第三步:服务发布后就是调用服务,在dubbo-consume,配置文件根据ip端口调用服务.

zookeeper作用是注册和发现服务.

 dubbo和其他分布式的比较

 

用webservice,但他的效率不高,基于soap协议。

用restful形式的服务http+json,但后来一想,服务太多,服务之间调用关系混乱。

httpclent是基于http协议的,效率低,他传输的是json,它是短链接,他不能实现分布式部署。

dubbo 底层理解: 包括  发布服务  调用服务  监控  容器

 

生产者跟消费者之间相当于长连接长请求,长连接我个人理解就是,消费者和生产者之间修通了一个水管,一但spring容器项目一启动,dubbo生产者和消费者之间就接通了,它一直保存接通状态,所以它传一个对象,性能是非常高的,多半是基于tcp协议,tcp协议属于交换机层,性能比较高,传统的分布式,采用的是http协议,请求一次,响应一次,如果消费者之间和生产者之间采用http协议的话,相当于喝水时,一种是系统之间修通一个水龙头随时喝随时有,一种是接一杯喝一杯;

项目应用 dubbo : service+dao 发布服务  表现层调用服务. 根据ip和端口号.

dubbo首先向zookeerper暴露端口,消费者向它们这边订阅服务通过zookeerper,消费者发送请求,zookeerper用来调度,调度的方式有两种,轮循,随机,把这些请求都拿给生产者,如果其中一个生产者挂掉,在有新的生产者,会把请求分发给新的生产者。还可以设置服务超时时间

2.购物车业务流程:

 购物车: 一般分为两种状态 登录和未登录状态

 

a.当用户不登录的情况下,也可以加入购物车,主要是存浏览器的cookie里了,可以设置cookie的有效期,当浏览器关闭,cookie还会存在,我们在加入购物车的时候,会先把cookie中的购物车取出来,如果之前购物车有商品,我就把购物车加到购物车列表里边去,在判断商品在商品列表中是否存在,如果存在,把商品数量相加,如果不存在,根据商品id查询商品信息、把商品添加到购车列表。在把购车商品列表写入cookie。设置cookie中购物车的保存时间,返回到页面。(购物车存放在cookie的优缺点优点:不占用服务端空间,用户体验度好,代码实现简单,只对cookie读写,缺点:cookie的容量还是有限的,更换设备,不会同步,(在无登录情况下,购物车增删,都需要先从cookeie取,操作完以后,在写入cookie)

b.在用户登录的情况下,由于你不知道你在登录之前是否有过添加商品到购物车存放在cookie中,所以  也得获取一个cookie中的购物车信息.由于用户登录了,此时购物车的信息属于个人隐私了,你这时候要把cookie中的购物车信息(假如存在)和redis的购物车合并在一起,然后清空cookie中的购物车信息.在跳到添加成功页面.

这其中设计到了判断是否登录的问题

 

当时我们在项目中用拦截器实现的,首先实现HandlerInterceptor接口。它里边有三个方法,第一个prehandler它是前处理,执行handler之前执行此方法,如果返回TRUE,放行,返回FALSE,拦截,第二个是posthandler,它是handler执行之后,返回modelandview之前执行,第三个是aftercompletion,它是完成处理,返回modelandview之后执行,可以在这个方法里处理异常,我们当时在一个方法做相应的处理,首先从cookie中取token,如果没有取到token,说明用户未登录。放行,要是取到token,调用sso系统的服务,根据token查询用户信息。如果没有返回用户信息。说明登录已经过期,未登录状态,放行。如果返回用户信息。用户是登录状态。可以把用户对象保存到request中,在Controller中可以通过判断request中是否包含用户对象,来确定是否为登录状态。

3.订单问题

 

当用户在购物车点击去结算时,跳转到订单确认页面之前,首先要求用户登录,判断用户是否登录,当时也是用拦截器实现的,一旦用户登录以后,就取到用户ID了,根据用户ID取地址收货列表,调用购物车服务查询,展示到页面。当用户点击提交订单时,请求到后台,后台把它插入到数据库中,插入之前,我们这个订单状态默认是1,未付款状态,当时数据库有三张表,一个是订单表,订单表里防止订单号冲突,我们使用的redis的incr自增长来生成订单号,先给它一个初始值,在初始值上完成自增长,第二个是订单明细表,里边是商品ID,数量,价格等等,第三个是收货地址表,记录每一个订单的收货地址,当订单生成成功以后,删除购物车信息,把订单号传递给页面

 去订单结算页面同样设计登录问题

 

当用户查询订单的时候,我们会先判断用的登录状态,如果没登录,让用户登录,我们会从cookie里取token,调用sso服务,判断token有没有过期,sso服务呢会根据token查询redis,判断key有没有取到,如果取到说明用户是登录状态,这时候还要重置一下过期时间,假如我们设置的过期时间是30分钟,万一用户在29分时候刷新了一下页面,我们必须在重新设置一下过期时间,在返回用户已登录,显示订单信息,如果取的key是空,说明key已经过期了,过期了就要从redis中移除,移除之后,就是判断用户没有登录,直接跳转到登录页面,恩,实现流程就是这样。

4.静态化页面问题

 

我们在静态化的时候,主要涉及到网页的单页页面,访问量较大,更新少,我们可以将该页面用freemaker(velocity)生成静态化页面,在访问的时候,只需要访问静态化页面,不需要访问数据库,降低了数据库的压力,

 

我们的freemaker模板工具里封装当时是传三个参数,第一,传递模板名称,第二,传递当前的数据对象,第三,指 定生成的静态化页面存储的位置。(一般是Nginx中), 生成的页面名称一般是表名+id

页面是:freemark标签代替EL表达式.

5.重点还是reids缓存问题.

   答:后台数据的存放一般都是reids.

redis 存的数据类型 list String hash  set  hashset  ,我那用的是存的list,我们的历史报表数据经常用到而且存在redis,

redis的数据存在内存还是硬盘上:内存  。

由于Redis是一个基于key,value的支持多种数据类型的可进行持久化的内存数据库,是一个服务级的缓存。它支持string list map hash系列 对象  

项目中redis一般都是作为缓存使用,缓存目的就是减少对数据库的访问,降低数据库的压力.提高存取效率.

   应用场景:

会话缓存(Session Cache):最常用的一种使用Redis的情景是会话缓存(session cache)。用 Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化(AOF  rdb)

 购物车,前面有介绍就不说了, 存放购物车信息 ,生成订单id, 商品上架时也有商品id,方式一般是设置一个值 然后incy自增.

热卖问题:

做商品数据缓存时,因为数据量特别大,而且缓存是把数据保存到内存中,此时不可能把所有商品放到缓存中.需要设置商品数据的有效期,当用户访问到非热点数据时,将数据放到缓存中到期后再清除,而且长时间不会添加到缓存,而热点数据一旦从缓存到删除后又会马上添加到缓存中,这样就提高了缓存利用率,减轻数据库的压力.

 6.单点登录(不是我做的不是太懂)

因为我们的项目是拆分成不同工程,如果用户登录以后,跳转到首页,当用户搜索一个商品的时候,还会在让用户登录一次,然后当加入购物车的时候还要登录,用户体验度非常不好,之所以存在这样的问题,是因为session共享的问题,为了解决这个问题,我们做了一个单点登录,SSO,就是用户只需要登录一次就可以访问所有相互信任的应用系统。

根据我的理解,①使用tomcat配置session共享,代码不用做任何修改,一旦我在这登录,tomcat会做一个广播,当前节点会向其他tomcat集群广播自己的session信息,接收到消息的tomcat会把session信息复制到自己session里来,可以实现session共享,但是呢,在tomcat集群中配置session共享,会有一个session上限问题,核心问题就是tomcat配置了session共享,广播形式,导致集群中有个节点上限,如果不停的往集群中加tomcat的话,会形成网络的风暴,所以session复制会把整个网络带宽都占了,服务器的服务性能就会降低,这个问题解决不了高并发的问题。

②所以我们在项目中专门搭建了一个Session服务,把所有的session都放在这里边,保存Session信息,使每个节点是无状态。需要模拟Session。我们在项目中单点登录系统(sso)这一模块,用的是redis模拟Session,实现Session的统一管理。

但又有一个问题:我们把session放到redis里,如果是用户userID当做key,那么这个用户要是换一台电脑用同一个账号登录,用的不是一个session,那通过什么判断是不是登录了,如果根据userID判断的话,就重复了,怎么区分呢?

当时我是这样解决的,session本来就有一个sessionID在cookie里,因为我们是模拟的session,需要自己定义sessionID,我们自己随机生成的ID,叫token,保证sessionID不重复,把这个token当做key存入redis,value是用户信息,一个token对应一个session,一个session对应一个用户信息,这样的话同一个账号在不同的电脑上登录,就区分开了,并且设置了过期时间(expire),我们生成的这个token也要保存到cookie里,因为总得有一个标识来区分当前到底是哪个连接,所以需要把token写入cookie,我们在做登录的时候,会先判断用户是否登录成功,如果登录成功,调用了一个cookieUtils工具类,把token写入cookie,并不是直接写,是通过response响应给浏览器的,浏览器拿到响应的结果,一判读是写cookie,浏览器在把cookie写入在自己文件里,util里有好多方法,主要有读cookie和写cookie两大块。

但这个时候呢又有问题出现了,当用户登录成功以后,首页上要显示用户信息(就是页面导航条那一块),同样搜索页面也要显示用户信息,商品详情页面也要显示,每个页面都要展示用户的信息,这么多工程都要写一边,比较麻烦,而且还没办法让它通用,毕竟是不同的工程,当时我是这么处理的,使用ajax,每个页面上加上一个js,js里边就做ajax请求,我在sso工程这边发布一个(软set)服务,每个页面都引js,只要页面加载完成之后,就用ajax发送请求,把用户信息从token取出来,展示到页面上,这样我们后台controller就不用动了,但js有个限制,当我们发送ajax请求调用服务端,服务端也正常响应数据了,但数据到达浏览器,浏览器不让js去拿这个数据,因为这个工程是IP相同,但端口不同,跨域了(域名不同,IP地址不同,域名相同,端口不同,IP地址相同,端口不同),浏览器就限制了,就不让访问了,为了解决这个问题,就使用了jsonp。根据我个人理解,js有个漏洞,它不能跨域,但它有个特性,可以利用script src属性跨域加载js文件,首先呢,我们在本地定义了一个方法,叫mycall,做一个ajax跨域加载js文件,跨域带上一个参数,callback,它的值是我们定义好的方法mycall,把方法名作为参数,传递给服务端,服务端做个判断,是否有callback,如果有,就认为它是一个jsonp请求,服务端就会根据方法名拼接成一个js语句,相当于一个js文件,我们就把这个js语句响应给浏览器,浏览器会马上执行这个js语句,然后进行方法调用,把mycall方法里的参数取出来,做相应的处理就可以了,但这样做有点麻烦,我们在项目中使用的是jQuery封装好的js,在ajax请求的datatype指定是jsonp就可以了,然后在controller层使用MappingJacksonValue这个对象,这个对象有一个setJsonpFunction方法,设置jsonpFunction名,就是callback,直接响应一个对象回去就可以了,但这个MappingJacksonValue这个对象是在spring4.1以上才支持的,我们项目中用的是spring4.2。当时在项目中就是这么用的。

7.fastDF 图片上传

fastDFS是一个开源的分布式文件系统,对文件进行管理,文件存储同步文件访问.解决大容量存储和负载均衡的问题.

我们就在项目中使用了fastDFS,分布式文件系统,它可以储存文件,还可以在分布式环境下存储,分布式就可以把文件保存到多台服务器上,它充分考虑到冗(rong)余备份(高可用),负载均衡(这个服务器压力比较大,可以换另外一台服务器提供服务),线性扩容(存储容量不够了,可以往里边加服务器,他会自动管理,如果这个服务器挂了,还可以加备份机,他会自动同步)等机制。fastDFS只是解决图片保存的问题,保存以后,我们必须通过nginx发送请求http去访问图片。。。

fastDFS原理?

它有三个角色:1、client(客户端),2、Tracker(向导,集群管理工具,类似于dubbo中心),3、Storage(真正保存文件的地方,他可以分组,每个组里边有好多个成员,成员之间保存的是一样的,他们没有主从这个概念,地位都是平等的,他们起到了一个备份的作用,组和组之间保存的东西是不一样的,Storage他会定期向Tracker汇报自己的状态信息,比如存储情况,负载情况),Tracker记录了Storage集群状态,存储情况,当客户端要上传图片,其实客户端是不知道往哪个服务器上传图片的,他就会问Tracker我要上传图片,哪个服务器合适呢?Tracker就会挑一台不忙的服务器,还有存储空间的服务器,返回给客户端一个IP和端口号,客户端拿到IP和端口号,就可以把图片上传到服务器上了。他只是存到一台服务器上了,但组成员之间会有一个同步的线程,只要在一台服务器上传上去了,其他服务器就会把内容自动同步,这样保证整个组成员之间内容一致。Tracker是集群的入口,如果tracker挂了,后边服务器就找不到了,所以tracker也可以搭集群,tracker每个节点里边地位也是平等的,他们之间也会同步自己的信息,保证里边的数据是一致的,这是tracker集群的特点。

8.前台的日志模块

我们这个前台的日志模块的核心价值是为了统计用户的行为,方便进行用户行为分析。 考虑到对日志的统一处理以及前台访问量巨大导致的大并发和大数据量的问题。 当时是结合AOP和Mongodb来完成了这项功能。存日志的时候是通过SpringAOP写了个切面类,之后在切面类可以获取用户使用的浏览器的类型如是IE还是谷歌,还是火狐;以及用户使用的设备类型如是手机,平板,PC(电脑端);包括用户浏览过的商品信息,用户购买的商品信息等。将这些信息通过封装好的MongodbUtil将其插入到mongodb数据库中方便其他系统后续对其进行分析。当时考虑到mongodb的高可用性我们搭建了3台mongodb数据库来实现副本集,这样不仅可以达到故障自动转移的特性而且也可以通过读写分离提高性能,即便主服务器宕机了,还会通过投票选举出下一个主服务器继续提供服务。考虑到后续数据量的不断增加,为了方便扩容我们还建立了3个分片。

9.MQXactiveMQ  

答:实现系统间的通信,实现的是异步通信,原理是生产者生产消息,把消息发送给activeMQ.

activeMQ查询有几个消费者,然后把消息转发给消费者,此过程无生产者参与.

消费者接收到消息作用相应处理,与生产者无关,,

分为点对点,订阅者发布模式,

应用:实现系统间通信,系统间解耦,例如在图片上传商品上架时,将信息添加到索引库,生成静态化页面一系列操作,这个场景就是用了activeMQ,商品上架对mq发送了一条信息,然后通过mq把消息发送给消息的消费端,消费端接收到消息做出相应处理.

项目中的应用:a. 注册帐号时的发送短信阿里云.  向手机发送一个验证码;

                    b.商品上架时设计到了mq,商品上架发送商品id到activeMq 然后其他模块  比如同步到索引库,生成静态化页面.

10.Solr(搜索用的)

 

solr基于Luence开发的全文检索服务器,而Luence就是一套实现全文检索的api,

本质就是全文检索的过程,全文检索就是将原始文档按照一定的规则拆分为若干个关键字,在关键词上创建索引,查询时先查询索引,再根据索引找到关键词,通过关键词找到原始文档对应的文档,将结果返回到用户.

IK分词器的分词原理本质上是词典分词。现在内存中初始化一个词典,然后在分词过程中逐个读取字符,和字典中的字符相匹配,把文档中的所有的词语拆分出来的过程。

solr怎么设置搜索结果排名靠前(得分)?

答:设置文档中域的boost值,boost值越高计算出来的相关度越高,排名越考前此方法可以把热点商品或者是推广商品的排名提高

11跨域问题(单点登录也有所涉及)

  答:我的理解就是域名不同,不如我从www.taobao.com去访问www.jd.com  域名改变了  浏览器级别的

如何实现跨域请求

在jquery页面加一个jsonp ,后台接受callback,在用mapksonvalue设置当前结果和callback,return出去进行转换.

jsonp通过script标签的src可以跨域请求的特性,加载资源,将加载的资源(通过一个方法名将数据进行包裹)当做是js脚本解析,定义一个回调函数(是怎么实现的?),获取传入的数据。我们使用jsonp是因为Jsonp的兼容性比较好,并且在请求完毕后可以通过callback的方式回传结果。但jsonp有一个缺点是只支持get请求而不支持post等其他类型的http请求。

12.写一个单例模式;

public class Singleton{

private static void Singleton instancel;

private static Singeton(){}

public static Singleton getInstance(){

if(instance==null){

instance=new Singeton()

}

retrun instance;

}

}

13数据库sql优化?

https://www.cnblogs.com/yunfeifei/p/3850440.html  链接地址:

  • 对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
  • .应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描;
  • 应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描;
  • 应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描;
  • in 和 not in 也要慎用,否则会导致全表扫描;
  • 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段

14.数据库优化

 表优化 ,主要是分库分表,垂直分,水平分;

  比如一个表存的数据量特别大,我们采用了分库分表,当一个表的数据大额,我们按表分为了tab-1,tab-2,tab.tab-n,我们通过取余的方式去看应该存在哪个表中。

15.实现线程的方式:runable接口,继承thread累

16.事务方面的东西;什么是脏读,幻读,不可重复读,事务的特性,隔离级别(7个,一般说5个);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值