微服务第一轮

news2024/10/5 14:32:55

课程文档

目录

一、业务流程

1、登录

Controller中的接口: 

 Service中的实现impl:

Service中的实现impl所继承的接口IService(各种方法): 

VO:

 DTO:

2、搜索商品

​Controller中的接口:

3、购物车

​Controller中的接口:

二、拆分商品服务

1. 创建新module - maven模块,并引入依赖

2. 新建包com.hmall.xx(业务名),添加和修改启动类,新建mapper包、domain包 - service包 - controller包

3. 拷贝并修改yaml配置文件到resources中,分别修改 端口号、服务名称、datasource(需创建sql datebase)、swagger接口文档说明与controller扫描包

4.domain,mapper,service,controller包代码 

5. 刷新maven,添加该业务模块启动项到Services中,并把Active profiles 修改为 local

6. 运行,在访问地址后面添加doc.html访问swagger接口文档,进行调试

​三、拆分购物车服务

四、服务调用(RPC)

RestTemplate 

远程直接调用

五、Nacos注册中心

服务注册

 1、添加依赖,配置Nacos

 2、启动服务,访问http://192.168.150.101:8848/nacos/控制台,可以发现服务注册成功:

​服务发现

1、  添加依赖,配置Nacos

 2、根据负载均衡算法发现并调用方法


 

一、业务流程

1、登录

Controller中的接口: 


@Api(tags = "用户相关接口")
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {

    private final IUserService userService;

    @ApiOperation("用户登录接口")
    @PostMapping("login")
    public UserLoginVO login(@RequestBody @Validated LoginFormDTO loginFormDTO){
        return userService.login(loginFormDTO);
    }
}

 Service中的实现impl:

public interface IUserService extends IService<User> {

    UserLoginVO login(LoginFormDTO loginFormDTO);

    void deductMoney(String pw, Integer totalFee);
}

Service中的实现impl所继承的接口IService(各种方法): 


public interface IService<T> {
    int DEFAULT_BATCH_SIZE = 1000;

    default boolean save(T entity) {
        return SqlHelper.retBool(this.getBaseMapper().insert(entity));
    }

    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean saveBatch(Collection<T> entityList) {
        return this.saveBatch(entityList, 1000);
    }

    boolean saveBatch(Collection<T> entityList, int batchSize);

    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean saveOrUpdateBatch(Collection<T> entityList) {
        return this.saveOrUpdateBatch(entityList, 1000);
    }

    boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
}

VO:

@Data
public class UserLoginVO {
    private String token;
    private Long userId;
    private String username;
    private Integer balance;
}

 DTO:

@Data
@ApiModel(description = "登录表单实体")
public class LoginFormDTO {
    @ApiModelProperty(value = "用户名", required = true)
    @NotNull(message = "用户名不能为空")
    private String username;
    @NotNull(message = "密码不能为空")
    @ApiModelProperty(value = "用户名", required = true)
    private String password;
    @ApiModelProperty(value = "是否记住我", required = false)
    private Boolean rememberMe = false;
}

2、搜索商品

在首页搜索框输入关键字手机,点击搜索即可进入搜索列表页面: 

 Controller中的接口:

@Api(tags = "搜索相关接口")
@RestController
@RequestMapping("/search")
@RequiredArgsConstructor
public class SearchController {

    private final IItemService itemService;

    @ApiOperation("搜索商品")
    @GetMapping("/list")
    public PageDTO<ItemDTO> search(ItemPageQuery query) {
        // 分页查询
        Page<Item> result = itemService.lambdaQuery()
                .like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey())
                .eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand())
                .eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory())
                .eq(Item::getStatus, 1)
                .between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice())
                .page(query.toMpPage("update_time", false));
        // 封装并返回
        return PageDTO.of(result, ItemDTO.class);
    }
}

3、购物车

在搜索到的商品列表中,点击按钮加入购物车,即可将商品加入购物车:

 加入成功后即可进入购物车列表页,查看自己购物车商品列表:

 Controller中的接口:

@Api(tags = "购物车相关接口")
@RestController
@RequestMapping("/carts")
@RequiredArgsConstructor
public class CartController {
    private final ICartService cartService;

    @ApiOperation("添加商品到购物车")
    @PostMapping
    public void addItem2Cart(@Valid @RequestBody CartFormDTO cartFormDTO){
        cartService.addItem2Cart(cartFormDTO);
    }

    @ApiOperation("更新购物车数据")
    @PutMapping
    public void updateCart(@RequestBody Cart cart){
        cartService.updateById(cart);
    }

    @ApiOperation("删除购物车中商品")
    @DeleteMapping("{id}")
    public void deleteCartItem(@Param ("购物车条目id")@PathVariable("id") Long id){
        cartService.removeById(id);
    }

    @ApiOperation("查询购物车列表")
    @GetMapping
    public List<CartVO> queryMyCarts(){
        return cartService.queryMyCarts();
    }
    @ApiOperation("批量删除购物车中商品")
    @ApiImplicitParam(name = "ids", value = "购物车条目id集合")
    @DeleteMapping
    public void deleteCartItemByIds(@RequestParam("ids") List<Long> ids){
        cartService.removeByItemIds(ids);
    }
}

其中,查询购物车列表时,由于要判断商品最新的价格和状态,所以还需要查询商品信息,业务流程如下:

二、拆分商品服务

1. 创建新module - maven模块,并引入依赖

创建新模块 

选择maven模块,并设定JDK版本为11: 

 添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.heima</groupId>
        <artifactId>hmall</artifactId>
        <version>1.0.0</version>
    </parent>

    <groupId>org.qingshui</groupId>
    <artifactId>item-service</artifactId>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--common-->
        <dependency>
            <groupId>com.heima</groupId>
            <artifactId>hm-common</artifactId>
            <version>1.0.0</version>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <version>3.3.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2. 新建包com.hmall.xx(业务名),添加和修改启动类,新建mapper包、domain包 - service包 - controller包

 新建包com.hmall.item: 

 编写启动类ItemApplication:

@MapperScan("com.hmall.item.mapper")
@SpringBootApplication
public class ItemApplication {
    public static void main(String[] args) {
        SpringApplication.run(ItemApplication.class, args);
    }
}

 新建mapper包、domain包 - service包 - controller包:

3. 拷贝并修改yaml配置文件到resources中,分别修改 端口号、服务名称、datasource(需创建sql datebase)、swagger接口文档说明与controller扫描包

从hm-service中拷贝:

修改application.yaml为:

server:
  port: 8081
spring:
  application:
    name: item-service
  profiles:
    active: dev
  datasource:
    url: jdbc:mysql://${hm.db.host}:3306/hm-item?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: ${hm.db.pw}
mybatis-plus:
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
  global-config:
    db-config:
      update-strategy: not_null
      id-type: auto
logging:
  level:
    com.hmall: debug
  pattern:
    dateformat: HH:mm:ss:SSS
  file:
    path: "logs/${spring.application.name}"
knife4j:
  enable: true
  openapi:
    title: 商品服务接口文档
    description: "信息"
    email: zhanghuyi@itcast.cn
    concat: 虎哥
    url: https://www.itcast.cn
    version: v1.0.0
    group:
      default:
        group-name: default
        api-rule: package
        api-rule-resources:
          - com.hmall.item.controller

创建该模块的数据库: 

4.domain,mapper,service,controller包代码 

【1】domain包代码:dto、po、vo、(query)

dto:数据传输对象 

OrderDetailDTO: 

@ApiModel(description = "订单明细条目")
@Data
@Accessors(chain = true)
public class OrderDetailDTO {
    @ApiModelProperty("商品id")
    private Long itemId;
    @ApiModelProperty("商品购买数量")
    private Integer num;
}

 ItemDTO:


@Data
@ApiModel(description = "商品实体")
public class ItemDTO {
    @ApiModelProperty("商品id")
    private Long id;
    @ApiModelProperty("SKU名称")
    private String name;
    @ApiModelProperty("价格(分)")
    private Integer price;
    @ApiModelProperty("库存数量")
    private Integer stock;
    @ApiModelProperty("商品图片")
    private String image;
    @ApiModelProperty("类目名称")
    private String category;
    @ApiModelProperty("品牌名称")
    private String brand;
    @ApiModelProperty("规格")
    private String spec;
    @ApiModelProperty("销量")
    private Integer sold;
    @ApiModelProperty("评论数")
    private Integer commentCount;
    @ApiModelProperty("是否是推广广告,true/false")
    private Boolean isAD;
    @ApiModelProperty("商品状态 1-正常,2-下架,3-删除")
    private Integer status;
}

 po:实体


@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("item")
public class Item implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 商品id
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * SKU名称
     */
    private String name;

    /**
     * 价格(分)
     */
    private Integer price;

    /**
     * 库存数量
     */
    private Integer stock;

    /**
     * 商品图片
     */
    private String image;

    /**
     * 类目名称
     */
    private String category;

    /**
     * 品牌名称
     */
    private String brand;

    /**
     * 规格
     */
    private String spec;

    /**
     * 销量
     */
    private Integer sold;

    /**
     * 评论数
     */
    private Integer commentCount;

    /**
     * 是否是推广广告,true/false
     */
    @TableField("isAD")
    private Boolean isAD;

    /**
     * 商品状态 1-正常,2-下架,3-删除
     */
    private Integer status;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;

    /**
     * 创建人
     */
    private Long creater;

    /**
     * 修改人
     */
    private Long updater;


}

vo:视图对象 

在hm-service模块中没有与商品有关的代码。

query:分页查询 

@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel(description = "商品分页查询条件")
public class ItemPageQuery extends PageQuery {
    @ApiModelProperty("搜索关键字")
    private String key;
    @ApiModelProperty("商品分类")
    private String category;
    @ApiModelProperty("商品品牌")
    private String brand;
    @ApiModelProperty("价格最小值")
    private Integer minPrice;
    @ApiModelProperty("价格最大值")
    private Integer maxPrice;
}

【2】mapper包代码 :mapper接口 及mapper.xml文件

public interface ItemMapper extends BaseMapper<Item> {

    @Update("UPDATE item SET stock = stock - #{num} WHERE id = #{itemId}")
    void updateStock(OrderDetailDTO orderDetail);
}

【3】 service包:service接口及实现类

service接口: 

public interface IItemService extends IService<Item> {

    void deductStock(List<OrderDetailDTO> items);

    List<ItemDTO> queryItemByIds(Collection<Long> ids);
}

 修改sqlStatement后的实现类:

@Service
public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements IItemService {

    @Override
    public void deductStock(List<OrderDetailDTO> items) {
        String sqlStatement = "com.hmall.mapper.item.ItemMapper.updateStock";
        boolean r = false;
        try {
            r = executeBatch(items, (sqlSession, entity) -> sqlSession.update(sqlStatement, entity));
        } catch (Exception e) {
            throw new BizIllegalException("更新库存异常,可能是库存不足!", e);
        }
        if (!r) {
            throw new BizIllegalException("库存不足!");
        }
    }

    @Override
    public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
        return BeanUtils.copyList(listByIds(ids), ItemDTO.class);
    }
}

【4】controller包

@Api(tags = "商品管理相关接口")
@RestController
@RequestMapping("/items")
@RequiredArgsConstructor
public class ItemController {

    private final IItemService itemService;

    @ApiOperation("分页查询商品")
    @GetMapping("/page")
    public PageDTO<ItemDTO> queryItemByPage(PageQuery query) {
        // 1.分页查询
        Page<Item> result = itemService.page(query.toMpPage("update_time", false));
        // 2.封装并返回
        return PageDTO.of(result, ItemDTO.class);
    }

    @ApiOperation("根据id批量查询商品")
    @GetMapping
    public List<ItemDTO> queryItemByIds(@RequestParam("ids") List<Long> ids){
        return itemService.queryItemByIds(ids);
    }

    @ApiOperation("根据id查询商品")
    @GetMapping("{id}")
    public ItemDTO queryItemById(@PathVariable("id") Long id) {
        return BeanUtils.copyBean(itemService.getById(id), ItemDTO.class);
    }

    @ApiOperation("新增商品")
    @PostMapping
    public void saveItem(@RequestBody ItemDTO item) {
        // 新增
        itemService.save(BeanUtils.copyBean(item, Item.class));
    }

    @ApiOperation("更新商品状态")
    @PutMapping("/status/{id}/{status}")
    public void updateItemStatus(@PathVariable("id") Long id, @PathVariable("status") Integer status){
        Item item = new Item();
        item.setId(id);
        item.setStatus(status);
        itemService.updateById(item);
    }

    @ApiOperation("更新商品")
    @PutMapping
    public void updateItem(@RequestBody ItemDTO item) {
        // 不允许修改商品状态,所以强制设置为null,更新时,就会忽略该字段
        item.setStatus(null);
        // 更新
        itemService.updateById(BeanUtils.copyBean(item, Item.class));
    }

    @ApiOperation("根据id删除商品")
    @DeleteMapping("{id}")
    public void deleteItemById(@PathVariable("id") Long id) {
        itemService.removeById(id);
    }

    @ApiOperation("批量扣减库存")
    @PutMapping("/stock/deduct")
    public void deductStock(@RequestBody List<OrderDetailDTO> items){
        itemService.deductStock(items);
    }
}

5. 刷新maven,添加该业务模块启动项到Services中,并把Active profiles 修改为 local

6. 运行,在访问地址后面添加doc.html访问swagger接口文档,进行调试

 三、拆分购物车服务

同上 

四、服务调用(RPC)

背景: 

在拆分的时候,我们发现一个问题:就是购物车业务中需要查询商品信息,但商品信息查询的逻辑全部迁移到了item-service服务,导致我们无法查询。(也就是一个模块要进行查询但是查询代码都在另外一个模块) 

那么问题来了:我们该如何跨服务调用,准确的说,如何在cart-service中获取item-service服务中的提供的商品数据呢? 

 因此,现在查询购物车列表的流程变成了这样:

 假如我们在cart-service中能模拟浏览器,发送http请求到item-service,是不是就实现了跨微服务的远程调用了呢(也就是用Java代码发送Http请求)

RestTemplate 

Spring给我们提供了一个RestTemplate的API,可以方便的实现Http请求的发送。 

其中提供了大量的方法,方便我们发送Http请求,例如: 

我们在cart-service服务中定义一个配置类 

 先将RestTemplate注册为一个Bean:

package com.hmall.cart.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RemoteCallConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

远程直接调用

 在这个过程中,item-service提供了查询接口,cart-service利用Http请求调用该接口。因此item-service可以称为服务的提供者,而cart-service则称为服务的消费者或服务调用者。

五、Nacos注册中心

背景: 

RPC通过Http请求实现了跨微服务的远程调用,这种手动发送Http请求的方式存在一些问题。 

试想一下,假如商品微服务被调用较多,为了应对更高的并发,我们进行了多实例部署,如图: 

此时,每个item-service的实例其IP或端口不同,问题来了:

  • item-service这么多实例,cart-service如何知道每一个实例的地址?

  • http请求要写url地址,cart-service服务到底该调用哪个实例呢?

  • 如果在运行过程中,某一个item-service实例宕机,cart-service依然在调用该怎么办?

  • 如果并发太高,item-service临时多部署了N台实例,cart-service如何知道新实例的地址?

这时我们需要注册中心 (其实也是建立一个连接池)

流程如下:

  • 服务启动时就会注册自己的服务信息(服务名、IP、端口)到注册中心

  • 调用者可以从注册中心订阅想要的服务,获取服务对应的实例列表(1个服务可能多实例部署)

  • 调用者自己对实例列表负载均衡,挑选一个实例

  • 调用者向该实例发起远程调用

当服务提供者的实例宕机或者启动新实例时,调用者如何得知呢?

  • 服务提供者会定期向注册中心发送请求,报告自己的健康状态(心跳请求)

  • 当注册中心长时间收不到提供者的心跳时,会认为该实例宕机,将其从服务的实例列表中剔除

  • 当服务有新实例启动时,会发送注册服务请求,其信息会被记录在注册中心的服务实例列表

  • 当注册中心服务列表变更时,会主动通知微服务,更新本地服务列表

服务注册

将模块(微服务)注册到Nacos 

 1、添加依赖,配置Nacos

item-servicepom.xml中添加依赖:

<!--nacos 服务注册发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

 在item-serviceapplication.yml中添加nacos地址配置:

将nacos地址修改为自己的虚拟机地址 

spring:
  application:
    name: item-service # 服务名称
  cloud:
    nacos:
      server-addr: 192.168.150.101:8848 # nacos地址

 2、启动服务,访问http://192.168.150.101:8848/nacos/控制台,可以发现服务注册成功:

 服务发现

服务的消费者要去nacos订阅服务,这个过程就是服务发现 。

1、  添加依赖,配置Nacos

服务发现除了要引入nacos依赖以外,由于还需要负载均衡,因此要引入SpringCloud提供的LoadBalancer依赖。

我们在cart-service中的pom.xml中添加下面的依赖:

<!--nacos 服务注册发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

 cart-serviceapplication.yml中添加nacos地址配置:

spring:
  cloud:
    nacos:
      server-addr: 192.168.150.101:8848

 2、根据负载均衡算法发现并调用方法

接下来,服务调用者cart-service就可以去订阅item-service服务了。不过item-service有多个实例,而真正发起调用时只需要知道一个实例的地址。

因此,服务调用者必须利用负载均衡的算法,从多个实例中挑选一个去访问。常见的负载均衡算法有:

  • 随机

  • 轮询

  • IP的hash

  • 最近最少访问

  • ...

这里我们可以选择最简单的随机负载均衡。

另外,服务发现需要用到一个工具,DiscoveryClient,SpringCloud已经帮我们自动装配,我们可以直接注入使用:

 

 接下来,我们就可以对原来的远程调用做修改了,之前调用时我们需要写死服务提供者的IP和端口:

 但现在不需要了,我们通过DiscoveryClient发现服务实例列表,然后通过负载均衡算法,选择一个实例去调用:

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

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

相关文章

期望24K,商汤科技golang开发 社招一二三 + hr 面

商汤科技对数据库和中间件相关的东西问的比其他的大厂要少很多&#xff0c;可能他们更多是和算法相关&#xff0c;没有什么高并发的场景。总体感觉对技术的要求不是特别高。当时问了他们主管&#xff0c;我面试的部门的工作是主要去实现他们算法部门研究的算法&#xff0c;感觉…

CSS函数:fit-content与matrix的使用

网格函数 fit-content()属于网格函数&#xff0c;除此之外的网格函数还有&#xff1a;CSS函数&#xff1a; 实现数据限阈的数字函数。顾名思义&#xff0c;这三个函数只能在网格布局中使用。fit-content()函数主要是用于给定布局可用大小&#xff0c;适应内容&#xff0c;其功…

【微信小程序】页面导航

声明式导航 导航到 tabbar 页 tabBar页面指的是被配置为tabBar的页面。 在使用<navigator>组件跳转到指定的tabBar页面时&#xff0c;需要指定url属性和open-type属性&#xff0c;其中&#xff1a; url 表示要跳转的页面的地址&#xff0c;必须以/开头open-type表示跳…

【Vue】路由介绍

一、引入 思考 单页面应用程序&#xff0c;之所以开发效率高&#xff0c;性能好&#xff0c;用户体验好 最大的原因就是&#xff1a;页面按需更新 比如当点击【发现音乐】和【关注】时&#xff0c;只是更新下面部分内容&#xff0c;对于头部是不更新的 要按需更新&#xff…

企业微信hook接口协议,ipad协议http,内部联系人备注修改

内部联系人备注修改 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信 请求示例 {"uuid":"1688855749266556","vid":1688856554448765,"remark":"备注啦啦啦22222","des&quo…

Pycharm SSH远程连接时出现报错,测试 SFTP 连接,连接到 ‘connect.westb.seetacloud.com‘ 失败

问题由来 很离谱&#xff01;今天本来打算租借AutoDL的显卡完成一项深度学习的任务&#xff0c;很离谱的是同步文件夹的时候报了标题说的错。 就很莫名奇妙&#xff0c;一天都在网上找解决办法&#xff0c;结果都不对头。 其他报错 最后摸索着&#xff0c;在使用pycharm远程登…

[数据集][目标检测]手枪检测数据集VOC+YOLO格式3000张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;3000 标注数量(xml文件个数)&#xff1a;3000 标注数量(txt文件个数)&#xff1a;3000 标注…

数据流通与智能家居的未来

在科技飞速发展的今天&#xff0c;智能家居逐渐融入我们的日常生活&#xff0c;改变了传统的居住方式。智能生态网络&#xff08;IEN&#xff09;作为智能家居的核心&#xff0c;集成了家庭内的各种智能设备和传感器&#xff0c;实现了对家庭环境的智能化管理。而数据要素流通则…

SpringCloud 服务调用 spring-cloud-starter-openfeign

spring-cloud-starter-openfeign 是 Spring Cloud 中的一个组件&#xff0c;用于在微服务架构中声明式地调用其他服务。它基于 Netflix 的 Feign 客户端进行了封装和增强&#xff0c;使其与 Spring Cloud 生态更好地集成。 1. Feign Feign 是一个声明式的 Web Service 客户端…

绿联Nas docker 中 redis 老访问失败的排查

部署了一些服务&#xff0c;老隔3-5 天其他服务就联不上 redis 了&#xff0c;未确定具体原因&#xff0c;只记录观察到的现象 宿主机访问 只有 ipv6 绑定了&#xff0c;ipv4 绑定挂掉了 其他容器访问 也无法访问成功 当重启容器后&#xff1a; 一切又恢复正常。 可能的解…

使用 Django 和 MQTT 构建实时数据传输应用

文章目录 什么是 MQTT&#xff1f;Django 中的 MQTT结论 在现代的 Web 应用程序开发中&#xff0c;实时数据传输变得越来越重要。MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的发布/订阅消息传输协议&#xff0c;而 Django 是一个流行的 Pyt…

【最新鸿蒙应用开发】——Want信息载体

信息传递载体Want 1、概述 上一章节我们学习了UIAbility组件 【最新鸿蒙应用开发】——一篇搞懂什么是UIAbility-CSDN博客 &#xff0c;其中组件间的交互传递信息的媒介就是Want&#xff0c;本章节我们来更加深入学习Want的相关知识。 Want是一种对象&#xff0c;用于在应用组…

实践记录-docker-step1~5/10-参考docker官网步骤操作记录

参考来源&#xff1a; &#xff08;应用的容器化实践&#xff09;docker官方入门指南 https://docs.docker.com/get-started/ 本指南包含有关如何开始使用 Docker 的分步说明。本指南介绍如何&#xff1a; 将映像作为容器生成并运行。 使用 Docker Hub 共享映像。 使用带有数据…

OpenCv之简单的人脸识别项目(属性判断页面)

人脸识别 准备十二、属性判断页面1.导入所需的包2.设置窗口2.1定义窗口外观和大小2.2设置窗口背景2.2.1设置背景图片2.2.2创建label控件 3.定义预测性别脚本4.定义预测年龄脚本5.定义关闭窗口的函数6.按钮设计6.1预测性别按钮6.2预测年龄按钮6.3返回按钮 7.定义关键函数8.属性判…

python-opencv图像分割

文章目录 二值化图像骨骼连通域分割 二值化 所谓图像分割&#xff0c;就是将图像的目标和背景分离开来&#xff0c;更直观一点&#xff0c;就是把目标涂成白色&#xff0c;背景涂成黑色&#xff0c;言尽于此&#xff0c;是不是恍然大悟&#xff1a;这不就是二值化么&#xff1…

农业四情监测系统

TH-Q1农业&#xff0c;作为支撑国民经济建设与发展的基础产业&#xff0c;其稳定与高效的发展对于国家乃至全球的经济稳定具有举足轻重的意义。然而&#xff0c;农业的发展并非一帆风顺&#xff0c;它面临着诸如气候变化、病虫害、土壤质量等多种因素的挑战。在这一背景下&…

AJAX 跨域

这里写目录标题 同源策略JSONPJSONP 是怎么工作的JSONP 的使用原生JSONP实践CORS 同源策略 同源&#xff1a; 协议、域名、端口号 必须完全相同、 当然网页的URL和AJAX请求的目标资源的URL两者之间的协议、域名、端口号必须完全相同。 AJAX是默认遵循同源策略的&#xff0c;不…

yolov8摔倒检测(包含数据集+训练好的模型)

基于先进的YOLOv8模型&#xff0c;实现了一套高效可靠的人体摔倒检测系统。YOLOv8作为YOLO系列的最新成员&#xff0c;以其卓越的检测速度和准确性&#xff0c;在计算机视觉领域尤其是目标检测任务中表现出色。本系统不仅能够实时处理视频流或监控画面&#xff0c;还能对静态图…

Termux安装SSH服务与内网穿透工具实现远程SFTP传输文件

文章目录 前言1. 安装openSSH2. 安装cpolar3. 远程SFTP连接配置4. 远程SFTP访问4. 配置固定远程连接地址 前言 本教程主要介绍如何在安卓 Termux 系统中使用 SFTP 文件传输并结合[cpolar内网穿透工具](cpolar - 安全的内网穿透工具)轻松实现无公网IP远程传输&#xff0c;无需购…

斯坦福AI团队抄袭事件,清华回应:也算国际认可

近日&#xff0c;斯坦福大学人工智能&#xff08;AI&#xff09;团队的一项备受瞩目的研究——Llama3-V大模型&#xff0c;陷入了抄袭风波。该团队原本以其创新的模型和低廉的训练成本为亮点&#xff0c;声称能够在低成本下训练出性能卓越的SOTA多模态大模型。然而&#xff0c;…