1. 学习计划
1、订单系统实现
2、订单生成
3、Mycat数据库分片
2. 订单系统
2.1. 功能分析
1、在购物车页面点击“去结算”按钮,跳转到订单确认页面
a) 必须要求用户登录
b) 使用拦截器实现。
c) 如果用户未登录跳转到登录页面。
d) 如果用户已经登录,放行。展示确认页面。
e) 判断cookie中是否有购物车数据
f) 如果有同步到服务端。
2、订单确认页面中选择收货地址,选择支付方式,确认商品列表。
a) 根据用户id查询收货地址列表
b) 展示支付方式列表。
c) 从购物车中取商品列表,从服务端取购物车列表。
3、订单确认页面点击“提交”,生成订单。
4、展示订单生成完成,或者跳转到支付页面。
2.2. 工程搭建
E3-order
|--E3-order-interface(jar)
|--E3-order-service(war)
E3-order-web(war)
2.3. 展示订单确认页面
2.3.1. 功能分析
1、根据id查询用户的收货地址列表(使用静态数据)
2、从购物车中取商品列表,展示到页面。调用购物车服务查询。
2.3.2. Dao层
直接从redis中取购车商品列表。
2.3.3. Service层
收货地址静态数据,没有server。
调用购物车的service查询购物车商品列表。
2.3.4. Controller
引用购物车服务
请求的url:/order/order-cart
参数:没有参数
返回值:逻辑视图
Controller
@Controller
public class OrderCartController { @Autowired
private CartService cartService; @RequestMapping("/order/order-cart")
public String showOrderCart(HttpServletRequest request) {
//取用户信息
TbUser user = (TbUser) request.getAttribute("user");
//取购物车商品列表
List<TbItem> cartList = cartService.getCartList(user.getId());
//把商品列表传递给jsp
request.setAttribute("cartList", cartList);
//返回逻辑视图
return "order-cart";
}
}
2.4. 登录拦截器
2.4.1. 功能分析
1、从cookie中取token
2、如果没有取到,没有登录,跳转到sso系统的登录页面。拦截
3、如果取到token。判断登录是否过期,需要调用sso系统的服务,根据token取用户信息
4、如果没有取到用户信息,登录已经过期,重新登录。跳转到登录页面。拦截
5、如果取到用户信息,用户已经是登录状态,把用户信息保存到request中。放行
6、判断cookie中是否有购物车信息,如果有合并购物车
2.4.2. 拦截器实现
/**
* 用户登录判断拦截器
* <p>Title: LoginInterceptor</p>
* <p>Description: </p>
* <p>Company: www.itcast.cn</p>
* @version 1.0
*/
public class LoginInterceptor implements HandlerInterceptor { @Value("${COOKIE_TOKEN_KEY}")
private String COOKIE_TOKEN_KEY;
@Value("${COOKIE_CART_KEY}")
private String COOKIE_CART_KEY;
@Value("${SSO_URL}")
private String SSO_URL;
@Autowired
private UserService userService;
@Autowired
private CartService cartService; @Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub } @Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub } @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1、从cookie中取token
String token = CookieUtils.getCookieValue(request, COOKIE_TOKEN_KEY);
// 2、如果没有取到,没有登录,跳转到sso系统的登录页面。拦截
if (StringUtils.isBlank(token)) {
//跳转到登录页面
response.sendRedirect(SSO_URL + "/page/login?redirect=" + request.getRequestURL());
return false;
}
// 3、如果取到token。判断登录是否过期,需要调用sso系统的服务,根据token取用户信息
E3Result e3Result = userService.getUserByToken(token);
// 4、如果没有取到用户信息,登录已经过期,重新登录。跳转到登录页面。拦截
if (e3Result.getStatus() != 200) {
response.sendRedirect(SSO_URL + "/page/login?redirect=" + request.getRequestURL());
return false;
}
// 5、如果取到用户信息,用户已经是登录状态,把用户信息保存到request中。放行
TbUser user = (TbUser) e3Result.getData();
request.setAttribute("user", user);
// 6、判断cookie中是否有购物车信息,如果有合并购物车
String json = CookieUtils.getCookieValue(request, COOKIE_CART_KEY, true);
if (StringUtils.isNotBlank(json)) {
cartService.mergeCart(user.getId(), JsonUtils.jsonToList(json, TbItem.class));
//删除cookie中的购物车数据
CookieUtils.setCookie(request, response, COOKIE_CART_KEY, "");
}
//放行
return true;
} }
2.4.3. Springmvc配置
<!-- 拦截器配置 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.e3mall.order.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
2.4.4. 实现sso系统的回调
2.5. 提交订单
2.5.1. 功能分析
1、在订单确认页面点击“提交订单”按钮生成订单。
2、请求的url:/order/create
3、参数:提交的是表单的数据。保存的数据:订单、订单明细、配送地址。
a) 向tb_order中插入记录。
- 订单号需要手动生成。
要求订单号不能重复。
订单号可读性号。
可以使用redis的incr命令生成订单号。订单号需要一个初始值。
- Payment:表单数据
- payment_type:表单数据
- user_id:用户信息
- buyer_nick:用户名
- 其他字段null
b) 向tb_order_item订单明细表插入数据。
- Id:使用incr生成
- order_id:生成的订单号
- 其他的都是表单中的数据。
c) tb_order_shipping,订单配送信息
- order_id:生成的订单号
- 其他字段都是表单中的数据。
d) 使用pojo接收表单的数据。
可以扩展TbOrder,在子类中添加两个属性一个是商品明细列表,一个是配送信息。
把pojo放到e3-order-interface工程中。
public class OrderInfo extends TbOrder implements Serializable{
private List<TbOrderItem> orderItems;
private TbOrderShipping orderShipping;
public List<TbOrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(List<TbOrderItem> orderItems) {
this.orderItems = orderItems;
}
public TbOrderShipping getOrderShipping() {
return orderShipping;
}
public void setOrderShipping(TbOrderShipping orderShipping) {
this.orderShipping = orderShipping;
} }
业务逻辑:
1、接收表单的数据
2、生成订单id
3、向订单表插入数据。
4、向订单明细表插入数据
5、向订单物流表插入数据。
6、返回e3Result。
返回值:e3Result
2.5.2. Dao层
可以使用逆向工程。
2.5.3. Service层
参数:OrderInfo
返回值:e3Result
@Service
public class OrderServiceImpl implements OrderService { @Autowired
private TbOrderMapper orderMapper;
@Autowired
private TbOrderItemMapper orderItemMapper;
@Autowired
private TbOrderShippingMapper orderShippingMapper;
@Autowired
private JedisClient jedisClient; @Value("${ORDER_GEN_KEY}")
private String ORDER_GEN_KEY;
@Value("${ORDER_ID_BEGIN}")
private String ORDER_ID_BEGIN;
@Value("${ORDER_ITEM_ID_GEN_KEY}")
private String ORDER_ITEM_ID_GEN_KEY; @Override
public e3Result createOrder(OrderInfo orderInfo) {
// 1、接收表单的数据
// 2、生成订单id
if (!jedisClient.exists(ORDER_GEN_KEY)) {
//设置初始值
jedisClient.set(ORDER_GEN_KEY, ORDER_ID_BEGIN);
}
String orderId = jedisClient.incr(ORDER_GEN_KEY).toString();
orderInfo.setOrderId(orderId);
orderInfo.setPostFee("0");
//1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭
orderInfo.setStatus(1);
Date date = new Date();
orderInfo.setCreateTime(date);
orderInfo.setUpdateTime(date);
// 3、向订单表插入数据。
orderMapper.insert(orderInfo);
// 4、向订单明细表插入数据
List<TbOrderItem> orderItems = orderInfo.getOrderItems();
for (TbOrderItem tbOrderItem : orderItems) {
//生成明细id
Long orderItemId = jedisClient.incr(ORDER_ITEM_ID_GEN_KEY);
tbOrderItem.setId(orderItemId.toString());
tbOrderItem.setOrderId(orderId);
//插入数据
orderItemMapper.insert(tbOrderItem);
}
// 5、向订单物流表插入数据。
TbOrderShipping orderShipping = orderInfo.getOrderShipping();
orderShipping.setOrderId(orderId);
orderShipping.setCreated(date);
orderShipping.setUpdated(date);
orderShippingMapper.insert(orderShipping);
// 6、返回e3Result。
return e3Result.ok(orderId);
} }
2.5.4. Controller
请求的url:/order/create
参数:使用OrderInfo接收
返回值:逻辑视图。
业务逻辑:
1、接收表单提交的数据OrderInfo。
2、补全用户信息。
3、调用Service创建订单。
4、返回逻辑视图展示成功页面
a) 需要Service返回订单号
b) 当前日期加三天。
在拦截器中添加用户处理逻辑:
@RequestMapping(value="/order/create", method=RequestMethod.POST)
public String createOrder(OrderInfo orderInfo, HttpServletRequest request) {
// 1、接收表单提交的数据OrderInfo。
// 2、补全用户信息。
TbUser user = (TbUser) request.getAttribute("user");
orderInfo.setUserId(user.getId());
orderInfo.setBuyerNick(user.getUsername());
// 3、调用Service创建订单。
e3Result result = orderService.createOrder(orderInfo);
//取订单号
String orderId = result.getData().toString();
// a)需要Service返回订单号
request.setAttribute("orderId", orderId);
request.setAttribute("payment", orderInfo.getPayment());
// b)当前日期加三天。
DateTime dateTime = new DateTime();
dateTime = dateTime.plusDays(3);
request.setAttribute("date", dateTime.toString("yyyy-MM-dd"));
// 4、返回逻辑视图展示成功页面
return "success";
}
3. Mycat数据库分片
1 海量数据的存储问题
如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB。对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求。这个时候NoSQL的出现暂时解决了这一危机。它通过降低数据的安全性,减少对事务的支持,减少对复杂查询的支持,来获取性能上的提升。
但是,在有些场合NoSQL一些折衷是无法满足使用场景的,就比如有些使用场景是绝对要有事务与安全指标的。这个时候NoSQL肯定是无法满足的,所以还是需要使用关系性数据库。如果使用关系型数据库解决海量存储的问题呢?此时就需要做数据库集群,为了提高查询性能将一个数据库的数据分散到不同的数据库中存储。
1.1 什么是数据库分片
简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。
数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式。
(1)一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直(纵向)切分
(2)另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。
1.2 如何实现数据库分片
当数据库分片后,数据由一个数据库分散到多个数据库中。此时系统要查询时需要切换不同的数据库进行查询,那么系统如何知道要查询的数据在哪个数据库中?当添加一条记录时要向哪个数据库中插入呢?这些问题处理起来都是非常的麻烦。
这种情况下可以使用一个数据库中间件mycat来解决相关的问题。接下来了解一下什么是mycat。
2 Mycat介绍
2.1 什么是Mycat?
Mycat 背后是阿里曾经开源的知名产品——Cobar。Cobar 的核心功能和优势是 MySQL 数据库分片,此产品曾经广为流传,据说最早的发起者对 Mysql 很精通,后来从阿里跳槽了,阿里随后开源的 Cobar,并维持到 2013 年年初,然后,就没有然后了。
Cobar 的思路和实现路径的确不错。基于 Java 开发的,实现了 MySQL 公开的二进制传输协议,巧妙地将自己伪装成一个 MySQL Server,目前市面上绝大多数 MySQL 客户端工具和应用都能兼容。比自己实现一个新的数据库协议要明智的多,因为生态环境在哪里摆着。
Mycat 是基于 cobar 演变而来,对 cobar 的代码进行了彻底的重构,使用 NIO 重构了网络模块,并且优化了 Buffer 内核,增强了聚合,Join 等基本特性,同时兼容绝大多数数据库成为通用的数据库中间件。
简单的说,MyCAT就是:
·一个新颖的数据库中间件产品支持mysql集群,或者mariadb cluster,提供高可用性数据分片集群。你可以像使用mysql一样使用mycat。对于开发人员来说根本感觉不到mycat的存在。
2.2 Mycat支持的数据库
2.3 Mycat的分片策略
2.4 概念说明
2.4.1 逻辑库(schema) :
前面一节讲了数据库中间件,通常对实际应用来说,并不需要知道中间件的存在,业务开发人员只需要知道数据库的概念,所以数据库中间件可以被看做是一个或多个数据库集群构成的逻辑库。
2.4.2 逻辑表(table):
既然有逻辑库,那么就会有逻辑表,分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表,可以是数据切分后,分布在一个或多个分片库中,也可以不做数据切分,不分片,只有一个表构成。
分片表:是指那些原有的很大数据的表,需要切分到多个数据库的表,这样,每个分片都有一部分数据,所有分片构成了完整的数据。 总而言之就是需要进行分片的表。
非分片表:一个数据库中并不是所有的表都很大,某些表是可以不用进行切分的,非分片是相对分片表来说的,就是那些不需要进行数据切分的表。
2.4.3 分片节点(dataNode)
数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点(dataNode)。
2.4.4 节点主机(dataHost)
数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost),为了规避单节点主机并发数限制,尽量将读写压力高的分片节点(dataNode)均衡的放在不同的节点主机(dataHost)。
2.4.5 分片规则(rule)
前面讲了数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。
3 Mycat的下载及安装
3.1 安装环境
1、jdk:要求jdk必须是1.7及以上版本
2、Mysql:推荐mysql是5.5以上版本
3、Mycat:
Mycat的官方网站:
下载地址:
https://github.com/MyCATApache/Mycat-download
3.2 安装步骤
Mycat有windows、linux多种版本。本教程为linux安装步骤,windows基本相同。
第一步:下载Mycat-server-xxxx-linux.tar.gz
第二步:将压缩包解压缩。建议将mycat放到/usr/local/mycat目录下。
第三步:进入mycat目录,启动mycat
./mycat start
停止:
./mycat stop
mycat 支持的命令{ console | start | stop | restart | status | dump }
Mycat的默认端口号为:8066
4 Mycat的分片
4.1 需求
把商品表分片存储到三个数据节点上。
4.2 安装环境分析
两台mysql数据库服务器:
Host1:192.168.25.134
Host2:192.168.25.166
host1环境
操作系统版本 : centos6.4
数据库版本 : mysql-5.6
mycat版本 :1.4 release
数据库名 : db1、db3
mysql节点2环境
操作系统版本 : centos6.4
数据库版本 : mysql-5.6
mycat版本 :1.4 release
数据库名 : db2
MyCat安装到节点1上(需要安装jdk)
4.3 配置schema.xml
4.3.1 Schema.xml介绍
Schema.xml作为MyCat中重要的配置文件之一,管理着MyCat的逻辑库、表、分片规则、DataNode以及DataSource。弄懂这些配置,是正确使用MyCat的前提。这里就一层层对该文件进行解析。
schema 标签用于定义MyCat实例中的逻辑库
Table 标签定义了MyCat中的逻辑表
dataNode 标签定义了MyCat中的数据节点,也就是我们通常说所的数据分片。
dataHost标签在mycat逻辑库中也是作为最底层的标签存在,直接定义了具体的数据库实例、读写分离配置和心跳语句。
注意:若是LINUX版本的MYSQL,则需要设置为Mysql大小写不敏感,否则可能会发生表找不到的问题。 在MySQL的配置文件中/etc/my.cnf [mysqld] 中增加一行 lower_case_table_names=1 |
4.3.2 Schema.xml配置
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/"> <schema name="e3mall" checkSQLschema="false" sqlMaxLimit="100">
<!-- auto sharding by id (long) -->
<table name="tb_item" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
</schema>
<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataNode name="dn2" dataHost="localhost2" database="db2" />
<dataNode name="dn3" dataHost="localhost1" database="db3" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="192.168.25.134:3306" user="root"
password="root">
<!-- can have multi read hosts --> </writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="192.168.25.166:3306" user="root"
password="root">
<!-- can have multi read hosts --> </writeHost>
</dataHost>
</mycat:schema>
4.4 配置server.xml
4.4.1 Server.xml介绍
server.xml几乎保存了所有mycat需要的系统配置信息。最常用的是在此配置用户名、密码及权限。
4.4.2 Server.xml配置
<user name="test">
<property name="password">test</property>
<property name="schemas">e3mall</property>
<property name="readOnly">false</property>
</user>
4.5 配置rule.xml
rule.xml里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。这个文件里面主要有tableRule和function这两个标签。在具体使用过程中可以按照需求添加tableRule
和function。
此配置文件可以不用修改,使用默认即可。
4.6 测试分片
4.6.1 创建表
配置完毕后,重新启动mycat。使用mysql客户端连接mycat,创建表。
-- ----------------------------
-- Table structure for tb_item
-- ----------------------------
DROP TABLE IF EXISTS `tb_item`;
CREATE TABLE `tb_item` (
`id` bigint(20) NOT NULL COMMENT '商品id,同时也是商品编号',
`title` varchar(100) NOT NULL COMMENT '商品标题',
`sell_point` varchar(500) DEFAULT NULL COMMENT '商品卖点',
`price` bigint(20) NOT NULL COMMENT '商品价格,单位为:分',
`num` int(10) NOT NULL COMMENT '库存数量',
`barcode` varchar(30) DEFAULT NULL COMMENT '商品条形码',
`image` varchar(500) DEFAULT NULL COMMENT '商品图片',
`cid` bigint(10) NOT NULL COMMENT '所属类目,叶子类目',
`status` tinyint(4) NOT NULL DEFAULT '' COMMENT '商品状态,1-正常,2-下架,3-删除',
`created` datetime NOT NULL COMMENT '创建时间',
`updated` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `cid` (`cid`),
KEY `status` (`status`),
KEY `updated` (`updated`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';
4.6.2 插入数据
将此文件中的数据插入到数据库:
4.6.3 分片测试
由于配置的分片规则为“auto-sharding-long”,所以mycat会根据此规则自动分片。
每个datanode中保存一定数量的数据。根据id进行分片
经测试id范围为:
Datanode1:1~5000000
Datanode2:5000000~10000000
Datanode3:10000001~15000000
当15000000以上的id插入时报错:
[Err] 1064 - can't find any valid datanode :TB_ITEM -> ID -> 15000001
此时需要添加节点了。
JAVAEE——宜立方商城13:订单系统实现、订单生成、Mycat数据库分片的更多相关文章
-
JAVAEE——宜立方商城13:Mycat数据库分片、主从复制、读写分离、100%Linux中成功安装Mysql的方法
1 海量数据的存储问题 如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求.这个时候NoSQL ...
-
JAVAEE——宜立方商城01:电商行业的背景、商城系统架构、后台工程搭建、SSM框架整合
1. 学习计划 第一天: 1.电商行业的背景. 2.宜立方商城的系统架构 a) 功能介绍 b) 架构讲解 3.工程搭建-后台工程 a) 使用maven搭建工程 b) 使用maven的tomcat插件启 ...
-
JAVAEE——宜立方商城02:服务中间件dubbo、工程改造为基于soa架构、商品列表实现
1. 学习计划 第二天:商品列表功能实现 1.服务中间件dubbo 2.工程改造为基于soa架构 3.商品列表查询功能实现. 2. 将工程改造为SOA架构 2.1. 分析 由于宜立方商城是基于soa的 ...
-
JAVAEE——宜立方商城05:前台系统搭建、首页展示、Cms系统的实现
1. 学习计划 1.前台系统搭建 2.商城首页展示 3.Cms系统的实现 a) 内容分类管理 b) 内容管理 4.前台内容动态展示 2. 商城首页展示 系统架构: 页面位置: 2.1. 工程搭建 可以 ...
-
JAVAEE——宜立方商城12:购物车实现、订单确认页面展示
1. 学习计划 第十二天: 1.购物车实现 2.订单确认页面展示 2. 购物车的实现 2.1. 功能分析 1.购物车是一个独立的表现层工程. 2.添加购物车不要求登录.可以指定购买商品的数量. 3.展 ...
-
JAVAEE——宜立方商城14:项目部署规划、Tomcat热部署、反向代理的配置
1. 学习计划 1.系统部署 2. 项目部署 2.1. 项目架构讲解 2.2. 网络拓扑图 2.3. 系统部署 2.3.1. 部署分析 e3-manager e3-manager-web e3-por ...
-
JAVAEE——宜立方商城11:sso登录注册功能实现、通过token获得用户信息、Ajax跨域请求(jsonp)
1. 学习计划 第十一天: 1.sso注册功能实现 2.sso登录功能实现 3.通过token获得用户信息 4.Ajax跨域请求(jsonp) 2. Sso系统工程搭建 需要创建一个sso服务工程,可 ...
-
JAVAEE——宜立方商城10:使用freemarker实现网页静态化、ActiveMq同步生成静态网页、Sso单点登录系统分析
1. 学习计划 1.使用freemarker实现网页静态化 2.ActiveMq同步生成静态网页 2. 网页静态化 可以使用Freemarker实现网页静态化. 2.1. 什么是freemarker ...
-
JAVAEE——宜立方商城08:Zookeeper+SolrCloud集群搭建、搜索功能切换到集群版、Activemq消息队列搭建与使用
1. 学习计划 1.solr集群搭建 2.使用solrj管理solr集群 3.把搜索功能切换到集群版 4.添加商品同步索引库. a) Activemq b) 发送消息 c) 接收消息 2. 什么是So ...
随机推荐
-
MySQL数据库命名及设计规范
1.设计原则 1) 标准化和规范化 数据的标准化有助于消除数据库中的数据冗余.标准化有好几种形式,但 Third Normal Form(3NF)通常被认为在性能.扩展性和数据完整性方面达到了最好平衡 ...
-
【转】linux network namespace 学习
原文地址:https://segmentfault.com/a/1190000004059167 介绍 在专业的网络世界中,经常使用到Virtual Routing and Forwarding(VR ...
-
[Codeforces667A]Pouring Rain(数学,几何)
题目链接:http://codeforces.com/contest/667/problem/A 题意:一个杯子里有水,一个人在喝并且同时在往里倒.问这个人能不能喝完,多久能喝完. 把相关变量都量化成 ...
-
linux有用网址
正则表达式在线测试 http://tool.oschina.net/regex
-
<;modules runAllManagedModulesForAllRequests=";true"; />;(转1)
最近在使用 MVC 开发的时候,遇到一个对我来说“奇怪的问题”,就是使用 BundleTable 进行 CSS.JS 文件绑定,然后使用 Styles.Render.Scripts.Render 进行 ...
-
重大变革即将来临 5G CPE会替代光纤入户吗?
导读 从国内的新闻报道上我们可以看到,从2018年下半年开始各大重要活动.春晚直播等,都宣布已经使用5G网络.既然支持5G网络的终端都还没有正式上市,那么5G网络是如何使用的呢?答案是5G CPE设备 ...
-
c++ primer plus 第二章 \n与endl在输出上的区别
在书上看到如下一段话: 一个差别是,endl确保程序继续运行前刷新输出(将其立即显示在屏幕上):而使用"\n"不能提供这样的保证,这意味着在有些系统中,有时可能在您 ...
-
第一章 mysql的体系结构与存储引擎
数据库从逻辑上可以分为两部分,一部分负责存储即文件系统,这部分有个更时髦的名字叫存储引擎,存储引擎负责如何把数据以及索引相关的内容以合适的形式组织并存储到磁盘上.另一部分为server部分,负责和用户 ...
-
go语言入门(Hello World)
package main import "fmt" func main(){ fmt.Println("Hello world") }
-
Java学习笔记之——if条件语句和三目运算符
一.if条件语句 语法: if(条件){ 执行语句1: }else{ 执行语句2: } 二.三目运算符 ? 条件运算符 语法: 表达式?结果1:结果2: 如果表达式结果为true,则结果为结果1 ...