亿级高并发电商项目-- 实战篇 --万达商城项目 八(安装FastDFS、安装Nginx、文件服务模块、文件上传功能、商品功能与秒杀商品等功能)

news2024/11/18 2:44:15

专栏:高并发---分布式项目 

👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者
📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶
📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
🍂博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人 

安装FastDFS

接下来我们编写商品管理功能。在进行商品管理时,需要上传商品图片。在百战商城中,我们使用FastDFS存储上传的图片,还需要使用Nginx的代理功能访问FastDFS存储的图片。 接下来我们要在虚拟机中安装FastDFS和Nginx:

1、下载安装gcc编译器

yum install gcc-c++ perl-devel pcre-devel
openssl-devel zlib-devel wget

2、下载FastDFS和FastDFS依赖包

# 进入根目录
cd /
# 使用rz上传FastDFS(V6.06.tar.gz)和FastDFS依赖包(V1.0.43.tar.gz)

3、安装FastDFS依赖

# 解压FastDFS依赖包
tar -zxvf V1.0.43.tar.gz -C /usr/local
# 进入依赖解压包
cd /usr/local/libfastcommon-1.0.43/
# 编译依赖
./make.sh
# 安装依赖
./make.sh install

4、安装FastDFS

# 解压FastDFS
cd /
tar -zxvf V6.06.tar.gz -C /usr/local
# 进入FastDFS解压包
cd /usr/local/fastdfs-6.06
# 编译FastDFS
./make.sh
# 安装FastDFS
./make.sh install

# 进入etc目录
cd /etc/fdfs/
# 复制配置文件
cp client.conf.sample client.conf
cp storage.conf.sample storage.conf
cp tracker.conf.sample tracker.conf

5、启动tracker服务(跟踪服务)

# 创建tracker目录
mkdir -p /data/fastdfs/tracker
# 修改配置文件
vim /etc/fdfs/tracker.conf
disabled=false                  #启用配置文件
port=22122                      #设置
tracker的端口号
base_path=/data/fastdfs/tracker #设置
tracker的数据文件和日志目录
http.server_port=8888           #设置http端口号
# 启动tracker服务
/etc/init.d/fdfs_trackerd start
# 检查tracker服务
netstat -lntup |grep fdfs

6、启动storage服务(存储服务)

# 创建storage目录
mkdir -p /data/fastdfs/base
mkdir -p /data/fastdfs/storage
# 修改配置文件
vim /etc/fdfs/storage.conf
disabled=false                        #启用配置文件
group_name=group1                     #组名,根据实际情况修改
port=23000                          
#storage的端口号
base_path=/data/fastdfs/base        
#storage的日志目录
store_path_count=1                    #存储路径个数
store_path0=/data/fastdfs/storage     #存储路径
tracker_server=192.168.0.159:22122  
#tracker服务器路径
http.server_port=8888                 #设置http端口号
# 启动storage服务
/etc/init.d/fdfs_storaged start
# 查看storage服务
netstat -lntup |grep fdfs

7、配置客户端连接

# 创建日志目录
mkdir -p /data/fastdfs/client
# 修改Client配置文件
vim /etc/fdfs/client.conf
connect_timeout=30
network_timeout=60
base_path=/data/fastdfs/client      #日志路径
tracker_server=192.168.0.159:22122   # tracker服务器路径

安装Nginx

1、解压FastDFS的Nginx模块包

cd /
# 使用rz上传FastDFS的Nginx模块包(V1.22.tar.gz)
# 解压FastDFS的Nginx模块包
tar -zxvf V1.22.tar.gz -C /usr/local

 2、安装Nginx依赖文件

yum install -y gcc gcc-c++ zlib zlib-devel
openssl openssl-devel pcre pcre-devel gddevel epel-release

3、安装Nginx

# 使用rz上传Nginx(nginx-1.19.2.tar.gz)
# 解压Nginx
tar -xzvf nginx-1.19.2.tar.gz -C
/usr/local
# 进入Nginx安装路径
cd /usr/local/nginx-1.19.2/
# 建立Makefile文件,检查Linux系统环境以及相关的关键属性。
./configure --addmodule=/usr/local/fastdfs-nginx-module-1.22/src/
# 编译Nginx
make
# 安装Nginx
make install

4、拷贝配置文件

cp /usr/local/fastdfs-6.06/conf/mime.types /etc/fdfs/
cp /usr/local/fastdfs-6.06/conf/http.conf /etc/fdfs/
cp /usr/local/fastdfs-nginx-module1.22/src/mod_fastdfs.conf /etc/fdfs/

5、进行FastDFS存储配置

# 编辑配置文件
vim /etc/fdfs/mod_fastdfs.conf
#保存日志目录
base_path=/data/fastdfs/storage      
#tracker服务器的IP地址以及端口号
tracker_server=192.168.0.159:22122  
#文件url中是否有group名
url_have_group_name = true          
#存储路径
store_path0=/data/fastdfs/storage  
#设置组的个数
group_count = 1                      
#然后在末尾添加分组信息,目前只有一个分组,就只写一个
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/data/fastdfs/storage

6、配置Nginx

# 编辑Nginx配置文件
vim /usr/local/nginx/conf/nginx.conf
server {
    listen       80;
    server_name localhost;
    
    location ~ /group[1-3]/M00 {
        alias /data/fastdfs/storage/data;
       ngx_fastdfs_module;
   }
}

7、启动Nginx

# 进入sbin目录
cd /usr/local/nginx/sbin/
# 启动服务
./nginx -c /usr/local/nginx/conf/nginx.conf

创建文件服务模块

接下来我们创建文件服务模块,编写文件上传和文件删除的服务。

1、创建名为 shopping_file_service 的SpringBoot工程,添加相关依赖。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>com.itbaizhan</groupId>
        <artifactId>shopping_common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <!-- dubbo -->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>2.7.8</version>
    </dependency>
    <!-- 操作zookeeper -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
        <version>4.2.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- FastDFS -->
    <dependency>
        <groupId>com.github.tobato</groupId>
        <artifactId>fastdfs-client</artifactId>
        <version>1.26.5</version>
    </dependency>
</dependencies>

 2、设置该工程的父工程为 shopping

<parent>
    <groupId>com.ittxc</groupId>
    <artifactId>shopping</artifactId>
    <version>1.0-SNAPSHOT</version>
</parent>

 3、给 shopping 工程设置子模块

<!-- 子模块 -->
<modules>
    <!-- 文件服务 -->
    <module>shopping_file_service</module>
</modules>

4、编写配置文件 application.yml

# 端口号
server:
 port: 9003
# 日志格式
logging:
 pattern:
   console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n'
dubbo:
 application:
   name: shopping_file_service # 项目名
 registry:
   address: zookeeper://192.168.25.100 #注册中心地址
   port: 2181       # 注册中心的端口
   timeout: 10000 # 注册到zk上超时时间,ms
 protocol:
   name: dubbo # dubbo使用的协议
   port: -1 # dubbo自动分配端口
 scan:
   base-packages: com.itbaizhan.shopping_file_service.service # 包扫描
fdfs:
 so-timeout: 3000
 connect-timeout: 6000
 tracker-list: # TrackerList路径
   - 192.168.0.159:22122
 fileUrl: http://192.168.0.159 # 自定义配置,文件访问路径

5、启动类忽略数据源自动配置

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class ShoppingFileServiceApplication {
    public static void main(String[] args)
     {
       SpringApplication.run(ShoppingFileServiceApplication.class, args);
   }
}

编写文件上传功能

1、在通用模块添加文件服务接口

// 文件服务
public interface FileService {
    /**
     * 上传文件
     * @param fileBytes 图片文件转成的字节数组
     * @param fileName 文件名
     * @return 上传后的文件访问路径
     */
    String uploadImage(byte[] fileBytes,String fileName) throws IOException;
    /**
     * 删除文件
     * @param filePath 文件路径
     */
    void delete(String filePath);
}

2、在文件服务模块创建文件服务接口实现类

@DubboService
public class FileServiceImpl implements FileService {
    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    @Value("${fdfs.fileUrl}")
    private String fileUrl; // Nginx访问FastDFS中文件的路径

    @Override
    public String uploadImage(byte[] fileBytes, String fileName) {
        if (fileBytes.length != 0) {
            try {
                // 1.将文件字节数组转为输入流
                InputStream inputStream = new ByteArrayInputStream(fileBytes);
                // 2.获取文件的后缀名
                String fileSuffix = fileName.substring(fileName.lastIndexOf(".") + 1);
                // 3.上传文件
                StorePath storePath = fastFileStorageClient.uploadFile(inputStream, inputStream.available(), fileSuffix,null);
                // 4.返回图片路径
                String imageUrl = fileUrl + "/"+storePath.getFullPath();
                return imageUrl;
           } catch (IOException ioException) {
                throw new BusException(CodeEnum.UPLOAD_FILE_ERROR);
           }
       } else {
            throw new BusException(CodeEnum.UPLOAD_FILE_ERROR);
       }
   }

@Override
    public void delete(String filePath) {
       fastFileStorageClient.deleteFile(filePath);
   }
}

编写文件上传控制器

1、在后台管理Api模块编写文件控制器

/**
* 文件
*/
@RestController
@RequestMapping("/file")
public class FileController {
    @DubboReference
    private FileService fileService;
    /**
     * 上传文件
     * @param file 文件
     * @return 文件路径
     * @throws IOException
     */
    @PostMapping("/uploadImage")
    public BaseResult<String> upload(MultipartFile file) throws IOException {
        // MultipartFile对象不能再服务间传递,必须转为byte数组
        byte[] bytes = file.getBytes();
        String url = fileService.uploadImage(bytes,file.getOriginalFilename());
        return BaseResult.ok(url);
   }
    /**
     * 删除文件
     * @param filePath 文件路径
     * @return 操作结果
     */
    @DeleteMapping("/delete")
    public BaseResult delete(String filePath){
        fileService.delete(filePath);
        return BaseResult.ok();
   }
}

2、测试控制器

编写新增商品功能

1、在通用模块添加商品服务接口

/**
* 商品服务
*/
public interface GoodsService {
    // 新增商品
     void add(Goods goods);
    // 修改商品
    void update(Goods goods);
    // 根据id查询商品详情
    Goods findById(Long id);
    // 上架/下架商品
    void putAway(Long id,Boolean isMarketable);
    // 分页查询
    Page<Goods> search(Goods goods, int page, int size);
}

2 新增商品时,需要新增商品数据,商品图片数据,商品_规格项 数据。需要创建 GoodsMapperGoodsImageMapper

public interface GoodsMapper extends BaseMapper<Goods> {
    // 添加商品_规格项数据
    void addGoodsSpecificationOption(@Param("gid") Long gid, @Param("optionId")Long optionId);
}
public interface GoodsImageMapper extends BaseMapper<GoodsImage> { }

3、编写映射文件 GoodsMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper
3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-
mapper.dtd">
<mapper namespace="com.itbaizhan.shopping_goods_service.mapper.GoodsMapper">
    <insert id="addGoodsSpecificationOption">
       INSERT INTO bz_goods_specification_option VALUES(# {gid},#{optionId})
    </insert>
</mapper>

4、编写商品服务接口实现类

@DubboService
public class GoodsServiceImpl implements
GoodsService {
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private GoodsImageMapper goodsImageMapper;
    @Override
    public void add(Goods goods) {
        // 插入商品数据
        goodsMapper.insert(goods);
          // 插入图片数据
        Long goodsId = goods.getId(); // 获取商品主键
        List<GoodsImage> images = goods.getImages(); // 商品图片
        for (GoodsImage image : images) {
            image.setGoodsId(goodsId); // 给图片设置商品id
            goodsImageMapper.insert(image); //插入图片
       }
        // 插入商品_规格项数据
        // 1.获取规格
        List<Specification> specifications = goods.getSpecifications();
        // 2.获取规格项
        List<SpecificationOption> options = new ArrayList(); //规格项集合
        // 遍历规格,获取规格中的所有规格项
        for (Specification specification : specifications) {
            options.addAll(specification.getSpecificationOptions());
       }
        // 3.遍历规格项,插入商品_规格项数据
        for (SpecificationOption option : options) {
            goodsMapper.addGoodsSpecificationOption(goodsId,option.getId());
       }
   }
}

5、编写商品控制器

/**
* 商品
*/
@RestController
@RequestMapping("/goods")
public class GoodsController {
    @DubboReference
    private GoodsService goodsService;
  
    /**
     * 新增商品
     *
     * @param goods 商品实体
     * @return 执行结果
     */
    @PostMapping("/add")
    public BaseResult add(@RequestBody Goods goods) {
        goodsService.add(goods);
        return BaseResult.ok();
   }
}

6、测试接口

编写修改商品功能

1、修改商品时,修改商品图片和规格项,我们先删除旧的图片和规 格项数据,再插入新的图片和规格项数据。首先我们在 GoodsMapper 中添加 删除商品下的所有规格项方法。

public interface GoodsMapper extends BaseMapper<Goods> {
    // 删除商品下的所有规格项
    void deleteGoodsSpecificationOption(Long gid);
}

 2、编写映射文件 GoodsMapper.xml

<delete id="deleteGoodsSpecificationOption">
   DELETE FROM bz_goods_specification_option WHERE gid = #{gid}
</delete>

3、编写商品服务接口实现类

@Override
public void update(Goods goods) {
    // 删除旧图片数据
    Long goodsId = goods.getId(); // 商品 id
    QueryWrapper<GoodsImage> queryWrapper = new QueryWrapper();
    queryWrapper.eq("goodsId",goodsId);
    goodsImageMapper.delete(queryWrapper);
    // 删除旧规格项数据
    goodsMapper.deleteGoodsSpecificationOption(goodsId);
    // 插入商品数据
    goodsMapper.updateById(goods);
    // 插入图片数据
    List<GoodsImage> images = goods.getImages(); // 商品图片
    for (GoodsImage image : images) {
        image.setGoodsId(goodsId); // 给图片设置商品id
        goodsImageMapper.insert(image); //插入图片
   }
    // 插入商品_规格项数据
    List<Specification> specifications = goods.getSpecifications(); // 获取规格
    List<SpecificationOption> options = new ArrayList(); // 规格项集合
    // 遍历规格,获取规格中的所有规格项
    for (Specification specification : specifications) {
       options.addAll(specification.getSpecifica tionOptions());
   }
    // 遍历规格项,插入商品_规格项数据
    for (SpecificationOption option : options) {
        goodsMapper.addGoodsSpecificationOption(goodsId,option.getId());
   }
}

4、编写商品控制器

/**
* 修改商品
*
* @param goods 商品实体
* @return 执行结果
*/
@PutMapping("/update")
public BaseResult update(@RequestBody Goods goods) {
    goodsService.update(goods);
    return BaseResult.ok();
}

5、测试接口

编写上/下架商品功能

1、在 GoodsMapper 中添加修改商品上架状态方法

// 商品上/下架
void putAway(@Param("id") Long id,@Param("isMarketable") Boolean isMarketable);

2、编写映射文件 GoodsMapper.xml

<update id="putAway">
   UPDATE bz_goods SET isMarketable = # {isMarketable} WHERE id = #{id}
</update>

3、编写商品服务接口实现类

@Override
public void putAway(Long id, Boolean isMarketable) {
    goodsMapper.putAway(id,isMarketable);
}

4、编写商品控制器

/**
* 上架/下架商品
*
* @param id 商品id
* @param isMarketable 是否上架
* @return 执行结果
*/
@PutMapping("/putAway")
public BaseResult putAway(Long id,Boolean isMarketable) {
    goodsService.putAway(id,isMarketable);
    return BaseResult.ok();
}

5、测试接口

编写根据id查询商品功能

根据id查询商品时,需要关联查询图片数据、规格数据等,所以需要进行多表的关联查询。

1、在 GoodsMapper 中添加根据id查询商品详情方法 

// 根据id查询商品详情
Goods findById(Long id);

2、编写映射文件 GoodsMapper.xml

<resultMap id="goodsMapper"
type="com.itbaizhan.shopping_common.pojo.G
oods">
    <id property="id" column="bid"></id>
    <result property="goodsName" column="goodsName"></result>
    <result property="caption" column="caption"></result>
    <result property="price" column="price"></result>
    <result property="headerPic" column="headerPic"></result>
    <result property="isMarketable" column="isMarketable"></result>
    <result property="brandId" column="brandId"></result>
    <result property="productType1Id" column="productType1Id"></result>
    <result property="productType2Id" column="productType2Id"></result>
    <result property="productType3Id" column="productType3Id"></result>
    <result property="introduction" column="introduction"></result>
    <collection property="images" column="bid" ofType="com.itbaizhan.shopping_common.pojo.GoodsImage">
        <id property="id" column="imageId"></id>
        <result property="imageTitle" column="imageTitle"></result>
        <result property="imageUrl" column="imageUrl"></result>
    </collection>
    <collection property="specifications" column="bid" ofType="com.itbaizhan.shopping_common.pojo.Specification">
        <id property="id" column="specificationId"></id>
        <result property="specName" column="specName"></result>
        <result property="productTypeId" column="productTypeId"></result>
        <collection property="specificationOptions" column="specificationId" ofType="com.itbaizhan.shopping_common.pojo.SpecificationOption">
            <id property="id" column="optionId"></id>
            <result property="optionName" column="optionName"></result>
        </collection>
    </collection>
</resultMap>
<select id="findById"
resultMap="goodsMapper">
   SELECT
   bz_goods.`id` bid,
   bz_goods.`goodsName` goodsName,
   bz_goods.`caption` caption,
 bz_goods.`price` price,
   bz_goods.`headerPic` headerPic,
   bz_goods.`introduction` introduction,
   bz_goods.`isMarketable` isMarketable,
   bz_goods.`brandId` brandId,
   bz_goods.`productType1Id`
productType1Id,
   bz_goods.`productType2Id`
productType2Id,
   bz_goods.`productType3Id`
productType3Id,
   bz_goods_image.`id` imageId,
   bz_goods_image.`imageTitle`
imageTitle,
   bz_goods_image.`imageUrl` imageUrl,
   bz_specification.`id` specificationId,
   bz_specification.`specName` specName,
   bz_specification.`productTypeId`
productTypeId,
   bz_specification_option.`id` optionId,
   bz_specification_option.`optionName`
optionName
   FROM
   bz_goods,
   bz_goods_specification_option,
   bz_specification_option,
   bz_specification,
   bz_goods_image
   WHERE bz_goods.`id` =
bz_goods_specification_option.`gid`
AND
bz_goods_specification_option.`optionId` =
bz_specification_option.`id`
   AND bz_specification.`id` =
bz_specification_option.`specId`
   AND bz_goods.`id` =
bz_goods_image.`goodsId`
   AND bz_goods.id = #{gid}
</select>

3、编写商品服务接口实现类

@Override
public Goods findById(Long id) {
    return goodsMapper.findById(id);
}

4、编写商品控制器

/**
  * 根据id查询商品详情
  *
  * @param id 商品id
  * @return 商品详情
  */
@GetMapping("/findById")
public BaseResult<Goods> findById(Long id)
{
    Goods goods = goodsService.findById(id);
    return BaseResult.ok(goods);
}

5、测试接口

编写分页查询商品功能

1、编写商品服务接口实现类

@Override
public Page<Goods> search(Goods goods, int page, int size) {
    QueryWrapper<Goods> queryWrapper = new QueryWrapper();
    // 判断商品名不为空
    if (goods != null && StringUtils.hasText(goods.getGoodsName()))
      {
         queryWrapper.like("goodsName",goods.getGoodsName());
   }
    Page<Goods> page1 = goodsMapper.selectPage(new Page(page,size), queryWrapper);
    return page1;
}

2、编写商品控制器

/**
* 分页查询
* @param goods 商品条件对象
* @param page 页码
* @param size 每页条数
* @return 查询结果
*/
@GetMapping("/search")
public BaseResult<Page<Goods>> search(Goods goods, int page, int size) {
    Page<Goods> page1 = goodsService.search(goods, page, size);
    return BaseResult.ok(page1);
}

3、测试接口

编写秒杀商品服务接口

在管理员新增商品后,可以将商品设置为秒杀商品。“秒杀”是网络 卖家发布一些超低价格的商品,所有买家在同一时间网上抢购的一 种销售方式。用户秒杀商品时,需要通过一些技术方案降低服务器 的压力,这个我们编写用户端时再做介绍。管理员管理秒杀商品, 需要先在数据库拿到相应的普通商品,再将该商品构造为秒杀商品 添加到数据库中。接下来我们在通用模块编写秒杀商品服务接口:

public interface SeckillGoodsService {
    /**
     * 添加秒杀商品
     *
     * @param seckillGoods 秒杀商品实体
     */
     void add(SeckillGoods seckillGoods);
    /**
     * 修改秒杀商品
     *
     * @param seckillGoods 秒杀商品实体
     */
    void update(SeckillGoods seckillGoods);
    /**
     * 分页查询秒杀商品
     *
     * @param page 页数
     * @param size 每页条数
     * @return 查询结果
     */
    Page<SeckillGoods> findPage(int page, int size);
}

编写秒杀商品服务实现类

1、在商品服务模块编写秒杀商品Mapper:

public interface SeckillGoodsMapper extends BaseMapper<SeckillGoods> {
}

2、在商品服务模块编写秒杀商品服务实现类:

@DubboService
public class SeckillGoodsServiceImpl implements SeckillGoodsService {
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Override
    public void add(SeckillGoods seckillGoods) {
         seckillGoodsMapper.insert(seckillGoods);
   }
    @Override
    public void update(SeckillGoods seckillGoods) {
        seckillGoodsMapper.updateById(seckillGoods);
   }
    @Override
    public Page<SeckillGoods> findPage(int page, int size) {
        return seckillGoodsMapper.selectPage(new Page(page, size), null);
   }
}

编写秒杀商品控制器

在后台管理API模块秒杀商品控制器:

/**
* 秒杀商品
*/
@RestController
@RequestMapping("/seckillGoods")
public class SeckillGoodsController {
    @DubboReference
    private SeckillGoodsService seckillGoodsService;
    /**
     * 添加秒杀商品
     * @param seckillGoods 秒杀商品实体
     * @return 操作结果
     */
    @PostMapping("/add")
    public BaseResult add(@RequestBody SeckillGoods seckillGoods) {
        seckillGoodsService.add(seckillGoods);
        return BaseResult.ok();
   }
    /**
     * 修改秒杀商品
     * @param seckillGoods 秒杀商品实体
     * @return 操作结果
     */
    @PutMapping("/update")
    public BaseResult update(@RequestBody SeckillGoods seckillGoods) {
           seckillGoodsService.update(seckillGoods);
        return BaseResult.ok();
   }
    /**
     * 分页查询秒杀商品
     * @param page 页数
     * @param size 每页条数
     * @return 查询结果
     */
    @GetMapping("/findPage")
    public BaseResult<Page<SeckillGoods>> findPage(int page, int size) {
        Page<SeckillGoods> seckillGoodsPage = seckillGoodsService.findPage(page, size);
        return BaseResult.ok(seckillGoodsPage);
   }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/348997.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言进阶——自定义类型:枚举、联合

&#x1f307;个人主页&#xff1a;_麦麦_ &#x1f4da;今日名言&#xff1a;如果不去遍历世界&#xff0c;我们就不知道什么是我们精神和情感的寄托&#xff0c;但我们一旦遍历了世界&#xff0c;却发现我们再也无法回到那美好的地方去了。当我们开始寻求&#xff0c;我们就已…

2023春招java面试题及答案

2023春招java面试题及答案总结1.以下Dubbo服务负载均衡策略中&#xff0c;哪一个策略的功能是相同参数的请求总是发到同一个提供者&#xff08;&#xff09;2.如下代码&#xff1a;请问编译运行的结果是什么&#xff1f;3.给出如下代码&#xff1a;请问编译运行的结果是什么&am…

英国访问学者邀请函范例

下面是知识人网访问学者老师分享的一个英国访问学者邀请函范例&#xff0c;邀请函不要复杂&#xff0c;提供签证官想看到的东西即可。Chen xxxDate of Birth: September 1th , 19xxSchool of Computer and InformationXXXX UniversityNo.X South RoadXXX city, XXX Province, 1…

1.Unity之Shader新手入门

Unity Shader着色器的基本概念如何使用Unity Shader着色器示例&#xff1a;如何使用Unity Shader着色器创建复杂的效果总结 什么是Unity中的Shader着色器&#xff1f; Shader着色器是用来控制物体外观的编程代码&#xff0c;它可以改变物体的颜色、纹理、光照、凹凸等&#xf…

智慧校园综合解决方案

在网络和信息技术的普及和国家教育信息化建设的推动下&#xff0c;以计算机网络为基础&#xff0c;以信息和知识资源的共享为手段&#xff0c;强调合作、分享、传承精神的网络化、数字化、智能化有机结合的新型教育、学习和研究的教育环境建设显得尤为重要。 智慧校园是利用信息…

leaflet 纯CSS的marker标记,不用图片来表示(072)

第072个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中使用纯CSS来打造marker的标记。这里用到的是L.divIcon来引用CSS来构造新icon,然后在marker的属性中引用。 这里必须要注意的是css需要是全局性质的,不能被scoped转义为其他随机的css。 直接复制下面的 v…

【SPSS】频数分析和基本描述统计量详细操作教程(附实战案例)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

记录--『uni-app、小程序』蓝牙连接、读写数据全过程

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 本文简介 这是一次真实的 蓝牙收发数据 的全过程讲解。 本文使用 uni-app Vue3 的方式进行开发&#xff0c;以手机app的方式运行(微信小程序同样可行)。 uni-app 提供了 蓝牙 和 低功耗蓝牙 的 api &…

深圳硬件黑客松活动,开放报名!

开源社KAIYUANSHE近期微信公众号订阅功能做调整啦&#xff01;没有被星标的账号在信息流里可能不显示大图了&#xff01;快星标⭐我们&#xff0c;就可以及时看到发布的文章啦&#xff01;STEP01 点击右上角标志STEP02 点击【设为星标】近年来&#xff0c;创客文化越来越受到人…

figma通过什么方式可以转换为sketch

Figma 如何转为 Sketch 文件&#xff1f;巧了&#xff0c;刚好我对这个问题很熟悉&#xff0c;作为一个使用过 Figma 也使用过 Sketch 的人来说&#xff0c;我还蛮希望两个软件能够互相打通的&#xff0c;不过不管是 Figma 也好还是 Sketch 也好&#xff0c;两个设计软件&#…

含泪吐槽学C++的血与泪

含泪吐槽学C的血与泪 C在各位程序猿眼里并不陌生&#xff0c;但凡学习过C的人&#xff0c;都极有可能被它曾经蹂躏得不要不要的&#xff0c;而我就是其中一个。 文章目录1 我和C的那段血泪史2 再次与C重逢3 我想和你再来一次4 柳暗花明友情推荐5 福利赠书活动6 一个彩蛋大家好&…

FLUXNET数据下载具体步骤

一、FLUXNET数据介绍 全球长期通量观测网络概念最早起源于1993年&#xff0c;由国际地圈-生物圈计划首次提出&#xff0c;国际科学委员会在1995年的La Thuile研讨会上对此概念进行正式讨论&#xff0c;在这次会议上&#xff0c;通量观测委员会讨论了进行长期通量观测的可能性以…

KubeSphere

文章目录一、概述二、最小化安装 KubeSphere2.1 前提2.2 安装 nfs 服务器一、概述 KubeSphere是在Kubernetes之上构建的以应用为中心的企业级分布式容器平台&#xff0c;提供简单易用的操作界面以及向导式操作方式&#xff0c;在降低用户使用容器调度平台学习成本的同时&#…

超详细,Java 设计模式汇总(三)

装饰者模式 装饰者模式一般指装饰模式。 装饰模式指的是在不必改变原类文件和使用继承的情况下&#xff0c;动态地扩展一个对象的功能。它是通过创建一个包装对象&#xff0c;也就是装饰来包裹真实的对象。 装饰者模式&#xff08;Decorator Pattern&#xff09;允许向一个现…

springboot+vue简单对接支付宝完整流程

源码 前端 vue-demo https://www.aliyundrive.com/s/dmnY8G6N6RM 点击链接保存&#xff0c;或者复制本段内容&#xff0c;打开「阿里云盘」APP &#xff0c;无需下载极速在线查看&#xff0c;视频原画倍速播放。 后端 aliPay https://www.aliyundrive.com/s/H2JFBjGWuf2 …

JVM04 堆

一个JVM实例只存在一个堆内存&#xff0c;堆也是Java内存管理的核心区域。 一个JVM实例&#xff08;一个Runtime&#xff09;只存在一个堆内存&#xff0c;堆也是Java内存管理的核心区域。 Java堆区在JVM启动的时候即被创建&#xff0c;其空间大小也就确定了。是JVM管理的最大…

ios上架及证书最新申请流程

ios上架及证书最新申请流程在使用hbuilderx或apicloud等uniapp框架开发app的时候&#xff0c;需要安卓证书或ios证书&#xff0c;假如是开发ios应用&#xff0c;打包成ipa包后&#xff0c;还需要将这个ipa上架到app store。苹果官网推荐的方法中&#xff0c;生成ios证书和上架i…

字节跳动青训营--前端day9

文章目录前言PC web端一、 前端Debug的特点二、 前端Debug的方式1. 浏览器动态修改元素和样式2. Console3. Sorce Tab4. NetWork5. Application6. Performancee7. Lighthouse移动端调试IOSAndroid通过代理工具调试前言 仅以此文章记录学习。 PC web端 一、 前端Debug的特点 …

Redis学习【6】之BitMap、HyperLogLog、Geospatial操作命令 (1)

文章目录前言BitMap 操作命令1.1 BitMap 简介1.2 setbit1.3 getbit1.4 bitcount1.5 bitpos[pos:position]1.6 bitop1.7 应用场景二 HyperLogLog 操作命令2.1 HyperLogLog 简介2.2 pfadd2.3 pfcount2.4 pfmerge2.5 应用场景三 Geospatial【地理空间】操作命令3. 1 Geospatial 简…

Zynq非VDMA方案实现视频3帧缓存输出,无需SDK配置,提供工程源码和技术支持

目录1、前言2、VDMA的不便之处3、FDMA取代VDMA实现视频缓存输出4、Vivado工程详解5、上板调试验证并演示6、福利&#xff1a;工程代码的获取1、前言 对于Zynq和Microblaze的用户而言&#xff0c;要想实现图像缓存输出&#xff0c;多半要使用Xilinx推荐的VDMA方案&#xff0c;该…