Java,
分享于 点击 24828 次 点评:49
Java,
Java基础加强第一部分:JDK5.0部分新特性(泛型、枚举、自动装箱拆箱、静态导入、增强for循环、可变参数)、Java反射技术(Class、Constructor、Field、Method)Java基础加强第二部分:JDK新特性注解技术、Servlet3.0新特性、动态代理、复习多线程编程知识、Socket编程
注解技术:以@开始的一个描述信息,提供给JVM 编译器、运行环境 一些数据
JDK 常见注解
@override : 在编译时检查该方法是否构成覆盖,如果不构成覆盖发生编译错误
* override 在5.0 只能用于方法覆盖,在6.0以后可以用于方法实现
@Deprecated: 用于声明方法已经过时,通知编译器,在编译时产生一个警告信息
@suppressWarinings:忽略警告信息,通知编译器,在编译时忽略相应警告信息
JDK官方提供三个注解 都是在编译阶段,通知编译器一些信息
注解和配置文件 ?
传统程序编写,发现程序中出现很多需要改变信息(例如:JDBC连接参数),为了程序更好进行维护和扩展,建议将变化数据写到配置文件中,方便修改
随着软件越来越复杂,配置文件的内容越来越多,一个软件可能出现上千行甚至于上万行配置文件(缺点:可读性差),为了解决可读性差的问题 程序员们开始使用注解
* 注解比配置文件书写简单,可读性强
注解企业级应用:取代传统配置文件,运行程序通过反射技术 读取注解中配置信息 (不仅可以用于编译时,还能用于运行时)
开发注解的程序
1、定义一个注解
2、在类上面应用自定义注解
3、在java程序通过反射技术读取注解的信息
注解应用案例:银行最大转账金额限制
需求:银行规定了,每个账户一次最多转账多少金额 --- 将转账最大金额作为配置信息
使用@interface 定义一个注解 (相对于一个配置文件)
所有的Annotation自动继承java.lang. annotation.Annotation接口
注解支持类型:八种基本数据类型和String、Enum、Class、annotation以及以上类型的数组)
可以为属性提供默认值 String name() default "张三";
1、定义BankInfo注解,描述银行最大转账金额
public @interface BankInfo {
double maxTransferMoney();// 最大转账金额
}
自定义注解也可以用元注解来修饰
@Retention : 定义注解信息 保存在哪个阶段 (.java 源代码阶段 --- .class 字节码阶段 --- 运行阶段)
* SOURCE 源码阶段 CLASS编译后字节码阶段 RUNTIME运行阶段
@Target:指定注解用于修饰类的哪个成员
* TYPE 修饰类 FIELD 修饰成员变量 METHOD 修饰方法
@Documented :注解信息可以生成API文档
@Inherited :应用了该注解修饰注解类对象,子类将自动继承该注解
@Inherited
@interface A {
}
@A
class B {
}
class C extend B{// 虽然C没有使用A 注解,但是A注解可以继承的,B使用A注解,C将自动继承该注解A
}
2、在程序运行时读取注解信息
java.lang.reflect
接口 AnnotatedElement
getAnnotation(Class<T> annotationClass) 获得指定注解信息
isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断是否存在相应注解信息
首先获得注解修饰对象 --- 反射对象 类(Class) 构造方法(Constructor) 变量(Field) 方法(Method)
* 所有反射对象都实现了 AnnotatedElement 接口
// 获得注解修饰反射对象
Class c = Account.class;
// 判断是否含有需要注解信息
if (c.isAnnotationPresent(BankInfo.class)) {
// 存在注解信息 ,获得注解信息
BankInfo bankInfo = (BankInfo) c.getAnnotation(BankInfo.class);
// 获得最大转账金额
double maxTransferMoney = bankInfo.maxTransferMoney();
// 判断转账金额是否超过最大
if (money > maxTransferMoney) {
throw new RuntimeException("超出银行规定最大转账金额,最大金额:"
+ maxTransferMoney);
}
}
--------------------------------------------------------------------------------------------------------------------
课程中:JavaEE5.0 (Servlet2.5) ---- 最新JavaEE6.0(Servlet3.0)
Servlet3.0 开始出现很多新的特性
一、Servlet注解配置
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
</servlet>
<servlet-mapping>
<servlet-name></servlet-name>
<url-pattern></url-pattern>
</servlet-mapping>
从3.0 开始开始支持注解 技术 @WebServlet
* 必须需要tomcat7 、Eclipse3.7
启动eclipse3.7
1、新建Dynamic web project
添加runtime 环境 tomcat7 , 将servlet版本3.0
* 没有web.xml
2、通过注解配置 Servlet、Filter、Listener
@WebServlet --- Servlet程序
@WebFilter ---- Filter程序
@WebListener --- Listener程序
@WebInitParam 为Servlet和Filter提供初始化参数
web.xml 中提供 metadata-complete 属性,控制注解的开关
设置为true 将不支持注解技术
不设置 或者 设置为false 将支持注解 技术
二 、异步的处理支持
允许服务器端用多个线程生成同一个响应
1、@WebServlet(urlPatterns="/async",asyncSupported=true)
2、启动线程
AsyncContext asyncContext = request.startAsync();
new Thread(new Executor(asyncContext)).start();
3、通过asyncContext 获得request response进行操作
* 对异步操作 通过监听器 进行监控
异步线程开始时,调用 onStartAsync(AsyncEvent event) 方法
异步线程出错时,调用 onError(AsyncEvent event) 方法;
异步线程执行超时,调用 onTimeout(AsyncEvent event) 方法;
异步执行完毕时,调用 onComplete(AsyncEvent event) 方法;
三、对文件上传 API支持
1、Servlet上 添加
2、以前使用FileUpload ===== getParameter setCharacterEncoding 都不能用了
Servlet3.0 后 ==== getParameter setCharacterEncoding 可以用了
3、进行文件上传
Part part = request.getPart(文件域name属性);
手动解析文件名
public String getFileName(Part part) {
String filename = part.getHeader("content-disposition");
filename = filename.substring(filename.indexOf("filename=")+10,filename.length()-1);
int index = filename.lastIndexOf("\\");
if(index != -1){
filename = filename.substring(index+1);
}
return filename;
}
part.write("目标位置"); 完成文件上传
* 但是getParameter位于getPart操作之前 ----否则会有乱码问题
---------------------------------------------------------------------------------------------------------------------
Java 高级技术 --- 动态代理
重写连接池中Connection的close方法
重写方法:1、继承 方法覆盖 2、组合 装饰模式 3、动态代理
动态代理编程案例:银行取款收取手续费用
需求:ATM取钱 跨行2元 ,外地1% 费用 ------- 程序目标:实现1%手续费
1、被代理对象 必须要实现接口 ---- 要根据接口虚拟代理对象
2、编写正常取钱流程步骤
3、使用动态代理 加强取钱方法,收取手续费
public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {
// 改变取钱过程
if (method.getName().equals("getMoney")) {
double wantMoney = (Double) args[0];// 要取款金额
double tax = wantMoney * 0.01; // 手续费
double outMoney = (Double) method.invoke(atm,
wantMoney + tax);// 取钱动作
System.out.println("连同手续费,扣掉账户:" + outMoney);
return wantMoney;
}
// 不行改变原来流程
return method.invoke(atm, args);
}
-------------------------------------------------------------------------------------------------------------------------------
进程和线程知识
一个应用程序运行时,至少要开启一个进程,操作系统管理内存最小单位
编写main函数java程序,以线程方式进行运行 ---- 进程由多个线程来组成,线程是程序运行最小单位 ,线程所使用内存资源向进程申请
多个线程可以共享一个进程使用内存,发生数据并发操作问题 (多线程问题由来)
一、Java中多线程编程 两种方式
第一种 extends Thread
第二种 implements Runnable
* 优先推荐第二种,java是单继承,继承Thread类后就无法继承其它类,实现Runnable接口方式灵活性更大
在线程运行时,获得当前线程信息 (名字)
如果采用第一种方式 编写多线程 this.getName(); ---- 获得当前线程名称
如果采用第二种方式,本身对象不是Thread对象 无法使用this ,Thread.currentThread().getName();
二、线程四种状态
1、创建状态: new Thread对象
2、可运行状态 runnable : t.start()
3、被中断(阻塞)blocked : sleep睡眠 join等待目标线程执行结束 wait在监视器(锁)上等待
* IO操作都会造成线程阻塞 ---- 释放当前拥有CPU操纵权,无法进行数据计算
4、死亡状态:run方法运行结束,异常中断
* 不建议使用stop方法来停止线程,不安全 (资源无法及时释放、锁无法及时释放,造成死锁)
sleep和join 都会是当前线程阻塞,区别?
sleep 当前对象调用sleep 进行睡眠 Thread.sleep(2000);
join 等待目标线程调用join函数,表示当前线程等待目标线程执行结束
t.join(); // 当前线程等待t执行结束
三、监视器(锁)
每个对象拥有一把锁 --- 内存地址
synchronized 代码块 就是对一个对象内存地址加锁
1、synchronized static void a() {} ---- 静态方法加锁,锁的是Class对象 例如:A.class
2、synchronized void b() {} ---- 非静态方法加锁,锁的是this 对象
3、synchronized(任意对象) {} ---- 可以对象任意对象加锁
经典案例:卖票
四、死锁
资源的互相等待
Java中发生死错,synchronized 代码块嵌套
五、多线程通信
两个线程同时干活,第一个线程干了一部分,需要通知第二个线程开始干活,第二个线程做了一部分,通知第一个线程接着干活
Object对象提供 wait和notify : wait干了一部分需要别人干,在锁对象上进行等待,notify 唤醒在锁对象上面进行等待线程
wait和sleep区别
已经拥有锁线程,使用sleep等待,不会放掉持有锁对象
已经拥有锁线程,使用wait等待,会放掉持有锁对象
经典案例:生产者消费者模型
生产者生产商品,通知消费者来消费,消费者消费了商品后,通知生产者来生产
* 使用wait方法前,必须获得锁对象
-------------------------------------------------------------------------------------------
JDK5 有九个新特性: 泛型、枚举、自动装箱、静态导入、forin语句、可变参数、注解、字符串格式化、JDK5线程并发库
java.util.concurrent 包提供线程并发库操作类
java.util.concurrent.locks 提供和锁操作相关API:Lock和Condition
Lock取代synchronized代码块 完成同步 : lock.lock() 加锁 lock.unlock() 解锁
Condition实现 wait和notify 效果
* 传统wait 只能在锁对象上等待(只有一个选择),Condition允许在一个锁上面开启多个监视器,可以分别等待
线程池,允许根据需要一次性创建多个线程,放到线程池中,操作任务时,从线程池中随机获得一个线程,使用后, 将线程放回线程池
java.util.concurrent
类 Executors
用来获得一个线程池
newFixedThreadPool(int nThreads) 获得一个固定线程数量线程池
newCachedThreadPool() 根据任务需要自动创建线程个数
newSingleThreadExecutor() 单一线程池
shutdown 当线程池中所有任务结束后,正常关闭线程池,shutdownNow尝试马上打断线程中任务执行,InterruptedException (能否打断取决于程序逻辑)
---------------------------------------------------------------------------------------------
什么是协议:HTTP协议、SMTP、POP3协议 ----- 规定通信双方传递数据格式
OSI 七层结构:应用层 表示层 会话层 传输层 网络层 数据链路层 物理层
TCP/IP 四层 : 应用层、传输层、网际层 、网络接口层
HTTP 80、SMTP 25 、POP3 110、FTP 21 ... 都是应用层协议,提供默认端口
TCP/IP 协议详解 ---- 传输层 TCP、UDP
TCP 采用三层握手模型,数据不发生丢失
UDP 采用广播通知模式,接收方可以不产生回应数据,允许数据丢失
三层握手不会丢失数据原理
1、A 给B 通信,A先对B说:能收到我的数据吗
2、B回应A :可以收到,能收到我的数据吗
3、A回应B :可以收到
如果对方没有回应,选择数据重新发包,一直没回应 ---- 超时
Socket 代表两个程序之间的一个双向连接,通过socket在双方传递数据
Socket位于传输层之上,位于应用层之下 ,当需要使用应用层协议进行数据访问时,手动发送协议数据格式 ******
使用Socket技术 编写服务器成,还可以编写客户端程序
实验一:编写服务器Socket程序,通过浏览器可以访问
* socket的输出流 没有阻塞的,输入流会产生阻塞效果
实验二:socket编写HTTP协议客户端
URL和URLConnection时,HTTP请求内容自动生成发送的,响应数据自动解析的 ------ 面向应用层编程
socket编写客户端 面向传输层,手动拼接HTTP请求发送个服务器,接收完整HTTP响应信息需要手动进行解析
实验三:socket编写邮件客户端
socket写邮件客户端,面向传输层,自己手动拼写SMTP协议
相关文章
- 暂无相关文章
用户点评