第七周学习

tcp和udp

TCP客户端使用步骤

  • 1)创建客户端的Socket对象,指定ip和端口

  • 2)获取客户端通道内容字节输出流对象,写数据

  • 3)释放资源

TCP服务器端的代码实现

  • 1)创建服务器端的Socket对象

  • 2)监听客户端的连接

  • 3)获取监听到的客户端的通道内的自节输入流对象,读数据

  • 4)释放服务器端的资源

例题

TCP服务器端将复制客户端的文件内容,复制

public class TcpClientTest {
    public static void main(String[] args) throws IOException {
        //创建客户端的Socket对象
        Socket s = new Socket("10.35.162.121",2222) ;
        //创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(
                new FileReader("UdpReceive.java")) ;
​
        //获取客户端通道的字节输出流---->包装成BufferedWriter:字符缓冲输出流
        BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(s.getOutputStream())) ;
​
        //每次从.java文件读取一行,给通道流的流中写一行
        String line = null ;
        while((line=br.readLine())!=null){
            bw.write(line) ;
            bw.newLine();
            bw.flush();
        }
        System.out.println("文件读完,发送过去了...");
        //释放资源
        br.close();
        s.close();
​
    }
}
public class TcpServerTest {
    public static void main(String[] args) throws IOException {
        //创建服务器端的Socket对象
        ServerSocket ss = new ServerSocket(2222) ;
        //监听客户端连接
        Socket s = ss.accept();
        //获取监听客户端所在的通道内字节输入流对象---->包装成字符缓冲输入流
        BufferedReader br = new BufferedReader(
                new InputStreamReader(s.getInputStream())) ;
​
        //将监听客户端的通道内的字节流(已经被包装了字符缓冲输入流)的内容----通过的字符缓冲输出流写入到文件中
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\EE_2211\\day27_code_resource\\copy.java")) ;
        //一次读取一行,写一行到文件中
        String line = null ;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
​
        System.out.println("复制完毕");
        //释放资源
        bw.close();
        ss.close();
​
​
    }
}

问题解决:两个端都出现了互相等待

因为客户端的文本文件读完,是null作为结束条件,但是服务器端不断的从通道内的输入流去读数据,两端的通道不知道文件是否完了(服务器端不知道客户端的文件完没完),等待着写数据过来

解决方案:

通知服务器端,别等了,文件读完了

  • 1)自定义结束条件 ,服务器端读到自定义结束条件,就反馈!

    弊端:如果文件第一句话恰好是自定义的结束条件,就不好
  • 2)推荐:在客户端这边有个终止通道内的流 没有数据写过去了!禁止输出流输出!

    public void shutdownOutput() throws IOException

反射

什么是反射?

  • 编译某个类的时候---->获取这个类的字节码文件,然后去加载,调用里面的成员方法,访问成员变量,通过构造方法创建对象!

编译过程

对这个类的属性/成员/构造其进行校验---->类加载器(负责类的加载过程)

BoostrapClassLoader:启动类加载器,负责java核心库,rt.jar

如何获取一个类的字节码文件?

  • 任意Java对象的getClass方法

    Person p = new Person() ;
    Class clazz = p.getClass();
    System.out.println(clazz);
  • 任意Java类型的class属性

    Class clazz2 = Person.class ;
    System.out.println(clazz2);
  • java.lang.Class:代表正在运行的java类或者接口,通过静态方法

Class clazz3 = Class.forName("com.qf.reflect_06.Person");

通过反射方式获取类的字节码文件之后,创建当前类对象!

1)获取类的字节码文件对象

Class clazz = Class.forName("com.qf.reflect_06.Person") ;

2)获取类的Constructor所在的构造器对象

Constructor con = clazz.getConstructor();

3)通过它创建当前类实例

Object obj = con.newInstance();
System.out.println(obj);

在反射中如何调用成员方法

1)获取类的字节码文件对象

Class clazz = Class.forName("com.qf.reflect_06.Person") ;

2)通过无参构造器创建器Constructor创建当前类实例

如果你这个类没有提供任何构造方法(系统提供无参)或者无参构造方法是公共的---->此时可以直接使用Class类的newInstacne()创建当前类实例

Object obj = clazz.newInstance();
System.out.println(obj);

3)获取指定的成员方法所在的Method类对象

Method method = clazz.getMethod("show");//方法本身就是空参
System.out.println(method);
method.invoke(obj) ;

4)反射调用

Method m1 = clazz.getDeclaredMethod("method", String.class);
//私有方法取消Java语言检查
m1.setAccessible(true) ;
m1.invoke(obj,"hello,高圆圆") ;
//第一个参数:当前类实例
//第二个参数:给方法的形式参数赋的实际参数
//调用方法到时候将指定的方法实际参数作用在当前类实例上

通过反射调用Person类中的私有的function方法

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        //1)获取当前类的字节码文件对象
        Class clazz =  Class.forName("com.qf.reflect_01.Person") ;
        //2)无参构造方法公共的,直接创建当前类实例
        Object obj = clazz.newInstance();
        //3)通过字节码文件对象获取当前类的成员方法类对象Method
        Method method = clazz.getDeclaredMethod("function");       //System.out.println(method);
        //4)抑制Java语言访问检查
        method.setAccessible(true) ;
        //5)调用方法
        Object returnObj = method.invoke(obj);
     System.out.println(returnObj);
    }
}

通过反射获取这个类的成员变量所在的类对象Field,给成员变量赋值!

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

        //现在要通过反射获取成员变量的Field类对象并且去赋值
        //1)获取当前类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person") ;
        //2)创建当前类实例
        Object obj = clazz.newInstance() ;
        System.out.println(obj) ;
        //3)通过字节码文件对象获取成员变量的Field类对象
        //获取公共的字段(成员变量)Field类对象
        //public Field getField(String name)throws NoSuchFieldException,SecurityException
        //参数是属性名称
        //获取指定的成员变量的Field类对象
        //public Field getDeclaredField(String name)throws NoSuchFieldException,SecurityException

        //private String name ; //私有的成员变量
        Field nameField = clazz.getDeclaredField("name");
        //取消Java语言访问检查
        nameField.setAccessible(true) ;

        //给成员变量的类对象Field赋值
        //public void set(Object obj,Object value)throws IllegalArgumentException,IllegalAccessException
        //就是将指定的成员变量实际参数作用在指定实例上
        //参数1:当前类实例
        //参数2:成员变量的实际参数
        nameField.set(obj,"高圆圆") ;
        System.out.println(obj);
        System.out.println("---------------------------------------------") ;
        //给age赋值
        Field ageField = clazz.getField("age");
        ageField.set(obj,44) ;
        System.out.println(obj) ;
        System.out.println("---------------------------------------------") ;
        //给gender赋值
        Field genderField = clazz.getDeclaredField("gender");
        genderField.setAccessible(true) ;
        genderField.set(obj,"女") ;
        System.out.println(obj);
    }
}

ArrayList<Integer>通过反射给里面加入String类型的数据

public class ReflectTest {
    public static void main(String[] args)  throws Exception{
        //有一个ArrayList集合
        ArrayList<Integer> array = new ArrayList<>() ; //当前类的实例
        //泛型已经明确了数据类型
        array.add(100) ;
        array.add(10) ;
        array.add(25) ;
        array.add(55) ;
        //array.add("helloworld") ;
        System.out.println(array);
        System.out.println("-------------------------------------") ;
        //获取字节码文件对象方式 :三种
        //通过任意Java对象的getClass()获取到了当前正在运行的类字节码文件对象
        Class clazz = array.getClass() ;
        //获取当前它的add方法的Method类对象
        Method m = clazz.getMethod("add", Object.class);
       // System.out.println(m);
        //调用方法
       m.invoke(array,"helloworld") ;
        m.invoke(array,"高圆圆") ;
        System.out.println(array);
    }
}

通过修改配置文件实现不修改代码,而调用另一个类的方法

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        //原来的代码随着需求变化,可能需要用到不同类的某个的功能
        //导致代码改来改去,不灵活
        //设计原则---->"开闭原则" :对修改关闭,对扩展开放!
        // (对现有代码修改不好的,对现有带提供优化,扩展!)

        System.out.println("-------------------------------------------");
        //1)在当期类中读取src下面的xx.properties
        InputStream inputStream = ReflectDemo.class.
                getClassLoader().getResourceAsStream("classname.properties");
        //2)创建一个空的属性集合列表
        Properties prop = new Properties() ;
        //System.out.println(prop);
        //3)加载资源文件输入流的内容到属性集合列表中
        prop.load(inputStream);
        //System.out.println(prop);//{methodName=love, className=com.qf.reflect_02.Student}
        //4)通过属性集合列表中key获取value
        String className = prop.getProperty("className");
        //System.out.println(className);
        String methodName = prop.getProperty("methodName") ;
       // System.out.println(methodName);
        //反射
        //获取当前类的字节码文件对象
        Class clazz = Class.forName(className) ;
        //创建当前类实例 无参构造方法系统提供
        Object obj = clazz.newInstance() ;
        //通过字节码文件对象获取类的成员方法Method类对象
        Method method = clazz.getMethod(methodName);
        //调用方法
        method.invoke(obj) ;
    }
}

代理设计模式

静态代理

代理角色和真实角色需要实现同一个接

动态代理

jdk动态代理

里面需要前提有一个接口

java.lang.reflect.Proxy提供了创建动态代理类和实例的静态方法                    
public static Object newProxyInstance(                                 
ClassLoader loader,        //参数1:当前接口对象的类加载器                                    Class<?>[] interfaces,    //参数2:代理实现接口列表字节码文件对象的数组
InvocationHandler h  //参数3:代理实例 调用处理程序实现的接口
) throws IllegalArgumentException

数据库的事务

在一个业务中执行多个sql(多张表的sql),这个sql语句要么同时执行成功,要么同时执行失败

mysql管理事务

start transaction:开启事务--在操作多个sql语句之前,将整个操作业务管理起来,自动提交切换手动提交事务

执行业务操作:多个sql语句或多张表的增删改,

如果出现问题,可以回滚--rollback

事务特点ACID(关系型数据库传统事务)

原子性,一致性,隔离性,持久性

原子性:在事务管理的时候,执行多个sqk增删改,要么同时成功,要么同时失败

一致性:高并发的时候,需要保证事务多次读写,保证数据一致性

隔离性:事务和事务是独立的,相互不影响

持久性:事务一旦提交,对数据的影响是永久性的,即使关机,数据还是要更改

事务隔离的级别

read uncommitted:读未提交

read committed:读已提交

repeatable read:可重复读

serializable:串行话

  1. 第一种级别read uncommitted:读未提交,会造成“脏读”,脏读是事务管理的最严重的问题:一个事务读取到,另一个没有提交的数据

  2. 第二种级别read committed:读已提交,为了防止脏读,出现一个问题“不可重复读”,事务多次读取的事务不一致

  3. mysql的默认级别 repeatable read 可重复读,有效脏读,不可重复读,出现幻读!(一般有更新操作影响了数据)

  4. 最高级别:serializable:串行话 (一个事务读取到另一个没提交事务,数据查不到的,这个必须提交,才能操作数据!)

JDBC

连接数据库七大步骤

  • 1)导包驱动包

  • 2)注册驱动--加载驱动类

  • 3)获取数据库的连接对象java.sql.Connection

  • 4)准备sql语句

  • 5)通过Connection连接对象获取数据库的执行对象

  • 6)执行sql语句

  • 7)释放资源

public class JdbcDemo {
    public static void main(String[] args) throws Exception {
        //Jdbc的操作:java连接数据库
        //1)导入驱动jar包
        //2)注册驱动---加载驱动类Class.forName("com.mysql.jdbc.Driver") ; //mysql5.5或者5.1的jar包:都是这个全限定名称                                   //mysql8.0jar包: com.mysql.cj.jdbc.Driver
        //3)获取数据库连接对象
        //DriverManager驱动管理类--->
        //public static Connection getConnection(String url, 连接库地址  (统一资源定位符)
        //                        String user, mysql的用户名  root用户
        //                        String password) 登录MySQL的密码
        //                       throws SQLException
​
        //url--->组成: 协议名称 ://域名:端口号/具体的路径
        /*
        * mysql的驱动jar包如果是8.0以后:url的后面           编码格式         是否启用证书登录     服务器时区         是否公钥模式
        * jdbc:mysql://localhost:3306/ee_2211_02?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
        * */
​
        //  jdbc:mysql://localhost:3306/库名
        Connection conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/ee_2211_02",
                "root",
                "123456"
        );
​
        //4)准备sql语句
        String sql = "insert into account (name,balance) values('高圆圆',1000)" ;
​
        //5)通过数据库连接对象Connection获取数据库的执行对象
        //执行静态sql语句
        //Statement createStatement()throws SQLException创建一个Statement对象,用于将SQL语句发送到数据库
        Statement stmt = conn.createStatement();
​
        //6)执行sql语句
        //Statement--->
        //int executeUpdate(String sql)throws SQLException 通用的更新操作
        int count = stmt.executeUpdate(sql);
        System.out.println("影响了"+count+"行");
​
        //7)释放资源
        stmt.close();
        conn.close();
​
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值