java如何高质量的介绍自己的项目--关于Spring MVC+Springboot+Mybatis等(一)

首先介绍这个项目。面试官您好,我做过的这个项目是ERP经销存,适用与各大商场、超市、旅游等等企业适用。
首先商用项目技术更新迭代太快,我做的这个ERP 项目是B/S架构 分布式 高并发 负载均衡 ,数据量大 都是考虑的范围,其次就是系统的安全,服务器的安全;各个系统说明:后台管理系统, 前台系统;其次在这些系统下在进行划分:
系统功能,档案功能,档案功能其中包含,商品档案,供应商档案,等等;

人员的划分:
产品 三人 负责需求的修改, 项目经理 前端 三人 后端 分小组 三个组 一共 16人
系统架构,采用分布式的系统架构,其中前台系统和单点登录系统采用了集群的方式部署,在后台管理系统种用的maven 多模块管理 水平切分的方式 分为 pojo dao service web分层开发,可重用性更高;
系统内部接口调用采用;Httpclient,并且使用Httpclient连接池技术,接口提=提供采用restful方式定义接口;
系统通知机制采用MQ方式,使用了RabbitMQ实现,使用了RabbitMQ的消息订阅模式的消息机制;
系统的接口还对js的跨域做了支持,采用jsonp的解决方法,
采用的是nginx+tomcat来部署的,nginx主要用来是做静态文件资源
项目中我参与的相关系统的开发,主要有:后台管理系统:商品的管理,商品参数规格的管理,订单管理,会员管理;
前台系统:面向用户访问,使用httpclient和后台系统接口做交互,,并且该系统再部署上采用集群的方式;
单点登录系统,主要是提供集中用户登录凭证的记重解决方案,提供和用户信息的相关的接口,如:用户注册、查询等接口
搜索系统,主要提供商品的搜索,采用开源企业级系统solr实现,采用MQ机制保证了商品数据可以及时同步到solr中;
会员系统:维护用户的信息,采购订单 优惠卷 修改密码 等;
缓存的时候,主要用的Redis实现,并且对Redis做了集群来保证Redis服务的高可用;
支付对账,不是我负责的,只是略微知道大概的整体流程;

再做商品档案的录入和供应商档案的录入的时候:
使用 分页查询:
1.查询的结果集的sql,传入开始行数和结束的行数
select * from(select
from(
//内部sql
)
)
2.使用内部sql查询结果集的总条数
3.使用分页工具类,创建page对象更换每次的数据总条数和当页数和每页数的条数,查询出结果集后把结果集注入到page对象中,
public class page(
int total//
int pagesize//
int startNum//
//…
//get set 方法
// 有参方法

服务器的还有做反向代理和负载均衡(不了解的哥哥姐姐们查一查,一般都会问到,

我面试的时候问到过我除了会tomcat还会什么我当时蒙了没答上来),因为这种电商

项目需要在多个环境中运行,我们利用了nginx的反向代理解决不同系统中带来的各种问题。
在做这个项目的时候有架构师因为涉及的功能比较多,所以会采用分布式架构设

计,整个项目包括,后台管理系统,商品首页系统,搜索系统,商品详细系统,登录

系统。购物车系统。订单系统等、这样分出来交给每个人做是为了使模块独立出来,

降低了各个系统之间的耦合度,增加一个新的功能不会影响到其他的功能模块。在做

浏览器访问前端页面去加载后端系统数据时出现的跨域问题,因为项目是采用分布式

架构设计的,个个模块是相互独立的,而且访问的路径都不一样,当时跨域请求数据

时会受到跨域受限的问题,比如当用户首次访问网站首页时,首页会异步请求后台管

理系统,加载商品的项目,之前我们是通过ajax异步请求数据来实现这个功能的,测试

中ajax不支持跨域就改用了jsonp来解决这个问题,jsonp通过script标签的src可以实现

跨域请求的特性,加载资源,将加载的资源通过一个方法名数据进行包裹,当做是js脚

本。就是定义一个回调函数通过获取传入的数据。使用jsonp兼容性还比较好,并且在

请求完毕后可以通过callback的方式来实现回传结果,但是jsonp只支持get请求不支持

post等其他类型的http请求。

我们可以通过http请求,来访问后台数据,当时我们想到的是是使用

httpclient(Dubbo)来解决此问题,因为Httpclient可以使用java代码模拟浏览器发送

请求(差不多,可能不准确,不全自己在动手查查)执行流程如下:
【HttpClient httpclient = new DefaultHttpClient();

//准备一个请求对象
HttpGet httpget = new HttpGet(“http://www.apache.org/”);

//此处还可以添加请求消息头header,如果是post还可以设置请求参数
//执行请求
HttpResponse response = httpclient.execute(httpget);

//检查响应状态
System.out.println(response.getStatusLine());

//获取响应实体的持有
HttpEntity entity = response.getEntity();

//如果响应不包含实体,则没有必要
//担心连接释放
if(entity!= null){
InputStream instream = entity.getContent();
try{

     BufferedReader reader = new BufferedReader(
             new InputStreamReader(instream));
     //做一些有用的响应
     System.out.println(reader.readLine());

 } catch(IOException ex){

     //在IOException的情况下,连接将被释放
     //自动返回到连接管理器
     抛出

 } catch(RuntimeException ex){

     //如果出现意外异常,您可能希望中止
     // HTTP请求为了关闭底层
     //连接并将其释放回连接管理器。
     httpget.abort();
     抛出

 } finally {

     //关闭输入流将触发连接释放
     instream.close();

 }}

 //当不再需要HttpClient实例时,
 //关闭连接管理器以确保
 //立即释放所有系统资源
 httpclient.getConnectionManager()。shutdown();

}
1.创建出httpclient对象。

2.构建post和get请求。

3.如果有参数就去构造请求参数get和post各自构建的方式不一样。

4.执行请求,并且接受响应。

5.处理响应结果。

6.释放连接。无论何时执行方法是否成功,都必须释放连接。

httpclient访问线程是安全的因为每次发起http请求的时候都会重新建立起连接(差不多

三次)用完就会关闭连接(这是第四次),当然这样会消耗很多时间,采用了连接池

的方法。当然还有别的方法,如果不采用连接池都会导致每次打开一个端口,再大并

发的情况下导致端口资源很快就会被消耗完。,从而导致无法建立新的连接。

在使用get进行参数传递的时候在url中设置参数,通过key和value因为都是String类
型,然后将url传给httpget请求。Post的话模拟表单提交,将数据封装list集合中,将集合数据放入构造的表单实体中,在将表单实体请求放到httppost请求。

在项目中那些首页的大广告和商品类目这些不需要经常修改数据,就是说如果用户每次刷新页面的时候都要去数据库中查询这样的话就会浪费资源和增加数据库的压力。当时我们的解决方案是将这些数据添加到一个缓存中。我们使用的是redis把数据通过key-value的形式缓存到内存中,并且还提供了多种数据存储的类型:string、hash、list、set、sortedset、,还自身提供持久化功能,还可以吧数据备份到磁盘中,redis的save命令用于创建当前redis的数据库备份防止redis宕机的时候把数据丢失。总之就是会周期性的把数据写入磁盘或者把修改操作写入追加记录文件。对于redis内存受限的问题的话利用jedis做分片式集群。

还有的话单点登录系统。单点登录的话我之前实现的登录和注册时在同一个tomcat内部实现的,但是现在系统架构是每一个系统是由一个团队进行维护,每个系统都是单独部署运行一个单独tomcat,所以,不能将用户的登录信息保存到session中多个tomcat的session是不能共享的,就是session共享问题,所以需要一个单独的系统来维护用户的登录信息。我们是这样做的,用户去登录页面登录,发送含有用户信息的请求并且会携带cookie去服务端数据库查询是否有该用户,如果没有提示用户,如果有就把用户信息保存到redis中,并生成一个tooken保存到cookie。

在后台管理系统中采用了Maven多模块化的管理,采用了水平切分的方式,垂直于水平划分的区别,垂直:功能模块明确,层次不够清晰,代码重用性差。水平:层次清晰,代码重用性高,易于独立维护。分层开发,就能代码重用性高,层次清晰,易于独立维护。
①垂直划分
②水平划分
优缺点:
垂直:功能模块明确,层次不够清晰,代码重用性差。
水平:层次清晰,代码重用性高,独立维护。
接口提供的话就是采用restful风格,这是一种软件架构风格当然设计风格不是标准,就是提供了一组设计原则和约束条件通知机制采用activemq模式。我负责的话就是后台管理模块,实现商品管理和商品规格参数管理,对商品和商品规格进行CRUD增删改查操作。在实现前台调用后台的数据时为了实现系统间的调用就是用了httpclient技术来实现此功能,提供了调用时的接口。在使用前台数据与后台数据同步实现的时候使用的activemq插件消息队列机制。
其次 这种电商项目,肯定会问你高并发等等怎么解决数据并发量大的情况下,初中级的程序员肯定不会问你 秒杀系统所以说 弄清楚高并发数据是怎么解决和怎么处理即可:
系统前台是互联网上的用户访问的,会有大量用户来访问。
假定有1w个人打开你的网站来订商品,问你如何解决并发问题(可扩展到任何高并发网站要考虑的并发读写问题)
问题,1w个人来访问,商品没出去前要保证大家都能看到有商品,不可能一个人在看到商品的时候别人就不能看了。到底谁能抢到,那得看这个人的“运气”(网络快慢等)
其次考虑的问题,并发,1w个人同时点击购买,到底谁能成交?总共只有一张商品。

Update eb_sku t sett.stock = t.stock – 1 where t.sku_id = #{skuId} and t.stock > 0

Update eb_sku t set t.sale = t.sale +1 where t.sku_id = #{skuId}

首先我们容易想到和并发相关的几个方案 : 锁同步

同步更多指的是应用程序的层面,多个线程进来,只能一个一个的访问,java中指的是syncrinized关键字。锁也有2个层面,一个是java中谈到的对象锁,用于线程同步;另外一个层面是数据库的锁;如果是分布式的系统,显然只能利用数据库端的锁来实现。

在这里插入图片描述
假定我们采用了同步机制或者数据库物理锁机制,如何保证1w个人还能同时看到有商品,显然会牺牲性能,在高并发网站中是不可取的。使用hibernate后我们提出了另外一个概念:乐观锁(一定要用)、悲观锁(即传统的物理锁);采用乐观锁即可解决此问题。乐观锁意思是不锁定表的情况下,利用业务的控制来解决并发问题,这样即保证数据的并发可读性又保证保存数据的排他性,保证性能的同时解决了并发带来的脏数据问题。
hibernate中如何实现乐观锁:

前提:在现有表当中增加一个冗余字段,version版本号, long类型

原理:

1)只有当前版本号》=数据库表版本号,才能提交

2)提交成功后,版本号version ++

实现很简单:在ormapping增加一属性-lock="version"即可,以下是样例片段optimistic

<class name="com.insigma.stock.ABC" optimistic-lock="version" table="T_Stock" schema="STOCK">

更新的时候给版本号字段加上 1,然后 UPDATE 会返回一个更新结果的行数,通过这个行数去判断。

在这里插入图片描述
UPDATE 必须这样写:

Sale = 100

UPDATE EB_SKU u

SET u.SALES = #SALES#,

   u.version = u.version + 1

WHERE u.SKU_ID = #SKUID#

AND u.version = #version#

Update user t set t.address = #{address} where t.user_id = #{userId}

如果更新执行返回的数量是 0 表示产生并发修改了,需要重新获得最新的数据后再进行更新操作。

Hibernate、JPA 等 ORM 框架或者实现,是使用版本号,再判断 UPDATE 后返回的数值,如果这个值小于 1 时则抛出乐观锁并发修改异常。

解决大量用户访问量问题方案是集群部署,防止宕机,负载均衡

1.我们采用4台portal服务器来集群,使用2台nginx代理服务器,

1)反向代理,把4台portal的服务(host)集中起来,访问动态链接代理地址(代理IP:192.168.1.100)时候会把请求转发到4台portal上,如果访问静态页面直接访问nginx上的资源文件就可以了,静态html中有ajax的请求由nginx的反向代理功能来转发。

2)部署静态资源(html和图片)

2.Rsync用作资源同步

当console上传的图片,由于rsync的部署,会指定一个具体的同步目录(上传图片的目录),一旦发现目录中有文件就立刻同步到nginx上

3.Redis负责管理session和缓存搜索的数据

管理session的原因:用于多台服务器之间需要有相同的session,同享策略耗费资源,所以采用redis来存储session。缓存频繁被搜索的数据。

文件传输的时候还要注意,对上传的文件做校验;
数据库设计是一个软件设计的根基,数据库怎么设计直接影响到一个程序的实现、性能、和维护
获取利润,时间,等等;
其次就是 命名规范的问题,要么就根据接口文档规范命名,如果没有就事先沟通好;

例如 供应商、商品档案、客户信息、等等 是怎么实现的?
像这三个 一般来说都有分类 分级别 类别 大 中 小 等等 然后 等等 商品 供应商信息 姓名 商品数据规格等等;

考虑到时间问题,(二)会马上更! 感谢关注!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值