秒杀基本功能开发(不考虑高并发情况)

2024-06-02 23:44

本文主要是介绍秒杀基本功能开发(不考虑高并发情况),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 1.显示秒杀状态
        • 1.controller
          • 修改GoodsController.java的toDetail方法,响应秒杀状态和秒杀剩余时间
        • 2.前端
          • 1.goodsDetail.html 图片下面添加一行秒杀开始时间
          • 2.goodsDetail.html 添加计时器js代码
        • 3.测试
          • 1.秒杀进行中
          • 2.修改db的秒杀开始时间为明天
          • 3.出现秒杀倒计时
          • 4.修改db的秒杀结束时间比目前要早
          • 5.秒杀已结束
    • 2.秒杀按钮
        • 1.前端
          • 1.goodsDetail.html 添加抢购按钮
          • 2.goodsDetail.html 根据秒杀状态,控制按钮状态
        • 2.测试
          • 1.秒杀已结束,按钮不可用
          • 2.秒杀进行中,按钮可用
          • 3.秒杀未开始,按钮不可用
    • 3.秒杀基本功能(不考虑高并发)
        • 1.数据库表设计
          • 1.普通订单表
          • 2.秒杀订单表
        • 2.MyBatis-Plus生成基础代码(以t_order表为例)
          • 1.首先 ctrl + shift + c 复制基础包名(一定要是带点的)
          • 2.右键表名选择 MybatisX-Generator
          • 3.选择模块和基础包以及实体类名字
          • 4.进行配置
          • 5.点击生成,检查代码
            • 1.整个目录概览
            • 2.把实体类移动到pojo并检查
            • 3.检查 OrderMapper.java 发现没有加@Mapper注解
            • 4.查看启动类有@MapperScan所以不用加@Mapper了
            • 5.检查OrderMapper.xml
            • 6.检查application.yml是否自动扫描了Mapper.xml
            • 7.检查OrderService.java
            • 8.检查OrderServiceImpl.java
          • 6.使用MyBatis-Plus生成基础代码的小结
          • 7.以同样的方式生成t_seckill_order
        • 3.Service层
          • 1.OrderService.java 新增秒杀方法,返回订单
          • 2.OrderServiceImpl.java
          • 3.SeckillOrderService.java 根据普通订单和商品id插入秒杀订单
          • 4.SeckillOrderServiceImpl.java
        • 4.Controller层
          • 1.SeckillController.java 完成基础版本的秒杀,简单考虑库存和复购问题
          • 2.SeckillOrderService.java 新增方法,根据用户id和商品id查找记录
          • 3.SeckillOrderServiceImpl.java
          • 4.SeckillOrderMapper.java
          • 5.SeckillOrderMapper.xml
        • 5.前端
          • 1.goodsDetail.html 修改点击抢购按钮的请求(区分多环境)
          • 2.引入orderDetail.html
          • 3.引入secKillFail.html
        • 6.测试
          • 1.正常秒杀
            • 1.初始秒杀商品表(库存为10)
            • 2.秒杀1号商品
            • 3.秒杀成功
            • 4.秒杀商品库存减1
            • 5.普通订单新增一条记录
            • 6.秒杀订单新增一条记录
          • 2.当前用户再次购买
            • 成功跳转到限购页面
          • 3.模拟库存不足的情况
            • 1.将1号商品的库存修改为0
            • 2.切换一个浏览器再次秒杀
            • 3.成功跳转到库存不足的页面

1.显示秒杀状态

1.controller
修改GoodsController.java的toDetail方法,响应秒杀状态和秒杀剩余时间
    // 进入到商品详情页@RequestMapping("/toDetail/{goodsId}")public String toDetail(Model model, User user, @PathVariable Long goodsId) {// 判断是否有用户信息if (null == user) {return "login";}// 查询商品详情GoodsVo goodsVoByGoodsId = goodsService.findGoodsVoByGoodsId(goodsId);model.addAttribute("goods", goodsVoByGoodsId);// secKillStatus:秒杀状态 0:未开始 1:进行中 2:已结束// remainSeconds:秒杀剩余时间 >0:未开始 0:进行中 -1:已结束// 获取该商品的秒杀开始时间和结束时间long startAt = goodsVoByGoodsId.getStartDate().getTime();long endAt = goodsVoByGoodsId.getEndDate().getTime();long now = System.currentTimeMillis();// 根据当前时间与秒杀开始时间和结束时间的比较,判断秒杀状态int secKillStatus = 0;int remainSeconds = 0;if (now < startAt) {// 秒杀未开始secKillStatus = 0;remainSeconds = (int) ((startAt - now) / 1000);} else if (now > endAt) {// 秒杀已结束secKillStatus = 2;remainSeconds = -1;} else {// 秒杀进行中secKillStatus = 1;remainSeconds = 0;}// 将秒杀状态和剩余时间存入model中,返回到前端model.addAttribute("secKillStatus", secKillStatus);model.addAttribute("remainSeconds", remainSeconds);// 将用户信息存入model中,返回到前端model.addAttribute("user", user);return "goodsDetail";}
2.前端
1.goodsDetail.html 图片下面添加一行秒杀开始时间
            <tr><td>秒杀开始时间</td><td id="startTime" th:text="${#dates.format(goods.startDate,'yyyy-MM-dd HH:mm:ss')}"></td><td id="seckillTip"><input type="hidden" id="remainSeconds"th:value="${remainSeconds}"/><span th:if="${secKillStatus eq 0}">秒杀倒计时:<span id="countDown"th:text="${remainSeconds}"> </span></span><span th:if="${secKillStatus eq 1}">秒杀进行中</span><span th:if="${secKillStatus eq 2}">秒杀已结束</span></td></tr>
2.goodsDetail.html 添加计时器js代码
<script>$(function () {countDown();});function countDown() {var remainSeconds = $("#remainSeconds").val();var timeout;
//秒杀还未开始if (remainSeconds > 0) {timeout = setTimeout(function () {$("#countDown").text(remainSeconds - 1);$("#remainSeconds").val(remainSeconds - 1);countDown();}, 1000);} else if (remainSeconds == 0) {//秒杀进行中if (timeout) {//清空计时器clearTimeout(timeout);}$("#seckillTip").html("秒杀进行中");} else {$("#seckillTip").html("秒杀已结束");}}
</script>
3.测试
1.秒杀进行中

image-20240508143812867

2.修改db的秒杀开始时间为明天

image-20240508143929455

3.出现秒杀倒计时

image-20240508143950826

image-20240508144003627

4.修改db的秒杀结束时间比目前要早

image-20240508144158474

5.秒杀已结束

image-20240508144206709

2.秒杀按钮

1.前端
1.goodsDetail.html 添加抢购按钮
                <td><form id="secKillForm" method="post" action="/seckill/doSeckill"><input type="hidden" id="goodsId" name="goodsId" th:value="${goods.id}"><button class="btn btn-primary btn-block" type="submit" id="buyButton"> 抢 购</button></form></td>

image-20240508144706778

2.goodsDetail.html 根据秒杀状态,控制按钮状态

image-20240508145140688

2.测试
1.秒杀已结束,按钮不可用

image-20240508145400768

2.秒杀进行中,按钮可用

image-20240508145447048

3.秒杀未开始,按钮不可用

image-20240508145514987

3.秒杀基本功能(不考虑高并发)

1.数据库表设计
1.普通订单表
use seckill;
DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order`
(`id`               BIGINT(20)     NOT NULL AUTO_INCREMENT,`user_id`          BIGINT(20)     NOT NULL DEFAULT 0,`goods_id`         BIGINT(20)     NOT NULL DEFAULT 0,`delivery_addr_id` BIGINT(20)     NOT NULL DEFAULT 0,`goods_name`       VARCHAR(16)    NOT NULL DEFAULT '',`goods_count`      INT(11)        NOT NULL DEFAULT '0',`goods_price`      DECIMAL(10, 2) NOT NULL DEFAULT '0.00',`order_channel`    TINYINT(4)     NOT NULL DEFAULT '0' COMMENT '订单渠道 1pc,2Android,
3ios',`status`           TINYINT(4)     NOT NULL DEFAULT '0' COMMENT '订单状态:0 新建未支付 1 已支付
2 已发货 3 已收货 4 已退款 5 已完成',`create_date`      DATETIME                DEFAULT NULL,`pay_date`         DATETIME                DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE = INNODBAUTO_INCREMENT = 600DEFAULT CHARSET = utf8mb4;
2.秒杀订单表
use seckill;
DROP TABLE IF EXISTS `t_seckill_order`;
CREATE TABLE `t_seckill_order`
(`id`       BIGINT(20) NOT NULL AUTO_INCREMENT,`user_id`  BIGINT(20) NOT NULL DEFAULT 0,`order_id` BIGINT(20) NOT NULL DEFAULT 0,`goods_id` BIGINT(20) NOT NULL DEFAULT 0,PRIMARY KEY (`id`),UNIQUE KEY `seckill_uid_gid` (`user_id`, `goods_id`) USING BTREE COMMENT ' 用户 id,商品 id 的唯一索引,解决同一个用户多次抢购'
) ENGINE = INNODBAUTO_INCREMENT = 300DEFAULT CHARSET = utf8mb4;
2.MyBatis-Plus生成基础代码(以t_order表为例)
1.首先 ctrl + shift + c 复制基础包名(一定要是带点的)

image-20240508155502412

2.右键表名选择 MybatisX-Generator

image-20240508154408364

3.选择模块和基础包以及实体类名字

image-20240508160422478

4.进行配置

image-20240508160551731

5.点击生成,检查代码
1.整个目录概览

image-20240508160625655

2.把实体类移动到pojo并检查

image-20240508160745738

3.检查 OrderMapper.java 发现没有加@Mapper注解

image-20240508160846981

4.查看启动类有@MapperScan所以不用加@Mapper了

image-20240508160923942

5.检查OrderMapper.xml

image-20240508161252522

6.检查application.yml是否自动扫描了Mapper.xml

image-20240508161352765

7.检查OrderService.java

image-20240508161437807

8.检查OrderServiceImpl.java

image-20240508161524301

6.使用MyBatis-Plus生成基础代码的小结
  • 启动类配置MapperScan注解,扫描Mapper接口
  • application.yml配置扫描Mapper.xml
  • 复制基础包名,要带点的
  • 将Mapper.xml生成的最下面的删除即可
7.以同样的方式生成t_seckill_order
3.Service层
1.OrderService.java 新增秒杀方法,返回订单
package com.sxs.seckill.service;import com.sxs.seckill.pojo.Order;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.vo.GoodsVo;/**
* @author 8615941515990
* @description 针对表【t_order】的数据库操作Service
* @createDate 2024-05-08 16:05:29
*/
public interface OrderService extends IService<Order> {/*** 方法:秒杀* @param user* @param goodsVo* @return*/Order seckill(User user, GoodsVo goodsVo);
}
2.OrderServiceImpl.java
package com.sxs.seckill.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxs.seckill.mapper.SeckillGoodsMapper;
import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.SeckillGoods;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.service.OrderService;
import com.sxs.seckill.mapper.OrderMapper;
import com.sxs.seckill.service.SeckillOrderService;
import com.sxs.seckill.vo.GoodsVo;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @author 8615941515990* @description 针对表【t_order】的数据库操作Service实现* @createDate 2024-05-08 16:05:29*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>implements OrderService {@Resourceprivate SeckillGoodsMapper seckillGoodsMapper;@Resourceprivate SeckillOrderService seckillOrderService;@Overridepublic Order seckill(User user, GoodsVo goodsVo) {// 使用QueryWapper查询秒杀商品SeckillGoods seckillGoods = seckillGoodsMapper.selectOne(new QueryWrapper<SeckillGoods>().eq("goods_id", goodsVo.getId()));// 将库存减一seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);// 更新秒杀商品库存seckillGoodsMapper.updateById(seckillGoods);// 创建订单Order order = new Order();order.setUserId(user.getId());order.setGoodsId(goodsVo.getId());order.setDeliveryAddrId(0L);order.setGoodsName(goodsVo.getGoodsName());order.setGoodsCount(1);order.setGoodsPrice(goodsVo.getSeckillPrice());order.setOrderChannel(1);order.setStatus(0);order.setCreateDate(null);order.setPayDate(null);// 插入订单baseMapper.insert(order);// 生成秒杀商品订单seckillOrderService.insertSeckillOrder(order, goodsVo.getId());// 返回订单return order;}
}
3.SeckillOrderService.java 根据普通订单和商品id插入秒杀订单
package com.sxs.seckill.service;import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.SeckillOrder;
import com.baomidou.mybatisplus.extension.service.IService;/**
* @author 8615941515990
* @description 针对表【t_seckill_order】的数据库操作Service
* @createDate 2024-05-08 16:20:14
*/
public interface SeckillOrderService extends IService<SeckillOrder> {/*** 根据普通订单和商品id插入秒杀订单*/void insertSeckillOrder(Order order, Long goodsId);
}
4.SeckillOrderServiceImpl.java
package com.sxs.seckill.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.SeckillOrder;
import com.sxs.seckill.service.SeckillOrderService;
import com.sxs.seckill.mapper.SeckillOrderMapper;
import org.springframework.stereotype.Service;/**
* @author 8615941515990
* @description 针对表【t_seckill_order】的数据库操作Service实现
* @createDate 2024-05-08 16:20:14
*/
@Service
public class SeckillOrderServiceImpl extends ServiceImpl<SeckillOrderMapper, SeckillOrder>implements SeckillOrderService{@Overridepublic void insertSeckillOrder(Order order, Long goodsId) {// 根据普通订单插入秒杀订单SeckillOrder seckillOrder = new SeckillOrder();seckillOrder.setUserId(order.getUserId());seckillOrder.setOrderId(order.getId());seckillOrder.setGoodsId(goodsId);baseMapper.insert(seckillOrder);}
}
4.Controller层
1.SeckillController.java 完成基础版本的秒杀,简单考虑库存和复购问题
package com.sxs.seckill.controller;import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.service.GoodsService;
import com.sxs.seckill.service.OrderService;
import com.sxs.seckill.service.SeckillOrderService;
import com.sxs.seckill.vo.GoodsVo;
import com.sxs.seckill.vo.RespBeanEnum;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import javax.annotation.Resource;/*** Description:** @Author sun* @Create 2024/5/8 18:49* @Version 1.0*/
@Controller
@RequestMapping("/seckill")
public class SeckillController {@Resourceprivate GoodsService goodsService;@Resourceprivate OrderService orderService;@Resourceprivate SeckillOrderService seckillOrderService;@RequestMapping("/doSeckill")public String doSeckill(Model model, User user, Long goodsId) {// 判断用户是否登录if (user == null) {return "login";}// 将用户信息传递到页面model.addAttribute("user", user);// 根据goodsId获取GoodsVoGoodsVo goodsVoByGoodsId = goodsService.findGoodsVoByGoodsId(goodsId);// 判断是否有库存if (goodsVoByGoodsId.getStockCount() < 1) {// 没有库存,返回秒杀失败页面model.addAttribute("errmsg", RespBeanEnum.EMPTY_STOCK.getMessage());return "secKillFail";}// 通过秒杀订单表判断是否复购if (seckillOrderService.findSeckillOrderByUserIdAndGoodsId(user.getId(), goodsId) != null) {// 重复购买,返回秒杀失败页面model.addAttribute("errmsg", RespBeanEnum.REPEATE_ERROR.getMessage());return "secKillFail";}// 秒杀Order seckill = orderService.seckill(user, goodsVoByGoodsId);// 判断秒杀是否成功if (seckill == null) {// 秒杀失败,返回秒杀失败页面model.addAttribute("errmsg", RespBeanEnum.ERROR.getMessage());return "secKillFail";}// 秒杀成功,返回订单详情页面model.addAttribute("order", seckill);model.addAttribute("goods", goodsVoByGoodsId);// 返回订单详情页面return "orderDetail";}
}
2.SeckillOrderService.java 新增方法,根据用户id和商品id查找记录
    /*** 根据用户id和商品id查询秒杀订单*/SeckillOrder findSeckillOrderByUserIdAndGoodsId(Long userId, Long goodsId);
3.SeckillOrderServiceImpl.java
    @Overridepublic SeckillOrder findSeckillOrderByUserIdAndGoodsId(Long userId, Long goodsId) {// 根据用户id和商品id查询秒杀订单return baseMapper.findSeckillOrderByUserIdAndGoodsId(userId, goodsId);}
4.SeckillOrderMapper.java
package com.sxs.seckill.mapper;import com.sxs.seckill.pojo.SeckillOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/**
* @author 8615941515990
* @description 针对表【t_seckill_order】的数据库操作Mapper
* @createDate 2024-05-08 16:20:14
* @Entity com.sxs.seckill.pojo.SeckillOrder
*/
public interface SeckillOrderMapper extends BaseMapper<SeckillOrder> {/*** 根据用户id和商品id查询秒杀订单*/SeckillOrder findSeckillOrderByUserIdAndGoodsId(Long userId, Long goodsId);
}
5.SeckillOrderMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sxs.seckill.mapper.SeckillOrderMapper"><resultMap id="BaseResultMap" type="com.sxs.seckill.pojo.SeckillOrder"><id property="id" column="id" jdbcType="BIGINT"/><result property="userId" column="user_id" jdbcType="BIGINT"/><result property="orderId" column="order_id" jdbcType="BIGINT"/><result property="goodsId" column="goods_id" jdbcType="BIGINT"/></resultMap><select id="findSeckillOrderByUserIdAndGoodsId" resultType="com.sxs.seckill.pojo.SeckillOrder">SELECT*FROMt_seckill_orderWHEREuser_id = #{userId}ANDgoods_id = #{goodsId}</select></mapper>
5.前端
1.goodsDetail.html 修改点击抢购按钮的请求(区分多环境)

image-20240508204340828

2.引入orderDetail.html
<html lang="en"xmlns:th="http://www.thymeleaf.org">
<head><title>订单详情</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><!--jquery--><script type="text/javascript" th:src="@{/js/jquery.min.js}"></script><!-- bootstrap --><link rel="stylesheet" type="text/css" th:href="@{/bootstrap/css/bootstrap.min.css}"/><script type="text/javascript" th:src="@{/bootstrap/js/bootstrap.js}"></script><!-- layer --><script type="text/javascript" th:src="@{/layer/layer.js}"></script><!-- common.js --><script type="text/javascript" th:src="@{/js/common.js}"></script><style>* {margin: 0;padding: 0;font-family: "Open Sans", sans-serif;text-transform: uppercase;letter-spacing: 3px;font-size: 11px;}body {background: #c9302c;}.main-header {width: 100%;height: 100px;background: whitesmoke;display: block;}.navbar {display: inline-block;float: right;margin-right: 50px;margin-top: 30px;}.logo {display: inline-block;margin-top: 30px;margin-left: 30px;text-decoration: none;}.logo-lg {font-size: 20px;font-weight: lighter;color: #232324;}.logo-lg > b {font-size: 20px;font-weight: lighter;color: #232324;}.container {background: #FFFFFF;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;width: 750px;}</style>
</head>
<body>
<header id="site-header" class="main-header"><!-- Logo --><a class="logo" onclick="toList()"><span class="logo-lg"><b>商品抢购</b></span></a><nav class="navbar navbar-static-top"><!-- Sidebar toggle button--><a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></a><div class="navbar-custom-menu"><ul class="nav navbar-nav"><li class="dropdown user user-menu"><a href="#" class="dropdown-toggle" data-toggle="dropdown"><img class="user-image" src="/imgs/user.png" height="32" alt="User
Image"><span class="hidden-xs"></span></a><ul class="dropdown-menu"><!-- User image --><li class="user-header"><img class="img-circle" alt="User Image"><p>Hello ABC - Hello ABC<small>Hello ABC</small></p></li><!-- Menu Body --><li class="user-body"></li><li class="user-footer"><div class="pull-middle"><a onclick="toList()" class="btn btn-lg btn-default btn-block">退出系统</a></div></li></ul></li></ul></div></nav>
</header>
<div class="panel panel-default"><div class="panel-heading" style="background: #c9302c;color: white">秒杀订单详情</div><div class="container"><table class="table" id="order"><tr><td>名称</td><td id="goodName" colspan="3" th:text="${goods.goodsName}"></td></tr><tr><td>图片</td><td colspan="2"><img id="goodImg" width="200" th:src="@{${goods.goodsImg}}" height="200"/></td></tr><tr><td>订单价格</td><td colspan="2" id="goodPrice" th:text="${order.goodsPrice}"></td></tr><tr><td>下单时间</td><td id="createDate" colspan="2"th:text="${#dates.format(order.createDate,'yyyy-MM-dd HH:mm:ss')}"></td></tr><tr><td>订单状态</td><td id="status" ><span th:if="${order.status eq 0}">未支付</span><span th:if="${order.status eq 1}">代发货</span><span th:if="${order.status eq 2}">已发货</span><span th:if="${order.status eq 3}">已收货</span><span th:if="${order.status eq 4}">已退款</span><span th:if="${order.status eq 5}">已完成</span></td><td><button class="btn btn-primary btn-block" type="submit"id="payButton">立即支付</button></td></tr><tr><td>收货人</td><td colspan="2">XXX 13300000000</td></tr><tr><td>收货地址</td><td colspan="2">北京市幸福小区 6 单元 101 号</td></tr></table></div>
</div>
<script>
</script>
</body>
</html>
3.引入secKillFail.html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title><style>* {margin: 0;padding: 0;font-family: "Open Sans", sans-serif;text-transform: uppercase;letter-spacing: 3px;font-size: 11px;}</style>
</head>
<body>
<h1>秒杀失败 : </h1>
<p th:text="${errmsg}"></p>
</body>
</html>
6.测试
1.正常秒杀
1.初始秒杀商品表(库存为10)

image-20240508204704283

2.秒杀1号商品

image-20240508204758962

3.秒杀成功

image-20240508204812058

4.秒杀商品库存减1

image-20240508204939374

5.普通订单新增一条记录

image-20240508205006209

6.秒杀订单新增一条记录

image-20240508205031531

2.当前用户再次购买
成功跳转到限购页面

image-20240508205230614

3.模拟库存不足的情况
1.将1号商品的库存修改为0

image-20240508205330949

2.切换一个浏览器再次秒杀

image-20240508205543103

3.成功跳转到库存不足的页面

image-20240508205606440

这篇关于秒杀基本功能开发(不考虑高并发情况)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1025431

相关文章

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

WDF驱动开发-WDF总线枚举(一)

支持在总线驱动程序中进行 PnP 和电源管理 某些设备永久插入系统,而其他设备可以在系统运行时插入和拔出电源。 总线驱动 必须识别并报告连接到其总线的设备,并且他们必须发现并报告系统中设备的到达和离开情况。 总线驱动程序标识和报告的设备称为总线的 子设备。 标识和报告子设备的过程称为 总线枚举。 在总线枚举期间,总线驱动程序会为其子 设备创建设备对象 。  总线驱动程序本质上是同时处理总线枚

JavaWeb系列六: 动态WEB开发核心(Servlet) 上

韩老师学生 官网文档为什么会出现Servlet什么是ServletServlet在JavaWeb项目位置Servlet基本使用Servlet开发方式说明快速入门- 手动开发 servlet浏览器请求Servlet UML分析Servlet生命周期GET和POST请求分发处理通过继承HttpServlet开发ServletIDEA配置ServletServlet注意事项和细节 Servlet注

手把手教你入门vue+springboot开发(五)--docker部署

文章目录 前言一、前端打包二、后端打包三、docker运行总结 前言 前面我们重点介绍了vue+springboot前后端分离开发的过程,本篇我们结合docker容器来研究一下打包部署过程。 一、前端打包 在VSCode的命令行中输入npm run build可以打包前端代码,出现下图提示表示打包完成。 打包成功后会在前端工程目录生成dist目录,如下图所示: 把

Sapphire开发日志 (十) 关于页面

关于页面 任务介绍 关于页面用户对我组工作量的展示。 实现效果 代码解释 首先封装一个子组件用于展示用户头像和名称。 const UserGrid = ({src,name,size,link,}: {src: any;name: any;size?: any;link?: any;}) => (<Box sx={{ display: "flex", flexDirecti

ROS2从入门到精通4-4:局部控制插件开发案例(以PID算法为例)

目录 0 专栏介绍1 控制插件编写模板1.1 构造控制插件类1.2 注册并导出插件1.3 编译与使用插件 2 基于PID的路径跟踪原理3 控制插件开发案例(PID算法)常见问题 0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 🚀详情:《ROS2从入门到精通》 1 控制插

JavaWeb 学习笔记 spring+jdbc整合开发初步

JdbcTemplate类是Spring的核心类之一,可以在org.springframework.jdbc.core中找到它。JdbcTemplate类在内部已经处理数据库的建立和释放,可以避免一些常见的错误。JdbcTemplate类可直接通过数据源的应用实例化,然后在服务中使用,也可在xml配置中作为JavaBean应用给服务使用直接上一个实例步骤1.xml配置 <?xml version

Android开发的一些不错的学习资料

一个有趣的学习网站:http://hukai.me/android-training-course-in-chinese/index.html 这个是一些基础的教程,看看很好的,赏心悦目。 工具下载网站:http://www.androiddevtools.cn/ 这里的东西很不错,AndroidStudio,UIStyle的压缩工具,开发必备。

大型网站架构演化(四)——使用应用服务器集群改善网站的并发能力

使用集群是网站解决高并发、海量数据问题的常用手段。当一台服务器的处理能力、存储空间不足时,不要企图去更换更强大的服务器,对大型服务器而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求。这种情况下,更恰当的做法是增加一台服务器分担原有服务器的访问及存储压力。 对网站架构而言,只要能通过增加一台服务器的方式改善负载压力,就可以以同样的方式持续增加服务器不断改善系统性能,从而实现系统