意思是:Write Once *.java(源文件), Run Anywhere on JVM(Java Virtual Machine)!!!
所以我们的The Operating System 必须Config jre(Java Run Environment):jre=常用类库+JVM
我们在大学期间第一次接触Java时,第一步就是下载JDK,(Java development kit | Java程序的开发工具)JDK其实有很多厂商,如Oracle JDK ,Oracle OpenJDK,IBM OpenJDK等等,JDK就是包含Java开发环境jre以及一些Java开发工具:javac.exe,java.exe
PATH:我们希望在操作系统的任何目录下都运行java程序
环境变量 | Why | Function | So |
---|---|---|---|
PATH | 因为Java的编译器和解释器都在JDK的lib目录下 | path环境变量在Operating System中function是在执行命令时要搜索的路径,在DOS命令行下面执行命令如javac Hello.java编译程序时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序 | So我们需要把jdk安装目录下的bin目录增加到现有的PATH变量中,bin目录中包含经常要用到的可执行文件如javac/java/javadoc等,设置好PATH变量后,就可以在任何目录下执行javac/java等工具了 |
CLASSPATH | 因为JDK的jre文件夹中包含着Java类库,这些类库被包含在jre\lib下 | 作用是指定类搜索路径,要使用已经编写好的类,前提当然是能够找到它们了,JVM就是通过CLASSPTH来寻找类的 | So我们需要把jdk安装目录下的lib子目录中的dt.jar和tools.jar设置到CLASSPATH中 |
JAVA_HOME | 它指向jdk的安装目录,Eclipse/NetBeans/Tomcat等软件就是通过搜索JAVA_HOME变量来找到并使用安装好的jdk | 有点像全局变量 |
JDK环境变量配置
1.配置环境变量
注意:不是W10:变量值之间用";"隔开。
注意:原来Path的变量值末尾有没有;号,如果没有,先输入;号再输入。
public class ThrowableTest {
@Test
public void testOutOfMemoryError(){
Object[] objects = new Object[Integer.MAX_VALUE];
System.out.println(objects.length);
}
}
StackOverflowError
就是自己调用自己
@Test
public void testStackOverflowError(){
testStackOverflowError();
}
@Test
public void testRuntimeException(){
int[] ints = new int[5];
System.out.println(ints[6]);//ArrayIndexOutOfBoundsException数组下标越界
String str =null;
System.out.println(str.length());//NullPointerException空指针
//ClassCastException类型转换异常
//ArithmeticException(算术异常)
}
JDK=JRE+开发工具
JRE=常用类库+JVM
启动类
1)根类加载器(bootstrap class loader):
它用来加载 Java 的核心类,是用原生代码来实现的,并不继承自 java.lang.ClassLoader(负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
2)扩展类加载器(extensions class loader):
它负责加载JRE的扩展目录,lib/ext或者由java.ext.dirs系统属性指定的目录中的JAR包的类。由Java语言实现,父类加载器为null。
3)系统类加载器(system class loader):
被称为系统(也称为应用)类加载器,它负责在JVM启动时加载来自Java命令的-classpath选项、java.class.path系统属性,或者CLASSPATH换将变量所指定的JAR包和类路径。程序可以通过ClassLoader的静态方法getSystemClassLoader()来获取系统类加载器。如果没有特别指定,则用户自定义的类加载器都以此类加载器作为父加载器。由Java语言实现,父类加载器为ExtClassLoader。
Name | 线程私有/共享 | 设置参数 | Function |
---|---|---|---|
程序计数器(PC Registers) | 私有 | 固定大小 | 保存当前线程执行的方法 |
本地方法栈(Native Method Stack) | 私有 | 固定大小 | JNI调取本地方法 |
方法区(Method Area) | 共享 | -XX | static,class类结构,常量(池) |
堆(Heap) | 共享 | -Xms:初始堆值;-Xmx:最大堆值 | new出来的实例对象和数组 |
JVM栈(JVM Stack) | 私有 | -Xss | (每个线程)方法的栈帧、局部变量表、操作数栈 |
1:Java语言中的类、方法、变量、参数和包等都可以注解标记,程序运行期间我们可以获取到相应的注解以及注解中定义的内容,这样可以帮助我们做一些事情。
2:比如说Spring中如果检测到说你的类被@Component注解标记的话,Spring容器在启动的时候就会把这个类归为自己管理,这样我们就可以通过@Autowired注解注入这个对象了。
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的功能就叫“反射机制”
1:在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但是不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关。
2:例如模块化的开发,通过反射去调用对应的字节码;
3:动态代理设计模式也采用了反射机制
4:还有我们日常使用的Spring/Hibernate等框架也大量使用到了反射机制。
5:我们在使用JDBC连接数据库使用的Class.forName()就是通过反射加载数据库的驱动程序
6:Spring框架的IOC(动态加载管理Bean)创建对象,以及AOP(动态代理)功能都和反射有联系;
7:动态配置实例的属性
1:JDK动态代理:只能代理实现了接口的类,而CGLIB可以代理未实现任何接口的类,
2:CGLIB动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为final类型的类和方法。
3:两者的效率来说,大部分情况是JDK动态代理更优秀,随着JDK版本的升级,这个优势会更加明显。
@Test
public void addTest(){
int i=1;
i=i++;//i=1
int j=i++;//j=1;i=2
int k=i+ ++i*i++;//2+3*3;i=4
System.out.println("i="+i);
System.out.println("j="+j);
System.out.println("k="+k);
}
-StringBuiler线程不安全
StringBuffer线程安全
HashMap | HashTable | ConcurrentHashMap |
---|---|---|
HashMap是可以把null作为key或者value的 | 而HashTable是不可以 | |
线程不安全 | 线程安全 | 安全 |
效率低 | 效率高 | 效率高 |
我们拷贝的文件不确定只包含字符流,比如音频和图片,所以通用字节流
ByteArrayInputStream:字节数组输入流,该类的功能就是从字节数组(byte[])中进行以字节为单位的读取,也就是将资源文件都以字节的形式存入到该类中的字节数组中去,我们拿也是从这个字节数组中拿
指多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
如下图所示,线程A持有资源2,线程B持有资源1,这时候两个同时想要申请对方的资源,所以这两个线程就会相互等待进入死锁状态。
1.New:初始状态,线程被创建,没有调用start()
2. Runnable:运行状态,Java线程把操作系统中的就绪和运行两种状态统一称为“运行中”。调用start()后就会执行run()
3. Blocked:阻塞,线程进入等待状态,线程因为某种原因,放弃了CPU的使用权
Blocked | 阻塞 |
---|---|
等待阻塞 | 运行的线程执行了wait(),JVM会把当前线程放入等待队列 |
同步阻塞 | 运行的线程在获取对象的同步锁时,如果该同步锁被其他线程占用了,JVM会把当前线程放入锁池中 |
其他阻塞 | 运行的线程执行sleep(),join()或者发出IO请求时,JVM会把当前线程设置为阻塞状态,当sleep()执行完,join()线程终止,IO处理完毕线程再次恢复 |
线程的六种状态之间的转换:
六种状态 | 转换 |
---|---|
1 | 当实例化一个线程之后,首先进入初始状态,即New状态,此时线程在启动的时候并不是立刻就运行,而是要等到操作系统调度之后才运行, |
2 | 然后调用start()进入运行状态,即runnable,其中运行状态中包括运行(running)和就绪(ready)两种状态,这两种状态在操作系统的调度下可以互相转换,如果运行中的线程时间片被CPU抢占的话就会变成就绪状态; |
3 | 运行中的线程通过调用synchronized方法或synchronized块进入阻塞状态,即blocked,当线程获取到锁之后进入运行状态; |
4 | 如果线程在执行过程中调用了sleep(),wait().join(),Locksupported.parkUtil()等方法时,会进入等待状态(waiting) |
5 | 或超时等待状态,即timed_waiting, |
2 | 再次调用notify(),notifyAll(),Locksupported.unpark()等方法时,又会重新进入运行时状态, |
4 | 当线程执行完成时,就进入了终止状态,即terminated状态。 |
注:Locksupported是JDK 1.6提供的一个工具类,在java.util.concurrent包中,它所提供的park,unpark方法比wait,notify方法的灵活性更高。
- | - |
---|---|
通过继承Thread类实现一个线程 | 通过实现Runnable接口实现一个线程 |
继承扩展性不强,类只能继承一个类 | |
怎么启动 | Thread thread=new Thread(继承了Thread的对象/实现了Runnable的对象) |
thread.start(); | 启动线程使用start方法,而启动了以后执行的是run方法。 |
怎么区分线程? | 在一个系统中有很多线程,每个线程都会打印日志,我想区分是哪个线程打印的怎么办? |
thread.setName(“设置一个线程名称”) | 这也是一种工作规范,在创建线程完成后,都需要设置名称 |
JDK5 | java通过Executor提供四个静态方法创建四种线程池 |
---|---|
Executors.newFixedThreadPool(5) | 固定5个处理线程 |
Executors.newSingleThreadPool() | 一个线程的线程池 |
Executors.newCacheThreadPool() | 自动扩容的线程池 |
Executors.newScheduledThreadPool(5) | 一个定长的线程池,支持定时及周期性任务执行 |
new ThreadPoolExecutor
作用 | |
---|---|
限制线程的个数,不会导致由于线程过多,导致系统运行缓慢或崩溃 | |
线程池不需要每次都去创建和销毁,节省创建和响应的开销 | |
响应时间也就更快 |
连接池也一样!
参数 | ThreadPoolExecutor |
---|---|
int corePoolSize | 核心线程数 |
int maximumPoolSize | 最大线程数 |
long keepAliveTime | 非core线程的存活时间 |
TimeUnit unit | 时间单位 |
BlockingQueue |
(候客区)阻塞队列 |
ThreadFactory | 线程工厂 |
RejectedExecutionHandler | 拒绝策略 |
设计模式就是经过无数前人无数次的实践,总结出的。设计过程中可以反复使用的一种策略模板。
常用的设计模式 | - | - |
---|---|---|
单例模式 | 饿汉式 | 1:构建方法私有化(只能自己创建,其他地方都不能创建)。2:在自己的类中创建一个单实例。3:提供一个方法获取该实例的对象 |
- | 饱汉式 | |
工厂模式 | SpringIOC就是一个工厂模式。对象的创建交给一个工厂来创建 | |
代理模式 | SpringAOP动态代理 |
Server Applet | Java编写的服务器端程序 | 这些servlet都要实现Servlet这个接口 |
---|---|---|
主要功能 | 在于交互式地浏览和修改数据,生成动态Web内容。 | Servlet运行于支持Java的应用服务器中 |
HTTPServlet重写doGet和doPost方法 | 或者自己重写service方法 | 完成对get和post请求的响应 |
加载servlet的class | Servlet启动时,开始加载servlet生命周期 |
---|---|
实例化servlet | Servlet被实例化后,容器运行其**init( )**方法 |
init( ) | 完成初始化 |
请求到达时运行service( ) | service方法自动派遣运行与请求对应的doXXX方法(doGet、doPost) |
服务器关闭时destory( ) |
Servlet | JSP |
---|---|
Server Applet服务应用 | Java Server Pages服务器页面 |
JSP是Servlet技术的扩展 | 所有的jsp文件都会被翻译为一个继承HttpServlet的类。 |
JSP最终是一个Servlet | 这个Servlet对外提供服务 |
Servlet从Html表示层分离出来 | 而JSP是Java和Html可以组合成一个扩展名为.jsp的文件 |
PrintWriter writer=response.writer(); writer.print("<html>") | <% java语言%> |
侧重控制逻辑 | 侧重视图 |
JSP | Java Server Pages |
---|---|
request | 用户端请求,包含GET/POST请求参数 |
response | 网页传回用户端的响应 |
pageContext | 网页属性都在这里管理 |
session | 与请求有关的会话 |
application | servlet正在执行的内容 |
out | 用来传送回应的输出 |
config | servlet的构架部件 |
page | JSP网页本身 |
exception | 针对错误页面,未捕捉的例外 |
JSP四大作用域 | 作用范围 |
---|---|
pageContext | 一个页面内 |
request | 一次请求 |
session | 一次会话 |
application | 一次应用服务 |
可用通过jstl从四大作用域中取值
JSP传递值request、session、application、cookie也能传值
范式就是规范 | 要想满足第二范式就要满足第一范式 | 要想满足第三范式就要先满足第二范式 |
---|---|---|
1NF | 数据库表中的每一列都是不可分割的基本数据项,不能有重复的属性 | 列数据不可分割 |
2NF | 要求每一行必须可以被唯一地区分(主键) | 允许冗余 |
3NF | 不能包含其他表中已经包含的非主键信息(可用外键引用进来) | 不允许冗余 |
反3范式 | 为了查询效率,可以设置重复或者可以推导出的字段 | 比如订单(总价)和订单项(单价),每添加一个单价,就修改总价 |
并发控制的单位,是用户定义的一个操作序列,是不可分割的工作单位。比如转账。
ACID | - |
---|---|
原子性 | 表示事务内操作不可分割。要么都成功,要么都失败 |
隔离性 | 一个事务开始后,不能受其他事务干扰 |
持久性 | 表示事务开始后,就不能终止? |
一致性 | 要么都成功,要么都失败。失败了要回滚! |
事务 | 并发问题 |
---|---|
脏读 | 事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据 |
不可重复读 | 事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。 |
幻读 | 系统管理员A将数据库中所有学生的成绩从具体分数更新为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。 |
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommitted) | √ | √ | √ |
读已提交(read-committed) | × | √ | √ |
可重复读(repeatable-read) | × | × | √ |
串行化(serializable) | × | × | × |
MyISAM | InnoDB |
---|---|
不支持事务 | 支持事务 |
不支持外键 | 有外键 |
表锁 | 行锁 |
二叉树,随着我们的数据的增大的话,树的高度很高。高度导致IO操作多,导致查询满
max_connection=100
mysql是使用关键字limit来进行分页。
limit offset,size表示从多少索引
String sql=“select * from student order by id limit”+pageSize*(pageNumber-1)+“,”+pageSize;
触发器。
插入后触发。每收藏一次,每报名一次,就添加ExamTips的热度+1.
触发器的效率高
优点 | 对比 | 改善 |
---|---|---|
存储过程只在创建时进行编译,以后每次执行存储过程都不需要再重新编译 | 一般的SQL语句每执行一次就编译一次 | 因此使用存储过程可以大大提高数据库执行速度 |
复杂的业务逻辑需要多条SQL语句 | 这些语句要分别地从客户机发送到服务器,当客户机和数据库服务器之间的操作很多时,就会产生大量的网络传输。 | 如果将这些操作放在一个存储过程中,那么客户机和服务器之间的网络传输就会大大减少,降低了网络负载 |
存储过程创建一次便可以重复使用 | 从而可以减少数据库开发人员的工作量 | |
安全性高 | 存储过程可以屏蔽对底层数据库对象的直接访问 | 使用execute权限调用存储过程,无需拥有访问数据库对象的显式权限 |
create procedure insert_Student(name varchar(50),age int,out_id int)
begin
insert into student value(null,name,age);
select max(stuId) into_id from student;
end;
//使用存储过程
call insert_Student('fly',23,@id);
select @id;
步骤 | 语句 |
---|---|
加载驱动 | Class.forName("com.mysql.jdbc.Driver") |
获取连接 | Connection cn =DriverManager.getConnection("jdbc:mysql:///test","root","88888888") |
执行 | CallableStatement cstmt=cn.prepareCall("{call inser_Student(?,?,?)}"); |
连接
Java DataBase Connection | Java数据库连接 |
---|---|
数据库管理系统是很多的,每个数据库管理系统支持的命令是不一样的 | Java只定义接口,对应数据库厂商自己实现接口,对于开发者而言,只需要导入对应厂商的实现即可。 |
以接口方式进行调用(mysql+mysql驱动(实现)+jdbc) |
PreparedStatement | Statement |
---|---|
预编译,执行速度较快 | Prepared |
代码的可读性和可维护性 | 占位符/拼接 |
安全性,防止SQL注入攻击 | 【‘or’1‘=’1】 |
都是Http的请求方式:
get | 查 | 在URL显示提交的数据,不安全,有长度限制 |
---|---|---|
post | 改 | 相对安全,没有长度限制 |
put | 增 | |
delete | 删 |
都是会话跟踪技术
session | cookie |
---|---|
在服务器端记录信息确定用户身份 | 在客户端 |
session的实现依赖于Cookie | SessionID(session的唯一标识需要存放在客户端) |
安全但是占服务器内容 | 不安全 |
session会在一定时间内保存在服务器。当访问增多,会比较占用服务器的性能,为了减轻压力,这时考虑使用cookie | cookie不是很安全,别人可以分析本地的cookie并进行cookie欺骗,考虑安全的数据应该放在session |
登录信息放在session | 其他信息如果需要保留,可以放在cookie(购物车)。 |
- | 单个cookie保存的数据不能超过4k,很多浏览器都限制一个站点最多保存20个cookie |
购物车最好使用cookie,但是cookie是可以在客户端禁用的,这时候我们要使用cookie+数据库的方式来实现,当从cookie中不能获取出数据时,就从数据库获取。
一些常用的状态码
Http | 网络状态码 | 含义 |
---|---|---|
200 | OK | 请求处理成功,返回相关信息 |
204 | No Content | 请求处理成功,但响应报文没有主题返回 |
206 | Partial Content | 客户端进行了范围请求,服务器成功执行请求并返回指定范围的实体内容 |
301 | Moved Permanently | 永久性重定向。请求的资源已经被分配到新的url |
302 | Found | 临时性重定向 |
304 | Not Modified | 客户端发送附带条件的请求后,服务器允许请求,但内容并没修改,返回304。即客户端可以使用缓存的内容 |
400 | Bad Request | 请求报文存在语法错误。需要修正请求报文后再次发送请求 |
403 | Forbidden | 请求资源的访问被服务器拒绝。服务器没必要给出拒绝的理由。 |
404 | Not Found | 服务器上无法找到被请求的资源 |
500 | Internet Server Error | 服务器在执行请求时发生了错误。可能是Web应用存在的 bug 或者临时的障碍 |
503 | Service Unavailable | 服务器处于超载或者故障状态。如果事先得知何时可以解决故障,可以将时间写入Retry-after首部字段再返回给客户端。 |