一、服务器端优化
服务端优化:
第一个弊端:
服务器只能处理一个客户端请求,接收完一个图片之后,服务器就关闭了。
改进方式:
循环
第二个弊端:
第二次上传文件的时候,会把第一次的文件给覆盖
改进方式:
UUID. randomUUID()方法生成随机的文件名
加入循环以后又引发了一个问题:
使用循环虽然可以让服务器处理多个客户端请求。但是还是无法同时跟多个客户端进行通信。
改进方式:
开启多线程处理
加入多线程以后又引发了一个问题:
使用多线程虽然可以让服务器同时处理多个客户端请求。但是资源消耗太大。
改进方式:
加入线程池
日志概述:日志技术
弊端:
什么是日志:
日志与输出语句的区别:
日志技术的特点:
日志体系结构:
体系结构
Logback
Logback介绍
Logback主要分为三个技术模块:
Logback快速入门:
package com.log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Scanner;
public class LogDemo {
//获取日志对象
private static final Logger LOGGER = LoggerFactory.getLogger(LogDemo.class);
public static void main(String[] args) {
//打日志 --- 类似于写输出语句
Scanner sc = new Scanner(System.in);
System.out.println("请输入您的姓名");
LOGGER.debug("用户开始输入信息了");
String name = sc.nextLine();
//System.out.println(name);
LOGGER.info("用户输出录入姓名为:" + name);
System.out.println("请输入您的年龄");
String age = sc.nextLine();
try {
int ageInt = Integer.parseInt(age);
LOGGER.info("用户输入的年龄格式正确" + age);
} catch (NumberFormatException e) {
LOGGER.info("用户输入的年龄格式错误" + age);
}
}
}
请输入您的姓名
22:56:27.942 [main] DEBUG com.log.LogDemo - 用户开始输入信息了
薛鸿金
22:57:24.675 [main] INFO com.log.LogDemo - 用户输出录入姓名为:薛鸿金
请输入您的年龄
23
22:57:27.227 [main] INFO com.log.LogDemo - 用户输入的年龄格式正确23
Process finished with exit code 0
日志的6种级别:
![]()
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--
CONSOLE :表示当前的日志信息是可以输出到控制台的。
-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--输出流对象 默认 System.out 改为 System.err-->
<target>System.out</target>
<encoder>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度
%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %c [%thread] : %msg%n</pattern>
</encoder>
</appender>
<!-- File是输出的方向通向文件的 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!--日志输出路径-->
<file>C:/code/itheima-data.log</file>
<!--指定日志文件拆分和压缩规则-->
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--通过指定压缩文件名称,来确定分割文件方式-->
<fileNamePattern>C:/code/itheima-data2-%d{yyyy-MMdd}.log%i.gz</fileNamePattern>
<!--文件拆分大小-->
<maxFileSize>1MB</maxFileSize>
</rollingPolicy>
</appender>
<!--
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
, 默认debug
<root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
-->
<root level="DEBUG"><!--表示日志级别-->
<appender-ref ref="CONSOLE"/><!--表示当前文件只能再控制台打印-->
<appender-ref ref="FILE" /><!--保存到文件当中-->
</root>
</configuration>
主要对日志做什么:修改日志级别,修改输出位置,
三、枚举
为什么有枚举
枚举
数据类型
基本数据类型 引用数据类型(枚举也是引用数据类型)
枚举:当我们描述的事物,有固定的几种形式出现的时候,可以采用枚举的方式描述
季节{
春
夏
}
package com.myenum.demo1;
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER;
}
package com.myenum.demo2;
public class EnumDemo {
public static void main(String[] args) {
/*
1.所有枚举类都是Enum的子类
2.我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
3.每一个枚举项其实就是该枚举的一个对象
4.枚举也是一个类,也可以去定义成员变量
5.枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,
但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
6.枚举类可以有构造器,但必须是private的,它默认的也是private的。
枚举项的用法比较特殊:枚举("");
7.枚举类也可以有抽象方法,但是枚举项必须重写该方法
*/
//第二个特点的演示
//我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
System.out.println(Season.SPRING);//枚举类名.枚举项名称
System.out.println(Season.SUMMER);
System.out.println(Season.AUTUMN);
System.out.println(Season.WINTER);
//第三个特点的演示
//每一个枚举项其实就是该枚举的一个对象
Season spring = Season.SPRING;
}
}
特点:
枚举的方法:
package com.myenum.demo3;
public class EnumDemo {
public static void main(String[] args) {
// String name() 获取枚举项的名称
String name = Season.SPRING.name();
System.out.println(name);
System.out.println("-----------------------------");
// int ordinal() 返回枚举项在枚举类中的索引值
int index1 = Season.SPRING.ordinal();
int index2 = Season.SUMMER.ordinal();
int index3 = Season.AUTUMN.ordinal();
int index4 = Season.WINTER.ordinal();
System.out.println(index1);
System.out.println(index2);
System.out.println(index3);
System.out.println(index4);
System.out.println("-----------------------------");
// int compareTo(E o) 比较两个枚举项,返回的是索引值的差值
int result = Season.SPRING.compareTo(Season.WINTER);
System.out.println(result);//-3
System.out.println("-----------------------------");
// String toString() 返回枚举常量的名称
String s = Season.SPRING.toString();
System.out.println(s);
System.out.println("-----------------------------");
// static <T> T valueOf(Class<T> type,String name)
// 获取指定枚举类中的指定名称的枚举值
Season spring = Enum.valueOf(Season.class, "SPRING");
System.out.println(spring);
System.out.println(Season.SPRING == spring);
System.out.println("-----------------------------");
// values() 获得所有的枚举项
Season[] values = Season.values();
for (Season value : values) {
System.out.println(value);
}
}
}
字符流+缓冲流 properties
字符缓冲流输入流和字符输入流的对比:
properties集合的特有特点:
字符流+缓冲流 --文件复制
经典案例:
使用字节流+数组完成文件复制
对比缓冲流+数组完成文件复制
的性能
单例模式:饿汗式懒汉式
测试: