如何使用Spring Boot,Thymeleaf和Bootstrap上传多个文件

news2024/11/19 5:49:37

在本教程中,我将向您展示如何使用Spring Boot,Thymeleaf和Bootstrap上传多个文件。我们还使用 Spring Web MultipartFile界面来处理 HTTP 多部分请求并显示上传文件的列表。

春季启动多文件上传与百里香叶概述

我们的 Spring Boot + Thymeleaf 多文件上传示例将具有以下功能:

  • 将多个文件上传到服务器中的静态文件夹
  • 使用链接从服务器下载文件
  • 获取文件信息列表(文件名和URL)

– 这是多文件上传表格:

– 如果其中一个文件超过特定的最大大小:

– 如果某些文件与上传的文件同名:

– 这是存储所有上传文件的静态文件夹:

– 您可以查看带有下载链接的上传文件列表:

在本教程中,我不解释删除文件的方法。如果你想知道这一点,只需访问:
弹簧启动删除文件示例与百里香叶

或者使用以下教程添加分页:
春季启动百里香叶分页示例

科技

  • Java 8
  • Spring Boot 2.7 (with Spring Web MVC, Thymeleaf)
  • Maven 3.6.1
  • Bootstrap 4
  • jQuery 3.6.1

项目结构

让我简要解释一下。

FileInfo包含上传文件的信息。
FilesStorageService帮助我们初始化存储,保存新文件,加载文件,获取文件信息列表,删除文件。
FileController和FilesStorageService用于处理多个文件上传/下载和模板请求。
FileUploadExceptionAdvice在控制器处理文件上传时处理异常。
template存储项目的 HTML 模板文件。

– application.properties 包含 Servlet Multipart 的配置。
– 
uploads 是用于存储文件的静态文件夹。
– pom.xml 用于 Spring Boot 依赖项。​​​​​​​​​​​​​​

创建和设置Spring Boot MultiFile Upload项目

使用 Spring Web 工具或开发工具(Spring Tool Suite、Eclipse、Intellij)创建 Spring Boot 项目。

然后打开pom.xml并为Spring Web,Thymeleaf,Bootstrap,Jquery添加依赖项:

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

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

<dependency>
	<groupId>org.webjars</groupId>
	<artifactId>bootstrap</artifactId>
	<version>4.6.2</version>
</dependency>

<dependency>
	<groupId>org.webjars</groupId>
	<artifactId>jquery</artifactId>
	<version>3.6.1</version>
</dependency>

<dependency>
	<groupId>org.webjars</groupId>
	<artifactId>webjars-locator-core</artifactId>
</dependency>

为文件存储创建服务

首先,我们需要一个将在控制器中自动连接的接口。
服务文件夹中,创建类似于以下代码的FilesStorageService接口:

service/FilesStorageService.java

package com.bezkoder.spring.thymeleaf.file.upload.service;

import java.nio.file.Path;
import java.util.stream.Stream;

import org.springframework.core.io.Resource;
import org.springframework.web.multipart.MultipartFile;

public interface FilesStorageService {
  public void init();

  public void save(MultipartFile file);

  public Resource load(String filename);
  
  public void deleteAll();

  public Stream<Path> loadAll();
}

现在我们创建接口的实现。

service/FilesStorageServiceImpl.java

package com.bezkoder.spring.thymeleaf.file.upload.service;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;

@Service
public class FilesStorageServiceImpl implements FilesStorageService {
  private final Path root = Paths.get("./uploads");

  @Override
  public void init() {
    try {
      Files.createDirectories(root);
    } catch (IOException e) {
      throw new RuntimeException("Could not initialize folder for upload!");
    }
  }

  @Override
  public void save(MultipartFile file) {
    try {
      Files.copy(file.getInputStream(), this.root.resolve(file.getOriginalFilename()));
    } catch (Exception e) {
      if (e instanceof FileAlreadyExistsException) {
        throw new RuntimeException("Filename already exists.");
      }

      throw new RuntimeException(e.getMessage());
    }
  }

  @Override
  public Resource load(String filename) {
    try {
      Path file = root.resolve(filename);
      Resource resource = new UrlResource(file.toUri());

      if (resource.exists() || resource.isReadable()) {
        return resource;
      } else {
        throw new RuntimeException("Could not read the file!");
      }
    } catch (MalformedURLException e) {
      throw new RuntimeException("Error: " + e.getMessage());
    }
  }

  @Override
  public void deleteAll() {
    FileSystemUtils.deleteRecursively(root.toFile());
  }

  @Override
  public Stream<Path> loadAll() {
    try {
      return Files.walk(this.root, 1).filter(path -> !path.equals(this.root)).map(this.root::relativize);
    } catch (IOException e) {
      throw new RuntimeException("Could not load the files!");
    }
  }
}

为多个文件上传创建控制器

控制器包中,我们创建FileController .

controller/FileController.java

package com.bezkoder.spring.thymeleaf.file.upload.controller;
// ...
import com.bezkoder.spring.thymeleaf.file.upload.service.FilesStorageService;

@Controller
public class FileController {

  @Autowired
  FilesStorageService storageService;

  @GetMapping("/")
  public String homepage() {
    return "redirect:/files";
  }

  @GetMapping("/files/new")
  public String newFile(Model model) {
    return "upload_form";
  }

  @PostMapping("/files/upload")
  public String uploadFiles(Model model, @RequestParam("files") MultipartFile[] files) {
    ...

    return "upload_form";
  }

  @GetMapping("/files")
  public String getListFiles(Model model) {
    ...

    return "files";
  }

  @GetMapping("/files/{filename:.+}")
  public ResponseEntity<Resource> getFile(@PathVariable String filename) {
    ...

    // return File
  }
}

@Controller注释用于定义控制器。
@GetMapping@PostMapping注释用于将 HTTP GET & POST 请求映射到特定的处理程序方法并返回适当的模板文件。
@Autowired我们使用将 FilesStorageService bean 的实现注入到局部变量中。​​​​​​​​​​​​​​​​​​​​​

设置模板

在 src/main/resources 文件夹中,按以下结构创建文件夹和文件:

页眉和页脚

我们将使用百里香叶碎片()来重用一些常见的部分,例如页眉和页脚。
让我们为它们编写 HTML 代码。th:fragment

fragments/footer.html

<footer class="text-center">
  Copyright © BezKoder
</footer>

以及包含导航栏的标题:

fragments/header.html

<header th:fragment="header">
  <nav class="navbar navbar-expand-md bg-dark navbar-dark mb-3">
    <a class="navbar-brand" th:href="@{/files}">
      BezKoder
    </a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#topNavbar">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="topNavbar">
      <ul class="navbar-nav">
        <li class="nav-item">
          <a class="nav-link" th:href="@{/files/new}">Upload</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" th:href="@{/files}">Files</a>
        </li>
      </ul>
    </div>
  </nav>
</header>

现在我们需要创建HTML文件,然后导入Thymeleaf片段,Bootstrap,jQuery和Font Awesome。

多文件上传表单

upload_form.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0" />
  <title>Thymeleaf Multiple File Upload example</title>
  <link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" />
  <script type="text/javascript" th:src="@{/webjars/jquery/jquery.min.js}"></script>
  <script type="text/javascript" th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
</head>

<body>
  <div th:replace="fragments/header :: header"></div>

  -- Multiple file upload form --

  <div th:replace="fragments/footer :: footer"></div>
</body>

</html>

文件列表

files.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0" />
  <title>Thymeleaf Multiple File Upload example</title>

  <link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
    integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
    crossorigin="anonymous" referrerpolicy="no-referrer" />
  <script type="text/javascript" th:src="@{/webjars/jquery/jquery.min.js}"></script>
  <script type="text/javascript" th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
</head>

<body>
  <div th:replace="fragments/header :: header"></div>

  -- list of files display --
  
  <div th:replace="fragments/footer :: footer"></div>
</body>

</html>

实现多文件上传功能

我们使用@GetMapping@PostMapping注释用于将HTTP GET和POST请求映射到特定的处理程序方法:​​​​​​​

  • 获取/文件/新:newFile() – 返回upload_form.html模板
  • 发布/文件/上传:ploadFiles() – 上传多个文件u

uploadFiles()是主要方法我们使用MultipartFile[] files参数,Java 8 Stream API 来处理数组中的每个文件。​​​​​​​

FileController.java

import com.bezkoder.spring.thymeleaf.file.upload.service.FilesStorageService;

@Controller
public class FileController {

  @Autowired
  FilesStorageService storageService;

  @GetMapping("/files/new")
  public String newFile(Model model) {
    return "upload_form";
  }

  @PostMapping("/files/upload")
  public String uploadFiles(Model model, @RequestParam("files") MultipartFile[] files) {
    List<String> messages = new ArrayList<>();

    Arrays.asList(files).stream().forEach(file -> {
      try {
        storageService.save(file);
        messages.add(file.getOriginalFilename() + " [Successful]");
      } catch (Exception e) {
        messages.add(file.getOriginalFilename() + " <Failed> - " + e.getMessage());
      }
    });

    model.addAttribute("messages", messages);

    return "upload_form";
  }
}

upload_form.html

<form
  id="uploadForm"
  method="post"
  th:action="@{/files/upload}"
  enctype="multipart/form-data">
  <input type="file" multiple name="files" />
  <button class="btn btn-sm btn-outline-success float-right" type="submit">
    Upload
  </button>
</form>

<div th:if="${messages != null}" class="alert alert-secondary alert-dismissible fade show message mt-3" role="alert">
  <div th:each="message : ${messages}">[[${message}]]</div>
  <button type="button" class="close btn-sm" data-dismiss="alert" aria-label="Close">
    <span aria-hidden="true">×</span>
  </button>
</div>

显示文件列表

首先,我们需要创建具有name和url字段的FileInfo模型:&.​​​​​​​nameurl

model/FileInfo.java

package com.bezkoder.spring.thymeleaf.file.upload.model;

public class FileInfo {
  
  private String name;
  private String url;

  public FileInfo(String name, String url) {
    this.name = name;
    this.url = url;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getUrl() {
    return this.url;
  }

  public void setUrl(String url) {
    this.url = url;
  }
}

在控制器中,我们将返回FileInfo对象列表作为模型属性。
​​​​​​​@GetMapping@PostMapping注释用于将 HTTP GET & POST 请求映射到特定的处理程序方法:

  • 获取/文件: getListFiles()– 返回文件.html模板
  • 获取 /files/[文件名]: getFile()– 下载filename文件​​​​​​​

FileController.java

import com.bezkoder.spring.thymeleaf.file.upload.model.FileInfo;
import com.bezkoder.spring.thymeleaf.file.upload.service.FilesStorageService;

@Controller
public class FileController {

  @Autowired
  FilesStorageService storageService;

  // ...

  @GetMapping("/")
  public String homepage() {
    return "redirect:/files";
  }

  @GetMapping("/files")
  public String getListFiles(Model model) {
    List<FileInfo> fileInfos = storageService.loadAll().map(path -> {
      String filename = path.getFileName().toString();
      String url = MvcUriComponentsBuilder
          .fromMethodName(FileController.class, "getFile", path.getFileName().toString()).build().toString();

      return new FileInfo(filename, url);
    }).collect(Collectors.toList());

    model.addAttribute("files", fileInfos);

    return "files";
  }

  @GetMapping("/files/{filename:.+}")
  public ResponseEntity<Resource> getFile(@PathVariable String filename) {
    Resource file = storageService.load(filename);

    return ResponseEntity.ok()
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"").body(file);
  }
}

files.html

<div class="container-fluid" style="max-width: 600px; margin: 0 auto;">
  <h2 class="text-center">List of Files</h2>

  <div th:if="${files.size() > 0}">
    <table class="table table-hover">
      <thead class="thead-light">
        <tr>
          <th scope="col">File Name</th>
          <th scope="col">Link</th>
          <th scope="col">Actions</th>
        </tr>
      </thead>
      <tbody>
        <tr th:each="file : ${files}">
          <td>[[${file.name}]]</td>
          <td><a th:href="@{${file.url}}">Download</a></td>
          <td>
            <a th:href="@{'/files/delete/' + ${file.name}}" th:fileName="${file.name}" id="btnDelete"
              title="Delete this file" class="fa-regular fa-trash-can icon-dark btn-delete"></a>
          </td>
        </tr>
      </tbody>
    </table>
  </div>

  <div th:unless="${files.size() > 0}">
    <span>No files found!</span>
  </div>
</div>

要删除文件,请访问以下教程:
弹簧启动删除文件示例与百里香叶

为 Servlet 配置多部分文件

让我们定义可以在 application.properties 中上传的最大文件大小,如下所示:

spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=1MB

spring.servlet.multipart.max-file-size:每个请求的最大文件大小。
spring.servlet.multipart.max-request-size:多部分/表单数据的最大请求大小。

处理文件上传异常

这是我们处理请求超过最大上传大小的情况的地方。系统将抛出MaxUploadSizeExceededException,我们将使用@ControllerAdvice和@ExceptionHandler注释来处理异常。​​​​​​​

exception/FileUploadExceptionAdvice.java

package com.bezkoder.spring.thymeleaf.file.upload.exception;

import org.springframework.web.multipart.MaxUploadSizeExceededException;

import java.util.ArrayList;
import java.util.List;

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class FileUploadExceptionAdvice {

  @ExceptionHandler(MaxUploadSizeExceededException.class)
  public String handleMaxSizeException(Model model, MaxUploadSizeExceededException e) {
    List<String> messages = new ArrayList<>();
    messages.add("One of selected files is too large!");

    model.addAttribute("messages", messages);

    return "upload_form";
  }
}

初始化存储

我们需要运行​​​​​​​FilesStorageService的init()方法(如有必要deleteAll())。所以打开ThymeleafMultipleFileUploadApplication.java并实现CommandLineRunnerrun()方法:​​​​​​​​​​​​​​​​​​​​​

package com.bezkoder.spring.thymeleaf.file.upload;

import javax.annotation.Resource;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.bezkoder.spring.thymeleaf.file.upload.service.FilesStorageService;

@SpringBootApplication
public class ThymeleafMultipleFileUploadApplication implements CommandLineRunner {

  @Resource
  FilesStorageService storageService;

  public static void main(String[] args) {
    SpringApplication.run(ThymeleafMultipleFileUploadApplication.class, args);
  }

  @Override
  public void run(String... arg) throws Exception {
//    storageService.deleteAll();
    storageService.init();
  }
}

使用百里香叶运行春季引导多文件上传示例

使用以下命令运行 Spring 引导应用程序:mvn spring-boot:run

源代码

您可以在 Github 上找到本教程的完整源代码。

用于删除文件:
弹簧启动删除文件示例与百里香叶

结论

今天我们已经学习了如何使用多部分文件创建 Spring 启动 Thymeleaf 多文件上传应用程序,并使用静态文件夹获取文件信息。

或带前端的全栈: – Angular + Spring Boot:文件上传示例 – React + Spring Boot:
文件上传示例

您还可以了解如何上传Excel / CSV文件并将内容存储在MySQL数据库中,并带有以下帖子: – Spring Boot:将Excel文件数据上传/导入MySQL数据库 – Spring Boot:将CSV文件数据上传/导入MySQL数据库
 

如果要像这样将文件存储在数据库中:

您可以在以下位置找到说明:
Spring 引导上传/下载文件到/从数据库示例

快乐学习!再见。

延伸阅读

– Spring Boot 上传多个文件 Rest API
– Spring Boot Thymeleaf CRUD 示例 – Spring Boot Thymeleaf 分页和排序示例

异常处理:
– Spring Boot @ControllerAdvice & @ExceptionHandler 示例 – Spring Boot 中的@RestControllerAdvice示例

单元测试:
– JPA 存储库的弹簧引导单元测试
– 其余控制器的弹簧引导单元测试

部署:
– 在 AWS 上部署 Spring Boot 应用程序 – Elastic Beanstalk

关联:
– 带有 JPA 的 Spring Boot 一对一示例,Hibernate – 使用 JPA 的 Spring Boot One To More 示例,Hibernate – 使用 JPA 的 Spring Boot Many to Many 示例,Hibernate

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

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

相关文章

如何通过“推送文案的千人千面”有效提升用户转化和留存

随着互联网用户红利消失和获客成本不断飙升、互联网正从“增量时代”迈向“存量时代”。 通过精细化运营激活存量用户&#xff0c;从而带动企业的第二增长曲线发力&#xff0c;已经成为行业共识。 在此趋势下&#xff0c;企业纷纷开始搭建私域流量池&#xff08;如会员体系、…

HTML学生个人网站作业设计:HTML做一个公司官网首页页面(纯html代码)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

基于鹰优化算法和粒子群优化算法结合焊接梁设计,拉伸/压缩,压力容器,悬臂梁设计的应用(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【Linux学习】进程概念(下)

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 进程概念&#xff08;下&#xff09;&#x1f35f;进程优先级&#x1f35f;进程切换&#x1f35f…

Logistic回归(随机梯度上升算法)

梯度上升算法 def gradAscent(dataMatIn, classLabels):dataMatrix np.mat(dataMatIn) #转换成numpy的matlabelMat np.mat(classLabels).transpose() #转换成numpy的mat,并进行转置m, n np.shape(dataMa…

Elasticsearch入门(三)高级查询操作

前期准备 先把上一个内容的 student 索引删除掉 在 Postman 中&#xff0c;向 ES 服务器发 DELETE 请求&#xff1a;http://127.0.0.1:9200/student 在 Postman 中&#xff0c;向 ES 服务器发五个 POST 请求&#xff1a;http://127.0.0.1:9200/student/_doc/100x x分别是1&…

Linux下用文件IO的方式操作GPIO

1.首先查看系统中有没有 “/sys/class/gpio” 这个文件夹。如果没有请在编译内核的时候通过make menuconfig加入。 Device Drivers -> GPIO Support ->/sys/class/gpio/… (sysfs interface)。2./sys/class/gpio 的使用说明 如果是在已经适配好的 Linux 内核上&#xf…

【Vue路由】路由的简介及基本使用

文章目录路由的简介路由的基本使用几个使用路由的注意点组件分类组件去向路由组件路由的简介 再说路由之前&#xff0c;我们先来看看生活中的路由器&#xff0c;它的作用就是让多台设备同时上网&#xff0c;同时每一个接口对应一个网络设备&#xff1a; 我们可以这样来看&am…

面试题分享|Linux定时任务调度机制是怎么回事?

一. 前言 在求职过程中&#xff0c;有过面试经历的小伙伴们都知道&#xff0c;企业对linux的考察还是蛮频繁的。作为java开发程序员&#xff0c;在企业中我们的服务器都是在linux环境中部署的&#xff0c;所以熟练使用linux已经成为企业招聘人才的基本需求。但很多小伙伴在学习…

基于蚁群算法的车辆路径规划问题的研究(Matlab代码实现)

目录 1 概述 1.1研究背景 2 运行结果 3 Matlab代码实现 4 结语 5 参考文献 1 概述 车辆路径规划问题&#xff08;Vehicle Routing Problem,VRP&#xff09;是现代物流配送过程中的关键环节,而且其在众多领域中都有广泛的应用,因此它的提出引起了不同学科的专家和物流管理…

LeetCode HOT 100 —— 146.LRU缓存

题目 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则返回…

TI Lab_SRR学习_3 速度扩展_1 预备知识

首先先了解一下SRR模式下的chirp配置是什么样子,SRR的chirp的配置文件可以看(位置位于toolbox中)C:\mmwave_automotive_toolbox_3_1_0__win\mmwave_automotive_toolbox_3_1_0\labs\lab0002_short_range_radar\src\commonsrr_config_chirp_design_SRR80.h 通过以上代码可以知…

网络编程套接字——UDP

一、基础知识 1.区分源地址、目的地址 &#xff08;1&#xff09;源IP地址和目的地址&#xff1a;最开始的IP地址与送达数据的地址 &#xff08;2&#xff09;源MAC地址和目的MAC地址&#xff1a;相当于上一站的地址与下一站的地址&#xff0c;在不断地变化 socket通信&#…

数据库专辑--SQL分类汇总(group by...with rollup),增加“总计”字段

系列文章 C#底层库–数据库访问帮助类&#xff08;MySQL版&#xff09; 数据库专辑–WITH CHECK OPTION的用法 文章目录系列文章前言一、概念介绍二、测试用例2.1 创建表2.2 初始化数据2.3 数据查询2.4 分析问题2.5 解决问题2.6 推荐另一种写法&#xff0c;使用COALESCE三、用…

如何撰写品牌故事?品牌故事软文撰写技巧分享

你听过哪些有温度的品牌故事&#xff1f;我首先想到的是香奈儿&#xff1a; 我的生活不曾取悦于我&#xff0c;所以我创造了自己的生活。 这是香奈儿的创始人可可香奈儿给世人留下的一句话&#xff0c;也是她一生的真实写照。 她被后人看作女性解放和独立的一个象征&#xf…

查询网站有没有被搜狗收录复杂吗?查询搜狗收录简单的方法

对于网站收录的概念&#xff0c;互联网中或者搜索引擎中已经有大量的相关定义。网站收录&#xff0c;指的是爬虫爬取了网页&#xff0c;并将页面内容数据放入搜索引擎数据库中这一结果。 查询网站有没有被搜狗收录复杂吗&#xff1f; 用网站批量查询工具呀&#xff01;操作超简…

React高级备忘录(生命周期)class component

须知 什么是生命周期?就像人有生老病死,component也有类似这样的概念,了解生命周期可以让我们知道如何在「对」的时间做「对」的事。 — Lieutenant 过! 常用生命周期 可以分为三大部分 创建component (componentDidMount)更新component(componentDidUpdate)销毁compone…

照一次CT,对人体的伤害有多大?终于有医生肯站出来说实话

CT是一种检查身体的方式&#xff0c;对于这项检查项目&#xff0c;一直有都有不好的传言&#xff0c;有的人听说CT有辐射&#xff0c;而且辐射比较大&#xff0c;所以比较排斥。 也有的人听说频繁做CT会致癌&#xff0c;所以不愿意做&#xff0c;还有的人把CT当作筛查癌症的神器…

Spring从入门到精通(二)

文章目录1.动态代理1.1 概念1.2 jdk动态代理&#xff08;重点&#xff09;1.3 基于子类的动态代理&#xff08;了解&#xff09;2.AOP2.1 概念2.2 springAop — 基于AspectJ技术2.2.1 AspectJ使用&#xff08;XML&#xff09;2.2.2 AspectJ使用&#xff08;注解开发&#xff09…

【数据结构】二叉树的实现OJ练习

文章目录前言(一) 二叉树的接口实现构建二叉树前序遍历中序遍历后序遍历层序遍历二叉树的节点个数二叉树叶子节点个数二叉树第K层节点个数二叉树的高度查找指定节点判断完全二叉树销毁二叉树(二) 二叉树基础OJ练习单值二叉树相同的树另一棵树的子树二叉树的前序遍历二叉树的最大…