Spring学习笔记2

目录

  • 1. 代理
    • 1.1 **JDK 动态代理**
    • 1.2 **CGLIB 代理**
    • 1.3 JDK 动态代理与 CGLIB 的对比
  • 2. AOP思想
    • 2.1 基本概念
    • 2.2 AspectJ 技术
    • 2.3 **AspectJ 使用 XML 配置**
    • 2.4 **AspectJ 使用注解配置**
    • 2.5 通知
  • 3. JdbcTemplate
    • 3.1 **主要特点**
    • 3.2 **核心方法**
    • 3.3 **使用步骤**
    • 3.4 **优点**
  • 4. 配置平台事务管理器和事务管理模板
    • 4.1 配置平台事务管理器
    • 4.2 配置事务管理模板
      • 4.2.1 编程式事务管理
      • 4.2.2 声明式事务管理

1. 代理

1.1 JDK 动态代理

JDK 动态代理是 Java 标准库自带的一种代理机制,基于 接口 实现。它的核心是 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。

特点

  • 基于接口:JDK 动态代理只能代理实现了接口的目标对象。
  • 性能较低:相较于 CGLIB,JDK 动态代理在运行时的性能稍低。
  • 灵活性高:可以在运行时动态生成代理类,适用于需要动态增强接口方法的场景。

实现步骤

  1. 定义接口:目标对象需要实现一个接口。
  2. 实现 InvocationHandler:用于处理代理类的方法调用。
  3. 生成代理对象:通过 Proxy.newProxyInstance() 方法生成代理对象。

示例代码

  1. 定义接口
public interface BankService {
    void transferMoney(Long fromAccountId, Long toAccountId, double amount);
}
  1. 实现目标类
public class BankServiceImpl implements BankService {
    @Override
    public void transferMoney(Long fromAccountId, Long toAccountId, double amount) {
        System.out.println("Transferring money from account " + fromAccountId + " to account " + toAccountId);
    }
}
  1. 实现 InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class TransactionHandler implements InvocationHandler {

    private Object target; // 目标对象

    public TransactionHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 事务控制逻辑
        System.out.println("Transaction started...");
        try {
            Object result = method.invoke(target, args); // 调用目标方法
            System.out.println("Transaction committed.");
            return result;
        } catch (Exception e) {
            System.out.println("Transaction rolled back.");
            throw e;
        }
    }
}
  1. 生成代理对象
import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        // 目标对象
        BankService target = new BankServiceImpl();

        // 创建 InvocationHandler
        TransactionHandler handler = new TransactionHandler(target);

        // 生成代理对象
        BankService proxy = (BankService) Proxy.newProxyInstance(
            target.getClass().getClassLoader(), // 类加载器
            target.getClass().getInterfaces(), // 目标类实现的接口
            handler // InvocationHandler
        );

        // 调用代理对象的方法
        proxy.transferMoney(1L, 2L, 100.0);
    }
}

输出结果

Transaction started...
Transferring money from account 1 to account 2
Transaction committed.

1.2 CGLIB 代理

CGLIB(Code Generation Library)是一种基于 字节码生成 的代理技术,允许代理 没有实现接口的类。它的核心是 net.sf.cglib.proxy.Enhancer 类和 net.sf.cglib.proxy.MethodInterceptor 接口。

特点

  • 基于类:CGLIB 可以代理没有实现接口的类。
  • 性能较高:CGLIB 生成的代理类直接基于目标类的字节码,性能通常优于 JDK 动态代理。
  • 动态生成子类:CGLIB 通过生成目标类的子类来实现代理。
    实现步骤
  1. 定义目标类:目标类不需要实现接口。
  2. 实现 MethodInterceptor:用于处理代理类的方法调用。
  3. 生成代理对象:通过 Enhancer 类生成代理对象。

示例代码

  1. 定义目标类
public class BankService {
    public void transferMoney(Long fromAccountId, Long toAccountId, double amount) {
        System.out.println("Transferring money from account " + fromAccountId + " to account " + toAccountId);
    }
}
  1. 实现 MethodInterceptor
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class TransactionInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 事务控制逻辑
        System.out.println("Transaction started...");
        try {
            Object result = proxy.invokeSuper(obj, args); // 调用目标方法
            System.out.println("Transaction committed.");
            return result;
        } catch (Exception e) {
            System.out.println("Transaction rolled back.");
            throw e;
        }
    }
}
  1. 生成代理对象
import net.sf.cglib.proxy.Enhancer;

public class Main {
    public static void main(String[] args) {
        // 创建 Enhancer 对象
        Enhancer enhancer = new Enhancer();

        // 设置目标类的父类
        enhancer.setSuperclass(BankService.class);

        // 设置 MethodInterceptor
        enhancer.setCallback(new TransactionInterceptor());

        // 生成代理对象
        BankService proxy = (BankService) enhancer.create();

        // 调用代理对象的方法
        proxy.transferMoney(1L, 2L, 100.0);
    }
}

输出结果

Transaction started...
Transferring money from account 1 to account 2
Transaction committed.

1.3 JDK 动态代理与 CGLIB 的对比

特性JDK 动态代理CGLIB 代理
基于接口
性能较低(基于反射)较高(基于字节码生成)
目标对象必须实现接口可以是任意类
代理对象代理接口生成目标类的子类
适用场景需要代理接口方法需要代理没有接口的类
依赖JDK 自带需要额外依赖 CGLIB 库

2. AOP思想

2.1 基本概念

AOP(Aspect-Oriented Programming) 是一种编程范式,旨在通过将横切关注点(Cross-Cutting Concerns)从核心业务逻辑中分离出来,提高代码的模块化程度。横切关注点是指那些在多个模块中都会用到的功能,例如日志记录、事务管理、安全性检查等。AOP 的核心思想是将这些横切关注点从核心业务逻辑中解耦,封装成独立的模块(切面),并通过配置或注解的方式,将它们动态地应用到需要增强的类或方法上。

AOP 的关键术语

  1. 切面(Aspect):模块化的横切关注点,例如日志记录、事务管理等。
  2. 连接点(Join Point):程序执行过程中的某个点,例如方法调用、异常抛出等。
  3. 通知(Advice):切面在特定的连接点上执行的动作,例如在方法调用前后执行的日志记录。
  4. 切点(Pointcut):定义了通知应该应用到哪些连接点的规则,例如所有以 transferMoney 开头的方法。
  5. 引入(Introduction):允许向现有的类添加新方法或属性。
  6. 织入(Weaving):将切面应用到目标对象的过程,可以在编译时、类加载时或运行时进行。

2.2 AspectJ 技术

AspectJ 是一个成熟的 AOP 框架,提供了丰富的语法和工具,支持在 Java 应用中实现 AOP。AspectJ 可以在编译时或运行时将切面织入到目标类中。

AspectJ 的主要特点

  1. 强大的定义切点的能力:AspectJ 提供了灵活的切点表达式,可以精确地指定通知应该应用到哪些方法或代码块。
  2. 多种通知类型:支持多种通知类型,包括前置通知(Before)、后置通知(After)、环绕通知(Around)等。
  3. 编译时织入:可以在编译时将切面织入到目标类中,提高运行时性能。
  4. 运行时织入:也可以在运行时通过代理或字节码操作将切面织入到目标类中。
  5. 丰富的注解和 XML 配置:支持通过注解或 XML 配置来定义切面和切点。

2.3 AspectJ 使用 XML 配置

添加 AspectJ 依赖
如果使用 Maven,在 pom.xml 中添加 AspectJ 的依赖。

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.7</version>
</dependency>

实例代码

1. 切面类

public class LoggingAspect {

    // 前置通知
    public void logBefore() {
        System.out.println("Logging before method execution");
    }
}

2. 目标类

package com.example.service;

public class BankService {

    public void transferMoney(Long fromAccountId, Long toAccountId, double amount) {
        System.out.println("Transferring money from account " + fromAccountId + " to account " + toAccountId);
    }
}

3. XML 配置文件

在 XML 配置文件中定义切面、切点和通知:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 定义目标 bean -->
    <bean id="bankService" class="com.example.service.BankService" />

    <!-- 定义切面 bean -->
    <bean id="loggingAspect" class="com.example.aspect.LoggingAspect" />

    <!-- 定义切面 -->
    <aop:config>
        <!-- 定义切点 -->
        <aop:pointcut id="serviceMethods" expression="execution(* com.example.service.*.*(..))"/>

        <!-- 定义切面和通知 -->
        <aop:aspect ref="loggingAspect">
            <aop:before pointcut-ref="serviceMethods" method="logBefore"/>
        </aop:aspect>
    </aop:config>
</beans>

4. 测试代码

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        BankService bankService = context.getBean(BankService.class);
        bankService.transferMoney(1L, 2L, 100.0);
    }
}

输出结果

Logging before method execution
Transferring money from account 1 to account 2

2.4 AspectJ 使用注解配置

添加 AspectJ 依赖
如果使用 Maven,在 pom.xml 中添加 AspectJ 的依赖。

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.7</version>
</dependency>

实例代码

1. 切面类

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect  // 标记这是一个切面
public class LoggingAspect {

    // 定义切点
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}

    // 定义前置通知
    @Before("serviceMethods()")
    public void logBefore() {
        System.out.println("Logging before method execution");
    }
}

2. 目标类

package com.example.service;

public class BankService {

    public void transferMoney(Long fromAccountId, Long toAccountId, double amount) {
        System.out.println("Transferring money from account " + fromAccountId + " to account " + toAccountId);
    }
}

3. Spring 配置文件

如果使用 Spring,需要在 Spring 的 XML 配置文件中启用注解支持:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 启用 AspectJ 注解支持 -->
    <aop:aspectj-autoproxy/>

    <!-- 定义切面 bean -->
    <bean id="loggingAspect" class="com.example.aspect.LoggingAspect" />

    <!-- 定义目标 bean -->
    <bean id="bankService" class="com.example.service.BankService" />
</beans>

4. 测试代码

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        BankService bankService = context.getBean(BankService.class);
        bankService.transferMoney(1L, 2L, 100.0);
    }
}

输出结果

Logging before method execution
Transferring money from account 1 to account 2

2.5 通知

AspectJ 提供了多种通知(Advice)类型,每种通知类型在不同的连接点(Join Point)上执行不同的逻辑。以下是 AspectJ 中常见的通知类型及其作用和语法。

1. Before 通知(前置通知)

  • 作用:在目标方法执行之前执行。
  • 语法
@Aspect
public class BeforeAspect {

    @Pointcut("execution(* com.example.service.*.*(..))")  // 定义切点
    public void serviceMethods() {}

    @Before("serviceMethods()")  // 前置通知
    public void beforeAdvice() {
        System.out.println("Before advice executed");
    }
}

2. After 通知(后置通知)

  • 作用:在目标方法执行之后执行(无论方法是否抛出异常)。
  • 语法
@Aspect
public class AfterAspect {

    @Pointcut("execution(* com.example.service.*.*(..))")  // 定义切点
    public void serviceMethods() {}

    @After("serviceMethods()")  // 后置通知
    public void afterAdvice() {
        System.out.println("After advice executed");
    }
}

3. AfterReturning 通知(返回通知)

  • 作用:在目标方法成功返回且没有抛出异常时执行。
  • 语法
@Aspect
public class AfterReturningAspect {

    @Pointcut("execution(* com.example.service.*.*(..))")  // 定义切点
    public void serviceMethods() {}

    @AfterReturning(pointcut = "serviceMethods()", returning = "result")  // 返回通知
    public void afterReturningAdvice(Object result) {
        System.out.println("AfterReturning advice executed. Result: " + result);
    }
}
  • 参数说明
    • returning = "result":将方法返回值绑定到通知方法的参数 result

4. AfterThrowing 通知(异常通知)

  • 作用:在目标方法抛出异常时执行。
  • 语法
@Aspect
public class AfterThrowingAspect {

    @Pointcut("execution(* com.example.service.*.*(..))")  // 定义切点
    public void serviceMethods() {}

    @AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")  // 异常通知
    public void afterThrowingAdvice(Exception ex) {
        System.out.println("AfterThrowing advice executed. Exception: " + ex.getMessage());
    }
}
  • 参数说明
    • throwing = "ex":将异常对象绑定到通知方法的参数 ex

5. Around 通知(环绕通知)

  • 作用:在目标方法执行前后执行,并且可以完全控制方法的执行流程。
  • 语法
@Aspect
public class AroundAspect {

    @Pointcut("execution(* com.example.service.*.*(..))")  // 定义切点
    public void serviceMethods() {}

    @Around("serviceMethods()")  // 环绕通知
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Around advice: Before method execution");

        // 调用目标方法
        Object result = joinPoint.proceed();

        System.out.println("Around advice: After method execution");
        return result;
    }
}
  • 关键点
    • ProceedingJoinPoint 是关键对象,调用其 proceed() 方法以执行目标方法。
    • 可以修改方法的返回值,或完全阻止方法的执行。

3. JdbcTemplate

JdbcTemplate 是 Spring 框架提供的一个核心工具类,用于简化 JDBC 操作。它封装了 JDBC 的繁琐操作(如连接管理、异常处理、资源释放等),使开发者能够更专注于 SQL 语句和业务逻辑的实现。

引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
</dependencies>

3.1 主要特点

  1. 简化 JDBC 操作

    • 自动管理数据库连接、语句和结果集的创建与释放。
    • 减少样板代码,提高开发效率。
  2. 统一的异常处理

    • 将 JDBC 的 SQLException 转换为 Spring 的 DataAccessException,提供更清晰的异常层次结构。
  3. 支持多种操作

    • 支持查询、更新、批量操作、存储过程调用等。
  4. 与 Spring 集成

    • 与 Spring 的事务管理、数据源等无缝集成。

3.2 核心方法

1. 更新操作(增删改)

  • update():用于执行 INSERT、UPDATE、DELETE 等 SQL 语句。

    int update(String sql, Object... args);
    

    示例:

    String sql = "UPDATE users SET name = ? WHERE id = ?";
    int rows = jdbcTemplate.update(sql, "John", 1);
    

2. 查询操作

  • queryForObject():查询单行数据并映射为对象。

    <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args);
    

    示例:

    String sql = "SELECT * FROM users WHERE id = ?";
    User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), 1);
    
  • query():查询多行数据并映射为对象列表。

    <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args);
    

    示例:

    String sql = "SELECT * FROM users";
    List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
    

3. 执行任意 SQL

  • execute():用于执行任意 SQL 语句(如 DDL 语句)。

    void execute(String sql);
    

    示例:

    jdbcTemplate.execute("CREATE TABLE users (id INT, name VARCHAR(100))");
    

3.3 使用步骤

  1. 配置数据源

    • 在 Spring 配置文件中配置数据源(如 DataSource)。

    • 示例:

      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
          <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
          <property name="url" value="jdbc:mysql://localhost:3306/test"/>
          <property name="username" value="root"/>
          <property name="password" value="password"/>
      </bean>
      
  2. 创建 JdbcTemplate

    • 将数据源注入到 JdbcTemplate 中。

    • 示例:

      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
          <property name="dataSource" ref="dataSource"/>
      </bean>
      
  3. 在代码中使用

    • 通过依赖注入获取 JdbcTemplate 实例并调用其方法。

    • 示例:

      @Autowired
      private JdbcTemplate jdbcTemplate;
      
      public void addUser(User user) {
          String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
          jdbcTemplate.update(sql, user.getName(), user.getAge());
      }
      

3.4 优点

  1. 简化代码
    • 减少 JDBC 样板代码,提高开发效率。
  2. 异常处理
    • 提供统一的异常处理机制,避免繁琐的 try-catch 块。
  3. 与 Spring 集成
    • 与 Spring 的事务管理、数据源等无缝集成。
  4. 灵活性
    • 支持自定义 RowMapperResultSetExtractor,满足复杂需求。

4. 配置平台事务管理器和事务管理模板

在 Spring 框架中,事务管理是一个非常重要的功能,用于确保数据库操作的完整性。Spring 提供了多种事务管理方式,其中最常见的两种是声明式事务管理和编程式事务管理。

4.1 配置平台事务管理器

平台事务管理器是 Spring 事务管理的核心接口,它负责事务的开始、提交和回滚。最常见的实现是 DataSourceTransactionManager,用于管理 JDBC 数据源的事务。

  1. 配置数据源

首先,需要配置一个数据源。这里我们使用 DriverManagerDataSource 作为示例数据源:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/test"/>
    <property name="username" value="root"/>
    <property name="password" value="password"/>
</bean>
  1. 配置平台事务管理器

接下来,配置 DataSourceTransactionManager,将数据源注入到事务管理器中:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

4.2 配置事务管理模板

事务管理模板(TransactionTemplate)是一个辅助类,用于简化事务管理的编程式操作。它可以自动管理事务的开始、提交和回滚。

配置事务管理模板

在 Spring 配置文件中配置 TransactionTemplate,并将平台事务管理器注入到模板中:

<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
    <property name="transactionManager" ref="transactionManager"/>
</bean>

4.2.1 编程式事务管理

使用 TransactionTemplate 进行编程式事务管理,可以通过 lambda 表达式或 TransactionCallback 接口来实现。

示例代码

@Autowired
private TransactionTemplate transactionTemplate;

@Autowired
private JdbcTemplate jdbcTemplate;

public void addUser(User user) {
    transactionTemplate.execute(status -> {
        try {
            String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
            jdbcTemplate.update(sql, user.getName(), user.getAge());
            // 模拟异常
            // int i = 1 / 0;
            return null;
        } catch (Exception e) {
            // 回滚事务
            status.setRollbackOnly();
            throw e;
        }
    });
}

4.2.2 声明式事务管理

声明式事务管理通过在 Spring 配置文件中使用 AOP 配置事务,实现更简洁的事务管理。

  1. 配置事务管理器

确保已经配置了 DataSourceTransactionManager

  1. 配置事务管理器的 AOP 支持

使用 tx:annotation-driven 开启基于注解的事务管理:

<tx:annotation-driven transaction-manager="transactionManager"/>
  1. 使用 @Transactional 注解

在需要事务管理的类或方法上使用 @Transactional 注解:

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    public void addUser(User user) {
        String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
        jdbcTemplate.update(sql, user.getName(), user.getAge());
        // 模拟异常
        // int i = 1 / 0;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

信号弱开启手机Wifi通话,MIUI显示/隐藏5G开关的方法

1.开启手机Wi-Fi通话&#xff0c;提升无信号或弱信号时的通话质量 Wi-Fi 通话(Wi-Fi calling)&#xff0c;又称VoWiFi&#xff0c;是一项名为“ Voice over Wi-Fi ”的服务&#xff0c;它允许手机用户使用他们的智能手机使用 Wi-Fi网络拨打电话&#xff0c;即在Wi-Fi环境下就能…

Echarts的认识和基本用法

Echarts介绍和使用 Echarts介绍 官网地址&#xff1a;Apache ECharts Echarts是一个基于JavaScript的开源可视化图表库&#xff0c;由百度前端开发团队研发和维护。它提供了丰富的图表类型、数据统计分析、动态数据更新、多维数据展示等功能&#xff0c;可以帮助开发人员在 W…

在JavaScript开发中,如何判断对象自身为空?

前言 如何判断一个对象为空是我们在开发中经常会遇到的问题&#xff0c;今天我们来聊聊几种经常使用的方法&#xff0c;以及在不同的场景下我们如何去使用。 1. JSON.stringify JSON.stringify 方法可以使对象序列化&#xff0c;转为相应的 JSON 格式。 const obj {};cons…

大语言模型训练的数据集从哪里来?

继续上篇文章的内容说说大语言模型预训练的数据集从哪里来以及为什么互联网上的数据已经被耗尽这个说法并不专业&#xff0c;再谈谈大语言模型预训练数据集的优化思路。 1. GPT2使用的数据集是WebText&#xff0c;该数据集大概40GB&#xff0c;由OpenAI创建&#xff0c;主要内…

Wireshark 学习笔记1

1.wireshark是什么 wireshark是一个可以进行数据包的捕获和分析的软件 2.基本使用过程 &#xff08;1&#xff09;选择合适的网卡 &#xff08;2&#xff09;开始捕获数据包 &#xff08;3&#xff09;过滤掉无用的数据包 &#xff08;4&#xff09;将捕获到的数据包保存为文件…

RK3568平台(USB篇)禁用USB端口

一.linux中怎样查看usb的端口号 在USB口插入U盘: [ 198.141319][ T106] usb 3-1.3: new SuperSpeed Gen 1 USB device number 5 using xhci-hcd [ 198.161695][ T106] usb 3-1.3: New USB device found, idVendor=0781, idProduct=5591, bcdDevice= 1.00 [ 198.161721]…

3298.统计重新排列后包含另一个字符串的字符串数目 I II滑动窗口 优化思路解析全网最详细

II相比于I是数据范围变成了10的6次方了 我们来维护大小关系&#xff0c;把不用的都去掉&#xff0c;优化到O&#xff08;26n&#xff09; 首先判断一下要找子字符串的s长度是否小于t字符串&#xff0c;如果小于的话直接返回0 初始答案变量和left左指针为0 用Counter来记录t中所…

双向导航和单向导航

目录 双向导航 单向导航 迁移数据库异常 解决办法 1.导航属性改为空 2.使用 ON DELETE NO ACTION 或 ON UPDATE NO ACTION 选择 双向导航 一对多&#xff1a;一个Article有多个Comment class Article {public long Id { get; set; }public string Title { get; set; }pu…

静态路由配置与调试——计算机网络实训day1

TOC 软件及基本配置下载 通过网盘分享的文件&#xff1a;计网实训 链接: https://pan.baidu.com/s/1AY5qNSN1dnw5Vy1OtwdJGg?pwdijde 提取码: ijde 操作前准备 1.下载软件 2.双击1.基本配置.pkt 3.进入实验环境 一、实验目的 1、掌握路由器的基本配置&#xff1b; 2、掌握…

EasyExcel上传校验文件错误信息放到文件里以Base64 返回给前端

产品需求&#xff1a; 前端上传个csv 或 excel 文件&#xff0c;文件共4列&#xff0c;验证文件大小&#xff0c;类型&#xff0c;文件名长度&#xff0c;文件内容&#xff0c;如果某行某个单元格数据验证不通过&#xff0c;就把错误信息放到这行第五列&#xff0c;然后把带有…

EtherCAT转Modbus网关与TwinCAT3的连接及配置详述

在工业自动化控制系统中&#xff0c;常常需要整合不同的通信协议设备。本案例旨在展示如何利用捷米特JM-ECT-RTU协议转换网关模块&#xff0c;实现 EtherCAT 网络与 Modbus 设备之间的无缝连接&#xff0c;并在 TwinCAT3 环境中进行有效配置&#xff0c;以构建一个稳定可靠的自…

Linux 工作队列

系列文章目录 Linux内核学习 Linux 知识&#xff08;1&#xff09; Linux 知识&#xff08;2&#xff09; Linux 工作队列 Linux 内核源代码情景分析&#xff08;一&#xff09; Linux 设备驱动程序&#xff08;二&#xff09; 文章目录 系列文章目录综述工作&#xff08;work_…

如何评价deepseek-V3 VS OpenAI o1 自然语言处理成Sql的能力

DeepSeek-V3 介绍 在目前大模型主流榜单中&#xff0c;DeepSeek-V3 在开源模型中位列榜首&#xff0c;与世界上最先进的闭源模型不分伯仲。 准备工作&#xff1a; 笔者只演示实例o1 VS DeepSeek-V3两个模型&#xff0c;大家可以自行验证结果或者实验更多场景&#xff0c;同时…

【UI自动化测试】selenium八种定位方式

&#x1f3e1;个人主页&#xff1a;謬熙&#xff0c;欢迎各位大佬到访❤️❤️❤️~ &#x1f472;个人简介&#xff1a;本人编程小白&#xff0c;正在学习互联网求职知识…… 如果您觉得本文对您有帮助的话&#xff0c;记得点赞&#x1f44d;、收藏⭐️、评论&#x1f4ac;&am…

百度视频搜索架构演进

导读 随着信息技术的迅猛发展&#xff0c;搜索引擎作为人们获取信息的主要途径&#xff0c;其背后的技术架构也在不断演进。本文详细阐述了近年来视频搜索排序框架的重大变革&#xff0c;特别是在大模型技术需求驱动下&#xff0c;如何从传统的多阶段级联框架逐步演变为更加高…

sequelize-cli 多对多关系处理 及某一单项游戏根据成绩降序排名

一、生成模型 Game(游戏表)GameGrades(游戏成绩表)GameUser&#xff08;用户表&#xff09; 1.1 对非中间表 做多对多逻辑处理 Game模型 static associate(models) {// define association heremodels.GameUser.belongsToMany(models.Game, {through: models.GameGrade,fore…

调整Python+Pytest+Allure+Yaml+Pymysql框架中需要执行的用例顺序

当pytest框架中有时时候会因为用例的前后关联关系需要调整用例执行顺序时则可以跟进具体的要求调整pytest.ini配置文件中执行用例文件夹的前后顺序 当如果是需要调整某个文件夹中用例的执行顺序时&#xff0c;则跟进具体的文件调整对应testcases中test_*.py文件中的执行顺序

[云原生之旅] K8s-Portforward的另类用法, 立省两个端口

前言 此方法适用于Pod不需要大量连接的情况: 有多个pod在执行任务, 偶尔需要连接其中一个pod查看进度/日志;对pod执行一个脚本/命令; 不适用于大量连接建立的情况: pod启的数据库服务;pod启的Api服务;pod启的前端服务;pod启的Oss服务; Portforward简介 Portforward就是端…

Transformer 中缩放点积注意力机制探讨:除以根号 dk 理由及其影响

Transformer 中缩放点积注意力机制的探讨 1. 引言 自2017年Transformer模型被提出以来&#xff0c;它迅速成为自然语言处理&#xff08;NLP&#xff09;领域的主流架构&#xff0c;并在各种任务中取得了卓越的表现。其核心组件之一是注意力机制&#xff0c;尤其是缩放点积注意…

Qt监控系统远程网络登录/请求设备列表/服务器查看实时流/回放视频/验证码请求

一、前言说明 这几个功能是近期定制的功能&#xff0c;也非常具有代表性&#xff0c;核心就是之前登录和设备信息都是在本地&#xff0c;存放在数据库中&#xff0c;数据库可以是本地或者远程的&#xff0c;现在需要改成通过网络API请求的方式&#xff0c;现在很多的服务器很强…