- 博客(106)
- 收藏
- 关注
原创 JavaWeb学习——Maven测试和打包运行
比如Maven项目有两个子项目child1和child2,想要让child1被child2引用,可以在child2的配置问家中加上:验证:①在Child1项目里创建一个Student类:int sid;②在Child2里写:(不需要import)
2026-04-30 03:00:00
319
原创 JavaWeb学习——Maven可选/排除依赖和继承关系
当项目中的某些依赖不希望被使用此项目作为依赖的项目使用时,我们可以给依赖添加optional标签表示此依赖是可选的,默认在导入依赖时,不会导入可选的依赖:此外,如果<scope>的作用域是test的时候就不会有。
2026-04-30 02:30:00
292
原创 JavaWeb学习——Properties配置文件(JUL)
之前学习过XML也是一种配置文件,但是读取过于麻烦。Properties也是Java的一种配置文件,格式为配置项=配置值。①创建一个test.properties文件;name=Test②主函数使用Properties进行读取并使用load写入文件的输入流:③读取某个配置项的值:或④读取某个配置项的值否则返回默认⑤插入注意插入的时候键或值不能为null⑥将配置信息输入到控制台:store⑦获取系统的参数。
2026-04-30 01:00:00
359
原创 JavaWeb学习——使用Maven管理项目
它相当于是我们整个Maven项目的配置文件,它也是使用XML编写的:</project>Maven的配置文件是以project为根节点,定义了当前模型的版本。
2026-04-30 01:00:00
379
原创 JavaWeb学习——JUnit和日志
在很多情况下项目可能会很庞大,不可能每次都去完整地启动一个项目来测试某一个功能,这样显然会降低我们的开发效率,因此,我们需要使用单元测试来帮助我们针对于某个功能或是某个模块单独运行代码进行测试,而不是启动整个项目。同时,在我们项目的维护过程中,难免会涉及到一些原有代码的修改,很有可能牵一发而动全身),而我们又不一定能立即察觉到,因此,我们可以提前保存一些测试用例,每次完成代码后都可以跑一遍测试用例,来确保之前的功能没有因为后续的修改而出现问题。
2026-04-30 00:00:00
379
原创 JavaWeb学习——缓存机制
之前在IO流里面学过缓存的buffer,可以提高效率,速度更快。比如我们在数据库里面查询数据后,将其缓存,下次查询时如果缓存中有就不用再和数据库请求了。Mybatis有一级缓存和二级缓存,默认一级缓存是打开的。每一个会话都有一级缓存。比如在主函数里:DML(比如插入数据)或会话结束都会使得对应的一级缓存失效。不同的SqlSession之间互不影响。所以一个会话DML操作只会重置当前会话的缓存,不会重置其他会话的缓存,也就是说,其他会话缓存是不会更新的!
2026-04-27 05:00:00
15
原创 JavaWeb学习——复杂查询和事务
比如有一个教师类,教师有id,name,和教的学生列表。sql语句是:select *,teacher.name as tname from student inner join teach on student.sid = teach.sid inner join teacher on teacher.tid = teach.tid where teach.tid = #{tid};①首先创建一个Teacher类:@Dataint tid;
2026-04-27 04:00:00
141
原创 JavaWeb学习——使用注解开发(Mybatis)
之前说到使用xml进行映射器的编写,需要先在XML中定义映射规则和SQL语句,然后再将其绑定到一个接口的方法定义上,然后再使用接口来执行:而现在,我们可以直接使用注解来实现。①每个操作都有一个对应的注解:②Mybatis-config.xml配置文件中(下面两种都可以)③主函数:之前要查询教师信息,且教师有教的学生列表,现在用注解进行查询。在接口里要使用Result进行规则的映射,且要使用@Many进行一对多的映射(单独定义getStudentByTid语句更清晰)主函数:①在接口函数里:②主函数:之前如果
2026-04-27 04:00:00
121
原创 JavaWeb学习——Lombok
没有Lombok时,我们添加getter、setter、构造器、toString方法点击右键后,选择点击::当我们添加或者删除其中的私有成员变量的时候,这些生成的setter和getter和构造函数不能够自适应的添加或删除。:我们你要使用lombok插件来解决这个问题比如在Student类:@Setter@GetterString sex;然后在主文件中直接用:Student student = new Student(1,"a","女");.getAge()
2026-04-27 02:30:00
305
原创 JavaWeb学习——Mybatis增删改查操作
之前说可以定义一个TestMapper接口来实现返回对象的方法,并且可以设置返回的实体对象是Student,那么如果不希望返回的数据是实体类,可以映射成一个Map:TestMapperMap"></select>其次,我们Study数据库的Student表里面的列分别是"sid""name""sex",而在Student实体类里面设置的属性也是这三个,所以默认情况下会一一对应其返回值。但是当Student类里面是xxx时就会返回数据出错:intxxx;String sex;
2026-04-27 02:30:00
307
原创 JavaWeb学习——JDBC
Java 连接数据库的标准 API,让 Java 代码能执行 SQL、操作 MySQL 的一套接口。演示一下://DriverManger获取数据库连接try(Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/study","root","密码");//创建一个执行SQL的statement对象){//执行SQL语句//查看结果//一列一列的去遍历,这里取第一列。
2026-04-27 01:00:00
367
原创 JavaWeb学习——使用Socket进行数据传输,文件传输,浏览器访问
首先在IDE的src文件夹下创建两个类:客户端向服务端发送数据,需要客户端创建套接字并传入IP地址和端口号,然后创建输出流读取用户输入数据,发送给服务端。服务端需要创建服务端的套接字并传入端口号,然后用套接字去接收,最后使用输入流进行读取。客户端:try(){System.out.println("已连接到服务器");System.out.println("服务端连接失败");服务端:try() {
2026-04-27 00:00:00
366
原创 JavaSE学习——定时器,守护线程和并行流
当我们希望某个任务3秒之后执行,可以使用定时器功能。首先创建一个Timer定时器,然后调用一个schedule方法,并传入参数:延迟的任务和延迟的时间:@OverrideSystem.out.println("我是延迟任务");},3000);可以看到这个任务一直没有结束,是因为这个定时器需要等所有的非守护线程全部结束之后擦能结束。比如现在我们希望这个任务3秒之后执行,并且能够每间隔一秒钟执行一次:@OverrideSystem.out.println("我是延迟任务");
2026-04-20 03:45:00
121
原创 JavaSE学习——生产者和消费者实战
System.out.println(new Date()+name+"出餐了");new Thread(Main::take,"消费者1").start();new Thread(Main::take,"消费者2").start();new Thread(Main::take,"消费者2").start();new Thread(Main::add,"厨师1").start();new Thread(Main::add,"厨师2").start();
2026-04-20 03:45:00
30
原创 JavaSE学习——ThreadLocal的使用
ThreadLocal 让每个线程都拥有自己独立的变量副本,线程之间互不干扰、不共享,从而彻底避免线程安全问题。
2026-04-20 03:00:00
326
原创 JavaSE学习——wait和notify方法
wait和sleep不同的是,sleep是线程Thread的一个方法,而wait属于对象方法且会使得当前持有锁的线程释放锁并进入等待状态。notify的作用是随机唤醒一个正在等待的线程(注意唤醒之后的线程不是直接运行,而是还需要重新抢占资源/锁才可以继续运行)Object对象还有三个方法,分别是wait/notify/notifyAll,它们是用来让线程之间相互通信、协作的:一个线程等着,另一个线程通知它可以继续跑了。System.out.println("线程1:我被唤醒了");// 等待 + 释放锁。
2026-04-20 02:00:00
21
原创 JavaSE学习——死锁
System.out.println("线程1持有B");System.out.println("线程2持有A");经典死锁代码示例:(线程1拿着A锁但是想要B锁;线程2拿着B锁但是想要A锁)System.out.println("线程1持有A");System.out.println("线程2持有B");System.out.println("线程1正常结束");System.out.println("线程2正常结束");// 线程1:先拿A,再拿B。// 线程2:先拿B,再拿A。
2026-04-20 00:30:00
20
原创 JavaSE学习——线程锁和线程同步
之前的有一个代码如下,两个代码同时去进行value的自增,最后输出的结果不是20000。而是永远都小于20000:i < 10000;System.out.println("线程1完成");});i < 10000;System.out.println("线程2完成");});t1.start();t2.start();// 主线程停止1秒,保证两个线程执行完成究其原因,是因为value++ 不是原子操作,多线程同时修改,出现了数据覆盖,所以结果 < 20000。
2026-04-20 00:15:00
294
原创 JavaSE学习——线程的优先级和礼让/加入
Java的每个线程不是平均分配CPU时间的,为了使得资源分配更加合理。优先级越高的线程优先使用CPU资源,一般优先级分为:MIN_PRIORITY;NOM_PRIORITY分别表示最低/最高/常规优先级。注意:优先级高 = 被 CPU 执行的概率更大不是一定先跑!优先级 高 更容易抢到 CPU,但这只是概率问题,不是绝对顺序。最终执行顺序 → 操作系统说了算。下面的代码大概率线程 1 先输出更多:i < 10;i++)System.out.println("线程1");});i < 10;
2026-04-20 00:00:00
367
原创 JavaSE学习——线程的睡眠和中断
之前我们使用sleep方法来设置线程睡眠的时间,其实它还有一个作用,就是响应中断,比如代码正处于睡眠中,那么这时候中断标志是true会使得sleep方法立刻抛出 InterruptedException!.isInterrupted())检查是否被中断,如果被中断,就响应break的内容。中断信号是柔性的,只是发出一个标志,至于是否立刻中断/不响应都可以,不强制执行。t.interrupt()把线程的中断标志位改成 true。System.out.println("线程被中断了");
2026-04-18 04:00:00
21
原创 JavaSE学习——多线程
getState里面的状态是一个枚举类,里面有NEW, RUNNABLE(运行或等待资源), BLOCKED(阻塞),WAITING,TIMED_WAITING,TERMINAL是终端结束的意思。还有一个方法是run,它和start的区别是,run相当于在main方法里面去运行(在当前线程去执行),而不是创建一个线程,比如;System.out.println("线程"+Thread.currentThread().getName());System.out.println("线程1完成");
2026-04-18 03:45:00
518
原创 JavaSE学习——字节数组流和输入流快捷操作
字节数组流:不以文件、不以网络为数据源,而以「内存中的字节数组」为数据源的流。特点:不调用底层操作系统资源不操作文件、不打开管道、不建立网络→ 不需要 close ()!关不关都行在内存中读写速度极快属于字节流、节点流(不是装饰流)ByteArrayInputArray作用:把一个 byte [] 变成 InputStream 来读byte[] bytes = "lhw哈哈哈哈".getBytes();){
2026-04-18 02:00:00
284
原创 JavaSE学习——打印流
System.out.printf("这是整数%d;这是浮点数%.3f;这是字符%c", 2, "lhw", 1.314520, 'h');打印流的作用就相当于将字符串放到文件里,中间经过了字符串->字符->字节的过程,即PrintStream转换成了一种FileOutputStream。最后介绍一下Scanner,他的作用是读取参数里的信息。%d相当于表示一个整数,2去填充。
2026-04-18 01:30:00
43
原创 JavaSE学习——转换流
上面的代码相当于使用OutputStreamWriter将FileOutputStream(字节流)进行包裹,这样得到的stream对象就可以使用Writer的一系列方法。之前我们学过字符流(InputStream和OutputStream)和字节流(常用Reader和Writer),但是它们二者一个只能是读取byte单位,一个只能是char单位。为什么需要转换流:如果用字节流读取只能用字符流输出的时候就需要转换,很麻烦。但是上面的代码还不够方便,最好是使用Buffer再包裹一层,这样可以直接读取一行。
2026-04-18 01:15:00
40
原创 JavaSE学习——缓冲流
IO读取比内存慢很多,为了效率高一些,在内存里提供一个缓冲区,这样首先将文件的输入流存入Buffer里,然后程序直接从Buffer里读取,程序的输出也直接放到内存的Buffer里,然后再以输出流到文件里。再来看mark里面调用的参数,参数其实是readlimit,代代表mark函数之后还能读取的最大次数,需要比buffer大,如果小于buffer自动按照buffer计算(默认8000多)// 缓冲区空了 → 去底层(比如文件/网络)重新读一批数据进缓冲区。// pos++:读取后,指针向后移动一位。
2026-04-18 01:00:00
343
原创 JavaSE学习——I/O
为什么会有I/O?读取硬盘的文件,网络文件传输,鼠标键盘的输入,都是I/O设备。在程序中,如果想要读取外部链接的I/O设备的内容,就需要将数据传输到内存中。这个过程凭借程序是无法做到的,操作系统的交互可以,它能够控制和管理计算机硬件/软件资源。从读取硬盘文件的角度,不同操作系统有不同的文件系统(即文件在硬盘中的存储排列方式),硬盘只能存储0/1二进制数据。
2026-04-11 02:00:00
118
原创 JavaSE学习——Files工具类
filter(Files::isRegularFile) //filter过滤判断是否为普通文件。}).forEach(path -> { //find的结果会以Stream的形式返回。//创建新的文件输入流。Files.walk(Path.of(".")) //返回Stream<Path>(path, Path.of("another"));//文件是否为隐藏文件。
2026-04-11 02:00:00
128
原创 JavaSE学习——有序集合功能规范
按理来说,不应该会出现这样的情况,因为我们只是在reverse列表上添加元素,为什么原本的list还会发生变化,就是因为”视图“其实就是在原本的上面发生变化,然后取反。现在就可以直接调用一个addFirst方法。删除操作也可以removeFirst。(底层是通过迭代器做的)
2026-04-11 01:30:00
13
原创 JavaSE学习——StreamAPI
发现对于元素1、3、5只执行了前两个步骤,这是因为当return是false的时候后面的步骤就不会执行了。从上面可以看出,流水线的一个好处是,当不满足条件的时候是逐一进行丢弃,而不是整体处理,所以内存就会进行节省开销。之前的工厂方法相当于是一种分两步的整体操作,而Stream是一种将整体的每一个元素进行两部操作最后汇合而成。上面的代码就是使用forEach方法进行触发的,如果不使用就不会有任何的效果。//希望变成["l","h","h","x","l","5"]
2026-04-11 01:30:00
286
原创 JavaSE学习——流聚集器
之前说的Stream流进行元素的逐个处理,中间不会保留任何的状态,元素之间互不影响。下面开始使用流聚集器去实现这样的一个效果:(gather相当于就让字符串先存起来然后等下一个字符串进来,刚好到达窗口长度2就可以交付下游打印)由此可见,windowFixed实现了对元素的有状态操作,它不断接收到来的元素并将其暂存,达到窗口的大小之后作为一种新的元素整体打包返回。上面的代码中,()->""相当于给与了cur一个初始值“”,item代表当前得到的流元素,cur会不断的被cur + item更新。
2026-04-11 01:30:00
323
原创 JavaSE学习——比较相关接口
Arrays可以调用sort方法,前提是这个数组类型实现了comparable方法。此外,如果在Student类并没有实现Comparable方法,也可以在调用Arrays.sort()的时候使用lambda表达式去添加。naturalOrder表示默认的比较(从小到大)Comparator是类外面手动定义的一个比较规则,Comparable是类内部自行定义的衣服比较规则。此外,可以单独写一行定义comparator,这样就直接传入:(reversed是在原来的基础上取反)有了比较的方法,就可以进行排序;
2026-04-11 01:00:00
340
原创 JavaSE学习——Map映射的底层代码
HashMap支持自动扩容,哈希表的大小不是一成不变的;HashMap不仅仅使用的是简单的链表地址,当链表的长度达到一定的限制会转变为效率更高的红黑树。
2026-04-11 00:15:00
319
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅