SpringBoot 框架学习笔记(七):Thymeleaf、拦截器 和 文件上传实现(解决了文件重名 和 按日期分目录存放问题)

1 Thymeleaf

1.1 基本介绍

(1)官方文档:Tutorial: Using Thymeleaf

(2)Thymeleaf 是什么

  • Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,可完全替代 JSP
  • Thymeleaf 是一个 java 类库,它是一个 xml/xhtml/html5 的模板引擎,可以作为mvc的web应用的view层

(3)Thymeleaf的优点

  • 实现 JSTL、OGNL 表达式效果,语法类似,上手快
  • Thymeleaf 模板页面无需服务器渲染,也可以被浏览器运行,页面简洁
  • SpringBoot支持 Thymeleaf、Velocity、FreeMarker

(4)Thymeleaf的缺点 

  • 并不是一个高性能的引擎,适用于单体应用
  • 如果要做一个高并发的应用,选择前后端分离更好,但是作为SpringBoot推荐的模板引擎,还是需要了解一下

1.2 Thymeleaf机制说明

(1)Thymeleaf 是服务器渲染技术,页面数据是在服务器端进行渲染的

(2)比如:manage.html 中一段 Thymeleaf 代码,是在客户请求该页面时,由 Thymeleaf 模板引擎完成处理的(在服务器端完成),并将结果返回。因此使用了Thymeleaf,并不是前后端分离

<tr bgcolor="pink" th:each="user:${users}"><td th:text="${user.id}">a</td><td th:text="${user.name}">b</td><td th:text="${user.age}">c</td><td th:text="${user.eamil}">d</td><td th:text="${user.password}">e</td>
</tr>

1.3 Thymeleaf语法

3.3.1 表达式

3.3.1.1 表达式一览
表达式名字语法用途
变量取值${...}获取请求域、session域、对象等值
选择变量*{...}获取上下文对象值
消息#{...}获取国际化等值
链接@{...}生成链接
片段表达式~{...}jsp:include 作用,引入公共页面片段
1.3.1.2 字面量

文本值:'hello'

数字:10,7,36.8

布尔值:true,false

空值:null

变量:name,age

注意:变量不能有空格

1.3.1.3 文本操作

字符串拼接:+

变量替换:|age= ${age}|

1.3.2 运算符

(1)数学运算

运算符:+,-,*,/,%

(2)布尔运算

运算符:and,or

一元运算符:!,not

(3)比较运算

比较:>,<,>=,<=( gt,lt,ge,le)

等式:==,!=(eq,ne)

(4)条件运算

If-then:(if) ? (then)

If-then-else:(if)?(then):(else)

Default:(value)?:(defaultvalue)

1.3.3 th属性

html有的属性,Thymeleaf基本都有,而常用的属性大概有七八个。其中th属性执行的优先级从1到8,数字越低,优先级越高

  • th:text:设置当前元素的文本内容,相同功能的还有th:utext,两者的区别在于前者不会转义html标签,后者会。优先级不高,order=7
  • th:value:设置当前元素的value值。类似修改指定属性的还有th:src,th:href。优先级不高,order=6
  • th:each:遍历循环元素,和th:text或th:value一起使用。注意该属性修饰的标签位置,详细往后看。优先级很高,order=2
<tr th:each="prod : ${prods}"># ${prod.name}的值会替换Onions<td th:text="${prod.name}">Onions</td><td th:text="${prod.price}">2.41</td><td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
<tr th:each="prod,iterStar : ${prods}" th:class="${iterStar.odd}?'odd'"><td th:text="${prod.name}">Onions</td><td th:text="${prod.price}">2.41</td><td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
  • th:if:条件判断,类似的还有th:unless,th:switch,th:case。优先级较高,order=3
<a href="comments.html"
th:href="@{/product/comments(prodId=${prod.id})}"
th:if="${not #lists.isEmpty(prod.comments)}">view</a><div th:switch="${user.role}"><p th:case="'admin'">User is an administrator</p><p th:case="#{roles.manager}">User is a manage</p><p th:case="*">User is some other thing</p>
</div>
  • th:insert:代码块引入,类似的还有th:replace,th:include,三者的区别较大,若使用不恰当会破坏html结构,常用于公共代码块提取的场景。优先级最高,order=1
  • th:fragment:定义代码块,方便被th:insert引用。优先级最低,order=8
  • th:object:声明变量,一般和*{}一起配合使用,达到偷懒的效果。优先级一般,order=4
  • th:attr:修改任意属性,实际开发中用的较少,因为有丰富的其他th属性帮忙,类似的还有th:attrappend,th:attrprepend。优先级一般,order=5

1.3.4 使用Thymeleaf的th属性需要注意的点

  • 若要使用Thymeleaf语法,首先要声明名称变量:xmlns:th="http://www.thymeleaf.org"
  • 设置文本内容 th:text,设置 input 的值 th:value,循环输出 th:each,条件判断 th:if,插入代码块 th:insert,定义代码块 th:fragment,声明变量 th:object
  • th:each 的用法需要格外注意:如果你要循环一个div中的标签,则th:each属性必须放在p标签上。若将th:each属性放在div上,则循环的是整个div
  • 变量表达式中提供了很多内置方法,该内置方法是用#开头,请不要与 #{} 消息表达式弄混

1.4 Thymeleaf综合案例

需求说明:使用SpringBoot + Thymeleaf 完成简单的用户登录-列表功能

代码实现:

(1)创建maven项目,项目名使用 springboot-usersys

(2)要支持Thymeleaf,需要引入starter-Thymeleaf,在 pom.xml 配置(其他依赖是springboot项目开发需要)

<!-- 导入 springboot 父工程 -->
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.3</version>
</parent><dependencies><!--引入Thymeleaf--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><!-- 导入 web 项目场景启动器,会自动导入和 web 开发相关依赖 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--引入lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--        引入配置处理器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></dependency>
</dependencies>

Thymeleaf 默认在类路径下的templates目录下去找对应的html文件,查看 ThymeleafProperties 源码即可知

(3)在resources目录下(maven项目的类路径就是resources)新建 templates 目录,在  templates 目录下创建 login.html 和 manage.html(这里使用了 Thymeleaf)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>login</title><style>* {margin: 0;padding: 0;}html {height: 100%;}body {height: 100%;}.container {height: 100%;background-image: linear-gradient(to right, #999999, #330867);}.login-wrapper {background-color: bisque;width: 358px;height: 588px;border-radius: 15px;padding: 0 50px;position: relative;left: 50%;top: 50%;transform: translate(-50%,-50%);}.header {font-size: 38px;font-weight: bold;text-align: center;line-height: 200px;}.input-item {display: block;width: 100%;margin-bottom: 20px;border: 0;padding: 10px;border-bottom: 1px solid rgb(128,125,125);font-size: 15px;outline: none;}.input-item::placeholder {text-transform: uppercase;}.btn {text-align: center;padding: 10px;width: 100%;margin-top: 40px;background-image: linear-gradient(to right,#a6c1ee, #fbc2eb);color: #fff;}.msg {text-align: center;line-height: 88px;}a {text-decoration-line: none;color: #abc1ee;}</style>
</head>
<body>
<div class="container"><div class="login-wrapper"><div class="header">Login</div><form class="form-wrapper" action="#" th:action="@{/login}" method="post"><label style="color: red" th:text="${msg}"></label><input type="text" name="name" placeholder="username" class="input-item"><input type="password" name="password" placeholder="password" class="input-item" /><button type="submit" class="btn" >Login</button><button type="reset" class="btn">Login</button></form><div class="msg">Don't have account?<a href="#">Sign up</a></div></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>管理后台</title>
</head>
<body bgcolor="#CED3FE">
<a href="#">返回管理页面</a>
<a href="#" th:href="@{/}">安全退出</a> 欢迎您:[[${session.adminLogin.name}]]
<hr/>
<div style="text-align: center"><h1>管理雇员</h1><table border="1px" cellspacing="0" bordercolor="green" style=""><tr bgcolor="#ffc0cb"><td>id</td><td>name</td><td>pwd</td><td>email</td><td>job</td></tr><tr bgcolor="#ffc0cb" th:each="user:${users}"><td th:text="${user.id}">a</td><td th:text="${user.name}">b</td><td th:text="${user.password}">c</td><td th:text="${user.email}">d</td><td th:text="${user.age}">e</td></tr></table>
</div>
</body>
</html>

(4)新建软件包bean,在该包下创建两个实体类 User.java 和 Admin.java

package org.wwj.bean;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {private Integer id;private String name;private String password;private Integer age;private String email;
}
package org.wwj.bean;import lombok.Data;@Data
public class Admin {private String name;private String password;
}

(5)新建软件包 controller,在该包下创建 IndexController.java 和 AdminController,java

IndexController.java 用于请求转发到登录页面,实现功能:浏览器输入 localhost:8080/ 和localhost:8080/login 均可以访问到登录页面

package org.wwj.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;@Controller
public class IndexController {// 编写方法,转发到登录页@GetMapping(value = {"/", "/login"})public String login() {// 因为引入了 Thymeleaf,Thymeleaf里面包含了视图解析// 这里就会直接使用视图解析器解析到templates下的模板文件login.htmlreturn "login";}
}

AdminController,java 用于对登录的校验,以及登录成功页面的跳转。实现功能:用户没有登录直接访问登录成功页面 以及 登录账号/密码 返回错误信息,并跳转到登录页面;如果校验通过就转发到 manage.html 页面显示用户信息

package org.wwj.controller;import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.wwj.bean.Admin;
import org.wwj.bean.User;import java.util.ArrayList;@Controller
public class AdminController {//响应用户的登录请求@PostMapping("/login")public String login(Admin admin, HttpSession session, Model model) {// 验证用户是否合法if (StringUtils.hasText(admin.getName()) && "666".equals(admin.getPassword())){session.setAttribute("adminLogin", admin);// 合法,重定向到 manage.html,重定向的请求方式为 get// 不能使用请求转发,防止刷新页面后表单重复提交// return "redirect: /manage.html"; 表示要去找映射路径为manage.html的controller方法return "redirect:/manage.html";}else {// 不合法,重新登录model.addAttribute("msg","账号/密码错误");return "login";}}// 处理用户的请求到 manage.html@GetMapping("/manage.html")public String mainPage(Model model, HttpSession session) {if (session.getAttribute("adminLogin") != null) {// 这里可以使用集合模拟用户数据,放入 request 域中ArrayList<User> users = new ArrayList<>();users.add(new User(1, "关羽~", "666666", 20, "gr@sohu.com"));users.add(new User(2, "张飞", "666666", 30, "zi@sohu.com"));users.add(new User(3, "赵云", "666666", 22, "zy@sohu.com"));users.add(new User(4, "马超", "666666", 28, "me@sohu.com"));users.add(new User(5, "黄忠", "666666", 50, "hz@sohu.com"));// 将数据放入到request域中model.addAttribute("users", users);// 因为引入了 Thymeleaf,Thymeleaf里面包含了视图解析// 这里的manage才会使用视图解析器转发到templates目录下相应的页面return "manage";}else {// 返回登录页,并给出提示model.addAttribute("msg", "你没有登录/请登录");return "login";}}
}

 (6)编写并启动主程序

package org.wwj;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class Application {public static void main(String[] args) {ApplicationContext ioc = SpringApplication.run(Application.class, args);}
}

(7)浏览器输入 localhost:8080/ 进行测试

2 拦截器

2.1 基本介绍

(1)在Spring Boot项目中,拦截器是开发中常用手段,用来做登录验证、性能验证、日志记录等。

(2)使用拦截器基本步骤

  • 编写一个拦截器实现 HandlerInterceptor接口
  • 将拦截器注册到配置类中(实现WebMvcConfigurer的addInterceptors)
  • 指定拦截规则

(3) Spring Boot实现拦截器的方式和springmvc差不多,区别是配置方式不同

2.2 拦截器应用实例

需求说明:使用拦截器防止用户非法访问,例如用户直接在浏览器输入 localhost:8080/manage.html,如果用户没有登录,则返回登录页面,并给出提示信息

代码实现:

在上面Thymeleaf案例的基础上进行拦截

(1)创建软件包 interceptor 用来存放拦截器,在该软件包下创建 LoginInterceptor.java 作为拦截器,该拦截器会对拦截的请求进行登录验证,只有用户是登录状态时才放行,非登录状态转发到登录页面

package org.wwj.interceptor;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;@Slf4j
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 为了看到访问的URLString requestURI = request.getRequestURI();log.info("preHandle拦截到的请求的URL={}",requestURI);// 进行登录验证HttpSession session = request.getSession();if (session.getAttribute("adminLogin") != null) return true;else {// 拦截,重新返回到登录页面request.setAttribute("msg", "你没有登录");request.getRequestDispatcher("/login").forward(request, response);return false;}}
}

(2)在配置类中注册拦截器,新建软件包 config,在该软件包下创建 WebConfig.java 作为配置类。这里注册拦截器的方式有两种

第一种

package org.wwj.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.wwj.interceptor.LoginInterceptor;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") //拦截所有请求.excludePathPatterns("/", "/login");// 放行登录请求}
}

第二种

package org.wwj.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.wwj.interceptor.LoginInterceptor;@Configuration
public class WebConfig{@Beanpublic WebMvcConfigurer webMvcConfigurer(){return new WebMvcConfigurer() {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/", "/login");}};}
}

2.3 注意事项和细节

(1)URI 和 URL 的区别

URI = Universal Resource Identifier

URL = Universal Resource Locator

Identifier:标识符,Locator:定位器。从字面上来看,URI可以唯一标识一个资源,URL可以提供找到该资源的路径

举例:

URI=/manage.html

URL=http://localhost:8080/manage.html

2.4 拦截器 VS 过滤器

(1)使用范围不同

  • 过滤器实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,Filter只能在web程序中使用
  • 拦截器 Interceptor 是一个Spring 组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于Application等程序中

(2)过滤器和;拦截器的触发时机不同,如下图

  • 过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后
  • 拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束 

(3)请求转发不会进入过滤器,会进入拦截器 

3 文件上传应用实例

需求说明:演示Spring-Boot 通过表单注册用户,并支持上传图片(简化了 Spring MVC文件上传的方式)

代码实现:

(1)创建 templates/upload.html,要求头像只能选择一个,而宠物可以上传多个图片

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div style="text-align: center"><h1>注册用户~</h1><form action="#" th:action="@{/upload}" method="post" enctype="multipart/form-data">用户名:<input type="text" style="width: 150px" name="name"><br/><br/>电 邮:<input type="text" style="width: 150px" name="email"><br/><br/>年 龄:<input type="text" style="width: 150px" name="age"><br/><br/>职 位:<input type="text" style="width: 150px" name="job"><br/><br/>头 像:<input type="file" style="width: 150px" name="header"><br/><br/><!--在该标签尾部加个 multiple 即可选择多张图片-->宠 物:<input type="file" style="width: 150px" name="photos" multiple><br/><br/><input type="submit" value="注册"/><input type="reset" value="重新填写"/></form>
</div>
<hr/>
</body>
</html>

(2)创建 UploadController.java,对注册的请求进行处理

package org.wwj.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;@Controller
@Slf4j
@SuppressWarnings("all")
public class UploadController {// 处理转发到用户注册-可以完成文件上传页面@GetMapping("/upload.html")public String uploadPage(){// Thymeleaf 进行视图解析,转发到templates/upload.htmlreturn "upload";}// 处理用户注册请求,包含处理文件上传@PostMapping("/upload")@ResponseBodypublic String upload(String name,String email,Integer age,String job,MultipartFile header,MultipartFile[] photos) throws IOException {// 输出获取到的信息log.info("上传的信息 name={} email={} age={} job={} header={} photos={}",name,email,age,job,header.getSize(),photos.length);// 成功获取到信息,将文件保存到当前项目类路径下的static/images/upload目录下// 得到类路径String path = ResourceUtils.getURL("classpath:").getPath();log.info("path = {}",path);// 拼接目录
//        String fullPath = path+"static/images/upload/";File file = new File(path + "static/images/upload/");if (!file.exists()){//如果目录不存在,就创建file.mkdirs();}// 处理头像if (!header.isEmpty()){String headerName = header.getOriginalFilename();header.transferTo(new File(file, headerName));}// 处理宠物头像for (MultipartFile multipartFile : photos) {String fileName = multipartFile.getOriginalFilename();multipartFile.transferTo(new File(file,fileName));}return "注册成功/文件上传成功";}
}

(3)在注册拦截器的配置类中放行注册请求

package org.wwj.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.wwj.interceptor.LoginInterceptor;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") //拦截所有请求.excludePathPatterns("/", "/login","/upload.html","/upload");// 放行登录注册请求}
}

(4)浏览器输入 localhost:8080/upload.html 进行测试

 

 注意事项:

(1)默认单个文件最大1MB,一次上传多文件最大10MB可以通过yaml配置文件修改该默认参数,在resouces目录下创建application.yml

spring:servlet:multipart:max-file-size: 2MBmax-request-size: 20MB

(2)如果文件名相同,会出现覆盖问题,解决办法如下

对上传的文件名进行处理,前面加一个前缀,保证前缀是是唯一即可

// 处理头像
if (!header.isEmpty()){String headerName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis() + "_"+ header.getOriginalFilename();header.transferTo(new File(file, headerName));
}// 处理宠物头像
for (MultipartFile multipartFile : photos) {String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis() + "_"+ multipartFile.getOriginalFilename();multipartFile.transferTo(new File(file,fileName));
}

效果如下

(3)解决文件分目录存放问题,如果将文件都上传到一个目录下,当上传文件很多时,会造成访问文件速度变慢,因此可以将文件上传到不同目录,比如一天上传的文件,统一放到一个文件夹 年/月/日,比如2022/11/11目录 

编写一个工具类用来动态生成当前日期的目录

package org.wwj.utils;import java.text.SimpleDateFormat;
import java.util.Date;public class WebUtils {// 定义文件上传的路径public static String UPLOAD_FILE_DIRECTORY = "static/images/upload/";// 编写方法,生成一个当前日期的目录 年/月/日public static String getUploadFileDirectory(){return UPLOAD_FILE_DIRECTORY +new SimpleDateFormat("yyyy/MM/dd").format(new Date());}
}

修改 UploadController.java,将固定文件上传目录修改为由工具类方法动态生成

测试效果如下 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.net core webapi 自定义异常过滤器

1.定义统一返回格式 namespace webapi;/// <summary> /// 统一数据响应格式 /// </summary> public class Results<T> {/// <summary>/// 自定义的响应码&#xff0c;可以和http响应码一致&#xff0c;也可以不一致/// </summary>public int Co…

vue 打包时候的分包

export default defineConfig({plugins: [vue()],resolve: {alias: {: fileURLToPath(new URL(./src/, import.meta.url))}},// 分包&#xff0c;node_modules中的单独打包成名字为vendor的js文件build: {rollupOptions: {manualChunks(id) {if (id.includes(node_modules)) {r…

EF8 学习过程中的问题和解决方案

一、varchar类型字段如果为null 无法使用contains来判断是否包含字符串 1. 有问题的代码&#xff1a; contractList _dbcontext.contractHeads.Where(u > u.code.Contains(queryStr) || u.name.Contains(queryStr) || u.companyName.Contains(queryStr) || u.customerNa…

uniapp开启数据压缩的坑-SpringBoot-gzip

1、服务器配置 服务端开启的数据压缩配置 server:port: ${port:8881}servlet:# 应用上下文路径context-path: /orderserverundertow:threads:io: 4worker: 500buffer-size: 2048# 开启Gzip压缩&#xff0c;compression:# 开启压缩enabled: true# 对json格式内容进行压缩mime-…

KCTF 闯关游戏:1 ~ 7 关

前言 看雪CTF平台是一个专注于网络安全技术竞赛的在线平台&#xff0c;它提供了一个供网络安全爱好者和技术专家进行技术交流、学习和竞技的环境。CTF&#xff08;Capture The Flag&#xff0c;夺旗赛&#xff09;是网络安全领域内的一种流行竞赛形式&#xff0c;起源于1996年…

嵌入式全栈开发学习笔记---数据结构(排序算法)

目录 排序的分类 稳定排序与不稳定排序 内部排序和外部排序 算法的复杂性 常见的排序算法 直接插入排序 希尔排序 快速排序 简单选择排序 堆排序 归并排序 基数排序 常见的排序总结 到目前为止&#xff0c;数据结构的线性结构和树状结构就都讲完了&#xff0c;本节…

使用 MongoDB 构建 AI:Flagler Health 的 AI 旅程如何彻底改变患者护理

Flagler Health 致力于为慢性病患者提供支持&#xff0c;为其匹配合适的医生以提供合适的护理。 通常&#xff0c;身患严重病痛的患者面临的选择有限&#xff0c;他们往往需要长期服用阿片类药物&#xff0c;或寻求成本高昂的侵入性外科手术干预。遗憾的是&#xff0c;后一种方…

SQL语句创建数据库(增删查改)

SQL语句 一.数据库的基础1.1 什么是数据库1.2 基本使用1.2.1 连接服务器1.2.2 使用案例 1.2 SQL分类 二.库的操作2.1 创建数据库2.2 创建数据库示例2.3 字符集和校验规则2.3.1 查看系统默认字符集以及校验规则2.3.2查看数据库支持的字符集2.3.3查看数据库支持的字符集校验规则2…

Android系统Android.bp文件详解

文章目录 1. 基本语法结构2. 常见模块类型3. 模块属性常见属性包括&#xff1a; 4. 具体示例5. 高级功能5.1. 条件编译5.2. 变量定义与使用5.3. 模块继承 6. 总结 Android.bp 是 Android 构建系统&#xff08;Android Build System&#xff09;中的配置文件&#xff0c;用于描述…

go之命令行工具urfave-cli

一、urfave/cli urfave/cli 是一个声明性的、简单、快速且有趣的包&#xff0c;用于用 Go 构建命令行工具。 二、快速使用 2.1 引入依赖 go get github.com/urfave/cli/v2 2.2 demo package mainimport ("fmt""log""os""github.com/ur…

OpenCV图像滤波(9)getGaussianKernel()函数的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 功能描述 cv::getGaussianKernel() 是 OpenCV 中的一个函数&#xff0c;用于生成一维高斯核。这种核通常用于实现高斯模糊滤波器&#xff0c;该滤波器可以…

备考CISSP,看这一篇就够了!(附备考资料下载)

作者在2023年发布过一篇博文《不报辅导班一次性通过CISSP经验分享》&#xff0c;后台收到很多备考小伙伴的私信咨询&#xff0c;我就基于大家经常问的问题整理了此文章为大家答疑解惑&#xff0c;同时附上备考过程中作者收集到的全部资源&#xff08;见文末&#xff09;&#x…

EasyCVR视频汇聚平台云计算技术核心优势:高效、灵活与可扩展性深度解读

随着科技的飞速发展和社会的不断进步&#xff0c;视频监控已经成为现代社会治安防控、企业管理等场景安全管理中不可或缺的一部分。在这一背景下&#xff0c;EasyCVR视频汇聚平台凭借其强大的云计算技术&#xff0c;展现出了卓越的性能和广泛的应用前景。本文将深入解析EasyCVR…

Rust学习----Rust安装

如何安装Rust&#xff1f; 1.官网&#xff1a;https://www.rust-lang.org/zh-CN/ 2.Linux or Max: curl https://sh.rustup.rs -sSf | sh 3.Windows按官网指导安装。 4.Windows Subsystem for Linux&#xff1a; curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs…

JavaDS —— 位图(BitSet)与 布隆过滤器

位图 引入问题&#xff1a;给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中。 首先要注意 40 亿个数据如果使用 整型&#xff08;int) 来存放的话&#xff0c;就是要 40 亿个整型&#xff0c;一个整型有…

redis面试(十一)锁超时

boolean res lock.tryLock(100, 10, TimeUnit.SECONDS); RedissonLock里面有这样一个方法tryLock()&#xff0c;意思是尝试获取锁的结果。 最大等待时间100s&#xff0c;并且获取到锁之后&#xff0c;10s之内没有释放的话&#xff0c;锁会自动失效。 尝试获取锁超时 time …

【vue3|第20期】vue3中Vue Router路由器工作模式

日期&#xff1a;2024年8月6日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xff…

LiveNVR监控流媒体Onvif/RTSP常见问题-页面上传SSL证书配置开启 HTTPS 服务?什么时候必须要开启HTTPS服务?

LiveNVR常见问题-页面上传SSL证书配置开启 HTTPS 服务&#xff1f;什么时候必须要开启HTTPS服务&#xff1f; 1、配置开启HTTPS1.1、准备https证书1.2、配置HTTPS端口1.3、配置证书路径1.3、 页面上传SSL证书 2、验证HTTPS服务3、为什么要开启HTTPS4、RTSP/HLS/FLV/RTMP拉流Onv…

IROS2024 | DarkGS:学习神经照明和3D高斯重新照明,用于黑暗中机器人探索

DarkGS&#xff1a;学习神经照明和3D高斯重新照明&#xff0c;用于黑暗中机器人探索 论文标题&#xff1a;DarkGS: Learning Neural Illumination and 3D Gaussians Relighting for Robotic Exploration in the Dark 论文地址&#xff1a;https://arxiv.org/abs/2403.10814 研…

PasteSpider快速上手开发者专用部署助手

【【【PasteSpider的安装--一键拉取镜像】】】 (首次使用&#xff0c;建议使用MemorySqlite的模式&#xff0c;只要2行代码即可启动一个PasteSpider&#xff0c;第一行拉取PasteSpider的镜像&#xff0c;第二行启动PasteSpider容器&#xff01;) 安装PasteSpider之后&#xf…