Java重要面试名词整理(二):SpringMyBatis
文章目录
- Spring篇
- Spring核心
- 推断构造方法
- AOP
- 动态代理
- Advice的分类
- Advisor的理解
- AOP相关的概念
- 定义Bean
- ASM技术
- JFR
- 依赖注入
- 循环依赖
- Lifecycle
- Spring AOT
- Spring事务
- Spring事务传播机制
- Spring事务传播机制是如何实现的呢?
- Spring事务传播机制分类
- SpringMVC
- Handler
- HandlerMapping
- HandlerAdapter
- @RequestMapping方法参数
- SPI
- Spring MVC不常用注解
- @InitBinder
- @SessionAttributes
- @RequestAttribute 与 @SessionAttribute
- @ModelAttribute
- flashMap
- MyBatis篇
- MyBatis执行SQL流程分析
- MyBatis重要类分析
- MyBatis的二级缓存原理
- OGNL表达式
- Mybatis中的OGNL表达式
- Mybatis中的OGNL表达式拓展
Spring篇
Spring核心
推断构造方法
Spring会根据入参的类型和入参的名字去Spring中找Bean对象(以单例Bean为例,Spring会从单例池那个Map中去找):
- 先根据入参类型找,如果只找到一个,那就直接用来作为入参
- 如果根据类型找到多个,则再根据入参名字来确定唯一一个,会根据入参名字来找Map里面一样名字的作为入参。
- 最终如果没有找到,则会报错,无法创建当前Bean对象
确定用哪个构造方法,确定入参的Bean对象,这个过程就叫做推断构造方法。
AOP
AOP全称是 Aspect Oriented Programming 即:面向切面编程。是OOP的延续,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。简单的说他就是把我们程序重复的代码抽取出来,在需要执行的时候使用动态代理技术在不修改源码的基础上,对我们的已有方法进行增强。
动态代理
代理模式的解释:为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。
在Spring中进行了封装,封装出来的类叫做ProxyFactory,表示是创建代理对象的一个工厂,使用起来会比JDK动态代理、cglib动态代理更加方便。
UserService target = new UserService();ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvice(new MethodInterceptor() {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("before...");Object result = invocation.proceed();System.out.println("after...");return result;}
});UserInterface userService = (UserInterface) proxyFactory.getProxy();
userService.test();
通过ProxyFactory,我们可以不再关心到底是用cglib还是jdk动态代理了,ProxyFactory会帮我们去判断,如果UserService实现了接口,那么ProxyFactory底层就会用jdk动态代理,如果没有实现接口,就会用cglib技术,上面的代码,就是由于UserService实现了UserInterface接口,所以最后产生的代理对象是UserInterface类型。
Advice的分类
- Before Advice:方法之前执行
- After returning advice:方法return后执行
- After throwing advice:方法抛异常后执行
- After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后
- Around advice:这是功能最强大的Advice,可以自定义执行顺序
Advisor的理解
跟Advice类似的还有一个Advisor的概念,一个Advisor是有一个Pointcut和一个Advice组成的,通过Pointcut可以指定要需要被代理的逻辑,比如一个UserService类中有两个方法,按上面的例子,这两个方法都会被代理,被增强,那么我们现在可以通过Advisor,来控制到具体代理哪一个方法,比如:
UserService target = new UserService();ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.setTarget(target);proxyFactory.addAdvisor(new PointcutAdvisor() {@Overridepublic Pointcut getPointcut() {return new StaticMethodMatcherPointcut() {@Overridepublic boolean matches(Method method, Class<?> targetClass) {return method.getName().equals("testAbc");}};}@Overridepublic Advice getAdvice() {return new MethodInterceptor() {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("before...");Object result = invocation.proceed();System.out.println("after...");return result;}};}@Overridepublic boolean isPerInstance() {return false;}});UserInterface userService = (UserInterface) proxyFactory.getProxy();userService.test();
上面代码表示,产生的代理对象,只有在执行testAbc这个方法时才会被增强,会执行额外的逻辑,而在执行其他方法时是不会增强的。
AOP相关的概念
- Aspect:表示切面,比如被@Aspect注解的类就是切面,可以在切面中去定义Pointcut、Advice等等
- Join point:表示连接点,表示一个程序在执行过程中的一个点,比如一个方法的执行,比如一个异常的处理,在Spring AOP中,一个连接点通常表示一个方法的执行。
- Advice:表示通知,表示在一个特定连接点上所采取的动作。Advice分为不同的类型,后面详细讨论,在很多AOP框架中,包括Spring,会用Interceptor拦截器来实现Advice,并且在连接点周围维护一个Interceptor链
- Pointcut:表示切点,用来匹配一个或多个连接点,Advice与切点表达式是关联在一起的,Advice将会执行在和切点表达式所匹配的连接点上
- Introduction:可以使用@DeclareParents来给所匹配的类添加一个接口,并指定一个默认实现
- Target object:目标对象,被代理对象
- AOP proxy:表示代理工厂,用来创建代理对象的,在Spring Framework中,要么是JDK动态代理,要么是CGLIB代理
- Weaving:表示织入,表示创建代理对象的动作,这个动作可以发生在编译时期(比如Aspejctj),或者运行时,比如Spring AOP
定义Bean
Spring中定义Bean的方式可以分为两类,分别是声明式和编程式。顾名思义,声明式可以理解为用一个的标记去标识相关的信息,代码底层再对这些标识符进行一个解析处理;编程式则更多侧重于使用代码的形式去处理相关逻辑。前者使用更友好,后者更底层。
声明式:标签、@Bean注解、@Component注解
编程式:BeanDefinition接口、FactoryBean接口、Supplier接口
ASM技术
在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader。需要注意的是,SimpleMetadataReader去解析类时,使用的ASM技术。
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。ASM并没有让这个类加载到JVM。
JFR
JFR资料介绍:JFR 是 Java Flight Record (Java飞行记录) 的缩写,是 JVM 内置的基于事件的JDK监控记录框架。这个起名就是参考了黑匣子对于飞机的作用,将Java进程比喻成飞机飞行。顾名思义,这个记录主要用于问题定位和持续监控。
依赖注入
依赖注入(Dependency Injection, DI)是一种设计模式,也是Spring框架的核心概念之一。其作用是去除Java类之间的依赖关系,实现松耦合,以便于开发测试。依赖注入分为手动注入和自动注入两种注入方式。
手动注入:在XML中定义Bean时,就是手动注入,因为是程序员手动给某个属性指定了值。手动注入分为两种:
-
set方法注入
<bean name="userService" class="com.luban.service.UserService"><property name="orderService" ref="orderService"/> </bean>
-
构造方法注入
<bean name="userService" class="com.luban.service.UserService"><constructor-arg index="0" ref="orderService"/> </bean>
自动注入:分为两种:
-
XML的autowire自动注入
在XML中,我们可以在定义一个Bean时去指定这个Bean的自动注入模式:
- byType
- byName
- constructor
- default
- no
<bean id="userService" class="com.luban.service.UserService" autowire="byType"/>
-
@Autowired注解的自动注入
@Autowired注解可以写在:
- 属性上:先根据属性类型去找Bean,如果找到多个再根据属性名确定一个
- 构造方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
- set方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
循环依赖
简单来说就是A对象依赖了B对象,B对象依赖了A对象。
如果不考虑Spring,循环依赖并不是问题,因为对象之间相互依赖是很正常的事情。但是,在Spring中循环依赖就是一个问题了,因为在Spring中,一个对象并不是简单new出来了,而是会经过一系列的Bean的生命周期,就是因为Bean的生命周期所以才会出现循环依赖问题。
Spring解决循环依赖使用了三级缓存。三级缓存是通用的叫法。
一级缓存为:singletonObjects
二级缓存为:earlySingletonObjects
三级缓存为**:singletonFactories**
-
singletonObjects中缓存的是已经经历了完整生命周期的bean对象。
-
earlySingletonObjects比singletonObjects多了一个early,表示缓存的是早期的bean对象。早期是什么意思?表示Bean的生命周期还没走完就把这个Bean放入了earlySingletonObjects。
-
singletonFactories中缓存的是ObjectFactory,表示对象工厂,表示用来创建早期bean对象的工厂。
Lifecycle
Lifecycle表示的是ApplicationContext的生命周期,可以定义一个SmartLifecycle来监听ApplicationContext的启动和关闭
@Component
public class isPaintingLifecycle implements SmartLifecycle {private boolean isRunning = false;@Overridepublic void start() {System.out.println("启动");isRunning = true;}@Overridepublic void stop() {// 要触发stop(),要调用context.close(),或者注册关闭钩子(context.registerShutdownHook();)System.out.println("停止");isRunning = false;}@Overridepublic boolean isRunning() {return isRunning;}
}
Spring AOT
Spring 6 提供了一项新功能,有望优化应用程序的性能: Ahead-of-Time(AOT) 编译支持。
Ahead-of-Time(AOT,提前编译或预编译)是一种在应用程序运行前将字节码预编译为本地机器码的技术。
通过 AOT 编译构建的应用程序在性能和资源消耗方面具有多重优势:
- 消除死代码:AOT 编译器可以消除运行时从未执行过的代码。这样可以减少需要执行的代码量,从而提高性能。
- 内联:内联是 AOT 编译器用函数的实际代码,替换函数调用的一种技术。这可以减少函数调用的开销,从而提高性能。
- 常量传播:AOT 编译器通过在编译时确定变量的常量值来替换变量,从而优化性能。这样就无需进行运行时计算,从而提高了性能。
- 过程间优化:AOT 编译器可通过分析程序的调用图来优化跨多个函数的代码。这可以通过减少函数调用的开销和识别常见的子表达式来提高性能。
- Bean 定义:Spring 6 中的 AOT 编译器可减少不必要的
BeanDefinition
实例,从而提高应用程序的效率。
因此,让我们使用 AOT 优化命令来构建应用程序:
mvn clean compile spring-boot:process-aot package
然后使用命令运行应用程序:
java -Dspring.aot.enabled=true -jar <jar-name>
我们可以设置构建插件,默认启用 AOT 编译:
<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><id>process-aot</id><goals><goal>process-aot</goal></goals></execution></executions>
</plugin>
Spring事务
Spring事务传播机制
Spring事务传播机制是如何实现的呢?
在执行某个方法时,判断当前是否已经存在一个事务,就是判断当前线程的ThreadLocal中是否存在一个数据库连接对象,如果存在则表示已经存在一个事务了。
Spring事务传播机制分类
REQUIRED (默认传播行为),支持当前事务,如果当前没有事务,就新建一个事务,这个当前事务指的是上一个方法的事务,是别人传递过去的,类似于重入锁,A方法和B方法都有事务,A方法调用B方法,A的事务会传递给B,使它们共用同一个事务,我起了个名字叫做重入事务
SUPPORTS 如果存在一个事务,支持当前事务,如果没有事务,则非事务执行,
REQUIRES_NEW 开启一个新的事务。如果一个事务已经存在,则先将这个存在的事务挂起
MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常
NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务
NEVER 总是非事务地执行,不加入任何事务;
NESTED 如果一个活动的事务存在,则运行在一个嵌套的事务中。 如果没有活动事务, 则按 REQUIRED 属性执行。
SpringMVC
Handler
Handler表示请求处理器,在SpringMVC中有四种Handler:
1、实现了Controller接口的Bean对象
2、实现了HttpRequestHandler接口的Bean对象
3、添加了@RequestMapping注解的方法
4、一个HandlerFunction对象
HandlerMapping
HandlerMapping负责去寻找Handler,并且保存路径和Handler之间的映射关系。
因为有不同类型的Handler,所以在SpringMVC中会由不同的HandlerMapping来负责寻找Handler
HandlerAdapter
由于有不同种类的Handler,所以执行方式是不一样的。所以,按逻辑来说,找到Handler之后,我们得判断它的类型。把不同种类的Handler适配成一个HandlerAdapter,后续再执行HandlerAdapter的handle()方法就能执行不同种类Hanlder对应的方法。
针对不同的Handler,会有不同的适配器。
@RequestMapping方法参数
当SpringMVC接收到请求,并找到了对应的Method之后,就要执行该方法了,不过在执行之前需要根据方法定义的参数信息,从请求中获取出对应的数据,然后将数据传给方法并执行。
一个HttpServletRequest通常有:
1、request parameter
2、request attribute
3、request session
4、reqeust header
5、reqeust body
比如如下几个方法:
public String test(String username) {return "ispainting";
}
表示要从request parameter中获取key为username的value
public String test(@RequestParam("uname") String username) {return "ispainting";
}
表示要从request parameter中获取key为uname的value
public String test(@RequestAttribute String username) {return "ispainting";
}
表示要从request attribute中获取key为username的value
public String test(@SessionAttribute String username) {return "ispainting";
}
表示要从request session中获取key为username的value
public String test(@RequestHeader String username) {return "ispainting";
}
表示要从request header中获取key为username的value
public String test(@RequestBody String username) {return "ispainting";
}
表示获取整个请求体
SPI
跟Tomcat的提供的扩展机制有关,在SpringMVC中有这样一个类:
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {@Overridepublic void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)throws ServletException {// ...}}
这个类实现了javax.servlet.ServletContainerInitializer接口,并且在SpringMVC中还有这样一个文件:META-INF/services/Tomcatjavax.servlet.ServletContainerInitializer,文件内容为org.springframework.web.SpringServletContainerInitializer。
很明显,是SPI,所以Tomcat在启动过程中会找到这个SpringServletContainerInitializer,并执行onStartup()
SPI(Service Provider Interface),是JDK内置的一种服务提供发现机制,可以用来启用框架扩展和替换组件。Java的SPI机制可以为某个接口寻找服务实现。Java中SPI机制主要思想是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要,其核心思想就是解耦。
SPI与API区别:
- API是调用并用于实现目标的类、接口、方法等的描述;
- SPI是扩展和实现以实现目标的类、接口、方法等的描述;
Spring MVC不常用注解
@InitBinder
在参数绑定时进行可以针对复杂对象自定义参数绑定逻辑,比如:
@GetMapping("/testInitBinder")
public String testInitBinder(Date date){return date.toString();
}
此时如果访问:http://localhost:8080/tuling-web/app/testInitBinder?date=1111-1-1,会报错。
此时可以在当前Controller中添加:
@InitBinder
public void initBinder(WebDataBinder binder) {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");dateFormat.setLenient(false);binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
有了这个就相当于添加了一个自定义的日期格式转换器,这样就能正常访问了。
注意,如果我们想把String类型转成我们自定义的User类,那么在User类中得提供一个String类型的构造方法
@SessionAttributes
只能写在类上,通过@SessionAttributes注解指定model中哪些key的value存到session中。
@RequestAttribute 与 @SessionAttribute
都只能写在方法参数前面,表示从相对应request.getAttribute()、session.getAttribute()中获取值传递给方法参数
@ModelAttribute
可以写在某个方法上,@ModelAttribute可以定义在一个Controller中,当请求这个Controller中的方法时,会先调用@ModelAttribute所修饰的方法,方法返回的值会添加到model中,比如以下代码就会向model中添加一个key为user,values为请求中user参数所传递的值。
flashMap
在重定向时,FlashMap机制提供了这么一种方式让一个请求传递一些参数给接下来的某个请求,FlashMap机制保证了参数的隐蔽性,不需要将参数传递到前端。
我们可以通过FlashMap来进行传递:
@Controller
public class IsPaintingController {@GetMapping("/a")public String test(HttpServletRequest request, Model model) {FlashMap outputFlashMap = RequestContextUtils.getOutputFlashMap(request);outputFlashMap.put("username", "ispainting");return "redirect:/b";}@GetMapping("/b")@ResponseBodypublic String a(HttpServletRequest request, Model model) {Map<String, ?> inputFlashMap = RequestContextUtils.getInputFlashMap(request);String username = (String) inputFlashMap.get("username");return username;}
}
把要传递的参数存入outputFlashMap,在b请求里通过inputFlashMap就可以拿到了,底层是基于session来实现的。
MyBatis篇
ORM是"Object-Relational Mapping"的缩写,中文通常翻译为"对象关系映射"。
传统JDBC规范(掌握四个核心对象):
DriverManager:用于注册驱动
Connection: 表示与数据库创建的连接
Statement: 操作数据库sql语句的对象
ResultSet: 结果集或一张虚拟表
MyBatis执行SQL流程分析
Executor分成两大类,一类是CacheExecutor,另一类是普通Executor。
CacheExecutor其实是封装了普通的Executor,和普通的区别是在查询前先会查询缓存中是否存在结果,如果存在就使用缓存中的结果,如果不存在还是使用普通的Executor进行查询,再将查询出来的结果存入缓存。
普通Executor又分为三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
- SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
- ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。
- BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
MyBatis重要类分析
重要类
- MapperRegistry:本质上是一个Map,其中的key是Mapper接口的全限定名,value的MapperProxyFactory;
- MapperProxyFactory:这个类是MapperRegistry中存的value值,在通过sqlSession获取Mapper时,其实先获取到的是这个工厂,然后通过这个工厂创建Mapper的动态代理类;
- MapperProxy:实现了InvocationHandler接口,Mapper的动态代理接口方法的调用都会到达这个类的invoke方法;
- MapperMethod:判断你当前执行的方式是增删改查哪一种,并通过SqlSession执行相应的操作;
- SqlSession:作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能;
- Executor:MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护;
StatementHandler:封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。
ParameterHandler:负责对用户传递的参数转换成JDBC Statement 所需要的参数,
ResultSetHandler:负责将JDBC返回的ResultSet结果集对象转换成List类型的集合;
TypeHandler:负责java数据类型和jdbc数据类型之间的映射和转换
MappedStatement:MappedStatement维护了一条节点的封装,
SqlSource:负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
BoundSql:表示动态生成的SQL语句以及相应的参数信息
Configuration:MyBatis所有的配置信息都维持在Configuration对象之中。
MyBatis的二级缓存原理
mybatis使用的是溢出淘汰机制。二级缓存在结构设计上采用装饰器+责任链模式
mybatis缓存分为一级缓存和二级缓存
- 一级缓存,又叫本地缓存,是PerpetualCache类型的永久缓存,保存在执行器中(BaseExecutor),而执行器又在SqlSession(DefaultSqlSession)中,所以一级缓存的生命周期与SqlSession是相同的。
- 二级缓存,又叫自定义缓存,实现了Cache接口的类都可以作为二级缓存,所以可配置如encache等的第三方缓存。二级缓存以namespace名称空间为其唯一标识,被保存在Configuration核心配置对象中。
二级缓存对象的默认类型为PerpetualCache,如果配置的缓存是默认类型,则mybatis会根据配置自动追加一系列装饰器。
OGNL表达式
OGNL是一种表达式语言,专门用于处理对象图中的数据。
OGNL表达式的语法非常简洁明了,类似于XPath表达式。它使用点符号(.)来访问对象的属性,使用方括号([])来访问集合和数组元素。以下是一些常见的OGNL语法示例:
-
访问属性:假设有一个名为person的对象,其中包含属性name和age,我们可以使用如下OGNL表达式来获取属性值:
person.nameperson.age
-
调用方法:假设有一个名为order的对象,其中包含方法getTotal(),我们可以使用如下OGNL表达式来调用该方法
order.getTotal()
-
访问集合和数组:假设有一个名为items的List对象,我们可以使用如下OGNL表达式来访问其中的元素:
items[0]items[1]
Mybatis中的OGNL表达式
在Mybatis中,可以在SQL映射文件中使用${和}符号来嵌入OGNL表达式,如:
<select id="findPersonById" resultType="Person">SELECT * FROM person WHERE id = #{id} AND city = #{address.city}
</select>
其中,#{id}和#{address.city}是OGNL表达式,用于访问Person对象的id属性和Address对象的city属性。
Mybatis中的OGNL表达式拓展
在Mybatis中,可以使用Hutool的OGNL工具类来实现OGNL表达式的拓展。
<select id="findPersons" resultType="Person">SELECT * FROM person<if test="@cn.hutool.core.util.StrUtil@isNotBlank(name)">AND name LIKE CONCAT('%', #{name}, '%')</if><if test="age != null">AND age = #{age}</if><if test="@cn.hutool.core.util.StrUtil@isNotBlank(city)">AND city = #{city.substring(0, 2)}</if>
</select>
其中,@cn.hutool.core.util.StrUtil@isNotBlank(name)和@cn.hutool.core.util.StrUtil@isNotBlank(city)是OGNL表达式,用于调用StrUtil工具类的isNotBlank方法,并将name和city属性作为参数传递。CONCAT(‘%’, #{name}, ‘%’)是SQL函数,用于实现字符串的拼接。#{city.substring(0, 2)}是OGNL表达式,用于实现字符串的截取。
需要注意的是,在使用Hutool的OGNL工具类时,需要在Mybatis的配置文件中进行相应的配置,如:
<configuration><settings><setting name="ognl.classResolver" value="cn.hutool.ognl.HutoolClassResolver"/></settings>
</configuration>
其中,ognl.classResolver是Mybatis的配置项,用于指定OGNL表达式的类加载器。cn.hutool.ognl.HutoolClassResolver是Hutool的OGNL类加载器,用于实现OGNL表达式的拓展。
相关文章:
Java重要面试名词整理(二):SpringMyBatis
文章目录 Spring篇Spring核心推断构造方法AOP动态代理Advice的分类Advisor的理解AOP相关的概念 定义BeanASM技术JFR依赖注入循环依赖LifecycleSpring AOT Spring事务Spring事务传播机制Spring事务传播机制是如何实现的呢?Spring事务传播机制分类 SpringMVCHandlerHandlerMappi…...
powershell美化
powershell美化 写在前面 除了安装命令,其他都是测试命令,后续再写进配置文件 安装主题控件 安装主题oh-my-posh,powershell中执行 winget install JanDeDobbeleer.OhMyPosh -s winget oh-my-posh init pwsh | Invoke-Expression # 查看…...
D102【python 接口自动化学习】- pytest进阶之fixture用法
day102 pytest的usefixtures方法 学习日期:20241219 学习目标:pytest基础用法 -- pytest的usefixtures方法 学习笔记: fixture调用方法 实际应用 总结 pytest.mark.usefixtures(func),pytest的usefixtures方法,无…...
Excel生成DBC脚本源文件
Excel制作 新建一个Excel,后缀为“.xls” 工作本名称改为“CAN_Matrix” 在首行按照列来起名字,在里面只需要填写必须的内容即可。 列数名称第0列Message Name第1列Message Format第2列Message ID第3列Message Length (byte)第4列Message Transmitte…...
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
问题背景 班里有 m m m 位学生,共计划组织 n n n 场考试。给你一个下标从 0 0 0 开始、大小为 m n m \times n mn 的整数矩阵 s c o r e score score,其中每一行对应一位学生,而 s c o r e [ i ] [ j ] score[i][j] score[i][j] 表示…...
Spring MVC(上)
上一篇博客的补充: 一般出现这种问题,我们就要检查版本了 我们需要查看这几个地方是否版本是对的 注意: jdk版本运行取决于什么? 1.通过cmd运行,jdk版本就是你设置的环境变量 2.通过Idea运行,取决于该项目设置的JDK版本 创建项目的方式: 1> 我们上个博客用idea进行创建 2…...
【优选算法---归并排序衍生题目】剑指offer51---数组中的逆序对、计算右侧小于当前元素的个数、翻转对
一、剑指offer51---数组中的逆序对 题目链接: LCR 170. 交易逆序对的总数 - 力扣(LeetCode) 题目介绍: 在数组中的两个数字,如果前面⼀个数字大于后面的数字,则这两个数字组成⼀个逆序对。输入一个数组,…...
单体到微服务:电商平台架构的演变与可扩展性探索
目录 一、整体理解可扩展性 二、从电商平台架构发展看架构的可扩展性 (一)单体架构 (二)分布式架构 (三)SOA架构 (四)微服务架构 三、1号店App服务端架构升级说明 ÿ…...
clickhouse-副本和分片
1、副本 1.1、概述 集群是副本和分片的基础,它将ClickHouse的服务拓扑由单节点延伸到多个节点,但它并不像Hadoop生态的某些系统那样,要求所有节点组成一个单一的大集群。ClickHouse的集群配置非常灵活,用户既可以将所有节点组成…...
C语言版解法力扣题:将整数按权重排序
1.题目描述 我们将整数 x 的 权重 定义为按照下述规则将 x 变成 1 所需要的步数: 如果 x 是偶数,那么 x x / 2 如果 x 是奇数,那么 x 3 * x 1 比方说,x3 的权重为 7 。因为 3 需要 7 步变成 1 (3 --> 10 -->…...
ubuntu18.04升级到ubuntu20.04
为了使用qt6,在ubuntu18.04上各种折腾失败,无奈只能升级到ubuntu20.04, 按照网上的教程没成功。自己摸索了 lsb_release -a df -h sudo apt update sudo apt upgrade -y sudo apt dist-upgrade -y sudo apt autoremove -y sudo apt clean sudo apt inst…...
【我的 PWN 学习手札】IO_FILE 之 stdin任意地址写
我们知道,stdin会往“缓冲区”先读入数据,如果我们劫持这个所谓“缓冲区”到其他地址呢?是否可以读入数据到任意地址?答案是肯定的。 注意!代码中的“-------”分隔,是为了区分一条调用链上不同代码片段&am…...
<mutex>注释 11:重新思考与猜测、补充锁的睡眠与唤醒机制,结合 linux0.11 操作系统代码的辅助(上)
(46)问题的起源: 因为上面的内核代码,我们编写多线程代码时,对手里的家伙事不那么自信。但我们知道,多线程在竞争锁时,若得不到锁,会进入睡眠,并会在被唤醒后重新尝试得…...
C/C++圣诞树
系列文章 序号直达链接1C/C爱心代码2C/C跳动的爱心3C/C李峋同款跳动的爱心代码4C/C满屏飘字表白代码5C/C大雪纷飞代码6C/C烟花代码7C/C黑客帝国同款字母雨8C/C樱花树代码9C/C奥特曼代码10C/C精美圣诞树11C/C俄罗斯方块12C/C贪吃蛇13C/C孤单又灿烂的神-鬼怪14C/C闪烁的爱心15C…...
upload-labs-master第21关超详细教程
目录 环境配置解题思路利用漏洞 操作演示 环境配置 需要的东西 phpstudy-2018 链接: phpstudy-2018 提取码:0278 32 位 vc 9 和 11 运行库 链接: 运行库 提取码:0278 upload-labs-master 靶场 链接: upload-lasb-ma…...
Python基础——数学运算
目录 1. 算术运算符 2. 比较运算符 3. 赋值运算符 4. 逻辑运算符 5. 成员运算符 6. 身份运算符 7. 三目运算符 Python数学计算通过多种运算符来执行,常用的运算符类型包括算术运算符、比较运算符、赋值运算符、逻辑运算符、成员运算符、身份运算符、三目…...
ubuntu 安装更新 ollama新版本
ubuntu 安装更新 ollama新版本 我这里是 2024-12-18 ollama 版本是 0.5.3 1手动下载 ollama-linux-amd64.tgz https://github.com/ollama/ollama/releases 2下载脚本 https://ollama.com/install.sh install.sh 和 ollama-linux-amd64.tgz 在相同路径下 修改:…...
汽车IVI中控开发入门及进阶(45):凌阳科技车载娱乐芯片
概述: Sunplus科技有限公司成立于1990年,是一家领先的多媒体和汽车应用芯片提供商,如DVD播放器、便携式DVD播放器、家庭娱乐音频产品、汽车信息娱乐和高级驾驶辅助系统(ADAS)。与此同时,凌阳正在为消费类、便携式和连接设备上的广泛应用提供高速I/O IP、高性能数据转换I…...
Linux export命令
本文来自智谱清言 --------- 在Linux系统中,export 是一个用来设置环境变量的命令。 环境变量是操作系统运行时用于存储有关系统环境的信息的变量,它们对于用户和程序都是可访问的。下面是关于 export 命令的一些基本用法: 基本语法 ba…...
AI自我进化的新篇章:谷歌DeepMind推出苏格拉底式学习,语言游戏解锁无限潜能
各位AI爱好者、技术研究者,大家好!今天我们来聊聊一个令人兴奋的AI研究新进展——谷歌DeepMind推出的“苏格拉底式学习”方法。这项研究的独特之处在于,它让AI在没有外部数据的情况下,通过“语言游戏”实现自我进化,这…...
【BUG】记一次context canceled的报错
文章目录 案例分析gorm源码解读gin context 生命周期context什么时候cancel的什么时候context会被动cancel掉呢? 野生协程如何处理 案例分析 报错信息 {"L":"ERROR","T":"2024-12-17T11:11:33.0050800","file"…...
JAVA前端开发中type=“danger“和 type=“text“的区别
在前端开发中,type 属性通常用于指定按钮或其他元素的样式或行为。不同的框架和库可能对 type 属性有不同的定义和用法。常见的框架包括 Bootstrap、Ant Design(antd)、Element Plus 等。下面我将分别介绍在这些框架中 type"danger"…...
sqlite3 支持位运算 和view和 triger
数据设置条件以后可以.根据门限自动调整其他的值 由数据库记录修改时间,及记录-> 网元设备的告警产生时间,设置超时清除时间,记录系统的原始时间戳 CPp 有 sqlite 支持 json 导出字符串,json 库将字符串,映射为结构体 triger update table 更新到一个 可设置参数列表 ,view …...
Mysql复习(一)
数据库系统的核心是( 数据库管理系统 )。 以下的标识符中符合标识符命名规则的有几个?(3个) 3abc7, abc73, bc73a, c73ab,*73abc 标识符的第一个字符允许包括哪些符号?( _ 或者 或者 #) 关系表达式运算的…...
Redis bitmaps 使用
应用场景: 记录id为 1 的用户,2024年12月签到情况,并统计; 记录 1号签到 zxys-redis:0>setbit 1:202412 1 1 记录 2号签到 zxys-redis:0>setbit 1:202412 2 1 记录 3号未签到 zxys-redis:0>setbit 1:202412 3 0 …...
计算无人机俯拍图像的地面采样距离(GSD)矩阵
引言 在无人机遥感、测绘和精细农业等领域,地面采样距离(Ground Sampling Distance,简称 GSD)是一个非常重要的指标。GSD 是指图像中每个像素在地面上实际代表的物理距离,通常以米或厘米为单位。GSD 决定了图像的空间…...
Java基础 | 数据库的命名规范
数据库的命名规范 1. 基本原则2. 命名规范详解2.1 命名禁止项2.2 命名规范3. 通用字段规范4. 特殊表命名建议 1. 基本原则 统一性:全库采用一致的命名规范简洁性:在表达清晰的前提下尽量简短规范性:遵循数据库标准规范可读性:命名…...
计算机网络基础(2):网络安全/ 网络通信介质
1. 网络安全威胁 网络安全:目的就是要让网络入侵者进不了网络系统,及时强行攻入网络,也拿不走信息,改不了数据,看不懂信息。 事发后能审查追踪到破坏者,让破坏者跑不掉。 网络威胁来自多方面:…...
Reactor
文章目录 正确的理解发送double free问题 1.把我们的reactor进行拆分2.链接管理3.Reactor的理论 listensock只需要设置_recv_cb,而其他sock,读,写,异常 所以今天写nullptr其实就不太对,添加为空就没办法去响应事件 获…...
介绍 Html 和 Html 5 的关系与区别
HTML(HyperText Markup Language)是构建网页的标准标记语言,而 HTML5 是 HTML 的最新版本,包含了一些新的功能、元素、API 和属性。HTML5 相对于早期版本的 HTML(比如 HTML4)有许多重要的改进和变化。以下是…...
已有 containerd 的情况下部署二进制 docker 共存
文章目录 [toc]学习目的开始学习dockerd启动 containerd准备配置文件启动 containerd 启动 docker准备配置文件启动 docker 环境验证停止 docker 和 containerd 学习目的 使用容器的方式做一些部署的交付,相对方便很多,不需要担心别人的环境缺少需要的依…...
Springboot @Transactional使用时需注意的几个问题
一、事务的隔离级别 在Springboot应用中,如果我们想实现方法一旦执行有异常产生,就触发事务回滚,可以在方法上面添加Transactional注解。如果应用采用mysql数据库,虽然mysql本身也有事务隔离机制,但在Sping数据库的应…...
西游记战力排名、笔记等
文章目录 战力排名对西游记的理解各个版本游戏题材西游记关卡和妖怪 西游记家喻户晓,没有谁不知道吧,无论是电视剧、影视,还是小说,乃至游戏,很多地方都有西游记的身影。 虽然知道,但总不如对三国啊、水浒啊…...
(2024.12)Ubuntu20.04安装ZED-SDK
一.官网地址 ZED SDK 4.2 - Download | Stereolabs 选择适配版本进行下载 二.安装程序 下载完成后,进入文件目录,打开终端,输入: chmod x ZED_SDK_Ubuntu20_cuda11.8_v4.2.2.zstd.run ./ZED_SDK_Ubuntu20_cuda11.8_v4.2.2.zst…...
Pytorch | 从零构建GoogleNet对CIFAR10进行分类
Pytorch | 从零构建GoogleNet对CIFAR10进行分类 CIFAR10数据集GoogleNet网络结构特点网络整体架构应用与影响Inceptionv1到Inceptionv2 GoogleNet结构代码详解结构代码代码详解Inception 类初始化方法前向传播 forward GoogleNet 类初始化方法前向传播 forward 训练过程和测试结…...
蓝桥杯刷题——day9
蓝桥杯刷题——day9 题目一题干解题思路一代码解题思路二代码 题目二题干解题思路代码 题目一 题干 小蓝最近在研究一种浮点数的表示方法:R格式。对于一个大于0的浮点数d,可以用R格式的整数来表示。给定一个转换参数n,将浮点数转换为R格式整…...
ffmpeg翻页转场动效的安装及使用
文章目录 前言一、背景二、选型分析2.1 ffmpeg自带的xfade滤镜2.2 ffmpeg使用GL Transition库2.3 xfade-easing项目三、安装3.1、安装依赖([参考](https://trac.ffmpeg.org/wiki/CompilationGuide/macOS#InstallingdependencieswithHomebrew))3.2、获取ffmpeg源码3.3、融合xf…...
分布式刚度编织,让可穿戴触觉更出色 ——Haptiknit
大家好!今天来了解一项非常有趣的科技成果 ——“Haptiknit:用于可穿戴触觉的分布式刚度编织”——《Haptiknit: Distributed stiffness knitting for wearable haptics》发表于《SCIENCE ROBOTICS》。在现代科技发展中,可穿戴触觉设备越来越…...
Elasticsearch:什么是查询语言?
查询语言定义 查询语言包括数据库查询语言 (database query language - DQL),是一种用于查询和从数据库检索信息的专用计算机语言。它充当用户和数据库之间的接口,使用户能够管理来自数据库管理系统 (database management system - DBMS) 的数据。 最广…...
PyQt介绍
**PyQt 和 PySide (Qt for Python) 简介** **PyQt** 和 **PySide** 是 Python 中用于开发图形用户界面 (GUI) 应用程序的两个主要框架,它们都是基于 Qt 库的绑定。Qt 是一个跨平台的应用程序开发框架,广泛用于创建图形用户界面、应用程序开发以及嵌入式…...
Oracle 数据库函数的用法(一)
Oracle数据库提供了大量的内置函数,可以用于完成各种操作,如字符串操作,数学计算,日期时间处理,条件判断,序列生成,聚合统计等。以下是一些常用的Oracle数据库函数: 一、oracle 使用…...
labelme标签批量转换数据集json_to_dataset
文章目录 labelme标签批量转换数据集json_to_dataset转换原理单张图片转换多张图片批量转换bat脚本循环法 标注图片提取标注图片转单通道 labelme标签批量转换数据集json_to_dataset 转自labelme批量制作数据集教程。 转换原理 在安装了labelme的虚拟环境中有一个labelme_js…...
《QT 5.14.1 搭建 opencv 环境全攻略》
《QT 5.14.1 搭建 opencv 环境全攻略》 一、引言二、准备工作(一)软件下载(二)系统环境确认 三、安装 QT 5.14.1(一)安装包下载与运行(二)环境变量配置 四、OpenCV 安装与配置&#…...
Sentry日志管理thinkphp8 tp8 sentry9 sentry8 php8.x配置步骤, tp8自定义异常处理类使用方法
tp8的默认使用的就是composer来管理第三方包, 所以直接使用 composer 来安装 sentry9 即可. 同时tp8和tp5的配置方式不太一样, 这里我们直接使用自定义异常类来处理Sentry的异常. 1. 安装 sentry9 包 # 安装 sentry9 包 composer require "tekintian/sentry9-php" …...
MySQL 基础:开启数据库之旅
MySQL 基础:开启数据库之旅 在当今数字化的时代,数据扮演着至关重要的角色,而数据库管理系统则是存储、管理和操作这些数据的强大工具。MySQL 作为一款广受欢迎的开源关系型数据库管理系统,被广泛应用于各类网站、应用程序以及企业…...
OpenTK 中帧缓存的深度解析与应用实践
摘要: 本文深入探讨了 OpenTK 中帧缓存的使用。首先介绍了帧缓存的基本概念与在图形渲染管线中的关键地位,包括其与颜色缓存、深度缓存、模板缓存等各类缓存的关联。接着详细阐述了帧缓存对象(FBO)的创建、绑定与解绑等操作,深入分析了纹理附件、渲染缓冲区附件在 FBO 中的…...
stm32制作CAN适配器5--WinUsb上位机编写
上次我们要stm32制作了一个基于winusb有canfd适配器,今天我们来制作一个上位机程序来进行报文收发。 上位机还是用以前写好的,只是更改下dll文件。 项目链接器,输入,附加依赖项中增加winusb.lib winusb初始化:#incl…...
【时间之外】IT人求职和创业应知【71】-专利费
目录 2025 ICT产业趋势年会召开,2024年度ICT十大新闻重磅揭晓 海纳致远数字科技申请定制化插件驱动的数据分析专利 阿波罗智联取得语音数据的处理方法、装置、设备和存储介质专利 心勿贪,贵知足。 感谢所有打开这个页面的朋友。人生不如意࿰…...
springboot vue 会员营销系统
springboot vue 会员营销系统介绍 演示地址: 开源版本:http://8.146.211.120:8083/ 完整版本:http://8.146.211.120:8086/ 移动端 http://8.146.211.120:8087/ 简介 欢迎使用springboot vue会员营销系统。本项目包含会员储值卡、套餐卡、计…...
Kafka快速扫描
Architecture 系统间解耦,异步通信,削峰填谷 Topic 消息主题,用于存储消息 Partition 分区,通过扩大分区,可以提高存储量 Broker 部署Kafka服务的设备 Leader kafka主分区 Follwer kafka从分区 高性能之道:…...