【后端开发】初识Spring IoC与SpringDI、图书管理系统
文章目录
- 图书管理系统
- 用户登录
- 需求分析
- 接口定义
- 前端页面代码
- 服务器代码
- 图书列表展示
- 需求分析
- 接口定义
- 前端页面部分代码
- 服务器代码
- Controller层
- service层
- Dao层
- modle层
- Spring IoC
- 定义
- 传统程序开发
- 解决方案
- IoC优势
- Spring DI
- IoC &DI使用
- 主要注解
- Spring IoC详解
- bean的存储
- 五大注解
- @Controller(控制器存储)
- getBean()方法
- 面试:ApplicationContext VS BeanFactory
- 为什么要这么多类注解
- 五大注解是否可以混用
- 程序被Spring管理的条件
- 方法注解--@Bean
- 扫描路径
- Spring DI详解
- 属性注入
- 构造方法注入
- Setter注入
- 优缺点
- @Autowired存在的问题
- @Primary
- @Qualifier
- @Resource
- 面试--@Autowird 与 @Resource的区别
图书管理系统
用户登录
需求分析
账号密码校验接口:根据输入用户名和密码校验登录是否通过。
接口定义
- url:/user/login
- type:post
- 请求参数:name=admin&password=admin
- 返回:true //账号密码验证成功,false//账号密码验证失败
前端页面代码
<body><div class="container-login"><div class="container-pic"><img src="pic/computer.png" width="350px"></div><div class="login-dialog"><h3>登陆</h3><div class="row"><span>用户名</span><input type="text" name="userName" id="userName" class="form-control"></div><div class="row"><span>密码</span><input type="password" name="password" id="password" class="form-control"></div><div class="row"><button type="button" class="btn btn-info btn-lg" onclick="login()">登录</button></div></div></div><script src="js/jquery.min.js"></script><script>function login() {$.ajax({url: "/user/login",type: "post",data: {userName: $("#userName").val(),password: $("#password").val()},success: function (result) {if (result == "") {location.href = "book_list.html";} else {alert(result)}}})}</script>
</body>
服务器代码
@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/login")public String login(String userName, String password, HttpSession session) {//1.校验参数//2.验证密码是否正确//3.返回结果if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {return "用户名或密码为空";}//理论上应该从数据库中读取,暂时先不用//一般正确情况下,会有后续的操作,因此建议将后续操作比较多的情况下放在括号外面if (!"admin".equals(userName) || !"admin".equals(password)) {return "密码错误";}session.setAttribute("userName", userName);return "";}
}
图书列表展示
需求分析
图书列表:提供图书列表信息
接口定义
- url:/user/login
- type:post
- 请求参数:无
- 返回:
[{“id”: 1,
“bookName”:“book1”,
“author” :“author1”,
“count”:270,
“price”: 20”,
publish":“publish1”,
“status”: 1,
“statusCN”:“可借阅”}…]
前端页面部分代码
<script>//这里需要直接访问到后端的图书列表信息,直接需要访问到后端,所以直接开始就使用ajax,但是为了代码的可读性,将其封装到一个方法里面先getBookList();function getBookList() {$.ajax({url:"/book/getBookList",type:"get",success:function(books){var finalHtml = "";//下面使用单引号的原因是因为html中也有双引号,可能会造成出错for(var book of books){finalHtml += '<tr>';finalHtml += '<td><input type="checkbox" name="selectBook" value="'+book.id+'" id="selectBook" class="book-select"></td>';finalHtml += '<td>'+book.id+'</td>';finalHtml += '<td>'+book.bookName+'</td>';finalHtml += '<td>'+book.author+'</td>';finalHtml += '<td>'+book.num+'</td>';finalHtml += '<td>'+book.price+'</td>';finalHtml += '<td>'+book.publishName+'</td>';finalHtml += '<td>'+book.statusCN+'</td>';finalHtml += '<td>';finalHtml += ' <div class="op">';finalHtml += '<a href="book_update.html?bookId='+book.id+'">修改</a>';finalHtml += '<a href="javascript:void(0)" onclick="deleteBook('+book.id+')">删除</a>';finalHtml += '</div></td></tr>';}$("tbody").html(finalHtml);}})}
服务器代码
Controller层
@RequestMapping("/book")
@RestController
public class BookController {@Autowiredprivate BookService bookService;@RequestMapping("/getBookList")public List<BookInfo> getBookList() {
// BookService bookService = new BookService();return bookService.getBookList();}
}
service层
@Component
public class BookService {@Autowiredprivate BookDao bookDao;public List<BookInfo> getBookList(){
// BookDao bookDao = new BookDao();List<BookInfo> bookInfos = bookDao.mockData();for (BookInfo bookInfo : bookInfos) {if (bookInfo.getStatus() == 2){bookInfo.setStatusCN("不可借阅");}else {bookInfo.setStatusCN("可借阅");}}return bookInfos;}
}
Dao层
@Component
public class BookDao {//理论上该方法应该从数据库中获取,当前采用mock方式public List<BookInfo> mockData(){List<BookInfo> bookInfos = new ArrayList<BookInfo>();//mock数据,也就是测试时候所有的模拟数据for (int i = 1; i <= 15; i++) {BookInfo bookInfo = new BookInfo();bookInfo.setId(i);bookInfo.setAuthor("作者" + i);bookInfo.setBookName("图书" + i);bookInfo.setNum(i * 2 + 1);bookInfo.setPrice(new BigDecimal(i*3));bookInfo.setPublishName("出版社" + i);if (i % 5 == 0){bookInfo.setStatus(2);
// bookInfo.setStatusCN("不可借阅");}else {bookInfo.setStatus(1);
// bookInfo.setStatusCN("可借阅");}bookInfos.add(bookInfo);}return bookInfos;}
}
modle层
@Data
public class BookInfo {private Integer id;private String bookName;private String author;private Integer num;private BigDecimal price;private String publishName;private Integer status;//1-可借阅 0-不可借阅 这里的数据都是要存放到数据库中的,尽量减少往数据库中存放文字信息private String statusCN;//这个字段不用网数据库中存储,仅是为了与status进行文字与数字的转换
}
Spring IoC
Spring的抽象概念:Spring是包含了众多⼯具⽅法的IoC容器。
定义
IoC 是Spring的核心思想,之前项目在类上添加 @Restcontroller 和@Controller 注解,就是把这个对象交给Spring管理,Spring框架启动时就会加载该类,把对象交给Spring管理,就是loC思想。
loC:Inversion of Control(控制反转),也就是说 Spring是一个"控制反转"的容器。
什么是控制反转呢?也就是控制权反转,什么的控制权发生了反转?
获得依赖对象的过程被反转了也就是说,当需要某个对象时,传统开发模式中需要自己通过 new 创建对象,现在不需要再进行创建,把创建对象的任务交给容器,程序中只需要依赖注入(DependencyInjection, Dl)就可以了这个容器称为:loC容器,Spring是一个loC容器,所以有时Spring 也称为Spring 容器。
传统程序开发
比如开发一个汽车,传统的设计思路为:
先设计轮子(Tire),然后根据轮子的大小设计底盘(Bottom),接着根据底盘设计车身(Framework),后根据车身设计好整个汽车(Car)。
这里就出现了一个"依赖"关系:汽车依赖车身,车身依赖底盘,底盘依赖轮子。
也就是Car类依赖Framework类,Framework类依赖Bottom类,Bottom类依赖Tire类。
这样的设计看起来没问题,但是可维护性却很低,接下来需求有了变更:随着对的车的需求量越来越大,个性化需求也会越来越多,我们需要加工多种尺寸的轮胎。
此时,开发一个汽车需要依赖再依赖,直至依赖到轮胎的尺寸,也就是下面的改法。
public static void main(String[] args) {public static void main(String[] args) {Car car = new Car(20);car.run();}}public class Car {private Framework framework;public Car(int size) {framework = new Framework(size);System.out.println("Car init....");}public void run() {System.out.println("Car run...");}
}public class Framework {private Bottom bottom;public Framework(int size) {bottom = new Bottom(size);System.out.println("Framework init...");}
}public class Bottom {private Tire tire;public Bottom(int size) {this.tire = new Tire(size);System.out.println("Bottom init...");}
}public class Tire {private int size;public Tire(int size) {this.size = size;System.out.println("轮胎尺⼨: " + size);}
}
以上代码可以看出,以上程序的问题是:当最底层代码改动之后,整个调用链上的所有代码都需要修改,程序的耦合度非常高(修改一处代码,影响其他处的代码修改)。
解决方案
我们尝试换一种思路,先设计汽车的大概样子,然后根据汽车的样子来设计车身,根据车身来设计底盘,最后根据底盘来设计轮子。这时候,依赖关系就倒置过来了:轮子依赖底盘,底盘依赖车身,车身依赖汽车。
可以尝试不在每个类中创建下级类,如果创建下级类就会出现当下级类发生改变操作,自己也要跟着修改。
此时,只需要将原来由自己创建的下级类,改为传递的方式(也就是注入的方式),因为我们不需要在当前类中创建下级类了,所以下级类即使发生变化(创建或减少参数),当前类本身也无需修改任何代码,这样就完成了程序的解耦。
public class Main {public static void main(String[] args) {Tire tire = new Tire(20);Bottom bottom = new Bottom(tire);Framework framework = new Framework(bottom);Car car = new Car(framework);car.run();}
}public class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;System.out.println("Car init....");}public void run() {System.out.println("Car run...");}
}public class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;System.out.println("Car init....");}public void run() {System.out.println("Car run...");}
}public class Framework {private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;System.out.println("Framework init...");}
}public class Bottom {private Tire tire;public Bottom(Tire tire) {this.tire = tire;System.out.println("Bottom init...");}
}public class Tire {private int size;public Tire(int size) {this.size = size;System.out.println("轮胎尺⼨: " + size);}
}
代码经过以上调整,无论底层类如何变化,整个调用链是不用做任何改变的,这样就完成了代码之间的解耦,从而实现了更加灵活、通用的程序设计了。
IoC优势
在传统的代码中对象创建顺序是:Car>Framework->Bottom->Tire
改进之后解耦的代码的对象创建顺序是:Tire->Bottom->Framework ->Car
改进之后的控制权发生的反转,不再是使用方对象创建并控制依赖对象了,而是把依赖对象注入将当前对象中,依赖对象的控制权不再由当前类控制了。
这样的话,即使依赖类发生任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是IoC的实现思想。
loC容器具备以下优点
- 资源集中管理:loC容器会帮助管理一些资源(对象等),需要使用时,只需要从loC容器中去取就可以了。
- 解耦合:在创建实例的时候不需要了解其中的细节,降低了使用资源双方的依赖程度,也就是耦合度。
Spring 就是一种loC容器,帮助我们来做了这些资源管理。
Spring DI
Dl:DependencyInjection(依赖注入),容器在运行期间,动态的为应用程序提供运行时所依赖的资源,称之为依赖注入。
程序运行时需要某个资源,此时容器就为其提供这个资源。
从这点来看,依赖注入(DI)和控制反转(l0C)是从不同的角度的描述的同一件事情,就是指通过引入loC容器,利用依赖关系注入的方式,实现对象之间的解耦。
上述代码通过构造函数的方式,把依赖对象注入到需要使用的对象中。
IoC是一种思想,也是"目标",而思想只是一种指导原则,最终还是要有可行的落地方案,而 DI 就属于具体的实现。
所以也可以说,DI是loC的一种实现。
IoC &DI使用
既然 Spring 是一个 loC(控制反转)容器,作为容器,那么它就具备两个最基础的功能:存、取。
Spring 容器管理的主要是对象,这些对象,我们称之为"Bean"。把这些对象交由Spring管理,由Spring来负责对象的创建和销毁,程序只需要告诉Spring,哪些需要存,以及如何从Spring中取出对象。
主要注解
@Component:交给Spring管理
@Autowired:注入运行时依赖的对象
@Component
public class BookService {@Autowiredprivate BookDao bookDao;public List<BookInfo> getBookList(){
// BookDao bookDao = new BookDao();List<BookInfo> bookInfos = bookDao.mockData();for (BookInfo bookInfo : bookInfos) {if (bookInfo.getStatus() == 2){bookInfo.setStatusCN("不可借阅");}else {bookInfo.setStatusCN("可借阅");}}return bookInfos;}
}
Spring IoC详解
前⾯提到IoC控制反转,就是将对象的控制权交给Spring的IOC容器,由IOC容器创建及管理对象,也就是bean的存储。
bean的存储
五大注解
- 五大类注解:@Controller、@Service、@Repository、@Component、@Configuration 。
- bean对象:在spring容器中存放的对象。
- ApplicationContext: 翻译为Spring上下文,指的就是当前的运行环境,也可以看作是⼀个容器。故ApplicationContext的对象中存放了所有与当前的运行环境有关的内容,比如 spring容器中存放的bean对象。
@Controller(控制器存储)
这里仅展示@Controller,其他四个注解与@Controller类似。
将UserControllerTest类用@Controller注解存放到IoC容器中。
@Controller
public class UserControllerTest {public void say(){System.out.println("hello, UserControllerTest");}
}
getBean()方法
这里分别使用三种getBean()方法来获取UserController对象,进行打印测试
@SpringBootApplication
public class LibraryApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(LibraryApplication.class, args);UserControllerTest bean = context.getBean(UserControllerTest.class);bean.say();System.out.println(bean);UserControllerTest userControllerTest = (UserControllerTest) context.getBean("userControllerTest");userControllerTest.say();System.out.println(userControllerTest);UserControllerTest userControllerTest1 = context.getBean("userControllerTest", UserControllerTest.class);userControllerTest1.say();System.out.println(userControllerTest1);}
}
结果成功输出也就是获取到了UserControllerTest对象,并且地址一样,说明是一个对象。
获取对象的功能是Application的父类BeanFactory的功能。
面试:ApplicationContext VS BeanFactory
继承关系和功能方面来说:Spring 容器有两个顶级的接口BeanFactory和ApplicationContext。
其中 BeanFactory 提供了基础的访问容器的能力,而ApplicationContext 属于 BeanFactony 的子类,它除了继承了 BeanFactory 的所有功能之外,它还拥有独特的特性,还添加了环境管理支持、资源访问支持、以及事件传播等方面的支持。
从性能方面来说:ApplicationContext 是一次性加载并初始化所有的 Bean 对象,而BeanFactory 是需要那个才去加载那个,因此更加轻量(空间换时间)。
为什么要这么多类注解
与应用分层呼应,让程序员看到类注解之后,就能直接了解当前类的用途。
- @Controller:控制层,接收请求,对请求进行处理,并进行响应
- @Servie:业务逻辑层,处理具体的业务逻辑
- @Repository:数据访问层,也称为持久层,负责数据访问操作
- @Configuration:配置层,处理项目中的一些配置信息
- @Component:是一个元注解,也就是说可以注解其他类注解@Controller,@Service,@Repository,@Confiquraion,这些注解被称为@Component 的行生注解,因为这些注解源代码里面都有一个注解@Component。
五大注解是否可以混用
功能上:@Service @Repository @Configuration @Component 可以完全混用,@Controller有自己的特殊性。
规范上:不可以混用。因为我们想要与应用分层呼应。
程序被Spring管理的条件
- 程序要被spring扫描到(默认路径是启动类所在的目录以及子目录),手动设置:@ComponentScan(basePackages = “~”)
- 程序需要配置五大注解和@Bean
方法注解–@Bean
@Bean要搭配类注解使用
类注解是添加到某个类上的,但是存在两个问题:
- 使用外部包里的类,没办法添加类注解
- 一个类,需要多个对象,比如多个数据源
示例1,@Bean要搭配类注解使用
@Configuration
public class UserConfig {public void say(){System.out.println("hi,UserConfig");}@Beanpublic User user(){return new User("张三");}
}
示例2:定义多个对象,使用类的类型扫描
@Service
public class UserService {public void say(){System.out.println("hello, UserService");}@Beanpublic BookInfo user(){return new BookInfo();}@Beanpublic BookInfo user1(){return new BookInfo();}
}@SpringBootApplication
public class LibraryApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(LibraryApplication.class, args);BookInfo bean = context.getBean(BookInfo.class);System.out.println(bean);}
}
通过类的类型扫描,这里出现了报错,通过类的类型扫描,此时容器中有两个User对象,根据类型获取对象,此时Spring不知道要获取哪个对象,所以报错了。
解决办法:用类的名字扫描。
@SpringBootApplication
public class LibraryApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(LibraryApplication.class, args);BookInfo bean1 = (BookInfo) context.getBean("user");System.out.println(bean1);BookInfo bean2 = (BookInfo) context.getBean("user1");System.out.println(bean2);}
}
扫描路径
把启动类放到其他的目录下面,再次启动程序,会出错。
就是因为没有找到对应的bean对象,使用五大注解声明的bean,要想生效,还需要配置扫描路径,让Spring扫描到这些注解也就是通过 @ComponentScan 来配置扫描路径。
@ComponentScan({"com.example.library"})
@SpringBootApplication
public class LibraryApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(LibraryApplication.class, args);}
}
Spring DI详解
DI(依赖注入):依赖注入是一个过程,是指loC容器在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象在上面程序案例中,我们使用了 @Autowired 这个注解,完成了依赖注入的操作简单来说,就是把对象取出来放到某个类的属性中。
在一些文章中,依赖注入也被称之为"对象注入”、"属性装配”,具体含义需要结合文章的上下文来理解。
关于依赖注入, Spring也给我们提供了三种方式:
属性注入(Field Injection)
构造⽅法注入(Constructor Injection)
Setter 注入(Setter Injection)
属性注入
@Controller
public class UserControllerTest {@Autowiredprivate UserService userService;//属性注入public void say(){System.out.println("hello, UserControllerTest");}
}
构造方法注入
只有一个构造方法的时候即使不加@Autowired也可以获取数据,但是要是加一个空的构造方法,会报出空指针异常。
因为程序启动的时候会首先调用无参数的构造方法,如果没有会调用我们写的,但是两个都有的话就会调用无参数的,此时并没有真正new对象,去调用say()方法就会出现空指针异常。
解决办法:就是在想要注入的构造方法中添加@Autowired注解
@Controller
public class UserControllerTest {private UserService userService;@Autowiredpublic UserService(UserService service){this.userService = service;}public void say(){System.out.println("hello, UserControllerTest");}
}
Setter注入
@Controller
public class UserControllerTest {private UserService userService;@Autowiredpublic void setUserService(UserService service){this.userService = service;}public void say(){System.out.println("hello, UserControllerTest");}
}
优缺点
- 属性注入
优点:简洁,使用方便
缺点:只能用于 loC 容器,如果是非 loC 容器不可用,并且只有在使用的时候才会出现 NPE(空指针异常);不能注入一个Final修饰的属性。 - 构造函数注入(Spring4.x推荐)
优点:可以注入final修饰的属性;注入的对象不会被修改依赖对象;在使用前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是在类加载阶段就会执行的方法;通用性好,构造方法是JDK支持的,所以更换任何框架都是适用的。
缺点:注入多个对象时,代码会比较繁琐。 - Setter注入
优点:方便在类实例之后,重新对该对象进行配置或者注入。
缺点:不能注入一个Final修饰的属性;注入对象可能会被改变,因为setter方法可能会被多次调用,就有被修改的风险。
@Autowired存在的问题
Student 实体类
@Data
public class Student {private String name;private Integer id;public Student() {}public Student(String name) {this.name = name;}public Student(String name, Integer id) {this.name = name;this.id = id;}
BeanConfig类
@Configuration
public class BeanConfig {@Beanpublic Student StudentInfo() {return new Student("wh",01);}@Beanpublic Student StudentInfo2() {return new Student("Bob",02);}
}
DomeController类
@Controller
public class DomeController {@Autowiredprivate Student student;public void say(){System.out.println(student);}
}
启动类
@SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(SpringIocApplication.class, args);DomeController bean = context.getBean(DomeController.class);bean.say();}
}
运行
报错的原因是,非唯一的 Bean 对象
解释:@Autowired是先按照类型去注入,匹配到多个对象时,再按照名称去注入。
如果明确注入对象的名称,则可以正确打印该学生信息。
@Controller
public class DomeController {@Autowiredprivate Student StudentInfo2;public void say(){System.out.println(StudentInfo2);}
}
那当没有明确注入对象的名称,又想得到正确结果我们可以怎么做?
有以下几种解决方案:
@Primary
@Qualifier
@Resource
@Primary
使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。
直接加到Bean注入的方法上。
@Primary
@Bean
public Student StudentInfo() {return new Student("wh", 01);
}
@Qualifier
使⽤@Qualifier注解:指定当前要注⼊的bean对象。 在@Qualifier的value属性中,指定注⼊的bean 的名称。
@Qualifier注解不能单独使⽤,必须配合@Autowired使用。
@Controller
public class DomeController {@Qualifier("StudentInfo2")@Autowiredprivate Student student;public void say(){System.out.println(student);}
}
@Resource
本身就是依赖注入注解,是按照bean的名称进行注入。
@Controller
public class DomeController {@Resource(name = "StudentInfo")private Student student;public void say(){System.out.println(student);}
}
面试–@Autowird 与 @Resource的区别
- @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解。
- @Autowired 默认是按照类型注入,而@Resource是按照名称注入,相比于 @Autowired 来说, @Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean。
相关文章:
【后端开发】初识Spring IoC与SpringDI、图书管理系统
文章目录 图书管理系统用户登录需求分析接口定义前端页面代码服务器代码 图书列表展示需求分析接口定义前端页面部分代码服务器代码Controller层service层Dao层modle层 Spring IoC定义传统程序开发解决方案IoC优势 Spring DIIoC &DI使用主要注解 Spring IoC详解bean的存储五…...
VMware虚拟机Ubuntu磁盘扩容
VMware中操作: 选择要扩容的虚拟机,点击编辑虚拟机设置 打开后点击磁盘——>点击扩展(注意:如果想要扩容的话需要删除快照) 调整到你想要的容量 点击上图的扩展——>确定 然后我们进到虚拟机里面 首先&#…...
嵌入式MCU常用模块
日后填坑。 无线通信模块 NRF24L01 基本介绍 使用方法 示例代码 蓝牙模块 基本介绍 使用方法 示例代码 WIFI模块 基本介绍 使用方法 示例代码 红外遥控模块 基本介绍 使用方法 示例代码 有线通信模块 can模块 基本介绍 使用方法 示例代码 传感器模块 DHT11模块 基本介绍 使用方…...
算法 模版
cin cout加快读取速度: ios::sync_with_stdio(false); 高精度*高精度 vector<int> mul(vector<int>& a, vector<int>& b) {vector<int>c(b.size()a.size()5,0);for (int i 0; i < a.size(); i) {for (int j 0; j < b.si…...
C++指针(三)
个人主页:PingdiGuo_guo 收录专栏:C干货专栏 文章目录 前言 1.字符指针 1.1字符指针的概念 1.2字符指针的用处 1.3字符指针的操作 1.3.1定义 1.3.2初始化 1.4字符指针使用注意事项 2.数组参数,指针参数 2.1数组参数 2.1.1数组参数的概念 2.1…...
二分查找4:35. 搜索插入位置
链接:35. 搜索插入位置 - 力扣(LeetCode) 题解: 本题是最基础的二分查找算法 class Solution { public:int searchInsert(vector<int>& nums, int target) {int left0;int rightnums.size()-1;int midleft(right-lef…...
数据可视化 —— 多边图应用(大全)
一、介绍: 多边形图,也就是在数据可视化中使用多边形来呈现数据的图表,在多个领域都有广泛的应用场景,以下为你详细介绍: 金融领域 投资组合分析:在投资组合管理中,多边形图可用于展示不同资…...
服务器加空间失败 growpart /dev/vda 1
[rootecm-2c5 ~]# growpart /dev/vda 1 unexpected output in sfdisk --version [sfdisk,来自 util-linux 2.23.2] [rootecm-2c5 ~]# xfs_info /dev/vda1 meta-data/dev/vda1 isize512 agcount21, agsize1310656 blks sectsz512 attr2, projid32bit1 crc1 finobt0…...
tree-sitter的grammar.js解惑
❓问题1:grammar.js 不是用正则表达式 /.../ 吗?为什么有 print 这样的字符串? ✅ 回答: grammar.js 分成两类“终结符”表示法: 表达方式含义xxx直接匹配该字符串字面量/regex/匹配符合正则的文本 💡 …...
前端-Vue3
1. Vue3简介 2020年9月18日,Vue.js发布版3.0版本,代号:One Piece(n 经历了:4800次提交、40个RFC、600次PR、300贡献者 官方发版地址:Release v3.0.0 One Piece vuejs/core 截止2023年10月,最…...
【毕设通关】——文献查阅
目录 🕒 1. 常见文献库🕒 2. 快速寻找文献🕒 3. 引用网页资料 🕒 1. 常见文献库 中文文献: CNKI中国知网万方数据维普资讯超星期刊 英文文献: 谷歌学术Sci-hubOALib(Open Access Library&am…...
贪心算法-跳跃游戏
55.跳跃游戏 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。输入…...
程序化广告行业(75/89):行业发展与PC端和移动端投放差异
程序化广告行业(75/89):行业发展与PC端和移动端投放差异 在互联网广告领域,程序化广告正发挥着越来越重要的作用。今天,咱们就来一起深入了解一下程序化广告行业,希望能和大家一起学习进步,共同…...
Windows 下搭建 Git 本地服务器并进行开发
目录 1. 安装 Git for Windows 2. 创建本地 Git 仓库(裸仓库) 3. 设置本地开发环境 (1) 在开发机器上克隆仓库 (2) 提交代码 4. 远程访问本地 Git 服务器 方法 1:使用 SSH 访问 (1) 配置 SSH 服务器 (2) 客户端连接 方法 2…...
C++中stack函数的用法示例
C++中stack函数的用法示例 std::stack 是C++标准模板库(STL)中的一个容器适配器,它提供了后进先出(LIFO)的数据结构。以下是stack的一些常用函数及其用法示例: 1. 基本操作 #include <iostream> #include <stack>int main() {// 创建一个整数栈std::stack<…...
网络安全1
一、网络安全的定义与重要性 定义 网络安全(信息技术安全):保护计算机系统和网络免受电子攻击的技术和过程,包括保护个人信息和企业数据不被盗窃、破坏或非法访问。涵盖范围:网络设备、数据传输、系统运行安全。 重要…...
腾讯会议for flatpak
今天想切换opensuse,无意间查询了腾讯会议等软件的下载方式,发现腾讯会议是deb包安装的。但是过程中,我发现flatpak仓库中居然有腾讯会议,然后尝试着在wayland下的debian12中进行了安装。 发现居然可以正常开启视频等操作。 下载…...
【C++初学】C++核心编程技术详解(二):类与继承
函数提高 3.1 函数默认参数 函数的形参可以有默认值,调用时可以省略这些参数。 示例代码: int func(int a, int b 10, int c 10) {return a b c; }int main() {cout << "ret " << func(20, 20) << endl;cout <<…...
紧急任务插入,如何不影响原计划
面对紧急任务插入,为确保不影响原计划,需要做到:重新明确任务优先级、合理调整资源配置、灵活管理时间和任务、建立紧急任务处理流程、有效沟通与反馈。其中,重新明确任务优先级最为关键。这可以帮助项目团队快速确定哪些任务需立…...
蓝桥杯赛前题
开始每个人能量为3 答题了,答题者1 扣分最后算 #include<bits/stdc.h> using namespace std;const int N1e510; int a[N]; int main(){int n,k,q;cin>>n>>k>>q;for(int i1;i<n;i){a[i]k; }for(int i1;i<q;i){int x;cin>>x;a[…...
ETL的核心概念与价值
在数字化转型的浪潮中,数据已成为企业决策的基石。然而,面对分散、异构且质量参差不齐的数据源,如何高效整合并挖掘其价值?这一问题的答案,指向了一项关键的技术——ETL(Extract-Transform-Load)…...
神经动力学系统与计算及AI拓展
大脑,一个蕴藏在我们颅骨之内的宇宙,以活动脉动,如同由电信号和化学信号编织而成的交响乐,精巧地协调着思想、情感和行为。但是,这种复杂的神经元舞蹈是如何产生我们丰富多彩的精神生活的呢?这正是神经动力…...
力扣DAY46-50 | 热100 | 二叉树:展开为链表、pre+inorder构建、路径总和、最近公共祖先、最大路径和
前言 中等 、困难 √,越来越有手感了,二叉树done! 二叉树展开为链表 我的题解 前序遍历树,当遇到左子树为空时,栈里pop节点,取右子树接到左子树位置,同时断开该右子树与父节点的连接&#x…...
备赛蓝桥杯-Python-考前突击
额,,离蓝桥杯开赛还有十个小时,最近因为考研复习节奏的问题,把蓝桥杯的优先级后置了,突然才想起来还有一个蓝桥杯呢。。 到目前为止python基本语法熟练了,再补充一些常用函数供明天考前再背背,算…...
蓝桥杯 Web 方向入门指南:从基础到实战
一、蓝桥杯 Web 方向简介 蓝桥杯是国内最具影响力的编程竞赛之一,Web 方向主要考察前端开发和后端服务能力。比赛形式为 4 小时限时编程,题型包括页面布局、数据交互、API 开发等。根据最新大纲,大学组需掌握 HTML5、CSS3、JavaScript、Vue.…...
生命篇---心肺复苏、AED除颤仪使用、海姆立克急救法、常见情况急救简介
生命篇—心肺复苏、AED除颤仪使用、海姆立克急救法、常见情况急救简介 文章目录 生命篇---心肺复苏、AED除颤仪使用、海姆立克急救法、常见情况急救简介一、前言二、急救1、心肺复苏(CPR)(1)适用情况(2)操作…...
C++Cherno 学习笔记day19 [76]-[80] std::optional、variant、any
b站Cherno的课[76]-[80] 一、如何处理OPTIONAL数据 std::optional二、单一变量存放多类型的数据 std::variant三、如何存储任意类型的数据 std::any四、如何让C运行得更快五、如何让C字符串更快 一、如何处理OPTIONAL数据 std::optional std::optional C17 数据是否存在是可选…...
【Python Requests 库详解】
目录 简介一、安装与导入安装导入 二、发送 HTTP 请求1. GET 请求基本请求URL 参数 2. POST 请求表单数据提交JSON 数据提交文件上传 3. 其他方法PUT 请求示例DELETE 请求示例 三、处理响应1. 响应内容解析文本内容处理二进制内容处理JSON 数据处理 2. 响应状态与头信息状态码检…...
二维偏序-蓝桥20102,没写完
代码: 暴力:只过了35%,双重for循环o(n^2)1e10; #include <iostream> #include <bits/stdc.h> using namespace std; const int N1e910; typedef long long LL; typedef pair<int,int> PII;int main() {// 请在此输入您的代码//相当于…...
ASEG的鉴定
等位基因特异性表达(Allele-Specific Expression, ASE)基因的鉴定是研究杂种优势和基因表达调控的重要手段。以下是鉴定ASE基因的详细流程和方法: ### **1. 实验设计与样本准备** - **选择材料**:选择杂交种及其亲本作为研究材料。例如,玉米中的B73和Mo17及其杂交组合B73…...
从零开始:在 GrapesJS Style Manager 中新增 row-gap 和 column-gap
在前端开发中,页面样式的灵活性和可扩展性至关重要。GrapesJS 作为一个强大的网页构建工具,其内置的 Style Manager 提供了常见的 CSS 样式的可视化设置,极大地方便了开发者和设计师。然而,随着项目需求的不断变化,有些…...
解决双系统ubuntu24.04开机出现花屏等情况
1. 问题描述: 刚刚装上的双系统ubuntu24.04开机就出现花屏情况 2. 解决方案 安装显卡驱动 查看显卡型号 查看显卡硬件支持的驱动类型 ubuntu-drivers devices如果输入没有反映,请更新软件源,或者换官方软件源 sudo add-apt-repository…...
基于SpringBoot的智慧社区管理系统(源码+数据库)
499基于SpringBoot的智慧社区管理系统,系统包含三种角色:管理员、用户主要功能如下。 【用户功能】 1. 首页:查看系统。 2. 超市商品:浏览超市中各类商品信息。 3. 动物信息:了解社区内的动物种类和相关信息。 4. 车位…...
通俗理解CLIP模型如何实现图搜图乃至文搜图
一、图搜图与文搜图 图搜图和文搜图的场景相信大家并不少见,比如度娘的搜索框就可以直接上传图片找到相似的图片,还有某宝某团都有这种上传图片匹配到相似商品或者商品页的推荐的功能。那比如我想搜一张“正在跳舞的狗”的图片,是不是就能搜…...
谷歌最近放出大招——推出全新“Agent Development Kit(简称ADK)
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
std::string` 类
以下是对 std::string 类中 修改操作 和 字符串操作 的示例代码,帮助你更好地理解这些函数的使用: 5. 修改操作 (1) operator 用于追加字符串、C 风格字符串或字符。 #include <iostream> #include <string>int main() {std::string str …...
Sping Cloud配置和注册中心
1.Nacos实现原理了解吗? Nacos是注册中心,主要是帮助我们管理服务列表。Nacos的实现原理大概可以从下面三个方面来讲: 服务注册与发现:当一个服务实例启动时,它会向Nacos Server发送注册请求,将自己的信息…...
Java基础 - 泛型(常见用法)
文章目录 泛型类泛型方法泛型类派生子类示例 1:子类固定父类泛型类型(StringBox 继承自 Box<String>)示例 2:子类保留父类泛型类型(AdvancedBox<T> 继承自 Box<T>)示例 3:添加子类自己的…...
待排序元素规模较小时,宜选取哪种排序算法效率最高
当待排序元素规模较小时,通常选择以下几种简单高效的排序算法,因为它们在小规模数据下具有更低的常数开销和良好的局部性表现: ✅ 插入排序(Insertion Sort) 推荐理由:在数据量小、数据部分有序的情况下&a…...
SAQ评级是什么,SAQ评级的意义?对企业发展好处
SAQ评级(Supplier Audit Questionnaire,供应商审计问卷评级)是供应链管理中常见的一种评估机制,主要用于对供应商的质量、合规性、风险管理能力等进行标准化审核和分级。它常见于汽车、电子、医药等对供应链要求严格的行业&#x…...
嵌入式---电机分类
一、按电流类型分类(最基础分类) 1. 直流电机(DC Motor) 工作原理:通过换向器(有刷)或电子换向(无刷)将直流电源转换为交变磁场,驱动转子旋转。 核心特点&a…...
定制一款国密浏览器(5):修改浏览器名称
在上一章中,我介绍了如何修改浏览器的 logo,这一章介绍修改浏览器的名称。 浏览器的名称是 AI 帮我想的,英文名 Mojo Browser,中文名墨舟浏览器。 第一步先修改 desktop 文件,desktop 文件支持多语言化,遵循 Freedesktop.org 制定的 Desktop Entry Specification 规范。…...
水库大坝安全监测系统
水库大坝安全监测系统是现代水利管理中至关重要的组成部分,是一种用于实时监控和评估大坝结构安全状况的技术系统,通过多种技术手段实现对水库大坝的全方位、全天候监测,旨在确保大坝的稳定性和安全性,预防潜在风险。 系统构成 …...
文件IO5(JPEG图像原理与应用)
JPEG图像原理与应用 ⦁ 基本概念 JPEG(Joint Photographic Experts Group)指的是联合图像专家组,是国际标准化组织ISO制订并于1992年发布的一种面向连续色调静止图像的压缩编码标准,所以也被称为JPEG标准。 同样,JP…...
开源Cursor替代品——Void
我原先写过很多关于Cursor文章。 今天分享一个开源的 Cursor 替代方案。 如果你也热爱开源项目,那么这篇文章正是为你准备的! 寻找开源替代的原因 我一直在思考:市面上这类产品层出不穷,但真正的核心技术似乎都依赖于大语言模型(LLM)。于是萌生了一个想法——何不自己…...
DAOS系统架构-组件
如上图所示,一个完整的DAOS系统是由管理节点组件、客户端节点组件、服务端节点组件以及网络通信组件四个部分组成。管理节点组件通过管理网络通道(蓝色)对DAOS服务管理和监控。客户端节点组件通过数据网络通道(红色)与…...
论文精读:MSCA-Net:多尺度上下文聚合网络在红外小目标检测中的突破
论文地址:https://arxiv.org/pdf/2503.17193 目录 一、论文结构解析 二、三大创新点详解 1. 多尺度增强检测注意力(MSEDA) 2. 位置卷积块注意力模块(PCBAM) 3. 通道聚合模块(CAB) 三、实验结果对比 定量分析(表I关键数据) 定性对比 四、应用场景展望 五、总…...
LangGraph 使用指南
安装配置 安装依赖 LangGraph 可以通过 pip 安装: pip install langgraph如果您想使用最新的功能和改进,可以从源代码安装: pip install githttps://github.com/langchain-ai/langgraph.git环境配置 LangGraph 与 LangChain 共享许多配置…...
C++指针(四)万字图文详解!
个人主页:PingdiGuo_guo 收录专栏:C干货专栏 前言 相关文章:C指针(一)、C指针(二)、C指针(三) 本篇博客是介绍函数指针、函数指针数组、回调函数、指针函数的。 点赞破六…...
【AI提示词】长期主义助手提供规划支持
提示说明 长期主义是一种关注长期利益和持续学习的思维模式,帮助个人和组织在快速变化的环境中保持耐心和系统性思考。 提示词 # Role: Long-termist Assistant## Profile - language: 中文 - description: 长期主义是一种关注长期利益和持续学习的思维模式&…...