装饰设计模式::
public static void abc(File desc,File src){
//不可将文件夹复制到它的子文件夹下.
if(desc.getAbsolutePath().contains(src.getAbsolutePath())){
System.out.println("父目录不能拷贝到子目录中");
}
//超长文件夹删除
//借助robocopy.rar百度如何使用
}
//文件分隔与合并
public static void randomaccessfile() throws IOException{
RandomAccessFile raf=new RandomAccessFile(new File(""), "r");
raf.seek(10);/
byte[] flush=new byte[1024];
int len=0;
while (-1!=(len=raf.read(flush))) {
System.out.println(new String(flush,0,len));
}
//文件的分隔思路
//1.分隔的块数,2.每一块的大小,3.最后一块的大小:总的文件大小-(n-1)*blocksize 4.每块的名称
//分割:第几块,每块的起点,实际大小
}
文件分割与合并::::::
package basic;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import javax.naming.InitialContext;
public class Basic {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws ParseException, FileNotFoundException, IOException {
SplitFile sf=new SplitFile("E:/a/b.rar",100);
System.out.println(sf.size);//输出分了多少块
sf.split("E:/a/b/c.rar");
}
}
class SplitFile{
private String filePath;//文件路径
private String fileName;//文件名称
private long blockSize;//每块大小
private long length;//文件大小
public int size;//块数
private List<String> blockPath;//每块的名称
public SplitFile() {
blockPath=new ArrayList<>();
}
public SplitFile(String filePath, long blockSize) {
this();
this.filePath = filePath;
this.blockSize = blockSize;
init();
}
public SplitFile(String filePath) {
this(filePath,1024);
}
public void init(){
File src=null;
if(null==filePath || !((src=new File(filePath)).exists())){
return;
}
this.fileName=src.getName();
this.length=src.length();
if(this.blockSize>length){
this.blockSize=length;
}
size=(int)(Math.ceil(length*1.0/this.blockSize));
//initPath();
}
private void initPath(String destPath){
for (int i = 0; i < size; i++) {
this.blockPath.add(destPath+"/"+fileName+".part"+i);
}
}
//文件的分割
public void split(String destPath){
//确定文件路径
initPath(destPath);
long beginPos=0;
long actualBlocksize=blockSize;
for (int i = 0; i < size; i++) {
if(i==size-1){
actualBlocksize=this.length-beginPos;
}
splitDetail(i,beginPos,actualBlocksize);
beginPos+=actualBlocksize;
}
}
private void splitDetail(int idx, long beginPos, long actualBlocksize) throws IOException {
// TODO Auto-generated method stub
File src=new File(this.filePath);
File dest=new File(this.blockPath.get(idx));
RandomAccessFile raf=null;//输入流
BufferedOutputStream bos=null;//输出流
raf=new RandomAccessFile(src, "r");
bos=new BufferedOutputStream(new FileOutputStream(dest));
raf.seek(beginPos);
byte[] flush=new byte[1024];
int len=0;
while (-1!=(len=raf.read(flush))) {
if(actualBlocksize-len>=0){
bos.write(flush, 0, len);
actualBlocksize-=len;
}else{
bos.write(flush, 0,(int)actualBlocksize);
break;
}
}
}
//文件合并
public void mergeFile(String destPath) throws IOException{
File dest=new File(destPath);
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(dest,true));//true表示追加
BufferedInputStream bis=null;
for(int i=0;i<this.blockPath.size();i++){
bis=new BufferedInputStream(new FileInputStream(new File(this.blockPath.get(i))));
byte[] flush=new byte[1024];
int len=0;
while(-1!=(len=bis.read(flush))){
bos.write(flush, 0, len);
}
}
bos.flush();
bis.close();
bos.close();
}
}
SequenceInputStream:表示其它输入流的逻辑串联,它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件结尾,接者从第二个输入流开始读取,依次类推。
//文件合并
public void mergeFile(String destPath) throws IOException{
File dest=new File(destPath);
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(dest,true));//true表示追加
SequenceInputStream sis=null;
Vector<InputStream> vi=new Vector<>();
for (int i = 0; i < this.blockPath.size(); i++) {
vi.add(new BufferedInputStream(new FileInputStream(new File(this.blockPath.get(i)))));
}
sis=new SequenceInputStream(vi.elements());//正好是enumeration类型对接
byte[] flush=new byte[1024];
int len=0;
while (-1!=(len=sis.read(flush))) {
bos.write(flush);
}
bos.flush();
}
IO流总结:
字节流:::可以处理一切纯文本,音频,视频
输入流:InputStream FileInputStream ByteArrayInputStream
操作:read(字节数组)
线程::::::
在JAVA中实现多线程的是java.lang.Thread类,可以通过创建Thread类的实例来创建新的线程,每个线程都是通过某个特定Thread对象的对应run方法来完成其操作,方法run()称为线程体。通过调用thread类的start方法来启动一个线程。
线程创建的第一种方式:继承Thread类:
package basic;
/**
* 模拟龟兔赛跑,创建多线程,继承Thread,重写run方法
* 使用线程:
* 创建子类对象,调用对象的start方法
* */
public class Rabbit extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("兔子跑了"+i+"步");
}
}
}
class wugui extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("乌龟跑了"+i+"步");
}
}
}
public static void main(String[] args) {
Rabbit rabbit = new Rabbit();
wugui wu = new wugui();
rabbit.start();// 不要调用run方法,run是普通的方法,start为启动一个线程。
wu.start();
for (int i = 0; i < 100; i++) {
System.out.println("主线程执行了");
}
}
静态代理模式:::
继承Thread类方式的缺点,那就是如果我们的类已经从一个类继承,则无法再继承Thread类。
通过Runnable接口实现多线程。避免单继承,方便共享资源,同一份资源多个代理访问。
public class Basic {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
marry y=new you();//创建真实角色
WeddingCompany w=new WeddingCompany(y);//代理角色,持有真实角色的引用
w.marry();//执行任务
}
}
// 静态代理模式
/*
* 实现同一个接口,
* 真实角色
* 代理角色
* */
interface marry {
void marry();
}
class you implements marry {
public void marry() {
}
}
class WeddingCompany implements marry {
private marry you;
public void before() {
}
public void marry() {
before();
you.marry();
after();
}
public void after() {
}
public WeddingCompany(basic.marry you) {
super();
this.you = you;
}
public WeddingCompany() {
super();
}
}
Runnable接口就是一个静态代理的例子,Thread类实现了Runnable接口。我们也只要实现Runnable接口,这样便可以了。
/*
* 使用runnable接口创建线程
* 启动多线程,使用静态代理。
* 创建真实角色,创建代理角色加上对真实角色的引用。调用start方法。
* */
public class Programmer implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 1000; i++) {
System.out.println("一边打架....");
}
}
}
public static void main(String[] args) {
Programmer pro=new Programmer();//创建真实角色
Thread thread=new Thread(pro);//创建代理角色
thread.start();//启动线程
for (int i = 0; i < 100; i++) {
System.out.println("一边聊QQ");
}
}
线程创建之三:
通过Callable接口实现:
public class Basic {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception, Exception {
//创建线程
ExecutorService e=Executors.newFixedThreadPool(1);
Race race=new Race();
Future<Integer> future=e.submit(race);
int num=future.get();
System.out.println(num);
e.shutdown();//停止服务
}
}
/*
* 使用callable接口
* Callable接口可以对外声明异常,同时可以返回值。而runnable接口不可以。
* */
class Race implements Callable<Integer>{
@Override
public Integer call() throws Exception {
// TODO Auto-generated method stub
return 1000;
}
}
创建callable实现类,重写call方法。
借助 执行调度服务 ExecutorService获取Future对象。
4.线程状态与停止线程
新生状态,就绪状态,运行状态,就绪状态,死亡状态。
5.线程阻塞:
join:合并线程.....等待该线程终止
public class Basic {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception, Exception {
Race race=new Race();
Thread t=new Thread(race);//新生状态
t.start();//就绪状态
for (int i = 0; i < 1000; i++) {
if (50==i) {
t.join();
}
System.out.println("主线程"+i);
}
}
}
class Race extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 1000; i++) {
System.out.println("race"+i);
}
}
}
if (50==i) {
Thread.yield();//静态方法,写在哪个线程中就是暂停哪个线程。
}
sleep()方法,在指定的毫秒数内让当前正在执行的线程休眠,静态方法……每一个对象都有一把锁,sleep休眠的时候不会释放锁。
sleep()两种场景:一是模拟倒计时,二是模拟网络延时。
public class Basic {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception, Exception {
//倒计时,倒数十个数,一秒打印一个
int num=10;
while (true) {
System.out.println(num--);
Thread.sleep(1000);
if(num<=0)
break;
}
}
public static void test1(){
//倒计时
Date endTime=new Date(System.currentTimeMillis()+10*10000);
long end=endTime.getTime();
while (true) {
System.out.println(new SimpleDateFormat("mm:ss").format(endTime));
endTime=new Date(endTime.getTime()-1000);//减去1秒
Thread.sleep(1000);
if(end-10000>endTime.getTime()){
break;
}
}
}
public static void test2() {
int num=40;
//模拟网络延时
//多线程中造成的资源冲突与并发问题。
//三个代理抢票,有可能抢到0,-1张票。
while(true){
if(num<=0)
break;
try {
Thread.sleep(2000);
} catch (Exception e) {
// TODO: handle exception
}
System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
}
}
}
线程基本信息,优先级:::
public static void main(String[] args) throws Exception, Exception {
Programmer programmer=new Programmer();
Thread thread=new Thread(programmer,"线程名称");
System.out.println(thread.getName());
thread.setName("纯种名称人");
System.out.println(thread.getName());
System.out.println(Thread.currentThread().getName());//输出main线程的名称
thread.start();
System.out.println(thread.isAlive());//线程是否存活,调用start之后才开始执行该线程.
//优先级代表的是概率,不是绝对的优先级,没有先后的顺序。
thread.setPriority(Thread.MAX_PRIORITY);
thread.setPriority(Thread.MIN_PRIORITY);
thread.setPriority(Thread.NORM_PRIORITY);
}
线程的同步(并发)::::存在多个线程访问同一份资源。必须确保这份资源安全。
synchronized-=------>线程同步。
同步块:
synchronized(引用类型|this|类.class){}用的最多的还是锁定对象。this
//同步包括:1.同步块,2.同步方法。
//在方法名前面加上synchronized关键字即可。
单例设计模式:确保一个类只有一个对象。
//确保一个类只有一个对象
class Jvm{
//构造器私有化,避免外部直接创建对象
private Jvm(){}
//声明一个静态变量
private static Jvm instance=null;
//创建一个对外的公共静态方法访问该变量,如是该变量没有对象,创建该对象。
public static Jvm of(){
if(null==instance)
instance=new Jvm();
return instance;
}
}
public class Basic {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception, Exception {
//线程同步,关键字:synchronized
//同步包括:1.同步块,2.同步方法。
//在方法名前面加上synchronized关键字即可。
Jvm jvm1=Jvm.of();
Jvm jvm2=Jvm.of();
System.out.println(jvm1);
System.out.println(jvm2);//在单线程模式下两个地址是一样。但多线程模式下就不一定了。多线程有可能不安全。
//因为多线程下访问的是同一份资源。同一个对象。
//第一种方法前加synchronized
//第二种方法同步块:::
//单例 应用:Runtime
}
}
//确保一个类只有一个对象,单例 设计模式
class Jvm{
//构造器私有化,避免外部直接创建对象
private Jvm(){}
//声明一个静态变量
private static Jvm instance=null;
//创建一个对外的公共静态方法访问该变量,如是该变量没有对象,创建该对象。
public static synchronized Jvm of(){//最简单的方式应对多线程
if(null==instance)
instance=new Jvm();
return instance;
}
public static Jvm of2(){//同步块方式 ,经典的double checking双重检查。
if(null==instance){//提高已经存在对象的访问效率
synchronized (Jvm.class) {//锁定该类的字节码文件.
if(null==instance)//安全
instance=new Jvm();
}
}
return instance;
}
}
//单例创建的其它方式
//
class Jvm2{
private Jvm2(){}
private static Jvm2 instance=new Jvm2();//类加载时创建
public static Jvm2 getJvm(){
return instance;//肯定是安全的
}
}
//单例创建的其它方式
//为了提高效率的另一种写法。类在使用的时候才会加载。
class Jvm3{
private Jvm3(){}
private static class JVMHolder{//延缓了加载时机,当使用到这个实例 时才加载。若不访问,则无需加载。
private static Jvm3 instance=new Jvm3();
public static Jvm3 getJvm(){
return instance;//肯定是安全的
}
}
}
设计模式之单例……
死锁::过多的同步方法造成死锁。容易造成死锁,不一定会死锁。
生产者消费者模式,信号灯法:解决多线程容易死锁的一个方案。不属于设计模式。
//一个场景,共同的资源。wait()等待会释放锁,与sleep不同。
//flag=true,生产者生产,消费者等待,生产完成后通知消费者。
//flag=false,生产者等待,消费者消费,消费完后通知生产者。
class Movie{
private String picString;
private boolean flag=true;
public synchronized void play(String pic) throws Exception{
if(!flag){
this.wait();//生产者等待
}
Thread.sleep(500);//开始生产
this.picString=pic;//生产完毕
this.notify();//通知消费
this.flag=false;
}
public synchronized void watch() throws Exception{
if(flag){
this.wait();
}
Thread.sleep(500);
System.out.println(picString);
this.notifyAll();
this.flag=true;
}
}
::::::::::::::::::
wait()与notify()方法一定要与同步在一起使用,没有同步,则无法等待。与synchronized一起使用。
任务调度:
Timer定时器类
TimerTask任务类
通过java Timer,TimerTask:(spring的任务调度就是通过它们实现的)
Timer实现的是类似闹钟的功能,Timer类本身实现的就是一个线程,只是这个线程被用来调用其它线程。而TimerTask类是一个抽象类,该类实现了Runnable接口。
在实际应用中,一个Timer可以启动多个TimerTask实现的线程,但是多个线程之间会存在阻塞。所以如果多个线程之间需要完全独立运行的话,最好还是一个Timer启动一个TimerTask实现。
public static void main(String[] args) throws Exception, Exception {
//任务调度,可以自学一下quartz
Timer timer=new Timer();
timer.schedule(new TimerTask() {//安排在什么时候开始执行
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("aaa");
}
}, new Date(System.currentTimeMillis()+1000), 1000);
}
网络编程::::
InetAddress,InetSocketAddress:
InetAddress:封装计算机的ip地址以及DNS.,没有端口。
InetSocketAddress包含了端口:
getHostAddress()返回IP地址……
getHostName()返回域 名,本机为计算机名。
InetAddress.getLocalHost();
InetAddress.getByName("ip地址|域 名")
public static void main(String[] args) throws Exception, Exception {
InetAddress addr = InetAddress.getLocalHost();
System.out.println(addr.getHostAddress());// IP地址
System.out.println(addr.getHostName());// 计算机名
// 根据域 名得到InetAddress对象
addr = InetAddress.getByName("www.163.com");
System.out.println(addr.getHostAddress());// IP地址
System.out.println(addr.getHostName());// 计算机名
// 根据IP得到InetAddress对象
addr = InetAddress.getByName("61.135.253.15");
System.out.println(addr.getHostAddress());// IP地址
System.out.println(addr.getHostName());// 计算机名,如果无法解析返回该IP地址。
//
InetSocketAddress isa=new InetSocketAddress("127.0.0.1",11111);
System.out.println(isa.getHostName());
System.out.println(isa.getPort());
}
URL:指向互联网资源的指针。
URL类:创建:
public static void main(String[] args) throws Exception, Exception {
//绝对路径构建
URL url=new URL("http://www.baidu.com:80/index.html#aa?uname=bjsxt");
System.out.println(url.getProtocol());//协义
System.out.println(url.getPort());//端口
System.out.println(url.getHost());//域名
System.out.println(url.getFile());//资源
System.out.println(url.getPath());//相对路径
System.out.println(url.getRef());//锚点
System.out.println(url.getQuery());//参数,存在锚点即为空。如果不存在返回正确。
//相对路径构建
url=new URL("http://www.baidu.com:80/");
url=new URL(url,"b.html");
url=new URL("http://www.baidu.com");//访问主页
//获取资源
InputStream is=url.openStream();
byte[] flush=new byte[1024];
int len=0;
while(-1!=(len=is.read(flush))){
//System.out.println(new String(flush));中文 乱码
}
//使用转换流解码
BufferedReader br=new BufferedReader(new InputStreamReader(url.openStream(),"utf-8"));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("E:/a/b.html")),"utf-8"));
String msg=null;
while((msg=br.readLine())!=null){
System.out.println(msg);
bw.append(msg);
bw.newLine();
}
bw.flush();
bw.close();
br.close();
}
爬虫的基本原理:后期要用到正则表达式来做。
UDP通信:
客户端:
1.创建:DatagramSocket类+指定端口
2.准备数据,字节数组。
3.打包,DatagramPacket+服务器地址及端口。
服务器端:
1.创建DatagramSocket类+指定端口
2.准备接收容器,字节数组。封装DatagramPacket
3.包接收数据
4.分析并释放资源。
public class Basic {
public static void main(String[] args) throws Exception, Exception {
//创建服务端+端口
DatagramSocket ds=new DatagramSocket(8888);
//准备接收容器
byte[] contains=new byte[1024];
//datagrampacket
DatagramPacket dp=new DatagramPacket(contains, contains.length);
//接收数据
ds.receive(dp);
//分析数据
byte[] data=dp.getData();
int len=dp.getLength();
System.out.println(new String(data, 0, len));
//释放
ds.close();
}
}
public class MyClient {
public static void main(String[] args) throws Exception {
//创建客户端
DatagramSocket ds=new DatagramSocket(6666);
//准备数据
String msg="udp编程";
byte[] data=msg.getBytes();
DatagramPacket dp=new DatagramPacket(data, data.length,new InetSocketAddress("127.0.0.1", 8888) );
//打包
ds.send(dp);
ds.close();
}
}
发送类型:double<->byte[]
public static byte[] convert(double d) throws Exception{
byte[] data = null;
ByteArrayOutputStream bos=new ByteArrayOutputStream();
DataOutputStream dos=new DataOutputStream(bos);
dos.writeDouble(d);
dos.flush();
data=bos.toByteArray();
dos.close();
return data;
}
public static double convert(byte[] data) throws Exception{
DataInputStream dis=new DataInputStream(new ByteArrayInputStream(data));
return dis.readDouble();
}
Socket编程:基于TCP
ServerSocket,Socket
public class Basic {
public static void main(String[] args) throws Exception, Exception {
//创建服务端,指定端口
ServerSocket sever=new ServerSocket(8888);
Socket socket=sever.accept();//接收客户端连接,阻塞式
System.out.println("建立连接");
//发送数据
String msg="欢迎使用";
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//DataoutputStream换
bw.write(msg);
bw.newLine();//加上,否则读取readLine的时候出错。
bw.flush();
}
//创建客户端,必须指定服务器和端口。此时就在连接
public static void name() throws Exception, Exception {
Socket socket=new Socket("localhost",8888);//TCP客户端端口由系统分配
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));//换DataInputStream
String msg=br.readLine();
System.out.println(msg);
}
}
这里连接的是一个客户端,如果连接多个客户端呢。?
public class Basic {
public static void main(String[] args) throws Exception, Exception {
//创建服务端,指定端口
ServerSocket sever=new ServerSocket(8888);
//死循环,多个客户端
while(true){
Socket socket=sever.accept();//接收客户端连接,阻塞式
DataInputStream dis=new DataInputStream(socket.getInputStream());
String msg=dis.readUTF();
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
dos.writeUTF("服务器端--->"+msg);
dos.flush();
}
}
}
public class MyClient {
public static void main(String[] args) throws Exception {
Socket socket=new Socket("localhost",8888);//TCP客户端端口由系统分配
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
BufferedReader console=new BufferedReader(new InputStreamReader(System.in));
dos.writeUTF(console.readLine());//从控制台读入一行
dos.flush();
DataInputStream dis=new DataInputStream(socket.getInputStream());
System.out.println(dis.readUTF());
}
}
聊天室之转发:
package basic;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Basic {
private List<MyChannel> list = new ArrayList<>();
public static void main(String[] args) throws Exception, Exception {
new Basic().start();
}
public void start() throws IOException{
//创建服务端,指定端口
ServerSocket sever=new ServerSocket(8888);
//死循环,多个客户端
while(true){
Socket socket=sever.accept();//接收客户端连接,阻塞式
MyChannel myChannel=new MyChannel(socket);//成员内部类放在了静态方法中,会出错
list.add(myChannel);
new Thread(myChannel).start();
}
}
class MyChannel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private boolean isRunning=true;
public MyChannel(Socket socket){
try {
dis=new DataInputStream(socket.getInputStream());
dos=new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
isRunning=false;
list.remove(this);
}
}
public void run() {
while (isRunning) {
sendOthers();
}
}
//发送给其它客户端
public void sendOthers(){
String msg=receive();
for(MyChannel myChannel:list){
if(myChannel==this)
continue;
//发送其它
myChannel.send(msg);
}
}
public String receive(){
String msgString="";
try {
msgString=dis.readUTF();
} catch (IOException e) {
isRunning=false;
}
return msgString;
}
public void send(String msg){
if(msg!=null&&!msg.equals("")){
try {
dos.writeUTF(msg);
dos.flush();//强制刷新
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package basic;
import java.net.Socket;
//输入流与输出流在同一个线程内,应该独立出来。
public class MyClient {
public static void main(String[] args) throws Exception {
Socket socket=new Socket("localhost",8888);//TCP客户端端口由系统分配
new Thread(new Send(socket)).start();//发送线程
new Thread(new Receive(socket)).start();//接收线程
}
}
package basic;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
//发送数据线程
public class Send implements Runnable {
private BufferedReader console;
private DataOutputStream dos;
public Send() {
super();
console=new BufferedReader(new InputStreamReader(System.in));
}
public Send(Socket client) throws IOException {
this();
this.dos = new DataOutputStream(client.getOutputStream());
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
send();
}
}
public void send(){
String msg=getStringFromConsole();
if(msg!=null&&!msg.equals("")){
try {
dos.writeUTF(msg);
dos.flush();//强制刷新
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String getStringFromConsole(){
try {
return console.readLine();
} catch (IOException e) {
return "";
}
}
}
package basic;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
//接收数据线程
public class Receive implements Runnable {
private DataInputStream dis;
private boolean isRunning=true;
public Receive(Socket socket){
try {
dis=new DataInputStream(socket.getInputStream());
} catch (IOException e) {
isRunning=false;
}
}
@Override
public void run() {
while(isRunning){
System.out.println(receive());
}
}
public String receive(){
String msgString="";
try {
msgString=dis.readUTF();
} catch (IOException e) {
isRunning=false;
}
return msgString;
}
}
私聊::
手写服务器:httpServer::::::::
前台表单中:name是给后台区分的,id是给前台区分的。
package basic;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
//创建服务器,并启动
public class Basic {
public static void main(String[] args) throws Exception, Exception {
Basic basic=new Basic();
basic.start();
}
//启动方法
public void start(){
ServerSocket server;
try {
server = new ServerSocket(8888);
receive(server);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//接受客户端
public void receive(ServerSocket server){
try {
Socket client=server.accept();
String msg=null;//接收客户端的请求信息
StringBuilder sb=new StringBuilder();
// BufferedReader br=new BufferedReader(new InputStreamReader(client.getInputStream()));
// while ((msg=br.readLine()).length()>0) {//使用readLine的话会出现问题,post的情况下.get情况下可以。因为post的数据中会有一个空行
// sb.append(msg);
// sb.append("\r\n");
// }
byte[] data=new byte[20480];
int len=client.getInputStream().read(data);
String requestInfo=new String(data,0,len).trim();
System.out.println(requestInfo);
//响应
StringBuilder responseContext=new StringBuilder();
responseContext.append("<html><head><title>che</title></head><body>cheaaa</body></html>");
StringBuilder response=new StringBuilder();
//http协议,状态码
response.append("HTTP/1.1").append(BLANK).append("200").append(BLANK).append("ok").append(CRLF);
//响应头
response.append("Server:bjsss Server/1.1.1").append(CRLF);
response.append("Date:").append(new Date()).append(CRLF);
response.append("Content-type:text/html;charset=GBK").append(CRLF);
//正文长度,字节长度
response.append("Content-Length:").append(responseContext.toString().getBytes().length).append(CRLF);
response.append(CRLF);
response.append(responseContext);
//输出
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
System.out.println(response.toString());
bw.write(response.toString());
bw.flush();//造成别忘了使用
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//停止
public void stop(){
}
public static final String CRLF="\r\n";
public static final String BLANK=" ";
}
HTTP中的响应分析:
最重要的两个:
Content-type:text/html;charset=GBK
text/plain;charset=GBK 纯文本
application/octet-stream 流的类型
借助于工具:HttpWatcherPro查看响应内容 IE浏览器。
封装Response::::
package basic;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;
public class Response {
private StringBuilder response;
public static final String CRLF="\r\n";
public static final String BLANK=" ";
//正文长度
private int len=0;
//正文
private StringBuilder content;
//构建流
private BufferedWriter bw;
public Response() {
super();
response=new StringBuilder();
content=new StringBuilder();
}
public Response(OutputStream os) {
super();
response=new StringBuilder();
content=new StringBuilder();
bw=new BufferedWriter(new OutputStreamWriter(os));
}
public Response(Socket client) throws IOException {
super();
response=new StringBuilder();
content=new StringBuilder();
bw=new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
}
public void pushToClient(int code) throws IOException{
createHeadInfo(code);
bw.append(response);
bw.append(content);
bw.flush();
}
public void close(){
try {
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//构建正文
public Response print(String content){
this.content.append(content);
len+=content.getBytes().length;
return this;
}
public Response println(String content){
this.content.append(content).append(CRLF);
len+=(content+CRLF).getBytes().length;
return this;
}
private void createHeadInfo(int code){
//http协议,状态码
response.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
switch (code) {
case 200:
response.append("ok");
break;
case 404:
response.append("not found");
default:
break;
}
response.append(CRLF);
//响应头
response.append("Server:bjsss Server/1.1.1").append(CRLF);
response.append("Date:").append(new Date()).append(CRLF);
response.append("Content-type:text/html;charset=GBK").append(CRLF);
//正文长度,字节长度
response.append("Content-Length:").append(len).append(CRLF);
response.append(CRLF);
}
}
封装request::::::
package basic;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
public class Request {
//请求方式
private String method;
//请求资源
private String url;
//请求参数
private Map<String, List<String>> parameterMapValues;
public static final String CRLF = "\r\n";
public static final String BLANK = " ";
private InputStream is;
private String requestInfo;
public Request(){
method="";
url="";
parameterMapValues=new HashMap<String, List<String>>();
requestInfo="";
}
public Request(InputStream is) {
this();
this.is=is;
byte[] data=new byte[20480];
int len=0;
try {
len = is.read(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
requestInfo=new String(data,0,len).trim();
System.out.println(requestInfo);
//分析头信息
parseRequestInfo();
}
private void parseRequestInfo() {
// TODO Auto-generated method stub
if (null==requestInfo&&requestInfo.equals("")) {
return;
}
//从信息的首行分解出请求方式,请求参数,请求路径
String paramString="";
String firstLine=requestInfo.substring(0, requestInfo.indexOf(CRLF));
int idx=firstLine.indexOf('/');
this.method=firstLine.substring(0,idx-1);//获取方法,去掉后面那个空格
String urlString=firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim();
System.out.println(urlString+" urlString");
if (this.method.equalsIgnoreCase("post")) {
this.url=urlString;
paramString=requestInfo.substring(requestInfo.lastIndexOf(CRLF));
}else if(this.method.equalsIgnoreCase("get")){
System.out.println(urlString.contains("?"));
if(urlString.contains("?")){
String[] urlArray=urlString.split("\\?");//必须是\\,第一个是转\,第二个转?
this.url=urlArray[0];
System.out.println("aaa");
paramString=urlArray[1];
}else{
this.url=urlString;
}
}
}
//将字符串转成map
public void parseParams(String paramString){
StringTokenizer tokenizer=new StringTokenizer(paramString, "&");
while (tokenizer.hasMoreElements()) {
String object = (String) tokenizer.nextElement();
String[] keyValues=object.split("=");
if(keyValues.length==1){
keyValues=Arrays.copyOf(keyValues, 2);
keyValues[1]=null;
}
String key=keyValues[0].trim();
String value=null==keyValues[1]?null:decode(keyValues[1].trim(),"gbk");//中文解码
if(!parameterMapValues.containsKey(key)){//包含key
parameterMapValues.put(key, new ArrayList<String>());
}
List<String> values=parameterMapValues.get(key);
values.add(value);
}
}
//根据页面name获取对应的多个值。
public String[] getParamValues(String name){
List<String> values=null;
if((values=parameterMapValues.get(name))==null){
return null;
}else{
return values.toArray(new String[0]);
}
}
//根据页面name获取单个值
public String getParamValue(String name){
String[] values=getParamValues(name);
if(null==values)
return null;
return values[0];
}
//解决中文
public String decode(String value,String code){
try {
return java.net.URLDecoder.decode(value, code);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return "Request [method=" + method + ", url=" + url + ", parameterMapValues=" + parameterMapValues + ", is=" + is + "]";
}
}
封装分发器:
package com.bjsxt.server.demo1;
import java.io.IOException;
import java.net.Socket;
import com.bjsxt.util.CloseUtil;
/**
* 一个请求与响应 就一个此对象
* @author Administrator
*
*/
public class Dispatcher implements Runnable{
private Socket client;
private Request req;
private Response rep;
private int code=200;
Dispatcher(Socket client){
this.client=client;
try {
req =new Request(client.getInputStream());
rep =new Response(client.getOutputStream());
} catch (IOException e) {
//e.printStackTrace();
code =500;
return ;
}
}
@Override
public void run() {
Servlet serv =new Servlet();
serv.service(req,rep);
try {
rep.pushToClient(code); //推送到客户端
} catch (IOException e) {
//e.printStackTrace();
}
try {
rep.pushToClient(500);
} catch (IOException e) {
e.printStackTrace();
}
CloseUtil.closeSocket(client);
}
}
package com.bjsxt.server.demo1;
public class Servlet {
public void service(Request req,Response rep){
rep.println("<html><head><title>HTTP响应示例</title>");
rep.println("</head><body>");
rep.println("欢迎:").println(req.getParameter("uname")).println("回来");
rep.println("</body></html>");
}
}
多请求处理,多态::::::::::
package com.bjsxt.server.demo2;
import java.util.HashMap;
import java.util.Map;
/**
* 上下文
* @author Administrator
*
*/
public class ServletContext {
//为每一个servlet取个别名,Servlet是一个对象,这样可以节省资源。
// login -->LoginServlet
private Map<String,Servlet> servlet ;
//url -->login
// /log -->login
// /login -->login
private Map<String,String> mapping;
ServletContext(){
servlet =new HashMap<String,Servlet>();
mapping =new HashMap<String,String>();
}
public Map<String, Servlet> getServlet() {
return servlet;
}
public void setServlet(Map<String, Servlet> servlet) {
this.servlet = servlet;
}
public Map<String, String> getMapping() {
return mapping;
}
public void setMapping(Map<String, String> mapping) {
this.mapping = mapping;
}
}
package com.bjsxt.server.demo2;
import java.util.Map;
public class WebApp {
private static ServletContext contxt;
static{
contxt =new ServletContext();
Map<String,String> mapping =contxt.getMapping();
mapping.put("/login", "login");
mapping.put("/log", "login");
mapping.put("/reg", "register");
Map<String,Servlet> servlet =contxt.getServlet();
servlet.put("login", new LoginServlet());
servlet.put("register", new RegisterServlet());
}
public static Servlet getServlet(String url){
if((null==url)||(url=url.trim()).equals("")){
return null;
}
return contxt.getServlet().get(contxt.getMapping().get(url));
}
}
package com.bjsxt.server.demo2;
/**
* 抽象为一个父类
* @author Administrator
*
*/
public abstract class Servlet {
public void service(Request req,Response rep) throws Exception{
this.doGet(req,rep);
this.doPost(req,rep);
}
public abstract void doGet(Request req,Response rep) throws Exception;
public abstract void doPost(Request req,Response rep) throws Exception;
}
package com.bjsxt.server.demo2;
public class LoginServlet extends Servlet{
@Override
public void doGet(Request req,Response rep) throws Exception {
String name = req.getParameter("uname");
String pwd =req.getParameter("pwd");
if(login(name,pwd)){
rep.println("登录成功");
}else{
rep.println("登录失败");
}
}
public boolean login(String name,String pwd){
return name.equals("bjsxt") && pwd.equals("12346");
}
@Override
public void doPost(Request req,Response rep) throws Exception {
}
}
package com.bjsxt.server.demo2;
public class RegisterServlet extends Servlet{
@Override
public void doGet(Request req,Response rep) throws Exception {
}
@Override
public void doPost(Request req,Response rep) throws Exception {
rep.println("<html><head><title>返回注册</title>");
rep.println("</head><body>");
rep.println("你的用户名为:"+req.getParameter("uname"));
rep.println("</body></html>");
}
}
package com.bjsxt.server.demo2;
import java.io.IOException;
import java.net.Socket;
import com.bjsxt.util.CloseUtil;
/**
* 一个请求与响应 就一个此对象
* @author Administrator
*
*/
public class Dispatcher implements Runnable{
private Socket client;
private Request req;
private Response rep;
private int code=200;
Dispatcher(Socket client){
this.client=client;
try {
req =new Request(client.getInputStream());
rep =new Response(client.getOutputStream());
} catch (IOException e) {
//e.printStackTrace();
code =500;
return ;
}
}
@Override
public void run() {
try {
Servlet serv =WebApp.getServlet(req.getUrl());
if(null==serv){
this.code=404; //找不到处理
}else{
serv.service(req, rep);
}
rep.pushToClient(code); //推送到客户端
}catch (Exception e) {
e.printStackTrace();
this.code=500;
}
try {
rep.pushToClient(500);
} catch (IOException e) {
e.printStackTrace();
}
req.close();
rep.close();
CloseUtil.closeSocket(client);
}
我们存的是一个servlet对象,在map中,存对象是很耗性能的,接下来就是要处理这个对象。
改成存字符串。
package com.bjsxt.server.demo3;
import java.util.HashMap;
import java.util.Map;
/**
* 上下文
* @author Administrator
*
*/
public class ServletContext {
//为每一个servlet取个别名
// login -->com.bjsxt.server.demo03.LoginServlet
private Map<String,String> servlet ;
//url -->login
// /log -->login
// /login -->login
private Map<String,String> mapping;
ServletContext(){
servlet =new HashMap<String,String>();
mapping =new HashMap<String,String>();
}
public Map<String, String> getServlet() {
return servlet;
}
public void setServlet(Map<String, String> servlet) {
this.servlet = servlet;
}
public Map<String, String> getMapping() {
return mapping;
}
public void setMapping(Map<String, String> mapping) {
this.mapping = mapping;
}
}
反射::::::
package com.bjsxt.server.demo3;
import java.util.Map;
public class WebApp {
private static ServletContext contxt;
static{
contxt =new ServletContext();
Map<String,String> mapping =contxt.getMapping();
mapping.put("/login", "login");
mapping.put("/log", "login");
mapping.put("/reg", "register");
Map<String,String> servlet =contxt.getServlet();
servlet.put("login", "com.bjsxt.server.demo3.LoginServlet");
servlet.put("register", "com.bjsxt.server.demo3.RegisterServlet");
}
public static Servlet getServlet(String url) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
if((null==url)||(url=url.trim()).equals("")){
return null;
}
//根据字符串(完整路径)创建对象
//return contxt.getServlet().get(contxt.getMapping().get(url));
String name=contxt.getServlet().get(contxt.getMapping().get(url));
return (Servlet)Class.forName(name).newInstance();//确保空构造存在
}
}
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException {
String str ="abc";
//Class对象
//对象.getClass()
Class<?> clz =str.getClass();
//类.class
clz =String.class;
//完整路径
clz=Class.forName("java.lang.String");
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class<?> clz =Class.forName("com.bjsxt.server.demo03.LoginServlet");
// 调用空构造 确保空构造存在
Servlet ser=(Servlet)clz.newInstance();
//retrun ser;
}
}
修改配置::加入配置文件:::::
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.bjsxt.server.demo4.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/g</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>reg</servlet-name>
<servlet-class>com.bjsxt.server.demo4.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>reg</servlet-name>
<url-pattern>/reg</url-pattern>
</servlet-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8" ?>
<persons>
<person>
<name>至尊宝</name>
<age>9000</age>
</person>
<person>
<name>白晶晶</name>
<age>7000</age>
</person>
</persons>
package com.bjsxt.xml;
public class Person {
private String name;
private int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.bjsxt.xml;
import java.io.IOException;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class ParseDemo01 {
/**
* @param args
* @throws SAXException
* @throws ParserConfigurationException
* @throws IOException
*/
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
//1、获取解析工厂
SAXParserFactory factory=SAXParserFactory.newInstance();
//2、从解析工厂获取解析器
SAXParser parse =factory.newSAXParser();
//3、加载文档 Document 注册处理器
//4、编写处理器
PersonHandler handler=new PersonHandler();
parse.parse(Thread.currentThread().getContextClassLoader()
.getResourceAsStream("com/bjsxt/xml/person.xml")
,handler );
List<Person> persons =handler.getPersons();
for(Person p:persons){
System.out.println(p.getName()+"-->"+p.getAge());
}
}
}
package com.bjsxt.xml;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* 存储对象
* @author Administrator
*
*/
public class PersonHandler extends DefaultHandler {
private List<Person> persons;
private Person person;
private String tag;//记录标签名
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
//System.out.println("处理文档开始");
persons =new ArrayList<Person>();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println("开始一个元素" +qName);
if(null!=qName){
tag=qName;
}
if(null!=qName &&qName.equals("person")){
person =new Person();
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String str =new String(ch,start,length);
if(null!=tag &&tag.equals("name")){
//System.out.println(new String(ch,start,length));
person.setName(str);
}else if(null!=tag &&tag.equals("age")){
Integer age = Integer.valueOf(str);
person.setAge(age);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//System.out.println("结束一个元素" +qName);
if(qName.equals("person")){
this.persons.add(person);
}
tag =null;
}
@Override
public void endDocument() throws SAXException {
System.out.println("文档处理结束");
}
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.bjsxt.server.demo4.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/g</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>reg</servlet-name>
<servlet-class>com.bjsxt.server.demo4.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>reg</servlet-name>
<url-pattern>/reg</url-pattern>
</servlet-mapping>
</web-app>
package com.bjsxt.server.demo4;
/*
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.bjsxt.server.demo4.LoginServlet</servlet-class>
</servlet>
*/
public class Entity {
private String name;
private String clz;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClz() {
return clz;
}
public void setClz(String clz) {
this.clz = clz;
}
}
package com.bjsxt.server.demo4;
import java.util.ArrayList;
import java.util.List;
/*
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/log</url-pattern>
</servlet-mapping>
*/
public class Mapping {
private String name;
private List<String> urlPattern;
public Mapping(){
urlPattern =new ArrayList<String>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getUrlPattern() {
return urlPattern;
}
public void setUrlPattern(List<String> urlPattern) {
this.urlPattern = urlPattern;
}
}
package com.bjsxt.server.demo4;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class WebHandler extends DefaultHandler{
private List<Entity> entityList;
private List<Mapping> mappingList;
private Entity entity;
private Mapping mapping;
private String beginTag ;
private boolean isMap;
@Override
public void startDocument() throws SAXException {
//文档解析开始
entityList =new ArrayList<Entity>() ;
mappingList =new ArrayList<Mapping>() ;
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
//开始元素
if(null!=qName){
beginTag=qName;
if(qName.equals("servlet")){
isMap=false;
entity=new Entity();
}else if(qName.equals("servlet-mapping")){
isMap=true;
mapping=new Mapping();
}
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//处理内容
if(null!=beginTag){
String str =new String(ch,start,length);
if(isMap ){
if(beginTag.equals("servlet-name")){
mapping.setName(str);
}else if(beginTag.equals("url-pattern")){
mapping.getUrlPattern().add(str);
}
}else{
if(beginTag.equals("servlet-name")){
entity.setName(str);
}else if(beginTag.equals("servlet-class")){
entity.setClz(str);
}
}
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//结束元素
if(null!=qName){
if(qName.equals("servlet")){
entityList.add(entity);
}else if(qName.equals("servlet-mapping")){
mappingList.add(mapping);
}
}
beginTag=null;
}
@Override
public void endDocument() throws SAXException {
//文档解析结束
}
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
//获取解析工厂
SAXParserFactory factory =SAXParserFactory.newInstance();
//获取解析器
SAXParser sax =factory.newSAXParser();
//指定xml+处理器
WebHandler web = new WebHandler();
sax.parse(Thread.currentThread().getContextClassLoader()
.getResourceAsStream("com/bjsxt/server/demo4/web.xml")
,web);
System.out.println(web.getEntityList());
}
public List<Entity> getEntityList() {
return entityList;
}
public void setEntityList(List<Entity> entityList) {
this.entityList = entityList;
}
public List<Mapping> getMappingList() {
return mappingList;
}
public void setMappingList(List<Mapping> mappingList) {
this.mappingList = mappingList;
}
}
package com.bjsxt.server.demo4;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class WebApp {
private static ServletContext contxt;
static{
try {
//获取解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//获取解析器
SAXParser sax = factory.newSAXParser();
//指定xml+处理器
WebHandler web = new WebHandler();
sax.parse(Thread.currentThread().getContextClassLoader()
.getResourceAsStream("com/bjsxt/server/demo4/web.xml"), web);
//将list 转成Map
contxt =new ServletContext();
Map<String,String> servlet =contxt.getServlet();
//servlet-name servlet-class
for(Entity entity:web.getEntityList()){
servlet.put(entity.getName(), entity.getClz());
}
//url-pattern servlet-name
Map<String,String> mapping =contxt.getMapping();
for(Mapping mapp:web.getMappingList()){
List<String> urls =mapp.getUrlPattern();
for(String url:urls ){
mapping.put(url, mapp.getName());
}
}
} catch (Exception e) {
}
}
public static Servlet getServlet(String url) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
if((null==url)||(url=url.trim()).equals("")){
return null;
}
//根据字符串(完整路径)创建对象
//return contxt.getServlet().get(contxt.getMapping().get(url));
String name=contxt.getServlet().get(contxt.getMapping().get(url));
return (Servlet)Class.forName(name).newInstance();//确保空构造存在
}
}
注解::::
/**
* 测试内置注解用法
* @author 尚学堂高淇
*
*/
@SuppressWarnings("all")
public class Demo01 /*extends Object*/ {
@Override
public String toString(){
return "";
}
@Deprecated
public static void test001(){
System.out.println("test001");
}
public static void test002(){
List list = new ArrayList();
List list2 = new ArrayList();
}
public static void main(String[] args) {
Date d = new Date();
test001();
}
}
注解也是一个类,点进去可以查看。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
用来抑制编译时的警告信息,与前两个注释有所不同,你需要添加一个参数才能正确使用。这些参数都定义好的。
@SuppressWarnings("unchecked")
@SuppressWarnings("all")
自定义注解:::
元注解@Retention:
SOURCE:在源文件中有效
CLASS:在CLASS文件中有效
RUNTIME:在运行时有效,可被反射读取。
package basic;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SxtAnnotation01 {
String studentName() default "";
int age() default 0;
int id() default -1; //String indexOf("abc") -1
String[] schools() default {"清华大学","北京上学堂"};
}
package basic;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SxtAnnotation02 {
String value();
}
/**
* 测试自定义注解的使用
*
*/
@SxtAnnotation01
public class Demo02 {
@SxtAnnotation01(age=19,studentName="老高",id=1001,
schools={"北京大学","北京航空航天大学"})
public void test(){
}
@SxtAnnotation02("aaaa")
public void test2(){
}
}
田田田田田田田田田田田田田田田田田lll
@Target(value={ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SxtField {
String columnName();
String type();
int length();
}
@Target(value={ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SxtTable {
String value();
}
@SxtTable("tb_student")
public class SxtStudent {
@SxtField(columnName="id",type="int",length=10)
private int id;
@SxtField(columnName="sname",type="varchar",length=10)
private String studentName;
@SxtField(columnName="age",type="int",length=3)
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
* 使用反射读取注解的信息,模拟处理注解信息的流程
* @author 尚学堂高淇
*
*/
public class Demo03 {
public static void main(String[] args) {
try {
Class clazz = Class.forName("com.bjsxt.test.annotation.SxtStudent");
//获得类的所有有效注解
Annotation[] annotations=clazz.getAnnotations();
for (Annotation a : annotations) {
System.out.println(a);
}
//获得类的指定的注解
SxtTable st = (SxtTable) clazz.getAnnotation(SxtTable.class);
System.out.println(st.value());
//获得类的属性的注解
Field f = clazz.getDeclaredField("studentName");
SxtField sxtField = f.getAnnotation(SxtField.class);
System.out.println(sxtField.columnName()+"--"+sxtField.type()+"--"+sxtField.length());
//根据获得的表名、字段的信息,拼出DDL语句,然后,使用JDBC执行这个SQL,在数据库中生成相关的表
} catch (Exception e) {
e.printStackTrace();
}
}
}
JAVA动态性之反射机制:reflection
JAVA的动态性:反射机制,动态编译,动态执行JAVASCRIPT代码。动态字节码操作。
package basic.bean;
public class User {
private int id;
private int age;
private String uname;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public void setUname() {
this.uname = "高淇";
}
public User(int id, int age, String uname) {
super();
this.id = id;
this.age = age;
this.uname = uname;
}
//javabean必须要有无参的构造方法!
public User() {
}
}
/**
* 测试各种类型(class,interface,enum,annotation,primitive type,void)对应的java.lang.Class对象的获取方式
* @author 尚学堂高淇 www.sxt.cn
*
*/
@SuppressWarnings("all")
public class Demo01 {
public static void main(String[] args) {
String path = "basic.bean.User";
try {
Class clazz = Class.forName(path);
//对象是表示或封装一些数据。 一个类被加载后,JVM会创建一个对应该类的Class对象,类的整个结构信息会放到对应的Class对象中。
//这个Class对象就像一面镜子一样,通过这面镜子我可以看到对应类的全部信息。
System.out.println(clazz.hashCode());
Class clazz2 = Class.forName(path); //一个类只对应一个Class对象
System.out.println(clazz2.hashCode());
Class strClazz = String.class;
Class strClazz2 = path.getClass();
System.out.println(strClazz==strClazz2);//true
Class intClazz =int.class;
int[] arr01 = new int[10];
int[][] arr02 = new int[30][3];
int[] arr03 = new int[30];
double[] arr04 = new double[10];
System.out.println(arr01.getClass().hashCode());
System.out.println(arr02.getClass().hashCode());
System.out.println(arr03.getClass().hashCode());//与arr01相同
System.out.println(arr04.getClass().hashCode());
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 应用反射的API,获取类的信息(类的名字、属性、方法、构造器等)
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class Demo02 {
public static void main(String[] args) {
String path = "basic.bean.User";
try {
Class clazz = Class.forName(path);
//获取类的名字
System.out.println(clazz.getName());//获得包名+类名:com.bjsxt.test.bean.User
System.out.println(clazz.getSimpleName()); //获的类名:User
//获取属性信息
// Field[] fields = clazz.getFields(); //只能获得public的field
Field[] fields = clazz.getDeclaredFields();//获得所有的field
Field f = clazz.getDeclaredField("uname");
System.out.println(fields.length);
for(Field temp:fields){
System.out.println("属性:"+temp);
}
//获取方法信息
Method[] methods = clazz.getDeclaredMethods();
Method m01 = clazz.getDeclaredMethod("getUname", null);
//如果方法有参,则必须传递参数类型对应的class对象
Method m02 = clazz.getDeclaredMethod("setUname", String.class);
for(Method m:methods){
System.out.println("方法:"+m);
}
//获得构造器信息
Constructor[] constructors = clazz.getDeclaredConstructors();
Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
System.out.println("获得构造器:"+c);
for(Constructor temp:constructors){
System.out.println("构造器:"+temp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 通过反射API动态的操作:构造器、方法、属性
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class Demo03 {
public static void main(String[] args) {
String path = "basic.bean.User";
try {
Class<User> clazz = (Class<User>) Class.forName(path);
//通过反射API调用构造方法,构造对象
User u = clazz.newInstance(); //其实是调用了User的无参构造方法
System.out.println(u);
Constructor<User> c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
User u2 = c.newInstance(1001,18,"高淇二");
System.out.println(u2.getUname());
//通过反射API调用普通方法
User u3 = clazz.newInstance();
Method method = clazz.getDeclaredMethod("setUname", String.class);
method.invoke(u3, "高淇三"); //u3.setUname("高淇三");
System.out.println(u3.getUname());
//通过反射API操作属性
User u4 = clazz.newInstance();
Field f = clazz.getDeclaredField("uname");
f.setAccessible(true); //这个属性不需要做安全检查了,可以直接访问
f.set(u4, "高淇四"); //通过反射直接写属性
System.out.println(u4.getUname()); //通过反射直接读属性的值
System.out.println(f.get(u4));
} catch (Exception e) {
e.printStackTrace();
}
}
}
反射性能问题:
setAccessible:启用和禁用访问安全检查的开关,true表示取消安全访问检查。禁止安全检查,可以提高反射的效率。
可以考虑使用:cglib/javaassist
/**
* 通过跳过安全检查,提高反射效率
* 三种执行方法的效率差异比较
*
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class Demo06 {
public static void test01(){
User u = new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
u.getUname();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
}
public static void test02() throws Exception{
User u = new User();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getUname", null);
// m.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
m.invoke(u, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射动态方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
}
public static void test03() throws Exception{
User u = new User();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getUname", null);
m.setAccessible(true); //不需要执行访问安全检查
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
m.invoke(u, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射动态方法调用,跳过安全检查,执行10亿次,耗时:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws Exception {
test01();
test02();
test03();
}
}
反身的效率大概是有30倍的差距。
反射操作泛型:
- ParameterizedType: 表示一种参数化的类型,比如Collection<String>
- GenericArrayType: 表示一种元素类型是参数化类型或者类型变量的数组类型
- TypeVariable: 是各种类型变量的公共父接口
- WildcardType: 代表一种通配符类型表达式,比如?, ? extends Number, ? super Integer【wildcard是一个单词:就是“通配符”】
package basic;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import basic.bean.User;
/**
* 通过反射获取泛型信息
* @author dell
*
*/
public class Demo04 {
public void test01(Map<String,User> map,List<User> list){
System.out.println("Demo04.test01()");
}
public Map<Integer,User> test02(){
System.out.println("Demo04.test02()");
return null;
}
public static void main(String[] args) {
try {
//获得指定方法参数泛型信息
Method m = Demo04.class.getMethod("test01", Map.class,List.class);
Type[] t = m.getGenericParameterTypes();
for (Type paramType : t) {
System.out.println("#"+paramType);
if(paramType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("泛型类型:"+genericType);
}
}
}
//获得指定方法返回值泛型信息
Method m2 = Demo04.class.getMethod("test02", null);
Type returnType = m2.getGenericReturnType();
if(returnType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("返回值,泛型类型:"+genericType);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 通过反射获取注解信息
* @author 尚学堂高淇
*
*/
public class Demo05 {
public static void main(String[] args) {
try {
Class clazz = Class.forName("com.bjsxt.test.annotation.SxtStudent");
//获得类的所有有效注解
Annotation[] annotations=clazz.getAnnotations();
for (Annotation a : annotations) {
System.out.println(a);
}
//获得类的指定的注解
SxtTable st = (SxtTable) clazz.getAnnotation(SxtTable.class);
System.out.println(st.value());
//获得类的属性的注解
Field f = clazz.getDeclaredField("studentName");
SxtField sxtField = f.getAnnotation(SxtField.class);
System.out.println(sxtField.columnName()+"--"+sxtField.type()+"--"+sxtField.length());
//根据获得的表名、字段的信息,拼出DDL语句,然后,使用JDBC执行这个SQL,在数据库中生成相关的表
} catch (Exception e) {
e.printStackTrace();
}
}
}