day43_jdbc

今日内容

0 复习昨日
1 SQL注入问题
2 PreparedStatement
3 完成CRUD练习
4 ORM
5 DBUtil (properties)

6 事务操作

0 复习昨日

已经找人提问…

1 SQL注入

1.1 什么是SQL注入

用户输入的数据中有SQL关键词,导致在执行SQL语句时出现一些不正常的情况.这就是SQL注入!


出现SQL注入是很危险

在这里插入图片描述

1.2 避免SQL注入

问题出现在用户输入数据时,里面有关键词,再配合字符串拼接导致出现SQL注入.所以为了避免SQL注入,可以在用户输入数据到SQL之前,先把SQL语句预编译,预处理后,JDBC就会知道此SQL需要几个参数,后续再将用户输入的数据给参数填充.

这就是PreparedStatement

2 PreparedStatement【重点】

PreparedStatement是Statement的子接口,用来预处理SQL语句

PreparedStatement使用

  • 先写SQL语句,SQL语句中的参数不能直接拼接,而是使用?占位
  • 使用ps预处理SQL语句,处理的?号,ps内部就会知道此SQL语句需要几个参数
  • 再动态给?处填充值
package com.qf.jdbc;

import java.sql.*;
import java.util.Scanner;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 登录-使用预处理语句完成
 */
public class Demo2_LoginPlus {

    public static void main(String[] args) throws Exception {

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:" );
        String username = scanner.nextLine( );

        System.out.println("请输入密码:" );
        String password = scanner.nextLine( );

        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");

        // 改造SQL,将拼接变量,变成?占位
        String sql = "select * from tb_user where username = ? and password = ?";
        System.out.println("处理前:  " + sql);

        // 由之前的Statement换成PreparedStatement
        // 将改造好的SQL,传入方法
        PreparedStatement ps = conn.prepareStatement(sql);
        System.out.println("处理后: " + ps );

        // 给处理好的占位参数赋值
        // ps.setXxx() 给指定Xxx类型赋值
        // 第一个?,下标是1
        ps.setString(1,username);
        ps.setString(2,password);

        System.out.println("填充后: " + ps );

        //【特别注意!!!!】 此处executeQuery不需要再传入SQL参数!!!
        ResultSet rs = ps.executeQuery();

        if (rs.next()) {
            System.out.println("登录成功!!" );
        } else {
            System.out.println("用户名或密码错误!" );
        }

        rs.close();
        ps.close();
        conn.close();
    }
}
请输入用户名:
111
请输入密码:
111' or '1=1
处理前:  select * from tb_user where username = ? and password = ?
处理后: select * from tb_user where username = ** NOT SPECIFIED ** and password = ** NOT SPECIFIED **
填充后: select * from tb_user where username = '111' and password = '111\' or \'1=1'
用户名或密码错误!

3 完成CRUD练习

3.1 插入

package com.qf.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Date;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc  使用预处理语句插入数据
 */
public class Demo3_insert {

    public static void main(String[] args) throws Exception {

        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");

        // 1 先改造SQL(由拼接变成?)
        String sql = "insert into tb_user (id,username,password,phone,createTime,money,sex) values (?,?,?,?,?,?,?)";

        // 2 预处理
        PreparedStatement ps = conn.prepareStatement(sql);

        // 3 给?处赋值
        ps.setInt(1,5);
        ps.setString(2,"亚鹏");
        ps.setString(3,"333000");
        ps.setString(4,"333333");
        // 【特别注意!!!】 setDate的参数,设置是java.sql.Date
        // 我们常用的是java.util.Date
        // java.sql.Date是java.util.Date的子类
        // java.sql.Date有个构造方法,可以通过毫秒值创建日期
        // 通过常用的java.util.Date获得毫秒值
        ps.setDate(5,new java.sql.Date(new java.util.Date().getTime()));

        // 如果需要设置日期时间 yyyy-MM-dd HH:mm:ss
        // 使用ps.setTimestamp();

        ps.setDouble(6,3000.1);
        ps.setInt(7,1);
        // 【特别注意!!!】 此处不要再填参数
        int num = ps.executeUpdate( );

        if (num > 0) {
            System.out.println("插入成功" );
        }
        ps.close();
        conn.close();
    }
}

3.2 更新

package com.qf.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Date;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Demo4_update {

    public static void main(String[] args) throws  Exception{

        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");

        // 1 改造sql
        String sql = "update tb_user set username = ? , createTime = ? , money = ? where id = ?";
        // 2 预处理
        PreparedStatement ps = conn.prepareStatement(sql);
        // 3 填充?
        ps.setString(1,"小谢");

        Date utilDate = new Date( );
        utilDate.setYear(100);
        utilDate.setMonth(0);
        utilDate.setDate(1);
        long time = utilDate.getTime( );
        ps.setDate(2,new java.sql.Date(time));

        ps.setDouble(3,4000.1);
        ps.setInt(4,5);

        int num = ps.executeUpdate( );

        if (num > 0) {
            System.out.println("更新成功" );
        }

        ps.close();
        conn.close();
    }
}

3.3 删除

    public static void main(String[] args) throws  Exception{

        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");

        // 1 改造sql
        String sql = "delete from tb_user where id = ?";
        // 2 预处理
        PreparedStatement ps = conn.prepareStatement(sql);
        // 3 填充?
        ps.setInt(1,5);

        int num = ps.executeUpdate( );

        if (num > 0) {
            System.out.println("删除成功" );
        }

        ps.close();
        conn.close();
    }

4 事务处理

事务是逻辑一组操作,要么全部成功,要么全部失败!


使用mysql客户端操作事务

  • 因为mysql支持事务,且每句话都在事务内,且自动提交
  • 所以关闭自动提交事务,手动开启事务 start transaction
  • 正常写sql/执行sql
  • 一切正常,提交事务 commit
  • 如果不正常,要回滚 rollback

JDBC也可以完成事务操作

  • conn.setAutoCommit(false) 关闭自动提交,就相当于是开启手动管理
  • 正常的处理sql
  • 一切正常,提交事务 conn.commit()
  • 如果不正常,回滚 conn.rollback()

演示: 以转账案例演示

package com.qf.tx;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 以转账为案例演示
 * --------------------
 * Statement语句和PreparedStatement语句
 * 与事务操作没有影响
 */
public class Demo6_TX {

    // 张三转账给李四
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps1 = null;
        PreparedStatement ps2 = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");

            // 【1 开启事务】
            conn.setAutoCommit(false);

            // 张三的钱减少100
            String sql1 = "update account set money = money - 100 where id = 1";
            ps1 = conn.prepareStatement(sql1);
            int num = ps1.executeUpdate( );
            if (num > 0) {
                System.out.println("张三转账(-100)完成!");
            }

            System.out.println(1/0 ); // 模拟在转账中,出现异常,后续不执行

            // 李四的钱要增加100
            String sql2 = "update account set money = money + 100 where id = 2";
            ps2 = conn.prepareStatement(sql2);
            int num2 = ps2.executeUpdate( );
            if (num2 > 0) {
                System.out.println("李四转账(+100)完成!");
            }

            // 【2 一切顺利,提交事务】
            conn.commit();

        } catch (Exception e) {
            try{
                // 【3 不顺利,中间有异常,回滚事务】
                conn.rollback();
            }catch (Exception e2) {
                System.out.println("回滚事务异常!!" );
                e2.printStackTrace();
            }
            System.out.println("SQL异常!!!");
            e.printStackTrace( );
        } finally {
            try {
                ps1.close( );
                ps2.close( );
                conn.close( );
            } catch (Exception e) {
                System.out.println("关流时有异常!!");
                e.printStackTrace( );
            }
        }
    }
}

另外发现: 建立与Mysql连接后,关流之前,可以执行很多次SQL语句

5 ORM【重点】

5.1 什么是ORM

目前使用JDBC完成了CRUD,但是现在是进行CRUD,增删改方法要设计很多参数,查询的方法需要设计集合才能返回.


在实际开发中,我们需要将零散的数据封装到对象处理.

ORM (Object Relational Mapping) 对象关系映射

是指数据库表Java的实体类有关系,可以进行映射

  • 数据库表 --> Java的类
    • tb_user —> User.java
  • 字段 --> 类的属性
    • id int --> private int id;
    • username varchar --> private String username;
  • 一行数据 --> 类的对象

5.2 实体类

实体类: 数据表中零散数据的载体,用来封装数据.

  • 表名 设计 类名
  • 将列名设计成属性名
    • id --> id
    • create_time --> createTime (下划线转驼峰)
  • 将列的数据类型设计成属性的数据类型
  • 给类提供对应set get

一般项目中一个表就会对应一个实体类,所有的实体类都会放在model/entity/pojo/javabeen包结构中


将来写项目,数据库设计完,搭建完项目,第一件事件就是根据表结构,创建实体类

package com.qf.model; // 包
public class User {   // 实体类,是表名
	// 属性是字段名
    private int id;
    private String username;
    private String password;
    private String phone;
    private Date createTime;
    private double money;
    private int sex;
    
    // setter getter...
}

在这里插入图片描述

5.3 使用ORM完成CRUD

5.3.1 查询使用ORM封装数据

package com.qf.orm;

import com.qf.model.User;

import java.sql.*;
import java.util.Scanner;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 登录完成,查询到数据,将数据封装到User对象
 * ---------------------------------------------
 * 使用ORM封装数据,将查询得到结果集封装到User对象中
 * 即登录成功  User对象中有值
 *  登录不成功 User对象不存在
 */
public class Demo7_Login_ORM {


    public static void main(String[] args) throws Exception{

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:" );
        String username = scanner.nextLine( );

        System.out.println("请输入密码:" );
        String password = scanner.nextLine( );

        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");

        String sql = "select * from tb_user where username = ? and password = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setString(1,username);
        ps.setString(2,password);

        ResultSet rs = ps.executeQuery( );

        // 声明用于封装数据表数据的实体类
        User user = null;

        if (rs.next()) {
            // 从结果集取值
            int id = rs.getInt("id");
            String uname = rs.getString("username");
            String pwd = rs.getString("password");
            String phone = rs.getString("phone");
            Date createTime = rs.getDate("createTime");
            double money = rs.getDouble("money");
            int sex = rs.getInt("sex");

            // 创建封装数据用的实体类对象
            user = new User();
            // 开始封装
            user.setId(id);
            user.setUsername(uname);
            user.setPassword(pwd);
            user.setPhone(phone);
            user.setCreateTime(createTime); // java.sql.Date是java.util.Date的子类
            user.setMoney(money);
            user.setSex(sex);
        }

        if (user != null) {
            System.out.println("登录成功!" );
            System.out.println("个人信息为:" + user );
        } else {
            System.out.println("登录失败!" );
        }
    }
}

5.3.2 插入使用ORM封装数据

package com.qf.orm;

import com.qf.model.User;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Date;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Demo8_Insert_ORM {

    public static void main(String[] args) {
        User user = new User( );
        user.setId(6);
        user.setUsername("李冰");
        user.setPassword("123456" );
        user.setCreateTime(new Date());
        user.setMoney(4000.1);
        user.setSex(2);
        user.setPhone("222333");

        insert(user);
    }

    public static void insert(User user) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");

            String sql = "insert into tb_user (id,username,password,phone,createTime,money,sex) values (?,?,?,?,?,?,?)";
            ps = conn.prepareStatement(sql);
            ps.setInt(1,user.getId());
            ps.setString(2,user.getUsername());
            ps.setString(3,user.getPassword());
            ps.setString(4,user.getPhone());
            ps.setDate(5,new java.sql.Date(user.getCreateTime().getTime()));
            ps.setDouble(6,user.getMoney());
            ps.setInt(7,user.getSex());

            int num = ps.executeUpdate( );
            if (num > 0) {
                System.out.println("注册成功!" );
            }
        } catch (Exception e) {
            System.out.println("SQL异常!!!" );
            e.printStackTrace();
        } finally {
            try{
                ps.close();
                conn.close();
            }catch (Exception e) {
                System.out.println("关流异常!!" );
                e.printStackTrace();
            }
       }
    }
}

6 DBUtil【理解,会用】

DBUtil操作数据库的工具类,因为发现每次操作数据库,JDBC的步骤第1,2,5步完全重复的,即加载驱动,获得连接对象,已经最后的关流是每次都要写但每次都是一样的!!!


现在设计工具类,简化第1,2,5步

  • 设计个方法,调用直接获得连接对象
  • 设计个方法,调用直接关闭全部的流对象
package com.qf.util;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class DBUtil {

    // 创建Properties类对象,专用于操作properties文件
    private static final Properties properties = new Properties();

    /**
     * 加载驱动的目的是为了在JVM中有sql运行的环境
     * 该环境有一份就行了,不用重复加载
     * ------------------------------------
     * static 静态代码块
     * 1) 保证内存中只有一份
     * 2) 保证随着类加载而加载,即该代码块会执行
     */
    static {

        // 通过反射的技术获得字节码文件
        // 再通过字节码文件将配置文件读取成输入流
        InputStream inputStream = DBUtil.class.getResourceAsStream("/jdbc.properties");
        try {
            // 再通过流获得其中数据
            properties.load(inputStream);
            // 从properties对象取值
            Class.forName(properties.getProperty("driverClass"));
        } catch (Exception e) {
            System.out.println("加载驱动异常!!" );
            e.printStackTrace( );
        }
    }

    /**
     * 一般会将关于JDBC配置信息,抽取出来,形成一个配置文件,方便维护
     * 文件类型是properties文件,该文件类似map,键值对类型
     * 名字 jdbc.properties
     * 位置 src/jdbc.properties
     * 内容
     */
    public static Connection getConnection() {
        Connection conn = null;
        try{
            conn = DriverManager.getConnection(properties.getProperty("url"),properties.getProperty("username") ,properties.getProperty("password") );
        } catch (Exception e) {
            System.out.println("获得连接出异常!!!" );
            e.printStackTrace();
        }
        return conn;
    }


    /**
     * 关闭所有流
     */
    public static void closeAll(Connection conn, Statement s) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }

        if (s != null) {
            try {
                s.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }
    }

    public static void closeAll(Connection conn, Statement s, ResultSet rs){
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }

        if (s != null) {
            try {
                s.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }

        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }
    }
}

在src下创建jdbc.properties文件

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/java2217?useSSL=false
username=root
password=123456

tion throwables) {
throwables.printStackTrace( );
}
}

    if (s != null) {
        try {
            s.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace( );
        }
    }

    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace( );
        }
    }
}

}


在src下创建jdbc.properties文件

```properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/java2217?useSSL=false
username=root
password=123456

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

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

相关文章

两种方式实现文本超出指定行数显示展开收起...

需要实现这样一个功能 默认高度下文本超出隐藏&#xff0c;点击展开可查看所有内容&#xff0c;点击收起可折叠 方法一&#xff1a;通过html和css实现 代码部分 html:<div className"expand-fold"><input id"check-box" type"checkbox&qu…

幻兽帕鲁游戏中走路卡顿并且会出现回弹是什么原因?

可能原因是最近的 1.4.0 更新后&#xff0c;代码中有一个启动参数的加入&#xff0c;导致 CPU 占用极高。 可以远程连接你的服务器 然后执行下面的代码&#xff0c;删除代码中的那个启动参数。 # 删除可能导致人物回弹的游戏服务器启动参数 sudo -u ecs-assist-user sed -i s…

ios搭建OpenGL环境

前言 本篇文章介绍在ios搭建OpenGL开发环境 在app的启动文章中&#xff0c;讲述了一个ios应用是如何启动的以及在IOS 13之后苹果公司推出的多窗口功能&#xff0c;通过app的启动这篇文章&#xff0c;我们基本能随心所欲的搭建一个app应用环境&#xff0c;搭建完成后的基本文件…

雨课堂怎么搜答案?七个受欢迎的搜题分享了 #微信#职场发展雨课堂怎么搜答案?七个受欢迎的搜题分享了 #微信#职场发展

积极参加社团活动和实践项目&#xff0c;可以帮助大学生拓宽人脉圈和锻炼实际操作能力。 1.福昕翻译 可以一键翻译文档内容&#xff0c;并提供还原排版的译文&#xff0c;对经常看外文文献的朋友来说&#xff0c;绝对是福音 福昕翻译是一流专业的在线翻译服务平台,支持PDF文…

一文带你了解编码集

编码集 1. ASCII编码&#xff1a; 127个字母 8个数据位足够存储字母、数字、符号&#xff0c;支持到0x7F。 2. GB2312编码 每个汉字占据2个字节(高位和低位)&#xff0c;16个数据。GB2312是对ASCII的中文扩展&#xff0c;共包含7000多个汉字。是计算机发展到中国后发展起来…

Python算法100例-1.3 牛顿迭代法求方程根

完整源代码项目地址&#xff0c;关注博主私信’源代码’后可获取 1&#xff0e;问题描述 编写用牛顿迭代法求方程根的函数。方程为 a x 3 b x 2 c x d 0 ax^3bx^2cxd0 ax3bx2cxd0&#xff0c;系数a、b、c、d由主函数输入&#xff0c;求x在1附近的一个实根。求出根后&…

VBA字典与数组第十一讲:普通公式与数组公式的本质区别

《VBA数组与字典方案》教程&#xff08;10144533&#xff09;是我推出的第三套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;字典是VBA的精华&#xff0c;我要求学员必学。7.1.3.9教程和手册掌握后&#xff0c;可以解决大多数工作中遇到的实际问题。…

MAE实战:使用MAE提高主干网络的精度(一)

摘要 MAE已经出来有几年了&#xff0c;很多人还不知道怎么去使用&#xff0c;本文通过两个例子说明一下。分两部分&#xff0c;一部分介绍一个简单的例子&#xff0c;让大家了解MAE训练的流程。一部分是一个新的模型&#xff0c;让大家了解如何将自己的模型加入MAE。 论文标…

Java 获取操作时区 ZonedDateTime

Java 获取操作时区 ZonedDateTime package com.zhong.timeaddress;import java.time.Clock; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Set;public class TimeAddress {public static void main(String[] args) {// 获取系统默认时区ZoneId…

PyTorch 中神经网络库torch.nn的详细介绍

1. torch.nn torch.nn 是 PyTorch 深度学习框架中的一个核心模块&#xff0c;它为构建和训练神经网络提供了丰富的类库。 以下是 torch.nn 的关键组成部分及其功能&#xff1a; nn.Module 类&#xff1a; nn.Module 是所有自定义神经网络模型的基类。用户通常会从这个类派生…

前端工程化之:webpack2-2(内置插件)

目录 一、内置插件 1.DefinePlugin 2.BannerPlugin 3.ProvidePlugin 一、内置插件 所有的 webpack 内置插件都作为 webpack 的静态属性存在的&#xff0c;使用下面的方式即可创建一个插件对象&#xff1a; const webpack require("webpack")new webpack.插件…

计算机设计大赛 深度学习 机器视觉 车位识别车道线检测 - python opencv

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 车位识别车道线检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) …

随机图论基础

一&#xff0c;随机图、随机图空间 1&#xff0c;随机图 一个n个点的无向图&#xff0c;最多有sn(n-1)/2条边。 每条边都有一定的概率存在&#xff0c;有一定概率不存在&#xff0c;那么每个图都有一个出现概率。 2&#xff0c;随机图空间 一共有2^s种不同的图&#xff0c…

C++:按键控制头文件Button.h

★&#xff0e;☆ &#xff0e;★∴★&#xff0e;∴☆ ∴ ☆&#xff0e;&#xff0e; ☆★∴∴ ☆&#xff0e;★∴&#xff0e; ◢◣。 ◢◣。 ☆圣★ ◢★◣。 ◢★◣。 ★诞☆ ◢■■◣。 ◢■■◣。 ☆节★ ◢■■■◣。 ◢■■■◣。 …

集合-02

文章目录 1.Set集合1.1Set集合概述和特点1.2Set集合的使用 2.TreeSet集合2.1TreeSet集合概述和特点2.2TreeSet集合基本使用2.3自然排序Comparable的使用2.4比较器排序Comparator的使用2.5两种比较方式总结 3.HashSet集合3.1HashSet集合概述和特点3.2HashSet集合的基本应用3.3哈…

Java 格式化时间以及计算时间

Java 格式化时间以及计算时间 package com.zhong.datetimeformat;import java.time.*; import java.time.format.DateTimeFormatter;public class DateTimeFormats {public static void main(String[] args) {// 创建一个日期格式化器对象DateTimeFormatter dateTimeFormatter…

【chisel】 环境,资料

Chisel环境搭建教程&#xff08;Ubuntu&#xff09; 根据上边的link去安装&#xff1b; 目前scala最高版本用scala-2.13.10,太高了 没有chisel的库文件支持&#xff1b;会在sbt下载的过程中报错&#xff1b; [error] sbt.librarymanagement.ResolveException: chisel chisel目…

深入理解网络通信和TCP/IP协议

目录 计算机网络是什么&#xff1f; 定义和分类 计算机网络发展简史 计算机网络体系结构 OSI 七层模型 TCP/IP 模型 TCP/IP 协议族 TCP/IP 网络传输中的数据 地址和端口号 MAC地址 IP 地址 端口号 为什么端口号有65535个&#xff1f; 综述 TCP 特性 TCP 三次握…

oc渲染器初始参数怎么设置?oc渲染器初始参数怎么弄

OC渲染器以其用户友好的界面、卓越的渲染品质而受到众多初学者的欢迎&#xff0c;而且它使得创建逼真的视觉效果变得轻而易举。对于产品展示、建筑设计以及室内布局渲染来说&#xff0c;OC渲染器都能表现出优异的性能。下面&#xff0c;我们将介绍新手如何进行OC渲染器的基本初…