后端开发框架Spring Boot快速入门
写在前面
推荐将本文与Spring Boot 相关知识和工具类一文结合起来看,本文为主,上面那篇文章为辅,一起食用,以达到最佳效果,当然,大佬随意。
IDEA创建Spring Boot工程
关于Spring Boot框架项目,IDEA为我们提供了比较快捷的创建方式,如下:
- 点击右上角的
file,选择Project Structure,如下图:

- 选择左侧的
Modules,点击上面的加号,如下图:

- 选择
New Module

- 左边一栏选择
Spring Initializr,右边一栏配置项目相关属性,如下图:

项目工程名,项目工程存储地址自定义,项目工程类型Type选择
Maven,语言Language选择Java,后面三项建议不要改,直接默认即可,项目工程的软件开发工具包project SDK选择你自己安装的java JDK版本(我安装的是JDK 17),字段java 选择你自己安装的java JDK版本号,我这里选择的是17,包类型 Packaging选择Jar。
5.点击Next后,选择该工程需要的依赖,这里我因为需要来开发Web应用,因此添加了Spring Web的依赖,又因为我选择了MySQL数据库来存储数据,因此我又添加了MySQL的依赖。


- 选好依赖后,点击Finish,整个
Spring Boot项目创建就完成了。
Spring Boot整合Mybatis
在SpringBoot的配置文件pom.xml中引入Mybatis的起步依赖

引入好配置后,就可以正常使用Mybatis了。
Mybatis 前后端交互详解

如上图所示:
controller层是故意暴露出来的,里面是一些接口,用来与前端页面进行交互。service层全是各种方法的接口,用来保护后端方法逻辑的具体实现,防止其源码泄露,该层作用类似于反向代理,每个接口都对应着一个具体方法的实现。service层后面是implement逻辑层,它是整个系统的核心部分,用来与数据库进行交互,实现对应的所有后端逻辑,与前面的service层中的接口一一对应,保证程序的正常进行。- 再往后面走,就是
dao层,即数据库,该层用于存放所有可以与数据库进行交互的方法接口,是十分重要的地方。 mapper层是dao层中数据库方法接口的具体实现,与dao层方法接口一一对应。
前后端交互代码具体实现
项目的具体结构图:

OneSpringbootApplication 是启动类,运行该文件,整个项目就启动了。
连接数据库:

打开resource目录下的application.properties文件,在里面配置数据库相关信息,如上图红框所示。
-
spring.datasource.driver-class-name作用:设置JDBC驱动类的完全限定名。com.mysql.cj.jdbc.Driver是MySQL Connector/J 8.0+的JDBC驱动类,它告诉Spring Boot应用程序要使用哪个类来加载和连接MySQL数据库。 -
spring.datasource.url作用:设置数据库连接的URL(即数据库所在路径),jdbc:mysql://localhost:3306/test233表示数据库服务器运行在本地主机(localhost),使用3306端口,并且想要连接名为test233的数据库。 -
spring.datasource.username和spring.datasource.password作用是用来记录数据库的用户名和密码。 -
mybatis.configuration.map-underscore-to-camel-case=true作用是开启驼峰名与下划线命名之间的转换(驼峰命名eatFood,下划线命名eat_food) -
使用上述数据库配置前提是你已经将数据库驱动依赖添加到了项目的配置文件中(Maven的pom.xml)
controller 层:
//注解@RestController用于标记一个类,表明该类是一个
//控制器,并且其下的方法都将前端页面的返回数据作为响应
//(即处理前端页面的http请求)@RestController
public class HelloController {//注解@RequestMapping用于将http请求和处理请求的控制器方法(类方法)//关联起来,建立映射关系,// 该注解有一个参数value,其作用就是设置请求路径,设置当客户端发送何种请求时,//下面的方法才会处理该请求//该注解的参数value是一个String类型的数组,也就是其中可以存放多个数据//当前端向"/hello"发出请求时,下面的函数就会接收到请求,//并自动调用来处理该请求@RequestMapping("/hello")public String hello() {return "hello world!";}//@Autowired 注解用于将下面的对象(已经通过组件扫描注册到了IOC容器中)通过
//依赖注入 从IOC容器中注入到字段(这里字段是“userService”)中以供使用,
// 该对象必须被IOC容器视为一个Bean@Autowiredprivate UserService userService;@RequestMapping("/findById")public book findById(Integer ID){return userService.findById(ID);}
}
service 层的项目结构:

service层的接口:
//该接口只是一个普通的接口,因此需要一个专门的类来实现这个接口中的方法
public interface UserService {public book findById(Integer ID);
}
service层的接口的具体实现(impl层):
//@Service注解用于标识一个类作为服务层组件
@Service
public class UserServiceImpl implements UserService {//IOC容器通俗解释就是一个负责管理对象生命周期和对象间关系的“大管家”,//具体来说,当我们需要某个对象时,我们不再直接在代码中创建它,而是告诉//IOC容器我们需要这个对象,容器会根据我们的请求和配置信息,自动创建对象,//并处理对象之间的依赖关系,以及一切与项目本身业务逻辑无关的东西//(这个对象在项目开始运行时就已经提前创建好了)// 我们想要使用直接从容器的取出即可,并且容器中已创建的对象可以被本项目其他//地方共享和使用,这种对象就是统称为Bean//一般被Spring框架提供的注解标注了的类,它们的对象都会被Spring容器视为Bean//(Spring容器就是IOC容器)//类本身不是Bean,类对应的实例才是Bean//@Autowired 注解用于将下面的对象(已经通过组件扫描注册到了IOC容器中)//通过依赖注入 从IOC容器中注入到字段(这里字段是“userMapper”)中以供使用,// 该对象必须被IOC容器视为一个Bean@Autowiredprivate UserMapper userMapper;//当子类继承父类并重写父类的方法时,@Override注解可以帮助编译器检查该方法//是否确实重写了父类中的方法// 如果子类的方法名、参数列表和返回类型与父类中的方法不一致,那么编译器会//报错,提示重写失败,这有助于开发者及时发现并修正重写错误,避免运行时错误//的发生//简单来说,该注解作用就是表明其下面的方法为重写的方法@Overridepublic book findById(Integer ID) { //对UserService接口中的方法进行重写(即接口方法的具体实现)return userMapper.findById(ID);}
}
dao层与mapper层:
//@Mapper注解用于标识一个接口为MyBatis的Mapper接口
// 这样,MyBatis就能知道这个接口是专门用于操作数据库的,进而能够自动为这个
//接口创建一个代理实现类
// 这意味着你可以直接在应用程序中注入这个接口的实例,并调用它的方法来执行SQL语句,
//而不需要自己手动实现这个接口
// 即直接拿来使用,不需要再手动的去定义一个类来专门实现这个接口
@Mapper
public interface UserMapper {//@Select注解在MyBatis框架中用于直接在Mapper接口的方法上编写SQL查询语句,// 从而取代了传统的在XML映射文件中编写SQL语句的方式//@Select注解内部可以编写具体的SQL查询语句,用于从数据库中查询数据,//@Select注解下方的对应方法函数与上面SQL语句成映射关系//调用方法函数就会自动执行上面的SQL语句,并将SQL语句的结果作为该方法函数的//返回值进行return//在@Select注解的SQL语句中,可以使用占位符(如#{param})来绑定//下面方法中的参数@Select("select * from test233.book where ID=#{ID}")public book findById(Integer ID);
}
通过上面注解@Select和@Mapper来将传统的Dao层和Mapper层合在了一起。
实体类层—entity层:

public class book {private Integer ID;private String name;public book() {}public book(Integer ID,String name){this.ID=ID;this.name=name;}public Integer getID(){return this.ID;}public void setID(Integer ID){this.ID=ID;}public String getname(){return this.name;}public void setname(){this.name=name;}
}
该层的作用是用于存放一些实体类,这些实体类将会被用来接收数据库中对应表的数据,一个类对应一张表,表的字段就是类的成员变量,在前后端数据交互的过程中,这些实体类对象接收的数据会被系统自动转换成JSON数据格式。
常用注解
- 注解
@Component是一个通用注解,可以将标记的类实例作为Bean注入IOC容器中。 - 注解
@ComponentScan("包路径")用于组件扫描,扫描对应路径下的包当没有包路径时,默认扫描启动类同级的包和各自下面的子包。
组件扫描:如果遇见被
Spring Boot提供的注解标记了的类,那么这些类的对象会被视为Bean,SpringBoot会自动将这些类实例化并注入IOC容器之中,供应用程序在运行时使用,若存在组件未被扫描到,则系统不会创建组件当中的Bean实例,也不会创建该组件,与之相关联的其他Bean将会注入失败,与之相关联的功能组件将缺失。
- 注解
@Bean作用:将标记的方法的返回值交给IOC容器,成为IOC容器的bean对象(当Spring容器启动时,它会查找@Configuration注解的类,并调用这些类中的@Bean注解的方法,将返回的实例注册为Bean,注入到IOC容器当中)。 - 注解
@RestController用于标记一个类,表明该类是一个控制器,并且其下的方法都将前端页面的返回数据作为响应(即处理前端页面的http请求)。 - 注解
@RequestMapping和注解@PostMapping都是用于将http请求和处理请求的控制器方法(类方法)关联起来,建立映射关系,这两个注解都有一个参数value,其作用就是设置请求路径,设置当客户端发送何种请求时,下面的方法才会处理该请求,该注解的参数value是一个String类型的数组,也就是其中可以存放多个数据。 - 注解:
Post 与 Requst 的区别:
- Post 它要求被请求服务器要对它所提交的请求进行确认或者处理后才能给予响应,相对更加安全,效率也相对低点
- Requst 它是更广泛地用于发送和接收数据,会将参数暴露在Url中,相对不安全,效率相对高点
- 注解
@Autowired用于将其标记的对象(已经通过组件扫描注册到了IOC容器中)通过依赖注入 从IOC容器中注入到字段(这里字段是“userService”)中以供使用。该对象必须被IOC容器视为一个Bean,因为只有这样才能保证IOC容器中拥有该对象。 - 注解
@Service用于标识一个类作为服务层组件。 - 注解
@Override可以帮助编译器检查该方法是否确实重写了父类中的方法。 - 注解
@Mapper用于标识一个接口为Mapper接口,这样,MyBatis就能知道这个接口是专门用于操作数据库的,进而能够自动为这个接口创建一个代理实现类,这意味着你可以直接在应用程序中注入这个接口的实例,并调用它的方法来执行SQL语句,而不需要自己手动实现这个接口;即直接拿来使用,不需要再手动的去定义一个类来专门实现这个接口。 - 注解
@RestControllerAdvice主要用于标注一个类来进行全局异常处理和全局数据绑定,该类中的方法会被同项目的其他程序自动调用,可以用于定义全局响应结果处理程序,确保应用程序返回给客户端的响应具有统一的格式和结构,总之,该注解作用就是标记其下面的类为一个全局的异常处理和所有数据预处理的"中央处理器"。 - 注解
@ExceptionHandler(异常类类名.class)用来标注处理 异常类 的方法,此处的异常类可以是自定义的异常类,使用该注解可以捕获指定的异常,并按照自定义的方法处理该异常,一般与上面的注解配合使用。 - 注解
@RequestBody用于将 HTTP 请求体中的数据绑定到对应的方法参数上。
@PostMapping("/create") public String create(@RequestBody MyObject myObject) { // 在这里,myObject 已经被自动填充了请求体中的数据 // 你可以直接操作这个对象,而不需要手动解析请求体 // ... 处理 myObject 的逻辑 ... return "Object created successfully"; }
- 注解
@ResponseBody:用于标记一个方法的返回值应该被绑定到响应体。然而注解@RestController已经默认组合了注解@ResponseBody,也就是说注解@RestController标记的类下面的所有方法的返回值都会自动绑定到了响应体中。
在HTTP通信中,请求体(Request Body)和响应体(Response Body)是两个重要的概念,它们分别代表了HTTP请求和响应中携带的数据部分,里面可以携带的数据类型主要是JSON格式和表单数据。
表单数据:当发送一个包含表单字段的HTTP POST请求时,请求体可能包含
application/x-www-form-urlencoded类型的数据。这种格式将表单字段和值编码为键值对,并使用&符号分隔,将这些数据放在请求体当中,一同发送给服务器。queryString格式数据就像是我们给网站地址“附加”一些额外的信息。比如,我们想在搜索引擎里搜索“苹果”,我们可能会输入
http://search.com/?q=苹果。这里的?q=苹果就是queryString,它告诉我们搜索引擎要搜索的关键字是“苹果”。这种方式很适合传递少量、简单的信息。
- 注解
@CookieValue:用于绑定cookie值到方法参数。
@GetMapping("/cookie")
public String cookie(
@CookieValue("JSESSIONID") String sessionId) {
// ...
}
//将cookie中的键JSESSIONID对应的值赋给sessionId
- 注解
@RequestHeader:用于绑定请求头到方法参数。
@GetMapping("/header")
public String header(
@RequestHeader("User-Agent") String userAgent) {
// ...
}
//将请求头中的键User-Agent对应的值赋给userAgent
- 注解
@Validated主要用于触发方法参数的校验,将它标记在类上,告诉系统该类中有方法需要进行参数校验。 - 注解
@Pattern用于验证一个字符串是否符合指定的正则表达式(参数regexp存放指定的正则表达式),通常应用于类的字段、属性或方法的参数上,以确保输入的数据满足特定的格式要求。

- 注解
@NotNull该注解标记的变量的值不能为null。 - 注解
@NotEmpty该注解标记的变量的值不能为null,且如果是字符串的话,不能为空字符串。 - 注解
@Email该注解标记的变量必须满足邮箱格式
上面这三个注解是放在实体类中的,当实体类作为方法参数时,外部有注解
@Validated标记且参数本身又是请求体的映射(@RequestBody)时,其内部的注解才会生效(这只对实体类内部Validation依赖相关的注解有效)。

- 注解
@URL用来判断其标记的参数是否是一个合法的url地址。

- 注解
@Test用于标记一个方法是测试方法,这样测试框架就能自动识别并运行它。 - 注解
@JsonIgnore,该注解标记的成员变量,当系统将数据转换成JSON格式时,将会忽略掉该成员变量的值(保护密码不被泄露) - 注解
@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")用来指定存放时间的字段的时间输出的格式(年-月-日 时-分-秒)
数据库相关注解在
MyBatis框架中用于直接在Mapper接口的方法上编写SQL语句,从而取代了传统的在XML映射文件中编写SQL语句的方式,这些数据库相关注解,其内部可以编写具体的SQL查询语句,用于从数据库中增删查改数据,数据库相关注解下方的对应方法函数与上面SQL语句成映射关系,调用方法函数就会自动执行上面的SQL语句,并将SQL语句的结果作为该方法函数的返回值进行return,在数据库相关注解的SQL语句中,可以使用占位符(如#{param})来绑定标记的方法中的参数。
数据库相关注解有:
- 注解
@Select用于标注查询语句 - 注解
@Insert用于标注插入语句 - 注解
@Update用于标注更新语句 - 注解
@Delete用于标注删除语句
传统xml文件映射(配置动态的SQL语句)
在Mapper接口层,可以直接使用注解来将SQL语句映射绑定到对应方法上,如下:
@Mapper
public interface CategoryMapper {//新增文章分类@Insert("insert into big_event.category(category_name, category_alias, create_user, create_time, update_time) " +"value(#{category.categoryName},#{category.categoryAlias},#{category.createUser},now(),now())")public void addCategory(Category category);//通过文章的分类名查找分类@Select("select * from big_event.category where category_name=#{categoryName}")public Category findByCategoryName(String categoryName);//通过文章的分类ID查找分类@Select("select * from big_event.category where id=#{id}")public Category findById(Integer id);//通过用户ID获得其创建的所有分类@Select("select * from big_event.category where create_user=#{userId}")public List<Category> findByCreateUser(Integer userId);}
但是,上面却无法映射绑定动态的SQL语句到对应方法上,要想映射动态的sql语句,就只要采用传统的数据库映射方式----xml文件映射。
xml映射文件要求
xml配置文件必须放在resources 目录下,在该目录下,它的路径必须与Mapper层接口所在路径一致。
例如
Mapper层接口路径:com.example.two_project.mapper,那么对应的xml文件路径就必须是resources/com/example/two_project/mapper
xml文件配置动态SQL语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.two_project.mapper.ArticleMapper">
<!-- namespace 必须是对应的Mapper层接口的全类名 --><select id="list" resultType="com.example.two_project.entity.Article">select * from big_event.article<where><if test="state!=null">state=#{state}</if><if test="categoryId">and category_id=#{categoryId}</if>and create_user=#{id}</where></select></mapper>
<select> 标签就表示Select语句,属性id为该条SQL语句对应的函数的函数名,
属性resultType为数据库查询结果的每一条数据的返回类型(即该表对应的实体类的全类名)
<where> 标签就是SQL语句中的where,与一般的where相比,它的区别是它可以通过if的判断来动态地改变查询条件
<if> 标签中的test参数为判断条件,如果条件满足,则将标签内的语句加入where当中且若这是where中的第一个条件,
那么该条件前面的and将会被省略,若不满足,则不将标签内的语句加入.
文件对应的映射方法中的参数可以直接在标签中使用
xml映射文件的配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
Spring Boot 配置文件
配置文件的格式
Spring Boot的配置文件有两种格式,分别是.properties和.yaml/yml,两种配置文件的作用并没有什么区别,只是写法上有所不同:

在企业级开发中,更加常用的是.yml格式的文件

书写配置信息
不只是.yml格式的配置文件,.properties格式也是一样的,它们都可以用来书写第三方技术配置信息也可以来书写自定义的配置信息;当书写自定义配置信息时,如下图:

将程序中的一些静态属性放在一起,写成一个配置文件,这样当属性发生变化时就不用改代码,只需要修改配置文件,然后重启服务器即可。

如上图所示,是书写.yml配置文件的一些要求。

如上图中的属性"hobbies",表示该属性是一个数组类型,格式: "-"+" "+数组中的元素
获取配置信息
当属性写入属性文件后,在代码中,我们该如何获取这些属性呢?

如上图所示,通过注解@Value("{键名}")来获得对应的属性,该注解下面的变量就是用来接收对应属性(键)的值的。但是如果属性过多,又不想给每一个变量都写注解,则可以采用下面这种方法:

如上图,在对应的类上面加注解@ConfigurationProperties(prefix="前缀")(这里的前缀也是在配置文件中由用户自定义的),当使用了该注解后,其类下面对应的成员变量名必须与配置文件中同一前缀的属性名相同且一一对应。
Bean 注册
第三方若想注册为Bean(即被SpringBoot自动创建实例并注入IOC容器),只靠在对应类上添加一般的注解是不行的,这里就需要特殊的注解了。
第三方注册为Bean方式一
方式一,在启动类中添加方法,并在该方法上面添加注解@Bean,如下图:

@Bean注解作用:将标记的方法的返回值交给IOC容器,成为IOC容器的bean对象(当Spring容器启动时,它会查找@Configuration注解的类,并调用这些类中的@Bean注解的方法,将返回的实例注册为Bean)
也可以单独开一个配置类(注解@configuration标记的类)的文件,将所有想注册为Bean的第三方集中处理,如下图:

如果在注解@Bean标记的方法中想使用在IOC容器中已经注册的Bean对象,那么只需要在方法上声明即可,spring会自动的注入,如下图(country是已经在IOC容器中注册好的Bean对象)。

第三方注册为Bean方式二
方式二, 通过注解@Import将对应的第三方类引入,Spring容器会自动将其类的对象注册为Bean,注入IOC容器中。
- 引入格式:
@Import(xxx.class) - 引入位置:整个项目的启动文件当中。

@Import(类名.class),其中引入的这个类可以普通类,也可以是配置类(@configuration标记了的类),或者是ImportSelector接口实现类。
ImportSelector接口实现类:

如上图所示,我们首先要实现ImportSelector这个接口,重写其中的 selectImports()方法(该方法是自动调用的),返回值返回一个字符串类型的数组,该数组中的每一个字符串都是用户需要注册为Bean对象的类的地址(全类名)。然后注解@Import只需要引入这个接口实现类的类名即可,这样就避免了因引入的类太多,导致代码不美观的问题。
在一般开发中,ImportSelector接口实现类的方法的返回值的这个字符串数组一般不是写死的,而是从配置文件中读出来的。
在Resources/META-INF/spring/ 目录下,创建后缀名为.imports的配置文件,里面书写上所有自定义的需要注册为Bean的类的地址(全类名),一个类占一行。
读取配置文件中的信息,示例如下图:


如图,imports是设置的一个字符串列表,用于存放配置文件中的各个类的全类名;is 是获取到的输入流,后面的 “common.imports” 是配置文件名,整行代码的作用就是将配置文件中的数据转换成输入流存入变量is中,下面的变量br是对输入流的一个封装,将其封装成一个缓冲字符流。while循环是用来按照每一行来读取缓冲字符流当中的数据,并用字符串变量line来接收,将每一行数据添加至字符串列表imports当中,所有数据读取完毕后,要关闭缓冲字符流br;最后,将字符串列表转换成字符串数组返回回去。
自定义组合注解

如上图所示,选择Annotation,创建自定义的组合注解。

如上图所示,上面两个注解都是必不可少的。第一个是表明该自定义注解可以在类上使用,第二个表明该自定义注解在系统运行期间,一直存在。除了这两个注解,其他的均可以自定义。若要使用这个注解,就像普通注解一样直接使用即可,注解名为创建的组合注解的文件名。常用于实现下图第三条:

Bean 的注册条件
用户可以通过注解@Conditional的衍生注解来设置对象注册为Bean的条件,常用的注解如下图所示。

在配置类中,注解@Bean所标记的方法,其返回值会被注册为Bean,我当然可以提前为要注册为Bean的对象赋值,如下图,在方法的参数上通过注解@Value("${键名}")来确保每个参数被传入指定的值。注解@ConditionalOnProperty(prefix="前缀",name={"键名1","键名2"}) 来判断配置文件中是否存在对应属性,若不存在,则其下面整个方法的返回值将不再被注册为Bean。

注解@ConditionalOnMissingBean(类名.class),如下图所示,如果IOC容器中不存在Country类的Bean对象,则执行下面的方法,注入Province,否则不注入。

注解@ConditionalOnClass(name="类的完整路径名"),如下图所示,如果当前配置环境存在指定的类,则执行下面的方法,注入Province,否则不注入。

自动配置的原理
自动配置就是在SpringBoot程序启动后,起步依赖中的一些Bean对象会自动注入到IOC容器之中。
原理:在
jar包内定义了一些类,目的是想要这些类的实例作为Bean注入到IOC容器中,即自动注入;首先定义一个配置类,配置类中用注解@Bean来标记方法,通过这些方法,SpringBoot会将它们返回的实例作为Bean注入到IOC容器中,再定义一个自动配置类,加上两个注解@import(配置类类名.class)和@AutoConfiguration;前者引入了配置类,保证其在不同级目录下也可以使用,后者标识这是一个自动配置类。最后在项目的resources目录下的META-INF目录下的spring目录下再定义一个后缀名为.imports的文件,在文件中加入该自动配置类的全类名;当系统启动时,系统会在该目录下(“/resources/META-INF/spring/xxx.imports”)的配置文件中找是否有自动配置类(注解@AutoConfiguration标记的类),有就自动调用实例化该类。实例化该类,会导致系统通过@import访问到配置类,配置类中的方法会被自动调用,这样就自动配置就搞定了。
@Configuration与@AutoConfiguration注解的区别:
1. @Configuration 必须通过组件扫描,才能自动配置Bean,若不在启动类的同级目录或子目录下,则需要@ComponentScan("路径")来专门指定扫描。
@AutoConfiguration会被加载执行两次,一次是由@ComponentScan(如果配置了的话),另一次是由自动配置机制,也就是说只要该类在该项目下,且配置文件.imports里有该类的全类名,该类就会被系统自动调用,自动配置Bean。@Configuration与@AutoConfiguration注解一般配合使用。
相关文章:
后端开发框架Spring Boot快速入门
写在前面 推荐将本文与Spring Boot 相关知识和工具类一文结合起来看,本文为主,上面那篇文章为辅,一起食用,以达到最佳效果,当然,大佬随意。 IDEA创建Spring Boot工程 关于Spring Boot框架项目࿰…...
I2C驱动实验:验证所添加的I2C设备的设备节点
一. 简介 前面一篇文章向设备树中的 I2C1控制器节点下,添加了AP3216C设备节点。文章如下: I2C驱动实验:向设备树添加 I2C设备的设备节点信息-CSDN博客 本文对设备树进行测试,确认设备节点是否成功创建好。 二. I2C驱动实验&a…...
160 Linux C++ 通讯架构实战14,epoll 反应堆模型
到这里,我们需要整理一下之前学习的epoll模型,并根据之前的epoll模型,提出弊端,进而整理epoll反应堆模型,进一步深刻理解,这是因为epoll实在是太重要了。 复习之前的epoll的整体流程以及思路。 参考之前写…...
根据mysql的执行顺序来写select
过滤顺序指的是mysql的逻辑执行顺序,个人觉得我们可以按照执行顺序来写select查询语句。 目录 一、执行顺序二、小tips三、案例第一轮查询:统计每个num的出现次数第二轮查询:计算**最多次数**第三轮查询:找到所有出现次数为最多次…...
spring 和spring boot的区别
Spring是一个开源的Java开发框架,旨在简化Java应用程序的开发。它提供了一个综合的编程和配置模型,用于构建各种类型的应用程序,从简单的命令行工具到复杂的企业级Web应用程序。 Spring Boot是Spring框架的一个扩展,旨在简化Spri…...
Day84:服务攻防-端口协议桌面应用QQWPS等RCEhydra口令猜解未授权检测
目录 端口协议-口令爆破&未授权 弱口令爆破 FTP:文件传输协议 RDP:Windows远程桌面协议 SSH:Linux安全外壳协议 未授权案例(rsync) 桌面应用-QQ&WPS&Clash QQ RCE 漏洞复现 WPS RCE 漏洞复现 Clas* RCE 漏洞复现 知识点…...
视频分块上传Vue3+SpringBoot3+Minio
文章目录 一、简化演示分块上传、合并分块断点续传秒传 二、更详细的逻辑和细节问题可能存在的隐患 三、代码示例前端代码后端代码 一、简化演示 分块上传、合并分块 前端将完整的视频文件分割成多份文件块,依次上传到后端,后端将其保存到文件系统。前…...
深入浅出 -- 系统架构之单体到分布式架构的演变
一、传统模式的技术改革 在很多年以前,其实没有严格意义上的前后端工程师之分,每个后端就是前端,同理,前端也可以是后端,即Ajax、jQuery技术未盛行前的年代。 起初,大部分前端界面很简单,显示的…...
每日一题 第七十期 洛谷 [蓝桥杯 2020 省 AB2] 回文日期
[蓝桥杯 2020 省 AB2] 回文日期 题目描述 2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 yyyymmdd 的格式写成一个 8 8 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。…...
蓝桥杯第十四届C++A组(未完)
【规律题】平方差 题目描述 给定 L, R,问 L ≤ x ≤ R 中有多少个数 x 满足存在整数 y,z 使得 。 输入格式 输入一行包含两个整数 L, R,用一个空格分隔。 输出格式 输出一行包含一个整数满足题目给定条件的 x 的数量。 样例输入 1 5 样例输出 …...
职场口才提升之道
职场口才提升之道 在职场中,口才的重要性不言而喻。无论是与同事沟通协作,还是向上级汇报工作,亦或是与客户洽谈业务,都需要具备良好的口才能力。一个出色的职场人,除了拥有扎实的专业技能外,还应具备出色…...
【算法练习】28:选择排序学习笔记
一、选择排序的算法思想 弄懂选择排序算法,先得知道两个概念:未排序序列,已排序序列。 原理:以升序为例,选择排序算法的思想是,先将整个序列当做未排序的序列,以序列的第一个元素开始。然后从左…...
【关于窗口移动求和的两种计算方法】
窗口移动计算方法 例子方法1方法2运行结果: 例子 在很多算法中都会涉及到窗口滑动,比如基于新息序列更新的自适应卡尔曼滤波器算法中便会使用到。 已知一个数列:OCV [1;2;3;4;5;6;7;8;9;10;11;12;13;14;15],定义窗口长度为5,每次…...
Win10文件夹共享(有密码的安全共享)(SMB协议共享)
前言 局域网内(无安全问题,比如自己家里wifi)无密码访问,参考之前的操作视频 【电脑文件全平台共享、播放器推荐】手机、电视、平板播放硬盘中的音、视频资源 下面讲解公共网络如办公室网络、咖啡厅网络等等环境下带密码的安全…...
Client sent an HTTP request to an HTTPS server
背景 最近踩坑了 我发现域名:8000可以访问我的服务 但是域名:443却不行,这很反常 结果发现是nginx配置的问题,需要把http改成https! 原因 如果你的后端服务(运行在8000端口上)已经配置了SS…...
Springboot传参要求
Web.java(这里定义了一个实体类交Web) public class Web{ private int Page; public int getPage() {return Page;}public void setPage(int page) {Page page;} } 1、通过编译器自带的getter、Setter传参 。只是要注意参数的名字是固定的,不能灵活改变。 传参的…...
数字乡村创新实践探索:科技赋能农业现代化与乡村治理体系现代化同步推进
随着信息技术的飞速发展,数字乡村作为乡村振兴的重要战略方向,正日益成为推动农业现代化和乡村治理体系现代化的关键力量。科技赋能下的数字乡村,不仅提高了农业生产的效率和品质,也为乡村治理带来了新的机遇和挑战。本文旨在探讨…...
C语言——找单身狗1
题目描述: 在一个整形数组中,只有一个数字出现一次,其他数组都是成对出现的,找出那个只出现一次的数字。 例如: 数组中:1,2,3,4,5,4,3…...
Day82:服务攻防-开发组件安全Solr搜索Shiro身份Log4j日志本地CVE环境复现
目录 J2EE-组件Solr-本地demo&CVE 命令执行(CVE-2019-17558) 远程命令执行漏洞(CVE-2019-0193) Apache Solr 文件读取&SSRF (CVE-2021-27905) J2EE-组件Shiro-本地demo&CVE CVE_2016_4437 Shiro-550Shiro-721(RCE) CVE-2020-11989(身…...
网络协议——VRRP(虚拟路由冗余协议)原理与配置
1. VRRP概述 单网关出现故障后下联业务中断,配置两个及以上的网关时由于IP地址冲突,导致通讯时断时续甚至通信中断。VRRP组播类的网络层协议 2. 协议版本 VRRP v2: 支持认证,仅适用于IPv4网络 VRRP v3: 不支持认证, 适用于IPv4和IPv6两种网…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
Element-Plus:popconfirm与tooltip一起使用不生效?
你们好,我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip,产品要求是两个需要结合一起使用,也就是鼠标悬浮上去有提示文字,并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…...
