北京行——java基础加强
Java基础加强第一天 : JDK5.0新特性(泛型、枚举、for/in、可变参数、自动装箱拆箱、静态导入) + 反射 API(Class、Construtctor 、Field、Method )
字符串格式化 StringFormat、System.out.printf
注解技术
线程并发库
Java基础加强第二天 :上午:注解技术使用 @override ----- Servlet3.0 新特性 (之前课程中2.5 特性) 、动态代理技术(方法增强三种方式)
下午:复习线程基础知识、多线程编写案例 、Java5 提供线程并发库 线程池 、Socket网络编程(自定义服务器案例 tomcat)
Java Annotation 注解技术 是java5.0 新特性 (如果编译环境是java1.4 之前版本 无法对注解进行编译)
JDK官方提供了三个注解
@Override: 限定重写父类方法, 该注解只能用于方法 ------ 编译时检查,不构成覆盖 报错
* JDK5.0 override注解只能用于方法覆盖 JDK6.0 该注解可以用于接口的方法实现
@Deprecated: 用于表示某个程序元素(类, 方法等)已过时 ----- 在编译器进行编译时 报出一个警告
* 为什么会有过时方法: 提供了新的方法取代 之前方法、发现某个方法存在安全隐患,不建议用户再使用
@SuppressWarnings: 抑制编译器警告. ---- 通知编译器在编译时 不要报出警告信息
* 使用 all 忽略所有警告信息
Annotation 其实就是代码里的特殊标记, 它用于替代配置文件!!
* 注解不但可以通知编译器,在运行时通知信息给 JVM虚拟机
注解典型应用:在一个类上面使用注解(配置信息),在程序中通过反射技术 获得配置注解信息 ---- 充当配置文件
已经有配置文件技术 xml、properties ,为什么还需要注解 ??
随着企业端软件应用越来越复杂,配置文件内容越来越多,导致上万行配置文件(配置文件过大,可读性会变得很差) ---- 反射案例:办晚会
* 引入注解目的:解决程序配置可读性问题 ,注解相当于代码中配置文件
注解程序开发流程
1、编写注解类
使用@interface 定义
所有注解类都默认继承 java.lang.annotation.Annotation 接口
注解支持类型:八种基本数据类型和String、Enum、Class、Annotation以及以上类型的数组)
如果注解属性提供默认值 ,使用注解是 不设置新的值
如果注解只有一个value 属性,使用注解 省略value=
2、在一个类 应用注解类
3、通过反射技术获得注解信息
通过java.lang.reflect.AnnotatedElement 在程序运行时 获得注解信息
元注解:修饰注解的注解
@Retention 声明注解存活生命周期 --Source Class Runtime --- 开发中主要使用Runtime
@Target 声明注解可以修饰对象类型 ---- FIELD 、TYPE、METHOD
@Documented 注解可以被 生成API文档
@Inherited 注解在使用时,可以被子类继承
注解案例 : 在运行阶段,通过注解充当配置文件,利用反射技术获得注解中信息
银行转账 : 最大一次只能汇款XXX钱 (转账金额大小限制)
读取注解信息
步骤一:获得注解修饰反射对象 Class Field Method ---- 这些所有反射对象 都实现了 AnnotatedElement接口
步骤二:通过 AnnotatedElement 接口 boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断目标注解是否存在
步骤三:通过 AnnotatedElement 接口 getAnnotation(Class<T> annotationClass) 获得目标注解
注解说的直白点就是替换了配置文件的庞大时阅读的不变,而产生的另一种技术
Servlet3.0 新特性 ----- 对于web 开发很有用的 ---- JavaEE6 最新开发工具
1、web.xml 关于 Servlet 、Filter、Listener 通过注解进行配置
2、服务器异步处理机制
3、集成文件上传API
安装eclipse3.7 和 tomcat7.0
启动Eclipse 版本必须和 JDK版本 位数匹配
启动错误 eclipse.ini -Xmx512m 尝试 修改256 或者 128
在Eclipse集成tomcat 编写web工程
1、创建Dynamic web project --- 配置target runtime 运行环境 tomcat
* eclipse目录默认 没有WebRoot 目录 --- 有WebContent
2、eclipse和my eclipse发布方式不同
* myeclipse 将目录复制tomcat/webapps
* eclipse 内部有tomcat插件,将web目录复制插件目录/webapps
* 自动生成Servers工程目录 --- 保存tomcat启动需要配置文件
1、3.0 web 工程没有web.xml
@WebServlet("/hello")
@WebFilter("/hello")
@WebListener
* 当你配置欢迎页面、错误页面 编写web.xml
* metadata-complete web-app元素的属性 设置为true 将不支持注解技术
2、异步处理支持
运行服务器端对Response 用多个线程统计信息响应生成
* 作用 改善用户体验
3、内部提供一套API 完成文件上传
编写文件上传form 表单
在服务器端Servlet 中 @MultipartConfig
* getParameter位于getPart操作之前 --- 必须先处理普通form域,再处理上传域
动态代理价值: 当.class文件 被类加载器加载 到内存 形成Class对象,所有程序访问都是针对Class对象 ,动态代理技术可以根据Class对象的实现接口,在内存中虚拟构造一个对象,该对象成为代理对象,访问真实对象的所有API的过程中 都将通过代理对象去访问 。
* 拦截对真实对象的访问 修改访问参数、拦截访问请求
* Java Spring 内部拦截器技术 -- 使用动态代理
动态代理案例
1、编写真实业务对象
2、使用动态代理,必须为真实对象提供一个接口
3、使用Proxy的newInstance 根据真实业务对象,创建代理对象
4. 根据代理对象取间接访问真实对象
5、拦截真实访问后,阻止对目标访问、修改参数、修改返回值
银行取钱案例 ATM : 取款手续费用
真实业务对象如果想动态代理,生成代理对象 -------- 实现接口
* 在实际企业开发中,动态代理经常用于加强方法原来逻辑功能 ---- 无需修改原来程序逻辑,就可以实现方法增强
线程和进程区别 ?一个进程是多个线程组成的,进程是操作系统管理内存最小单位,线程使用内存,从进程申请
线程的创建有两种方式:extends Thread、implements Runnable接口
* 获得当前线程的名字 Thread.currentThread().getName();
* 优先使用Runnable 接口 ---- 因为java单继承,如果继承Thread 就不能继承其他类
线程的四种状态:创建(new Thread().start())、执行状态 (线程run方法正在运行)、阻塞状态(run方法在执行一段时间后暂停执行)、线程死亡(run方法执行结束、发生异常)
* 新建 --- 运行 (获得cpu的使用权)
* 运行 --- 阻塞 (Thread.sleep join 使用同步锁 wait IO读写、网络传输)
* 阻塞 --- 运行 结束阻塞,重新获得cpu使用权
sleep 使当前线程睡眠一段时间,睡眠过程中,不释放锁资源
join 等待目标线程执行结束后,当前线程才能继续执行
同步锁,当运行一个代码块,使用同步锁机制,一个线程已经将代码块锁定,另一个线程无法进入代码块 ---- 执行等待锁
wait 当你获得一个同步锁后,选择在锁上面监视器进行等待,等待必须由别人进行 唤醒 notify notifyAll
锁:保证一段程序同一时间只能由一个线程进行执行 ---- 阻止两个线程同时执行一段代码
* java中每个对象都可以作为锁 ----- 锁的本质,锁定一块内存地址
* 特殊锁 锁定方法
public static synchronized void a() {} ---- 锁定 类的Class对象
public synchronized void b() {} --- 锁定this 对象
同步锁案例 : 售票系统 模拟火车站多个售票窗口同时售票 ---- 确保同一个时间 只能有一个窗口打票
死锁原因:互相等待 ------ 同步代码块嵌套
* 尽量同步代码块不要嵌套
锁监视器操作 ----- java中所有对象都可以作为锁,java 中 Object类 提供 wait notify notifyAll
wait :当前线程 在锁对象的监视器上进行等待
notify : 唤醒 一个 在 指定锁对象的监视器上等待的线程
notifyAll : 唤醒所有在指定 锁对象的监视器上等待的线程
* 线程通信案例 (当两个线程协同完成某个任务 )---- 生产者消费者模型
生产者消费者场景 :一个生产者、一个消费者,生产者生产一个面包,通知消费者来吃,消费者吃完了,通知生产者生产
* 生产者发现面包还没吃 需要等待
* 消费者发现面包已经吃了 需要等待
JDK5.0 之后提供两个接口 Lock 和 Condition ,简化同步和锁编程
java.util.concurrent.locks.Lock ---- 取代 synchronized
java.util.concurrent.locks.Condition ---- 取代 wait notify
* 在同一个锁上面 建立多个监视器
java.util.concurrent 包 和 子包 ---- ArrayBlockingQueue<E> CopyOnWriteArrayList<E> LinkedBlockingQueue<E>
线程池技术 Excutors
为什么用线程池,线程创建、关闭释放资源 ---- 消耗程序性能
一次创建多个线程,做任务,随机获得一个线程,完成任务,将线程归还线程池
newFixedThreadPool(int nThreads) 固定线程数量线程池
newCachedThreadPool() 返回根据程序需要自动扩充大小 线程池 ----- 最常用
newSingleThreadExecutor() 返回单线程处理程序
shutdown与shutdownNow的比较
shutdown 完成当前线程池中所有任务 再关闭
shutdownNow 会对当前线程池中所有线程,调用interrupt 尝试打断当前线程,如果无法打断,会执行结束
------------------------------------------------------------------------------------------------------------------
OSI 七层体系结构: 应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
*协议层次越高,越容易让人理解, 层次越低,数据越接近0 1
TCP/IP 四层 : 应用层、传输层、网际层、网络接口层
应用层、传输层
应用层:HTTP SMTP POP3 FTP TELNET
传输层:TCP(不允许丢包 三次握手) UDP(广播 允许丢包)
三次握手:
A 向 B 发送一个消息:能听到我说话吗
B 回复 A 消息:我能听到,你能听到我说话吗
A 回复 B :我能听到
TCP发送数据没有收到对方回应,选择重新发送 ---- 时间限制 超时
Socket 两台计算机之间一个连接 ---- 两台计算机可以通信
使用socket建立双方连接 -----传输协议需要自己编写 面向底层协议
socket 编写程序 可以模拟服务器,可以模拟客户端
服务器如何编写
* 使用socket进行通信过程中,如果调用in.readLine 但是对方没有写 ---- 程序一直等待 、out.print向对方发送信息 没有阻塞
socket 案例 ----- 模拟tomcat服务器
---------------------------------------------------------------------------------------
注解的使用 ---- 定义注解,利用反射解析注解内容 (案例:银行转账最大金额)
Servlet3.0 注解开发Servlet、异步技术、文件上传
动态代理 (案例:德华案例、银行取款 收取手续费用)
多线程:两种线程创建方式、四种状态、同步和锁、死锁、wait和notify (案例:卖票、生产蛋糕) ---- 使用JDK5 Lock和Condition 重写
socket编程 服务器怎么写 客户端怎么写
* 实际socket案例 按照协议发送内容 模拟tomcat 服务器 遵循HTTP协议