javassist implements interface 模拟mybatis 生成代理类

news2025/1/12 9:53:05

 

动态创建代理对象的工具类 

package com.wsd.util;

import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.CtMethod;
import org.apache.ibatis.session.SqlSession;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

/**
 * 使用javassist库动态生成dao接口的实现类
 * @author: Mr.Wang
 * @create: 2023-07-08 18:44
 **/
public class ProxyUtil {

    public static Object getMyMapper(SqlSession sqlSession, Class daoInterface){
        //mybatis 依赖中内置了 javassist,不需要再引入javassist dependency
        //获取一个默认的 ClassPool 实例
        //Javassist 是一个 Java 字节码编辑库,它可以在运行时修改已加载的类或者生成新的类。
        // ClassPool 是 Javassist 的核心组件,它是一个类容器,负责存储和管理字节码(.class 文件)
        ClassPool pool = ClassPool.getDefault();
        // 生成代理类
        CtClass ctClass = pool.makeClass(daoInterface.getPackage().getName() + ".impl." + daoInterface.getSimpleName() + "Impl");
        // 接口
        CtClass ctInterface = pool.makeClass(daoInterface.getName());
        // 代理类实现接口
        ctClass.addInterface(ctInterface);
        // 获取所有的方法
        Method[] methods = daoInterface.getDeclaredMethods();
        Arrays.stream(methods).forEach(method -> {
            // 拼接方法的签名
            StringBuilder methodStr = new StringBuilder();
            String returnTypeName = method.getReturnType().getName();
            //返回值类型
            methodStr.append(returnTypeName);
            methodStr.append(" ");
            //方法名
            String methodName = method.getName();
            methodStr.append(methodName);
            methodStr.append("(");
            //参数列表
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++) {
                methodStr.append(parameterTypes[i].getName());
                methodStr.append(" arg");
                methodStr.append(i);
                //不是最后一个参数的情况下,需要拼接一个逗号
                if (i != parameterTypes.length - 1) {
                    methodStr.append(",");
                }
            }
            methodStr.append("){");
            // 方法体当中的代码怎么写?
            // 获取sqlId(这里非常重要:因为这行代码导致以后namespace必须是接口的全限定接口名,sqlId必须是接口中方法的方法名。)
            String sqlId = daoInterface.getName() + "." + methodName;
            // 获取SqlCommondType 获取配置文件中该sql tag 的类型
            String sqlCommondTypeName = sqlSession.getConfiguration().getMappedStatement(sqlId).getSqlCommandType().name();
            if ("SELECT".equals(sqlCommondTypeName)) {
                methodStr.append("org.apache.ibatis.session.SqlSession sqlSession = com.wsd.util.SqlSessionUtil.openSession();");
                methodStr.append("Object obj = sqlSession.selectOne(\"" + sqlId + "\", arg0);");
                methodStr.append("return (" + returnTypeName + ")obj;");
            } else if ("UPDATE".equals(sqlCommondTypeName)) {
                methodStr.append("org.apache.ibatis.session.SqlSession sqlSession = com.wsd.util.SqlSessionUtil.openSession();");
                methodStr.append("int count = sqlSession.update(\"" + sqlId + "\", arg0);");
                methodStr.append("return count;");
            }
            methodStr.append("}");
            System.out.println(methodStr);
            try {
                // 创建CtMethod对象
                CtMethod ctMethod = CtMethod.make(methodStr.toString(), ctClass);
                //添加访问修饰符public
                ctMethod.setModifiers(Modifier.PUBLIC);
                // 将方法添加到类
                ctClass.addMethod(ctMethod);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        try {
            // 创建代理对象
            Class<?> aClass = ctClass.toClass();
            Constructor<?> defaultCon = aClass.getDeclaredConstructor();
            Object o = defaultCon.newInstance();
            return o;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}

 

pom.xml 

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.wsd</groupId>
  <artifactId>web-mybatis01</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>web-mybatis01 Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <!--mybatis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.10</version>
    </dependency>
    <!--MySQL驱动依赖-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.30</version>
    </dependency>
    <!--logback 日志依赖-->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.11</version>
    </dependency>
    <!--servlet 依赖-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>web-mybatis01</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

dao interface

package com.wsd.dao;

import com.wsd.pojo.Account;

/**
 * @author: Mr.Wang
 * @create: 2023-07-02 01:30
 **/
public interface AccountDao {

    /**
     * 根据账号获取账户信息
     * @param actno 账号
     * @return 账户信息
     */
    Account selectByActno(String actno);

    /**
     * 更新账户信息
     * @param act 账户信息
     * @return 1表示更新成功,其他值表示失败
     */
    int update(Account act);
}

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wsd.dao.AccountDao">
    <select id="selectByActno" resultType="com.wsd.pojo.Account">
        select * from t_act where actno = #{actno}
    </select>
    <update id="update">
        update t_act set balance = #{balance} where actno = #{actno}
    </update>
</mapper>

mybatis 配置文件 

<?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE configuration
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
</environments>
<mappers>
    <mapper resource="AccountMapper.xml"/>
</mappers>
</configuration>

jdbc.properties 

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root

获取sqlsession的工具类 

package com.wsd.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;


/**
 * @description: Utility class for mybatis
 * @author: Mr.Wang
 * @create: 2023-06-17 17:38
 **/

public class SqlSessionUtil {

    private SqlSessionUtil(){}

    private static SqlSessionFactory sqlSessionFactory;

    //保存sqlSession , 一个线程一个
    private static ThreadLocal<SqlSession> sqlSessionThreadLocal = new ThreadLocal<>();


    /**
     * 类加载时初始化sqlSessionFactory对象
     */
    static {
        try {
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 每调用一次openSession()可获取一个新的会话。
     *
     * @return 新的会话对象
     */

    public static SqlSession openSession() {
        // Get a sqlSession instance from sqlSessionThreadLocal
        SqlSession sqlSession = sqlSessionThreadLocal.get();
        //如果 sqlSessionThreadLocal 未获取到 sqlSession,让工厂生产一个新的sqlSession
        if(sqlSession == null){
            sqlSession = sqlSessionFactory.openSession();
            sqlSessionThreadLocal.set(sqlSession);
        }
        return sqlSession;
    }


    /**
     * @description close sqlSession and remove it from sqlSessionThreadLocal
     * @param sqlSession
     * @return
     */
    public static void close(SqlSession sqlSession) {
        if(sqlSession != null){
            sqlSession.close();
            //remove from sqlSessionThreadLocal
            sqlSessionThreadLocal.remove();
        }
    }
}

封装数据的 pojo  class

package com.wsd.pojo;

/**
 * @description: pojo for Account
 * @author: Mr.Wang
 * @create: 2023-07-01 23:41
 **/
public class Account {
    private Long id;
    private String actno;
    private Double balance;

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", actno='" + actno + '\'' +
                ", balance=" + balance +
                '}';
    }

    public Account() {
    }

    public Account(Long id, String actno, Double balance) {
        this.id = id;
        this.actno = actno;
        this.balance = balance;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }
}

service interface

package com.wsd.service;

import com.wsd.exception.AppException;
import com.wsd.exception.MoneyNotEnoughException;

public interface AccountService {


    void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException, AppException;
}

实现类

package com.wsd.service.impl;

import com.wsd.dao.AccountDao;
import com.wsd.exception.AppException;
import com.wsd.exception.MoneyNotEnoughException;
import com.wsd.pojo.Account;
import com.wsd.service.AccountService;
import com.wsd.util.ProxyUtil;
import com.wsd.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;

/**
 * @author: Mr.Wang
 * @create: 2023-07-02 01:19
 **/
public class AccountServiceImpl implements AccountService {

    //使用工具类生成代理对象
    private AccountDao accountDao = (AccountDao) ProxyUtil.getMyMapper(SqlSessionUtil.openSession(), AccountDao.class);

    @Override
    public void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException,AppException{
        //创建sql session
        SqlSession sqlSession =  SqlSessionUtil.openSession();

        // 查询转出账户的余额
        Account fromAct = accountDao.selectByActno(fromActno);
        //余额不足,抛出异常
        if (fromAct.getBalance() < money) {
            throw new MoneyNotEnoughException("对不起,您的余额不足。");
        }

        // 程序如果执行到这里说明余额充足
        // 修改账户余额
        Account toAct = accountDao.selectByActno(toActno);
        fromAct.setBalance(fromAct.getBalance() - money);
        toAct.setBalance(toAct.getBalance() + money);
        // 更新数据库
        int count = accountDao.update(fromAct);

        /*//模拟异常
        String s = null;
        s.toString();*/

        count += accountDao.update(toAct);
        if (count != 2) {
            throw new AppException("转账失败,未知原因!");
        }

        sqlSession.commit();
        SqlSessionUtil.close(sqlSession);
    }
}

Exception

package com.wsd.exception;

/**
 * @author: Mr.Wang
 * @create: 2023-07-02 11:57
 **/
public class AppException extends Exception {

    public AppException() {
    }

    public AppException(String message) {
        super(message);
    }
}
package com.wsd.exception;

/**
 * @author: Mr.Wang
 * @create: 2023-07-02 09:06
 **/
public class MoneyNotEnoughException extends Exception{
    public MoneyNotEnoughException() {
    }

    public MoneyNotEnoughException(String message) {
        super(message);
    }
}

servlet

package com.wsd.web;

import com.wsd.exception.AppException;
import com.wsd.exception.MoneyNotEnoughException;
import com.wsd.service.AccountService;
import com.wsd.service.impl.AccountServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @description:
 * @author: Mr.Wang
 * @create: 2023-07-02 00:52
 **/
@WebServlet("/transfer")
public class AccountServlet extends HttpServlet {

    private AccountService accountService = new AccountServiceImpl();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取页面表单数据
        String fromActno = req.getParameter("fromActno");
        String toActno = req.getParameter("toActno");
        Double money = Double.parseDouble( req.getParameter("money") ) ;
        //调用service
        try {
            accountService.transfer(fromActno,toActno,money);
            //Show the result after transfer success
            resp.sendRedirect(req.getContextPath()  + "/success.html");
        } catch (MoneyNotEnoughException e) {
            resp.sendRedirect(req.getContextPath()  + "/error1.html");
        } catch (Exception e) {
            resp.sendRedirect(req.getContextPath() + "/error2.html");
        }

    }
}

页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>银行账户转账</title>
</head>
<body>
<!--/mybatis是应用的根,部署web应用到tomcat的时候一定要注意这个名字-->
<form action="/mybatis/transfer" method="post">
    转出账户:<input type="text" name="fromActno"/><br>
    转入账户:<input type="text" name="toActno"/><br>
    转账金额:<input type="text" name="money"/><br>
    <input type="submit" value="转账"/>
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>transfer result</title>
</head>
<body>
<h1>The transfer failed because of insufficient balance</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>transfer result</title>
</head>
<body>
<h1>The transfer failed, error occurred</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>transfer result</title>
</head>
<body>
<h1>The transfer success</h1>
</body>
</html>

test:

table before test: 

 

 

 

 

mybatis 框架中的sqlSession.getMapper(接口类) 可以生成代理对象

//sqlsession.getMapper生成代理对象
private AccountDao accountDao = (AccountDao) SqlSessionUtil.openSession().getMapper(AccountDao.class);
package com.wsd.service.impl;

import com.wsd.dao.AccountDao;
import com.wsd.exception.AppException;
import com.wsd.exception.MoneyNotEnoughException;
import com.wsd.pojo.Account;
import com.wsd.service.AccountService;
import com.wsd.util.ProxyUtil;
import com.wsd.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;

/**
 * @author: Mr.Wang
 * @create: 2023-07-02 01:19
 **/
public class AccountServiceImpl implements AccountService {

    //sqlsession.getMapper生成代理对象
    private AccountDao accountDao = (AccountDao) SqlSessionUtil.openSession().getMapper(AccountDao.class);

    @Override
    public void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException,AppException{
        //创建sql session
        SqlSession sqlSession =  SqlSessionUtil.openSession();

        // 查询转出账户的余额
        Account fromAct = accountDao.selectByActno(fromActno);
        //余额不足,抛出异常
        if (fromAct.getBalance() < money) {
            throw new MoneyNotEnoughException("对不起,您的余额不足。");
        }

        // 程序如果执行到这里说明余额充足
        // 修改账户余额
        Account toAct = accountDao.selectByActno(toActno);
        fromAct.setBalance(fromAct.getBalance() - money);
        toAct.setBalance(toAct.getBalance() + money);
        // 更新数据库
        int count = accountDao.update(fromAct);

        /*//模拟异常
        String s = null;
        s.toString();*/

        count += accountDao.update(toAct);
        if (count != 2) {
            throw new AppException("转账失败,未知原因!");
        }

        sqlSession.commit();
        SqlSessionUtil.close(sqlSession);
    }
}

test:

 

 

 

 

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

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

相关文章

[工业互联-14]:机器人操作系统ROS与ROS2是如何提升实时性的?

目录 第1章 简介 第2章 历史 第3章 特点 &#xff08;1&#xff09;点对点设计 &#xff08;2&#xff09;不依赖编程语言 &#xff08;3&#xff09;精简与集成 &#xff08;4&#xff09;便于测试 &#xff08;5&#xff09;开源 &#xff08;6&#xff09;强大的库及…

ESP32连接云服务器【WebSocket】

ESP32连接云服务器【ESP32宝塔面板】 文章目录 ESP32连接云服务器【ESP32宝塔面板】&#x1f468;‍&#x1f3eb;内容1&#xff1a;背景&#x1f468;‍⚖️内容2&#xff1a;服务器配置&#x1f468;‍&#x1f4bb;内容3&#xff1a;ESP32配置 &#x1f468;‍&#x1f3eb;…

3.5.核函数的定义和使用

目录 前言1. 核函数2. 核函数案例总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习精简 CUDA 教程-核函数 课程大纲可看下面…

使用infura创建以太坊网络

创建账号 https://www.infura.io/zh 进入控制台Dashboard&#xff0c;选择CREATE API KEY 创建成功后&#xff0c;进入API KEY查看&#xff0c;使用PostMan测试 返回result即为当前区块。

Linux安装配置Oracle+plsql安装配置(超详细)

注意&#xff1a;本文有大量的界面截图&#xff0c;如观看效果不佳可前往文字版&#xff1a; 目录 1 安装虚拟机系统 1.1 安装虚拟机 2.配置虚拟机 2.1 设置机器名 2.2 修改域名映射 2.3 固定IP地址 ​ 2.4 关闭防火墙 2.5 更改安全机制 2.6 重启reboot 3 修改配置 3.1 …

2.深度学习:用Python实现深度神经网络(简单易懂)

深度学习是人工智能领域中的一个热门话题&#xff0c;也是目前业界最具前景和发展潜力的领域之一。本文将会介绍如何用Python实现深度神经网络&#xff0c;编写自己的深度学习模型。作为一篇简单易懂的教程&#xff0c;本文将会从以下两个方面进行讲解&#xff1a;1. 基础知识介…

java环境搭建2-idea安装激活

windows环境装Java开发环境与idea安装激活 安装jdk安装idea激活idea新建项目开启Java学习 java环境搭建2-idea安装激活 之前安装了wslLinux子环境的Java开发环境,但是再许多地方没有人使用vscode进行Java开发,因为环境配置很麻烦,还有各种插件. windows环境装Java开发环境与ide…

尚无忧多城市共享自助台球室台球厅预约开灯开门小程序源码

1、定位功能&#xff1a;可定位附近是否有店 2、能通过关键字搜索现有的店铺 3、个性轮播图展示&#xff0c;系统公告消息提醒 4、个性化功能展示&#xff0c;智能排序&#xff0c;距离、价格排序 5、现有店铺清单展示&#xff0c;订房可查看房间单价&#xff0c;根据日期、…

在 FPGA 上通过 2D CNN 进行高效视频理解的 TSM 网络

在这个项目中&#xff0c;将在线和离线 TSM 网络部署到 FPGA&#xff0c;通过 2D CNN 执行视频理解任务。 介绍 在这个项目中&#xff0c;展示了 Temporal-Shift-Module ( https://hanlab.mit.edu/projects/tsm/)在 FPGA 上解决视频理解问题的实用性和性能。 TSM 是一种网络结构…

C++常用库函数 2.字符分类函数

函数名&#xff1a;isalnum 函数原型&#xff1a;int isalnum(int c)&#xff1b; 所需头文件&#xff1a;<cctype> 功能&#xff1a;测试 c 是否字母或数字。 返回值&#xff1a;如果 c 在 A&#xff5e;Z、a&#xff5e;z 或0&#xff5e;9的范围内&#xff0c;则返回…

002-集成Dubbo

目录 集成架构架构分析 Spring boot 集成引入依赖提供API 调用桥梁添加Dubbo服务服务提供者-服务实现服务提供者-添加配置服务消费者-添加配置服务消费者-配置消费端请求任务服务调用 扩展为什么要新增Dubbo协议 集成 架构 架构分析 Dubbo作为一个RPC调用框架作用就是让服务具…

使用Yfinance和Plotly分析金融数据

大家好&#xff0c;今天我们用Python分析金融数据&#xff0c;使用Yfinance和Plotly绘制图表&#xff0c;带你了解在Python中使用Plotly制作图表&#xff0c;利用Plotly强大的图表功能来分析和可视化金融数据。 导语 在本文中&#xff0c;我们将深入研究Plotly&#xff0c;从…

Linux安装配置Oracle+plsql安装配置(详细)

如果觉得本文不够详细&#xff0c;没有效果图&#xff0c;可移步详细版&#xff1a; Linux安装配置Oracleplsql安装配置&#xff08;超详细&#xff09;_超爱慢的博客-CSDN博客 目录 1.安装虚拟机系统 1.安装虚拟机 2.配置虚拟机 1.设置机器名 2.修改域名映射 3.固定IP…

I.MX RT1170之FlexSPI(4):HyperRAM手册分析和参数配置详解

在上一篇文章中我分析了NOR Flash的手册和FlexSPI的相关配置&#xff0c;在这篇文章中&#xff0c;我将以HyperRAM为例&#xff0c;看看八线的HyperRAM在硬件设计和软件配置上有增加什么引脚和参数&#xff0c;然后以ISIS型号为IS66WVH64M8DALL/BLL的HyperRAM为例&#xff0c;看…

402 · 连续子数组求和

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a; 九章算法 - 帮助更多程序员找到好工作&#xff0c;硅谷顶尖IT企业工程师实时在线授课为你传授面试技巧 九章算法 - 帮助更多程序员找到好工作&#xff0c;硅谷顶尖IT企业…

微信小程序开发与应用——字体样式设置

要求&#xff1a;设置字体样式。 1、打开微信开发者工具&#xff0c;创建一个小程序&#xff0c;如下&#xff1a; 2、设置小程序的项目名称和路径&#xff0c;并选择开发语言为JavaScript&#xff0c;如下&#xff1a; 3、小程序的主体部分由三个文件组成&#xff0c;且都要…

2023.07.08力扣6题

167. 两数之和 II - 输入有序数组 给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] &#xff0c;则 1 < …

Carla与Ros联合仿真教学与踩坑经历

Carla与Ros联合仿真教学与踩坑经历 前言 本人需要用到carla进行仿真&#xff0c;做实验&#xff0c;研究了这个平台几个月。 需要注意的是&#xff0c;本人没有保留所有的ros包&#xff0c;而是选择一些进行使用&#xff0c;其他大家可以进行扩展。 carla0.9.5版本和carla0.…

雅思口语考试的顺序与技巧?

雅思口语的考试顺序&#xff0c;也是学生们在开始考试前要了解的信息。雅思的口语考试到底有怎样的考试顺序&#xff1f;下面就听小编讲讲它的考试顺序&#xff0c;以及考试中的技巧。 一、雅思口试考试顺序 众所周知&#xff0c;雅思考试分为笔试和口试。正常情况下&#xff…

YOLOV5-Lite轻量化部署与训练

文章目录 前言项目下载项目运行自定义数据集训练使用LabelImg标注制作数据集划分训练文件生成标签聚合操作辅助脚本需要运行的脚本 开始训练 总结 前言 没啥意思&#xff0c;很简单&#xff0c;需要实现一个目标检测&#xff0c;但是&#xff0c;不能占用太多运算资源&#xf…