尚庭公寓(五)

news2024/9/9 0:11:20

图片上传管理

由于公寓、房间等实体均包含图片信息,所以在新增或修改公寓、房间信息时,需要上传图片,因此我们需要实现一个上传图片的接口。

**1. 图片上传流程**

下图展示了新增房间或公寓时,上传图片的流程。

可以看出图片上传接口接收的是图片文件,返回的Minio对象的URL。

*2. 图片上传接口开发**

下面为该接口的具体实现

- **配置Minio Client**

  - 引入Minio Maven依赖

    在**common模块**的`pom.xml`文件增加如下内容:

spring框架专门用来接收文件的一个类 他里面包含文件 的内容和文件的各种信息 名称或者大小

前端接收到图片之后会保存到minio minio中每一个文件中都有一个url返回的是一个url

<dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
    </dependency>

- 配置Minio相关参数

    在`application.yml`中配置Minio的`endpoint`、`accessKey`、`secretKey`、`bucketName`等参数

    minio:
      endpoint: http://<hostname>:<port>
      access-key: <access-key>
      secret-key: <secret-key>
      bucket-name: <bucket-name>

    **注意**:上述`<hostname>`、`<port>`等信息需根据实际情况进行修改。

 - 在**common模块**中创建`com.atguigu.lease.common.minio.MinioConfiguration`,内容如下

    @Configuration
    @EnableConfigurationProperties(MinioProperties.class)
    public class MinioConfiguration {
    
        @Autowired
        private MinioProperties properties;
    
        @Bean
        public MinioClient minioClient() {
            return MinioClient.builder().endpoint(properties.getEndpoint()).credentials(properties.getAccessKey(), properties.getSecretKey()).build();
        }
    }

第一种方式:使用@value进行映射

第二种方式: - 在**common模块**中创建`com.atguigu.lease.common.minio.MinioProperties`,内容如下

    @ConfigurationProperties(prefix = "minio")
    @Data
    public class MinioProperties {
    
        private String endpoint;
    
        private String accessKey;
    
        private String secretKey;
        
        private String bucketName;
    }

configurationproperties就是把minio开头的类进行绑定

 但是没有注册

只需要

第二种方式

第一种方式只能逐个配置 第二种方式可以统一扫描

- **开发图片上传接口**

  - 编写Controller层逻辑

    在`FileUploadController`中增加如下内容
 

    @Tag(name = "文件管理")
    @RequestMapping("/admin/file")
    @RestController
    public class FileUploadController {
    
        @Autowired
        private FileService service;
    
        @Operation(summary = "上传文件")
        @PostMapping("upload")
        public Result<String> upload(@RequestParam MultipartFile file) {
    
            String url = service.upload(file);
            return Result.ok(url);
        }
    }

 **说明:**`MultipartFile`是Spring框架中用于处理文件上传的类,它包含了上传文件的信息(如文件名、文件内容等)。

  - 编写Service层逻辑

    - 在`FileService`中增加如下内容
  

      String upload(MultipartFile file);

    - 在`FileServiceImpl`中增加如下内容

   @Autowired
      private MinioProperties properties;
      
      @Autowired
      private MinioClient client;
      
      @Override
      public String upload(MultipartFile file) {
      
          try {
              boolean bucketExists = client.bucketExists(BucketExistsArgs.builder().bucket(properties.getBucketName()).build());
              if (!bucketExists) {
                  client.makeBucket(MakeBucketArgs.builder().bucket(properties.getBucketName()).build());
                  client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(properties.getBucketName()).config(createBucketPolicyConfig(properties.getBucketName())).build());
              }
      
              String filename = new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/" + UUID.randomUUID() + "-" + file.getOriginalFilename();
              client.putObject(PutObjectArgs.builder().
                      bucket(properties.getBucketName()).
                      object(filename).
                      stream(file.getInputStream(), file.getSize(), -1).
                      contentType(file.getContentType()).build());
      
              return String.join("/", properties.getEndpoint(), properties.getBucketName(), filename);
      
          } catch (Exception e) {
              e.printStackTrace();
          }
          return null;
      }
      
      private String createBucketPolicyConfig(String bucketName) {
      
          return """
                  {
                    "Statement" : [ {
                      "Action" : "s3:GetObject",
                      "Effect" : "Allow",
                      "Principal" : "*",
                      "Resource" : "arn:aws:s3:::%s/*"
                    } ],
                    "Version" : "2012-10-17"
                  }
                  """.formatted(bucketName);
      }

使用minio访问图片的时候 他会直接下载 是因为是以stream的方式

要想直接在网页里面展示的话只需要这行代码

   **注意**:
      
      上述`createBucketPolicyConfig`方法的作用是生成用于描述指定bucket访问权限的JSON字符串。最终生成的字符串格式如下,其表示,允许(`Allow`)所有人(`*`)获取(`s3:GetObject`)指定桶(`<bucket-name>`)的内容。
      
      ```json
      {
        "Statement" : [ {
          "Action" : "s3:GetObject",
          "Effect" : "Allow",
          "Principal" : "*",
          "Resource" : "arn:aws:s3:::<bucket-name>/*"
        } ],
        "Version" : "2012-10-17"
      }
      ``` 

由于公寓、房间的图片为公开信息,所以将其设置为所有人可访问。
      
    - **异常处理**
    
      - **问题说明**


    
        上述代码只是对`MinioClient`方法抛出的各种异常进行了捕获,然后打印了异常信息,目前这种处理逻辑,无论Minio是否发生异常,前端在上传文件时,总是会受到成功的响应信息。可按照以下步骤进行操作,查看具体现象
    
        关闭虚拟机中的Minio服务 

```bash
        systemctl stop minio
        ```
    
        启动项目,并上传文件,观察接收的响应信息
    
      - **问题解决思路**
    
        为保证前端能够接收到正常的错误提示信息,应该将Service方法的异常抛出到Controller方法中,然后在Controller方法中对异常进行捕获并处理。具体操作如下
    
        **Service层代码**
    

  @Override
        public String upload(MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException{
        
            boolean bucketExists = minioClient.bucketExists(
                    BucketExistsArgs.builder()
                            .bucket(properties.getBucketName())
                            .build());
            if (!bucketExists) {
                minioClient.makeBucket(
                        MakeBucketArgs.builder()
                                .bucket(properties.getBucketName())
                                .build());
                minioClient.setBucketPolicy(
                        SetBucketPolicyArgs.builder()
                                .bucket(properties.getBucketName())
                                .config(createBucketPolicyConfig(properties.getBucketName()))
                                .build());
            }
            String filename = new SimpleDateFormat("yyyyMMdd").format(new Date()) +
                    "/" + UUID.randomUUID() + "-" + file.getOriginalFilename();
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(properties.getBucketName())
                            .stream(file.getInputStream(), file.getSize(), -1)
                            .object(filename)
                            .contentType(file.getContentType())
                            .build());
        
            return String.join("/",properties.getEndpoint(),properties.getBucketName(),filename);
        }

    **Controller层代码**
    

 public Result<String> upload(@RequestParam MultipartFile file) {
            try {
                String url = service.upload(file);
                return Result.ok(url);
            } catch (Exception e) {
                e.printStackTrace();
                return Result.fail();
            }
        }

改动就是将service里面的异常 挪到了controller中

这样关闭mino之后前端就会正常反应失败

    - **全局异常处理**
    
        按照上述写法,所有的Controller层方法均需要增加`try-catch`逻辑,使用Spring MVC提供的**全局异常处理**功能,可以将所有处理异常的逻辑集中起来,进而统一处理所有异常,使代码更容易维护。
    
        具体用法如下,详细信息可参考[官方文档](https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-exceptionhandler.html):
    
        在**common模块**中创建`com.atguigu.lease.common.exception.GlobalExceptionHandler`类,内容如下

 @ControllerAdvice
        public class GlobalExceptionHandler {
        
            @ExceptionHandler(Exception.class)
            @ResponseBody
            public Result error(Exception e){
                e.printStackTrace();
                return Result.fail();
            }
        }

 上述代码中的关键注解的作用如下
    
        `@ControllerAdvice`用于声明处理全局Controller方法异常的类
    
        `@ExceptionHandler`用于声明处理异常的方法,`value`属性用于声明该方法处理的异常类型
    
        `@ResponseBody`表示将方法的返回值作为HTTP的响应体
    
        **注意:**
    
        全局异常处理功能由SpringMVC提供,因此需要在**common模块**的`pom.xml`中引入如下依赖
    

        <!--spring-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    - **修改Controller层代码**
    
        由于前文的`GlobalExceptionHandler`会处理所有Controller方法抛出的异常,因此Controller层就无序关注异常的处理逻辑了,因此Controller层代码可做出如下调整。
    

  public Result<String> upload(@RequestParam MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            String url = service.upload(file);
          return Result.ok(url);
        }

#### 7.2.2.9 公寓管理

公寓管理共有六个接口,下面逐一实现。

首先在`ApartmentController`中注入`ApartmentInfoService`,如下
 

@Tag(name = "公寓信息管理")
@RestController
@RequestMapping("/admin/apartment")
public class ApartmentController {

    @Autowired
    private ApartmentInfoService service;
}

##### 1. 保存或更新公寓信息

- **查看请求的数据结构**

  查看**web-admin模块**中的`com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitVo`类,内容如下:
 

@Schema(description = "公寓信息")
  @Data
  public class ApartmentSubmitVo extends ApartmentInfo {
  
      @Schema(description="公寓配套id")
      private List<Long> facilityInfoIds;
  
      @Schema(description="公寓标签id")
      private List<Long> labelIds;
  
      @Schema(description="公寓杂费值id")
      private List<Long> feeValueIds;
  
      @Schema(description="公寓图片id")
      private List<GraphVo> graphVoList;
  
  }

- **编写Controller层逻辑**

  在`ApartmentController`中增加如下内容
 

  @Operation(summary = "保存或更新公寓信息")
  @PostMapping("saveOrUpdate")
  public Result saveOrUpdate(@RequestBody ApartmentSubmitVo apartmentSubmitVo) {
      service.saveOrUpdateApartment(apartmentSubmitVo);
      return Result.ok();
  }

- **编写Service层逻辑**

  - 在`ApartmentInfoService`中增加如下内容


    void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo);
 - 在`ApartmentInfoServiceImpl`中增加如下内容

    **注意**:所需`Service`和`Mapper`的注入语句省略未写。
    @Override
    public void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo) {
        boolean isUpdate = apartmentSubmitVo.getId()!=null;
        super.saveOrUpdate(apartmentSubmitVo);
    
        if (isUpdate){
            //1.删除图片列表
            LambdaQueryWrapper<GraphInfo> graphQueryWrapper = new LambdaQueryWrapper<>();
            graphQueryWrapper.eq(GraphInfo::getItemType, ItemType.APARTMENT);
            graphQueryWrapper.eq(GraphInfo::getItemId,apartmentSubmitVo.getId());
            graphInfoService.remove(graphQueryWrapper);
    
            //2.删除配套列表
            LambdaQueryWrapper<ApartmentFacility> facilityQueryWrapper = new LambdaQueryWrapper<>();
            facilityQueryWrapper.eq(ApartmentFacility::getApartmentId,apartmentSubmitVo.getId());
            apartmentFacilityService.remove(facilityQueryWrapper);
    
            //3.删除标签列表
            LambdaQueryWrapper<ApartmentLabel> labelQueryWrapper = new LambdaQueryWrapper<>();
            labelQueryWrapper.eq(ApartmentLabel::getApartmentId,apartmentSubmitVo.getId());
            apartmentLabelService.remove(labelQueryWrapper);
    
            //4.删除杂费列表
            LambdaQueryWrapper<ApartmentFeeValue> feeQueryWrapper = new LambdaQueryWrapper<>();
            feeQueryWrapper.eq(ApartmentFeeValue::getApartmentId,apartmentSubmitVo.getId());
            apartmentFeeValueService.remove(feeQueryWrapper);
    
        }
    
        //1.插入图片列表
        List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();
        if (!CollectionUtils.isEmpty(graphVoList)){
            ArrayList<GraphInfo> graphInfoList = new ArrayList<>();
            for (GraphVo graphVo : graphVoList) {
                GraphInfo graphInfo = new GraphInfo();
                graphInfo.setItemType(ItemType.APARTMENT);
                graphInfo.setItemId(apartmentSubmitVo.getId());
                graphInfo.setName(graphVo.getName());
                graphInfo.setUrl(graphVo.getUrl());
                graphInfoList.add(graphInfo);
            }
            graphInfoService.saveBatch(graphInfoList);
        }
    
    
        //2.插入配套列表
        List<Long> facilityInfoIdList = apartmentSubmitVo.getFacilityInfoIds();
        if (!CollectionUtils.isEmpty(facilityInfoIdList)){
            ArrayList<ApartmentFacility> facilityList = new ArrayList<>();
            for (Long facilityId : facilityInfoIdList) {
                ApartmentFacility apartmentFacility = new ApartmentFacility();
                apartmentFacility.setApartmentId(apartmentSubmitVo.getId());
                apartmentFacility.setFacilityId(facilityId);
                facilityList.add(apartmentFacility);
            }
            apartmentFacilityService.saveBatch(facilityList);
        }
    
    
        //3.插入标签列表
        List<Long> labelIds = apartmentSubmitVo.getLabelIds();
        if (!CollectionUtils.isEmpty(labelIds)) {
            List<ApartmentLabel> apartmentLabelList = new ArrayList<>();
            for (Long labelId : labelIds) {
                ApartmentLabel apartmentLabel = new ApartmentLabel();
                apartmentLabel.setApartmentId(apartmentSubmitVo.getId());
                apartmentLabel.setLabelId(labelId);
                apartmentLabelList.add(apartmentLabel);
            }
            apartmentLabelService.saveBatch(apartmentLabelList);
        }
    
    
        //4.插入杂费列表
        List<Long> feeValueIds = apartmentSubmitVo.getFeeValueIds();
        if (!CollectionUtils.isEmpty(feeValueIds)) {
            ArrayList<ApartmentFeeValue> apartmentFeeValueList = new ArrayList<>();
            for (Long feeValueId : feeValueIds) {
                ApartmentFeeValue apartmentFeeValue = new ApartmentFeeValue();
                apartmentFeeValue.setApartmentId(apartmentSubmitVo.getId());
                apartmentFeeValue.setFeeValueId(feeValueId);
                apartmentFeeValueList.add(apartmentFeeValue);
            }
            apartmentFeeValueService.saveBatch(apartmentFeeValueList);
        }
    }

##### 2. 根据条件分页查询公寓列表

- **查看请求和响应的数据结构**

  - **请求数据结构**

    - `current`和`size`为分页相关参数,分别表示**当前所处页面**和**每个页面的记录数**。

    - `ApartmentQueryVo`为公寓的查询条件,详细结构如下:
 

  @Data
      @Schema(description = "公寓查询实体")
      public class ApartmentQueryVo {
      
          @Schema(description = "省份id")
          private Long provinceId;
      
          @Schema(description = "城市id")
          private Long cityId;
      
          @Schema(description = "区域id")
          private Long districtId;
      }

 - **响应数据结构**

    单个公寓信息记录可查看`com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo`,内容如下:
 

@Data
    @Schema(description = "后台管理系统公寓列表实体")
    public class ApartmentItemVo extends ApartmentInfo {
    
        @Schema(description = "房间总数")
        private Long totalRoomCount;
    
        @Schema(description = "空闲房间数")
        private Long freeRoomCount;
    
    }

 **配置Mybatis-Plus分页插件**

  在**common模块**中的`com.atguigu.lease.common.mybatisplus.MybatisPlusConfiguration`中增加如下内容:
 

  @Bean
  public MybatisPlusInterceptor mybatisPlusInterceptor() {
      MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
      interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
      return interceptor;
  }

- **接口实现**

  - **编写Controller层逻辑**

    在`ApartmentController`中增加如下内容:
 

   @Operation(summary = "根据条件分页查询公寓列表")
    @GetMapping("pageItem")
    public Result<IPage<ApartmentItemVo>> pageItem(@RequestParam long current, @RequestParam long size, ApartmentQueryVo queryVo) {
    
        IPage<ApartmentItemVo> page = new Page<>(current, size);
        IPage<ApartmentItemVo> list = service.pageApartmentItemByQuery(page, queryVo);
        return Result.ok(list);
    }

 - **编写Service层逻辑**

    - 在`ApartmentInfoService`中增加如下内容
 

   IPage<ApartmentItemVo> pageApartmentItemByQuery(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo);

    - 在`ApartmentInfoServiceImpl`中增加如下内容
 

  @Override
      public IPage<ApartmentItemVo> pageApartmentItemByQuery(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo) {
      
          return apartmentInfoMapper.pageApartmentItemByQuery(page, queryVo);
      }

- **编写Mapper层逻辑**

    - 在`ApartmentInfoMapper`中增加如下内容

   IPage<ApartmentItemVo> pageApartmentItemByQuery(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo);

 - 在`ApartmentInfoMapper.xml`中增加如下内容

 <select id="pageItem" resultType="com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo">
          select ai.id,
                 ai.name,
                 ai.introduction,
                 ai.district_id,
                 ai.district_name,
                 ai.city_id,
                 ai.city_name,
                 ai.province_id,
                 ai.province_name,
                 ai.address_detail,
                 ai.latitude,
                 ai.longitude,
                 ai.phone,
                 ai.is_release,
                 ifnull(tc.cnt,0) total_room_count,
                 ifnull(tc.cnt,0) - ifnull(cc.cnt,0) free_room_count
          from (select id,
                       name,
                       introduction,
                       district_id,
                       district_name,
                       city_id,
                       city_name,
                       province_id,
                       province_name,
                       address_detail,
                       latitude,
                       longitude,
                       phone,
                       is_release
                from apartment_info
                  <where>
                      is_deleted=0
                      <if test="queryVo.provinceId != null">
                          and province_id=#{queryVo.provinceId}
                      </if>
                      <if test="queryVo.cityId != null">
                          and city_id=#{queryVo.cityId}
                      </if>
                      <if test="queryVo.districtId != null">
                          and district_id=#{queryVo.districtId}
                      </if>
                  </where>
                ) ai
                   left join
               (select apartment_id,
                       count(*) cnt
                from room_info
                where is_deleted = 0
                  and is_release = 1
                group by apartment_id) tc
               on ai.id = tc.apartment_id
                   left join
               (select apartment_id,
                       count(*) cnt
                from lease_agreement
                where is_deleted = 0
                  and status in (2, 5)
                group by apartment_id) cc
               on ai.id = cc.apartment_id
      
      </select>

  **注意:**
  
  默认情况下Knife4j为该接口生成的接口文档如下图所示,其中的queryVo参数不方便调试
  
  <img src="images/flat-param-false.png" style="zoom:50%; zoom:50%;border: 1px solid #000;" />
  
  可在application.yml文件中增加如下配置,将queryVo做打平处理
  

  springdoc:
    default-flat-param-object: true

  将`spring.default-flat-param-object`参数设置为`true`后,效果如下。
  
  <img src="images/flat-param-true.png" style="zoom:50%; zoom:50%;border: 1px solid #000;" />

116(没看懂)

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

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

相关文章

翻译: 可视化深度学习神经网络二

并甚至在图像识别之外做各种各样智能的东西也许你也想分解成一些抽象的层 例如句子的分析涉及到把原始的语音提出一些独特的声音构成一些音节再构成词再构成词组以及更为抽象的思想等。 但回到这些实际是怎样工作的把你自己现在就放到这个的情景怎样来设计 如何在让这层中的激励…

阿里云主机 安装RabbitMQ

一、操作系统 用的是Alibaba Cloud Linux release 3 (Soaring Falcon)系统&#xff0c;可以通过命令&#xff1a;lsb_release -a 查看系统信息。 二、安装RabbitMQ RabbitMQ 是基于 Erlang 语言构建的&#xff0c;要安装RabbitMQ&#xff0c;需先安装Erlang环境。通过Erlang V…

SearchGPT:搜索引擎市场的潜在游戏规则改变者

关注公众号网络研究观获取更多内容。 OpenAI最近发布的SearchGPT原型标志着搜索技术领域的重大进展。我一直在等待这一天&#xff0c;任何关注搜索和搜索引擎优化领域的人也是如此。我们有充分的理由相信&#xff0c;这一举措很有可能颠覆长期由谷歌等巨头主导的搜索引擎市场&…

宠物医院预约系统-计算机毕业设计源码60818

目录 摘要 Abstract 第一章 绪论 1.1 选题背景及意义 1.2 国内外研究现状 1.3 研究方法 第二章 相关技术介绍 2.1 MySQL简介 2.2 Java编程语言 2.3 B/S模式 2.4 springboot框架 第三章 宠物医院预约系统 系统分析 3.1 系统目标 3.2 系统可行性分析 3.2.1 技术可行…

链式队列实现

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍+ 收藏⭐ + 留言​📝唯有主动付出,才有丰富的果实获得收获! 在计算机科学中,队列是一种先进先出(FIFO, First In First Out)的数据结构…

.NET周刊【7月第4期 2024-07-28】

国内文章 .NET 高性能缓冲队列实现 BufferQueue https://mp.weixin.qq.com/s/fUhJpyPqwcmb3whuV3CDyg BufferQueue 是一个用 .NET 编写的高性能的缓冲队列实现&#xff0c;支持多线程并发操作。 项目地址&#xff1a;https://github.com/eventhorizon-cli/BufferQueue 项目…

Robot Operating System——远程修改日志等级

大纲 日志输出Node修改其他Node日志等级的Node获取日志等级设置日志等级 测试默认等级Debug等级Warn等级Error等级 完整代码 在任何系统中&#xff0c;日志功能的重要性都是不容忽视的。日志功能为开发者、维护者甚至用户提供了一个关键的工具&#xff0c;以监控、理解和调试系…

基于Windows Docker desktop搭建pwn环境

安装虚拟机很重&#xff0c;占空间&#xff0c;影响速度。 今天试了下用Windows下的Docker搭建pwn做题环境&#xff0c;搭配MobaXterm真的很好! 一、Windows下安装Docker desktop 网上参考文章很多&#xff0c;不赘述。 说明&#xff1a;去https://www.docker.com/products/d…

PHP经销商订货管理系统小程序源码

经销商订货管理系统&#xff1a;重塑供应链效率的利器 &#x1f680; 开篇&#xff1a;解锁供应链管理的新纪元 在竞争激烈的商业环境中&#xff0c;经销商作为供应链的关键一环&#xff0c;其订货效率直接影响到整个供应链的流畅度和响应速度。传统的订货方式往往繁琐、易出…

【C++深度探索】深入解析AVL树的底层实现机制

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;C从入门至进阶 这里将会不定期更新有关C/C的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 前言 AV…

学习大数据DAY26 简单数据清洗练习和 Shell 脚本中的数据库编程

目录 上机练习 14 mysql 命令 sql 语句实现步骤 shell 脚本导入 csv 格式文件到 mysql 数据库 secure-file-priv 特性 把文件拷贝到 mysql 指定目录下 上机练习 15 mysqldump 命令 上机练习 16 上机练习 14 运用上一节课学的 Shell 工具完成 1. 清洗数据《infotest.t…

黑马头条Day12-项目部署_持续集成

一、今日内容介绍 1. 什么是持续集成 持续集成&#xff08;Continuous integration&#xff0c;简称CI&#xff09;&#xff0c;指的是频繁地&#xff08;一天多次&#xff09;将代码集成到主干。 持续集成的组成要素&#xff1a; 一个自动构建过程&#xff0c;从检出代码、…

Markdown 语法大全详解

Markdown 语法大全详解 Markdown是一种轻量级标记语言&#xff0c;排版语法简洁&#xff0c;让人们更多地关注内容本身而非排版。它使用易读易写的纯文本格式编写文档&#xff0c;可与HTML混编&#xff0c;可导出 HTML、PDF 以及本身的 .md 格式的文件。因简洁、高效、易读、易…

langchain 入门指南 - 实现一个多模态 chatbot

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 在前面的文章中&#xff0c;我们学会了如何通过 langchain 实现本地文档库的 QA&#xff0c;又或者通过 langchain 来实现对话式的问答系…

2024下半年,前端的技术风口来了

“ 你近期有体验过哪些大模型产品呢&#xff1f; 你有使用大模型API做过一些实际开发吗&#xff1f; 在你日常开发中&#xff0c;可以与大模型相关应用结合来完成工作吗&#xff1f; ” **最近&#xff0c;一直在和同事聊&#xff0c;关于前端可以用大模型干点啥&#xff…

Vue2和Vue3实战代码中的小差异(实时更新)

目录 前言1. 未使用自闭合标签2. 事件名连字符3. 换行符4. 弃用.sync5. 弃用slot 前言 以下文章实时更新&#xff0c;主打记录差异 1. 未使用自闭合标签 104:7 error Require self-closing on Vue.js custom components (<el-table-column>) vue/html-self-closing✖…

【华为OD机考】2024D卷最全真题【完全原创题解 | 详细考点分类 | 不断更新题目】

可上 欧弟OJ系统 练习华子OD、大厂真题 绿色聊天软件戳 od1441了解算法冲刺训练&#xff08;备注【CSDN】否则不通过&#xff09; 文章目录 相关推荐阅读栈常规栈单调栈 队列&#xff08;题目极少&#xff0c;几乎不考&#xff09;哈希哈希集合哈希表 前缀和双指针同向双指针 贪…

我与C语言二周目邂逅vlog——6.文件操作

1. 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失 了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久…

从区块链到股票市场的全方位布局,广辉团队创新引领共创财富未来!

广辉团队作为一家涉足互联网投资领域的团队&#xff0c;在短短几年内迅速崛起&#xff0c;成为行业中的佼佼者。这支团队汇聚了来自各行各业的商业精英&#xff0c;并在互联网金融领域创造了巨大的财富。业务范畴涵盖了资产管理、资本市场、消费金融、保险市场、零售银行及财富…

SSM项目实战

项目实战一 这里实战的是我Javaweb项目实战&#xff08;后端篇&#xff09;的改写 Javaweb项目实战用到的技术是servletvue3 这里用到的是springspringmvcmybatisvue3 项目结构 步骤一:导入需要依赖 <!--mybatis核心--><dependency><groupId>org.mybatis<…