Spring-boot 结合Thymeleaf--拦截器--文件上传

news2024/11/26 4:23:18

目录

Spring-boot 结合Thymeleaf

官方文档

基本介绍

● Thymeleaf 是什么

● Thymeleaf 的优点

● Thymeleaf 的缺点

● Thymeleaf 机制说明

Thymeleaf 语法

 表达式

1. 表达式一览

2.字面量

3. 文本操作

4.运算符

3. 比较运算

4. 条件运算

th 属性

迭代

条件运算

使用Thymeleaf -th 属性需要注意点

Thymeleaf 综合案例

需求说明

需求说明

代码实现 

配置pom.xml

引入starter-Thymeleaf , 项目会自动完成配置, 程序员按照规则开发即可

创建index.html 和manage.html 和静态图片到指定目录,

创建Admin.java

创建User.java

创建IndexController.java 默认进入登录页面

创建AdminController.java 处理登录请求完成测试

Spring-boot-拦截器-HandlerInterceptor

基本介绍

拦截器应用实例

创建LoginInterceptor.java   √ 编写一个拦截器实现HandlerInterceptor 接口

√拦截器注册到配置类中 创建WebConfig.java

修改AdminController.java 

注意事项和细节

1、URI 和URL 的区别

Identifier:标识符

Spring-boot--文件上传

应用实例

需求:

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

创建UploadController.java

创建WebUtils 

创建resources\application.yml 修改文件上传配置参数,

完成注册用户/上传图片-测试


Spring-boot 结合Thymeleaf

官方文档

1.在线文档: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
2 离线文档: usingthymeleaf.pdf 

基本介绍

● Thymeleaf 是什么

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

● Thymeleaf 的优点

1. 实现JSTL、OGNL 表达式效果, 语法相似, java 程序员上手快
2. Thymeleaf 模版页面无需服务器渲染,也可以被浏览器运行,页面简洁。
3. SpringBoot 支持FreeMarker、Thymeleaf、veocity 。

● Thymeleaf 的缺点

1. Thymeleaf: Thymeleaf is a modern server-side Java template engine for both web and standalone environments

2. 缺点: 并不是一个高性能的引擎,适用于单体应用

3. 说明:如果要做一个高并发的应用, 选择前后端分离更好,但是作为SpringBoot 推
荐的模板引擎  Thymeleaf 使用还是要了解的, 这样小伙伴在工作中使用到, 也能搞定


● Thymeleaf 机制说明

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

2. 比如: manage.html 中一段thymeleaf 代码, 是在用户请求该页面时,有thymeleaf 模板引擎完成处理的(在服务端完成), 并将结果页面返回.

3. 因此使用了Thymeleaf , 并不是前后端分离.

Thymeleaf 语法

 表达式

1. 表达式一览

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

2.字面量

文本值: 'dajiahao' , 'hello' ,…...

数字: 10 , 7 , 36.8 , ….....

布尔值: true , false

空值: null

变量: name,age,...... 变量不能有空格

3. 文本操作

字符串拼接: +

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

4.运算符

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)

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

.

● th:if:条件判断,类似的还有th:unless,th:switch,th:case。优先级较高:order=3

.

● 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

迭代

 

<tr th:each="prod : ${prods}">
    <td th:text="${prod.name}">Onions</td>//如果没有渲染就显示Onions
    <td th:text="${prod.price}">2.41</td>
    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>


<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.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>

条件运算

<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 manager</p>
    <p th:case="*">User is some other thing</p>
</div>

使用Thymeleaf -th 属性需要注意点

1、若要使用Thymeleaf 语法,首先要声明名称空间: xmlns:th="http://www.thymeleaf.org"

2、设置文本内容th:text,设置input 的值th:value,循环输出th:each,条件判断th:if,插入代码块th:insert,定义代码块th:fragment,声明变量th:object

3、th:each 的用法需要格外注意,打个比方:如果你要循环一个div 中的p 标签,则th:each属性必须放在p 标签上。若你将th:each 属性放在div 上,则循环的是将整个div。

4、变量表达式中提供了很多的内置方法,该内置方法是用#开头,请不要与#{}消息表达式弄混。

Thymeleaf 综合案例

需求说明

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

 

需求说明

说明: 使用SpringBoot + Thymeleaf 完成简单的用户登录-思路分析/图解 

代码实现 

配置pom.xml

   <!--导入springboot父工程-规定写法-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.5.3</version>
    </parent>
    <dependencies>
        <dependency>
            <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>
        <!--引入thymeleaf-start: 会进行默认配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

引入starter-Thymeleaf , 项目会自动完成配置, 程序员按照规则开发即可

创建index.html 和manage.html 和静态图片到指定目录,

从准备好的拷贝即可, 注意我将html 文件放到templates/ 目录下, 该目录, 不能直接访问 

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF"/>
<hr/>
<div style="text-align: center">
    <h1>用户登陆</h1>
    <form action="#" th:action="@{/login}"  method="post">
        <label style="color: red" th:text="${msg}"></label><br/>
        用户名:<input type="text" style="width:150px" name="name"/><br/><br/>
        密 码:<input type="password" style="width:150px" name="password"/><br/><br/>
        <input type="submit" value="登录"/>
        <input type="reset" value="重新填写"/>
    </form>
</div>
<hr/>
</body>
</html>

manage.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>管理后台</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF"/>
<a href='#'>返回管理界面</a>  <a href='#' th:href="@{/}">安全退出</a>   欢迎您:[[${session.loginAdmin.name}]]
<hr/>
<div style="text-align: center">
    <h1>管理雇员~</h1>
    <table border="1px" cellspacing="0" bordercolor="green" style="width:800px;margin: auto">
        <tr bgcolor="pink">
            <td>id</td>
            <td>name</td>
            <td>pwd</td>
            <td>email</td>
            <td>age</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>
    <br/>
</div>
<hr/>
</body>
</html>

创建Admin.java

@Data
public class Admin {
    private String name;
    private String password;
}

创建User.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private String password;
    private Integer age;
    private String email;
}

创建IndexController.java 默认进入登录页面

 

注意这里解释一下 就是说 直接http://localhost:8080/可以访问 和http://localhost:8080/login可以访问

@Controller
public class IndexController {

    //编写方法,转发到登录页面
    @GetMapping(value = {"/", "/login"})
    public String login() {
        /**
         * 解读
         * 1. 因为我们引入了starter-thymeleaf
         * 2. 这里就会直接使用视图解析到 thymeleaf下的模板文件adminLogin.html
         */
        return "adminLogin";
    }
}

创建AdminController.java 处理登录请求完成测试

@Controller
@Slf4j
public class AdminController {

    //响应用户的登录请求
    @PostMapping("/login")
    public String login(Admin admin, HttpSession session, Model model) {

        //验证用户是否合法
        if (StringUtils.hasText(admin.getName()) && "666".equals(admin.getPassword())) {

            //将登录用户保存到session
            session.setAttribute("loginAdmin", admin);

            //合法, 重定向到manage.html
            //请回忆,java web, 不使用请求转发是防止刷新页面会重复提交
            //这里为什么是写的 manage.html, 因为这样可以更加明确的表示到哪个页面
            //manage.html表示要去找 方法的映射路径为 manage.html
            return "redirect:/manage.html";
        } else {
            //不合法,就重新登录, 请求转发
            model.addAttribute("msg", "账号/用户错误");
            return "adminLogin";
        }
    }
    //处理用户的请求到 manage.html
    @GetMapping("/manage.html")
    public String mainPage(Model model, HttpSession session) {

        //这里暂时使用在方法验证,后面我们统一使用拦截器来验证

        Object loginAdmin = session.getAttribute("loginAdmin");
        if(null != loginAdmin) {//说明成功登录过
           //可以这里集合-模拟用户数据, 放入到request域中,并显示
           ArrayList<User> users = new ArrayList<>();
           users.add(new User(1, "关羽~", "666666", 20, "gy@sohu.com"));
           users.add(new User(2, "张飞", "666666", 30, "zf@sohu.com"));
           users.add(new User(3, "赵云", "666666", 22, "zy@sohu.com"));
           users.add(new User(4, "马超", "666666", 28, "mc@sohu.com"));
           users.add(new User(5, "黄忠", "666666", 50, "hz@sohu.com"));

           //将数据放入到request域
           model.addAttribute("users", users);
           return "manage"; //这里才是我们的视图解析到 /templates/manage.html
        } else {
           //这里就返回登录页,并给出提示
           model.addAttribute("msg","你没有登录/请登录");
           return "adminLogin";//请求转发到adminLogin.html
        }
    }
}

 


 

Spring-boot-拦截器-HandlerInterceptor

基本介绍

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

2. 基本步骤:

        √ 编写一个拦截器实现HandlerInterceptor 接口
        √ 拦截器注册到配置类中(实现WebMvcConfigurer 的addInterceptors)
        √ 指定拦截规则
        √ 回顾SpringMVC 中讲解的Interceptor 链接

拦截器应用实例

需求: 使用拦截器防止用户非法登录, 如图- 使用拦截器就不需要在每个方法验证了

● 浏览器输入: http://localhost:8080/manage.html , 如果用户没有登录,则返回登录界面.

创建LoginInterceptor.java   √ 编写一个拦截器实现HandlerInterceptor 接口

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 目标方法执行前被调用.
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //为了让小伙伴看到访问的URI
        String requestURI = request.getRequestURI();
        String requestURL = request.getRequestURL().toString();
        log.info("preHandle拦截到的请求的URI={}", requestURI);
        log.info("preHandle拦截到的请求的URL={}", requestURL);

        //进行登录的校验
        HttpSession session = request.getSession();
        Object loginAdmin = session.getAttribute("loginAdmin");
        if (null != loginAdmin) {//说明该用户已经成功登录
            //放行
            return true;
        }
        //拦截, 重新返回到登录页面
        request.setAttribute("msg", "你没有登录/请登录~~");
        request.getRequestDispatcher("/").forward(request, response);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle执行了...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion执行了...");
    }
}

√拦截器注册到配置类中 创建WebConfig.java

注意这里有二种方式来实现 一种是实现接口 一种是@Bean

@Configuration
public class WebConfig /*implements WebMvcConfigurer*/ {

    //@Override
    //public void addInterceptors(InterceptorRegistry registry) {
    //
    //    //注册自定义拦截器LoginInterceptor
    //    registry.addInterceptor(new LoginInterceptor())
    //            .addPathPatterns("/**") //拦截所有的请求
    //            .excludePathPatterns("/","/login","/images/**");//指定要放行的,后面可以根据业务需求,来添加放行的请求路径
    //}

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {

        return new WebMvcConfigurer() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                System.out.println("addInterceptors~~~");
                //注册拦截器
                registry.addInterceptor(new LoginInterceptor())
                        .addPathPatterns("/**")
                        .excludePathPatterns("/","/login","/images/**","/upload.html","/upload","/sql");
            }
        };
    }
}

修改AdminController.java 

去掉session 验证用户是否登录代码, 并完成测试, 注意看页面和后台日志.

    @GetMapping("/manage.html")
    public String mainPage(Model model, HttpSession session) {

        //有了拦截器, 不需再使用sessoin 验证    
        log.info("进入mainPage()");
        //可以这里集合-模拟用户数据, 放入到request域中,并显示
        ArrayList<User> users = new ArrayList<>();
        users.add(new User(1, "关羽~", "666666", 20, "gy@sohu.com"));
        users.add(new User(2, "张飞", "666666", 30, "zf@sohu.com"));
        users.add(new User(3, "赵云", "666666", 22, "zy@sohu.com"));
        users.add(new User(4, "马超", "666666", 28, "mc@sohu.com"));
        users.add(new User(5, "黄忠", "666666", 50, "hz@sohu.com"));

        //将数据放入到request域
        model.addAttribute("users", users);

        return "manage"; //这里才是我们的视图解析到 /templates/manage.html
    }
}

注意事项和细节

1、URI 和URL 的区别

URI = Universal Resource Identifier

URL = Universal Resource Locator

Identifier:标识符

Locator:定位器从字面上来看,

URI 可以唯一标识一个资源, URL 可以提供找到该资源的路径 

String requestURI = request.getRequestURI();
String requestURL = request.getRequestURL().toString();

 


 

Spring-boot--文件上传

应用实例

需求:

演示Spring-Boot 通过表单注册用户,并支持上传图片 

我们可以先看看Spring MVC 的文件上传 (5条消息) 处理 json 和 HttpMessageConverter--文件下载-ResponseEntity --SpringMVC 文件上传_尘觉的博客-CSDN博客

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

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>upload</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF"/>
<hr/>
<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>

创建UploadController.java

这里也解决了

如果文件名相同, 会出现覆盖问题, 如何解决

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


@Controller
@Slf4j
public class UploadController {

    //处理转发到用户注册-可以完成文件上传页面
    @GetMapping("/upload.html")
    public String uploadPage() {
        return "upload";// 视图解析,转发到templates/upload.html
    }

    //处理用户的注册请求-包括处理文件上传

    @PostMapping("/upload")
    @ResponseBody
    public String upload(@RequestParam("name") String name,
                         @RequestParam("email") String email,
                         @RequestParam("age") Integer age,
                         @RequestParam("job") String job,
                         @RequestParam("header") MultipartFile header,
                         @RequestParam("photos") MultipartFile[] photos) throws IOException {

        //输出获取到的信息
        log.info("上传的信息 name={} email={} age={} job={} header={} photos={} ",
                name, email, age, job, header.getSize(), photos.length);

        //如果信息都成功得到,我们就将文件保存到指定的目录,比如d:\\temp_upload
        //1. 我们先将文件保存到指定的目录 比如d:\\temp_upload
        //2. 后面我们在演示把文件保存到动态创建的目录.
        //   比如:

        //得到类路径(运行的时候)
        String path = ResourceUtils.getURL("classpath:").getPath();
        //log.info("path={}", path);

        //动态创建指定目录
        File file = new File(path + WebUtils.getUploadFileDirectory());
        if (!file.exists()) {//如果目录不存在,我们就创建, 在java io
            file.mkdirs();
        }

        if (!header.isEmpty()) {//处理头像
            //获取上传文件的名字
            String originalFilename = header.getOriginalFilename();
            String fileName = UUID.randomUUID().toString() + "_" + System.currentTimeMillis() + "_" + originalFilename;
            //这里我们需要指定保存文件的绝对路径 ,
            //即 D:\excel_springboot\springboot-usersys\target\classes\static\images\
            //header.transferTo(new File("d:\\temp_upload\\" + originalFilename));

            //log.info("保存文件的绝对路径={}" + file.getAbsolutePath());
            //保存到动态创建的目录
            header.transferTo(new File(file.getAbsolutePath() + "/" + fileName));
        }

        //处理宠物的图片
        if (photos.length > 0) {
            for (MultipartFile photo : photos) {//遍历
                if (!photo.isEmpty()) {
                    String originalFilename = photo.getOriginalFilename();
                    String fileName = UUID.randomUUID().toString() + "_" + System.currentTimeMillis() + "_" + originalFilename;
                    //photo.transferTo(new File("d:\\temp_upload\\" + originalFilename));
                    //保存到动态创建的目录
                    photo.transferTo(new File(file.getAbsolutePath() + "/" + fileName));
                }
            }
        }
        return "注册用户成功/文件上传成功";
    }
}

创建WebUtils 

//定义一个文件上传的路径这样直接调用就好了

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());
    }

}

根据项目需求修改文件上传的参数, 否则文件上传会抛出异常, [可以演示错误]

创建resources\application.yml 修改文件上传配置参数,

max-file-size 单个文件大小,
max-request-size 一次请求最大上传大小(多个文件.)

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 50MB

完成注册用户/上传图片-测试

 

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

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

相关文章

4年经验面试要15K,一问自动化却以为我在刁难他?

我这次是公司招聘的面试官之一&#xff0c;主要负责一些技术上的考核&#xff0c;这段时间还真让我碰到了不少奇葩求职者 昨天公司的HR小席刚跟我吐槽&#xff1a;这个星期没有哪天不加班的&#xff01;各种招聘网站上的消息源源不断&#xff0c;连吃饭都要回消息…… 看来最…

【Java面试】JVM垃圾回收相关知识点

文章目录 1. Java中对象有哪些引用类型&#xff1f;2. 有哪些基本的垃圾回收算法&#xff1f;3. 什么是分区收集算法&#xff1f;和分代收集什么区别&#xff1f;4. 什么是Minor GC、Major GC、Full GC?5. 什么情况下会触发Full GC&#xff1f; 1. Java中对象有哪些引用类型&a…

Linux 常用指令的使用

文章目录 1. 基础命令1&#xff09;ls2&#xff09;pwd3&#xff09;cd4&#xff09;touch5&#xff09;cat6&#xff09;mkdir7&#xff09;rm8&#xff09;cp9&#xff09;mv10&#xff09;more11&#xff09;less12&#xff09;head13&#xff09;tail14&#xff09;vim15&a…

《论文阅读》常识推理的生成知识提示

《论文阅读》常识推理的生成知识提示 前言简介相关知识模型构架Generated Knowledge PromptingKnowledge GenerationKnowledge Integration via Prompting推理阶段前言 你是否也对于理解论文存在困惑? 你是否也像我之前搜索论文解读,得到只是中文翻译的解读后感到失望? 小…

linux RVM安装使用

前言 RVM&#xff08;Ruby Version Manager&#xff09;是一个支持多版本Ruby的命令行程序&#xff0c;它有助于为开发和生产环境提供一致性可靠的Ruby版本。 它能够提供最新版本的Ruby&#xff0c;并管理多个版本&#xff0c;几乎在所有操作系统上都能安装和管理 Ruby。RVM 还…

RocketMQ之底层IndexFile存储协议

RocketMQ是一款高性能、高可靠、可伸缩的分布式消息中间件。在实现以上功能方面,RocketMQ采用了深度优化的存储设计方案。其中,底层IndexFile存储协议被认为是RocketMQ存储设计的关键,因此本篇文章将重点介绍RocketMQ底层IndexFile存储协议的实现机制及优缺点。 RocketMQ底…

LitCTF 2023 复现

文章目录 Hex&#xff1f;Hex&#xff01;梦想是红色的原来你也玩原神factordbP_Leake的学问Euler* Where is P?The same common divisormd5babyLCG* easy_math* Virginia* Is this only base?你是我的关键词(Keyworld)隐晦的聊天记录* baby_xor收获与体会 Hex&#xff1f;He…

VSCode中安装GPT插件详细教程

目录 安装插件 A.安装CodeGPT B.安装chatgpt 1.VSCode安装插件&#xff0c;使用本地下载vsix文件 2.获取 ChatGPT API 密钥 3.配置settings.json GPT-4主要有三大改进点 局限性 安装插件 AB功能一样&#xff0c;A安装的人最多&#xff0c;GPT具体功能可见标题链接 A.…

BLE解调

BLE解调前奏 如果不太了解IQ、FSK、GFSK的话&#xff0c;可以看上一篇&#xff0c;有一些关于这些内容的东西&#xff0c;写的应该还算好理解点吧&#xff0c;给出了自己学习时候的参考&#xff0c;具体的看他们写的。 调频与调相之间的关系 IQ调制中&#xff0c;调频是表现…

chatgpt赋能Python-anaconda降低python版本

Anaconda降低Python版本&#xff1a;为什么你需要做到这一点&#xff1f; 作为一个有10年Python编程经验的工程师&#xff0c;我经常会发现自己需要降低Pyhton的版本以便与我要使用的库兼容。为了解决这个问题&#xff0c;Anaconda是一个非常有用的工具&#xff0c;可以管理不…

基于fpga的图像处理之3x3_5x5算子模板设计

本文的思路框架&#xff1a; ①本文采用支持3x3算子模块和5x5算子模块的生成&#xff0c;用于后一级别的算法输入 ②本例程中采用的FPGA设计技巧&#xff0c;可用于借鉴&#xff0c;一是generate if参数定义&#xff1b;二是调用xilinx和altera的sync fifo和async fifo原语实现…

基于SpringBoot的招生管理系统的设计与实现

背景 本次设计任务是要设计一个招生管理系统&#xff0c;通过这个系统能够满足管理员和学生的招生公告管理功能。系统的主要功能包括首页、个人中心、学生管理、专业信息管理、专业报名管理、录取通知管理、系统管理等功能。 管理员可以根据系统给定的账号进行登录&#xff0…

做百度百科词条怎么写词条名,认证百度百科多少钱

很多人在做百度百科词条时不知道如何写百度百科词条名&#xff0c;总是因为词条不规范或者义项名不正确&#xff0c;而导致词条通过不了。认证申请百度百科到底多少钱能通过&#xff0c;实际上百度百科是免费的&#xff0c;需要费用的是请别人帮忙创建百度百科&#xff0c;下面…

SPI(Service Provider Interface)

ServiceLoad中的spi 1、简介 JDK1.6引入的特性&#xff0c;用来实现SPI&#xff08;Service Provider Interface&#xff09;&#xff0c;一种服务发现机制。 2、JDBC举例 2.1、引入mysql依赖jar <dependency><groupId>mysql</groupId><artifactId>…

[IntelliJ IDEA] 中Lombok插件的介绍和常见使用情景

文章目录 介绍使用Lombok 介绍 在编写项目时&#xff0c;尤其是在类进行类内部成员字段封装时&#xff0c;需要编写大量的get/set方法&#xff0c;不仅写的麻烦&#xff0c;如果字段名发生改变就要进行修改&#xff0c;因此非常麻烦&#xff1b;因此使用Lombok就能解决这样的问…

C++的vector使用

vector 1.vector的介绍2.vector的使用2.1. vector的定义&#xff08;构造函数&#xff09;2.2. vector iterator的使用2.3. vector空间增长问题2.4. vector的增删改查vector 迭代器失效问题&#xff08;重点&#xff09; 1.vector的介绍 vector是和数组类似的序列容器&#xf…

一文全览机器学习建模流程(Python代码)

注&#xff1a;本文基于之前的文章做了些修改&#xff0c;重复部分可以跳过看。示例的项目为基于LR模型对癌细胞分类的任务。 随着人工智能时代的到来&#xff0c;机器学习已成为解决问题的关键工具&#xff0c;如识别交易是否欺诈、预测降雨量、新闻分类、产品营销推荐。我们接…

深入浅出C语言——字符/字符串操作函数

文章目录 一、字符串操作函数1. strlen2. strcpy3. strcat4. strcmp5. strncpy6. strncat7. strncmp8. strstr9. strtok10. strerror二、字符操作函数 一、字符串操作函数 1. strlen size_t strlen ( const char * str );strlen 获取字符串长度。字符串已经 ‘\0’ 作为结束标…

Mybatis二级缓存详解

目录 二级缓存 MyBatis的缓存机制整体设计以及二级缓存的工作模式 二级缓存的划分 使用二级缓存&#xff0c;必须要具备的条件 一级缓存和二级缓存的使用顺序 二级缓存实现的选择 MyBatis自身提供的二级缓存的实现 二级缓存的作用 二级缓存的作用域 二级缓存应用场景…

Pruning 系列 (六)remove剪枝

环境 python 3.9numpy 1.24.1pytorch 2.0.0+cu117一、填0与remove剪枝的差异 直接填0的剪枝: 优点: 保留了原始网络结构,便于实现和微调。部分减少模型的计算量。缺点: 零权重仍然需要存储,因此不会减少内存使用。一些硬件和软件无法利用稀疏计算,从而无法提高计算效率…