1. Linux基本知识
  • Linux目录结构
  • 相对路径和绝对路径
    相对路径:文件或目录相对于当前工作目录的位置
    绝对路径:文件或目录相对于根目录的位置
相对路径:
	.表示当前目录
 	..表示上一级目录
 	绝对路径:
 	/home/soft01
  • pwd 显示当前的工作目录
  1. Java编译运行环境
    编写的java源文件(.java)首先经过编译,生成字节码文件(.class)。
    JVM为字节码文件提供运行环境(标准的.class文件,可以在不同的JVM上运行,一次编译,处处运行)。
  2. JDK、JRE、JVM
    JDK(Java Development Kit):Java开发工具包
    JRE(Java Runtime Encironment) :Java运行环境
    JVM:Java虚拟机
    运行一个java程序所需的最小环境为JRE,开发一个java程序需要最小的环境为JDK
  3. Java基本数据类型
    byte,short,char,int、long,double,boolean,float
  4. 重写和重载的区别:
    重载:
    在类内,相同的方法的名称,但参数的个数和类型不相同
    重写:
    跨类且继承,子类把长辈的方法体覆盖
  5. equals跟==的区别:
  • ==是一个判断相等的运算符
    这个运算符的两边如果是基本数据类型,判断的是基本数据类型的值是否相等。 这个运算符的两边如果是某个类类型的对象,判断的是两个对象是否是同一个地址,如果地址相同,那么内容就一定相同,如果地址不相同,内容就不一定相同。
  • equals方法不能判断基本数据类型的数据,只能判断对象是否相等。如果没有重写equals方法,那么equals方法判断的是地址。
  1. synchornized
    synchornized同步,asynchronized 异步
    同步资源,同步锁
  • 此关键字修饰在方法上
    比如:
public synchornized void method1(){
		//代码块
	}

当线程1调用method1方法的时候,
线程2,必须等待线程1调用完method1方法,
后才能调用method1方法

  • 此关键字修饰在对象上 ,同步块
    比如:
synchornized(某个对象){
   代码块
}

当线程1访问同步块的时候,
线程2,必须等待线程1调用完同步块,
后才能调用同步块

  • 此关键字修饰在类上, 同步块
    比如:
synchornized(类名.class){
   代码块
}
当线程1访问同步块的时候,

线程2,必须等待线程1调用完同步块,
后才能调用同步块

用户写线程有两种方式:
方式一:
用户自己写线程开发

Runnable r=new Runnable(){重写run方法}//写线程的逻辑
	 Thread t1=new Thread(r);
	 Thread t2=new Thread(r);
	      ...
	 线程对象.start();

方式二:
java给程序员提供一个线程池的概念

线程池:
就是把若干用户线程添加到线程池中,由线程池来统一管理线程

为什么要使用线程池:
  1.减少了创建和销毁线程的次数,每个工作线程都可以被重复
    使用,或利用,可以并发执行多个任务
  2.可以根据系统的承受能力,调整线程池中的工作线程数目
    防止因为消耗过多的内存,而是服务器宕机(down)
  结论:就是java给提供一批api方法,用于更好的管理线程
       程序员只需要专注于写run方法(线程的逻辑)
线程池的使用:
  有一个Executors的线程工具类,此类提供了若干静态方法
  这些静态方法用于生成线程池的对象
  
 1.Executors.newSingleThreadExecutor();
   创建一个单线程的线程池,这个线程池只有一个线程在工作
   即单线程执行任务,如果这个唯一的线程因为异常结束,
   那么就会有一个新的线程来替代它,,因此线程池保证所有的
   任务是按照任务的提交顺序来执行
 2.Executors.newFixedThreadPool();
   创建固定大小的线程池,每次提交一个任务就创建一个线程
   直到线程达到线程池的最大的大小,线程池的大小一旦达到
   最大就会保持不变,如果某个线程因为执行异常而结束,
   那么久会补充一个新的线程
 3.Executors.newCachedThreadPool();
   创建了一个可以缓冲的线程池,如果线程大小超过处理任务
   所需要的线程,那么就回收部分线程,当线程数增加的时候
   此线程池由可以智能添加新的线程来处理任务
   此线程不会对线程池大小做限制,线程池的大小完全依赖
   操作系统能够创建的最大大小
 4.Executors.newScheduledThreadPool()
   创建一个大小无限制的线程池,此线程池支持定时以及
   周期性的执行任务的需求
  1. 网络编程:
    分类:
  • tcp编程(重点):tcp 传输控制协议,能够保证在数据传递时,数据不丢失。
    tcp/ip:传输控制/网络协议
    传输控制协议用户传输数据
    网络协议用户定位源和目标
    数据在传输的过程中,如果数据丢失,会重传,
    目标正确接收完毕
  • udp编程(略掉):不保证数据能够传输到目标
若干名词:
 -socket:套接字
 -ip地址
    ipv4  4段地址
	ipv6  6段地址
   用于唯一确定网络上的计算机
 -端口号:
    每台计算机都有65535个端口  0-65535
	能够访问计算的"门"
	特殊的端口:
	  80端口:http协议的默认端口   超文本传输协议
	  21端口:ftp协议的默认端口    文件传输协议
	  25端口:smtp协议的默认端口   邮件传输协议
   -tcp/ip:传输控制协议/网络协议
socket套接字:
  用于描述ip地址和端口号,是一个通讯链的句柄(java中引用)
  在internet上的一个主机,一般运行多少个服务的软件,同时
  就提供多少个服务,每个服务监听一个端口,不同端口对应
  不同的服务
  最终应用程序和服务器通过socket套接字建立网络连接
  发送请求和接收请求
服务端套接字
  ServerSocket类
    Socket accept();
	  用于监听,并接收到套接字的连接
	void close();
	  关闭Socket
	InetAddress getInetAddress();
	  返回此服务器套接字的本地地址
	int getLocalPort()
	  返回此套接字在其上的监听的端口号
客户端套接字
    Socket类:
	  Socket(String host,int port);
	    创建一个套接字,并将其连接到指定ip地址,和这个
		IP地址对应的端口号
	  void close()
	    关闭socket
	  InetAddress getInetAddress();
	    返回此服务器套接字的本地地址
	  int getLocalPort()
	    返回此套接字在其上的监听的端口号
jdk1.5的新特性(重点):
自动装箱和拆箱:
  装箱:把基本数据类型的数据装箱成对象类型
  拆箱:把对象的类型变成基本数据类型
  在jdk1.5及以后版本自动装箱和拆箱
     int i=10;
	 Integer ii=i;
	 int k=ii
  在jdk1.5以前的版本
     int i=10;
     Integer ii=new Integer(10);
	 int k=ii.intValue();
  1. 反射的api:
  • 反射的方式创建对象
1.用无参数构造创建对象
    Class对象.newInstance();//常用的做法
  2.用有参数构造创建对象
    Class对象.getConstructor(new Class[]{若干参数的类类型})
	         .newInstance(构造函数的参数);
	比如:
	    //有参数构造
		public User(String name,String password){
		}
		Class clazz=User.class;
	    //传统的实例化对象
		User user=new User("zhangsan","zs");
		//反射的做法:
		User user=clazz.getConstructor(new Class[]{String.class,String.class})
		               .newInstance("张三","zs");
  • 反射方式获取Field中的信息
1.获取当前类以及长辈类的public Field
    Field[] fields=Class对象.getFields();
  2.获取当前类中的所有的属性Field
    Field[] fields=Class对象.getDeclaredFields()
  3.获取当前类以及长辈类中指定的共有属性
    Field field=Class对象.getField(String fieldName);
  4.获取当前类中指定的属性
    Field field=Class对象.getDeclaredField(String fieldName);
  5.通过反射设定Field属性
    Field对象.set(Object obj,Object value);
	如果Field是私有的
	必须先执行:Field对象.setAccessable(true);//设置属性可以访问
  6.通过反射获取Field的值
    Object value=Field对象.get(object);
	如果Field是私有的
	必须先执行:Field对象.setAccessable(true);//设置属性可以访问
  • 反射方式获取Method方法信息
1.获取当前类以及长辈类的public Method
    Method[] methods=Class对象.getMethods();
  2.获取当前类中的所有的属性Field
    Method[] methods=Class对象.getDeclaredMethods()
  3.获取当前类以及长辈类中指定的共有属性
    Method method=Class对象.getMethod(String methodName,new Class[]{方法参数类型});
  4.获取当前类中指定的属性
    Method method=Class对象.getDeclaredMethod(String methodName,new Class[]{方法参数类型});
  5.通过反射动态调用Method
    Object returnValue =Method对象.invoke(Object obj,object...args);
	解析:
	  就是通过obj这个对象,调用Method对象确定的方法,给这个方法传递的参数是args
	  Method对象对应的方法放回值returnValue;
-反射获取Constructor构造函数
  -具体查看api文档
-反射获取注解Annotation
  -具体查看api文档
在哪些地方使用反射,反射的应用场景
 -用反射实现jdbc的通用查询和通用更新
 -用反射解析注解
 -单元测设,就是用反射实现的
 -常见的框架,spring框架,springmvc框架等,都是用反射实现的
 -EL表达式
 等...
反射的优点:
  大幅度提高开发效率,框架就是反射实现的,框架可以大大提高开发效率
反射的缺点:
  反射执行效率比非反射的方式执行效率低
  反射可以暴露类中的所有细节,突破了封装.
  1. 注解:
注解可以提高开发效率,但是执行效率堪忧,因为其底层解析
	注解是用反射解析的
    用注解可以替换xml配置和属性文件
	注解是一个标识,注解所代表的功能一定要用反射来实现
	这些反射的代码,用于解析(寻找注解,获取注解的属性值)
	然后根据设定的属性值,来决定是否执行一些业务功能
使用注解有三个步骤:
  1.用户定义注解  创建注解
  2.把注解应用到对应的目标上  把注解放什么地方(包,类,属性,方法,方法参数等)
  3.用反射的代码来确定是否有注解和注解属性值,
    根据是否有注解以及注解的值做相应的功能
如何定义注解:
	//程序员创建注解
	//设定MyAnnotation注应用在什么位置上
	@Target(value={ElementType.METHOD})
	//指定注解的保留策略,source级别  class级别   runtime级别
	@Retention(RetentionPolicy.RUNTIME)
	public @interface MyAnnotation {
		//注解的value属性
		public String value();
		//注解的name属性,且有默认值abc
		public String name() default "abc";
		//注解的colors属性,且是一个数组,默认值为red和blue
		public String[] colors() default {"red","blue"};
	}
元注解/源注解
    @Target和	@Retention和@Override等...都是jdk自带的注解
   1.@Target(value={ElementType.Method,...})
     指定要修饰在什么样的目标上(包,注解,类/接口,方法,属性,参数等...)
	   value取值是一个枚举类型的数据
	   ElementType:
	     ANNOTATION  注解
		 METHOD   方法
		 FIELD    属性
		 CONSTRUCTOR 构造
		 TYPE   类/接口
		 PARAMETER  方法的参数上
		 等...	 
   2.@Retention(RetentionPolicy.RUNTIME)
      注解的保留策略
	  
	  .java--.class-->jvm执行.class
	  
	 SOURCE:源代码级别,Source修饰的注解是给编译看的
	        编译器把源代码编译完毕后,在class文件中就没有注解
	 CLASSS:类级别,Class修饰的注解给类加载器看的
	        在类加载的时候可以做一系列的引导操作,
			在编译器编译完毕后注解存在,在类加载加载之后
			就要丢弃注解
     RUNTIME:运行时级别,给JVM看的,在程序运行的过程中做相关的操作
	        可以在jvm中借助反射api解析注解
注解中的属性详解:
  a.注解定义属性和接口定义的方法类似,缺省默认public
      public 类型 属性名称();
  b.定义属性是,如果没有使用default指定默认值
    则在使用注解,必须给属性赋值
	如果带有默认值,是在使用注解的时候给属性赋值为新值
	也可以使用默认值
  c.注解中的属性类型必须遵守如下要求
     可以是八种基本数据类型,枚举类型,Class类型,String类型,
	 以及上面类型的一维数组
  d.在给数组赋值的时候,如果数组只有一个值就不用写{}
  e.有一个极特殊的属性value
    如果只为该属性赋值,value=值
	但是如果注解中只有value这一个属性,那么value可以省略
把注解应用到目标
   在对应的目标上写上注解
	@MyAnnotation(value="xx",name="yy",colors={"pink","green","gay"})
	public class Demo1 {
		
		private String str;
		@MyAnnotation(value="aa",name="bb")
		public void method1(String name){
			
		}
		public void method2(){
			
		}
	}
写反射代码来解析注解:
    a.解析类上的注解
	b.解析方法上的注解
  1. lambda表达式:
lambda表达式可以称之为闭包,他是java8中的一个非常重要的特性
  很多java8新特性的写法都会用到lambda表达式
  lambda表达式允许函数作为一个方法的参数,函数作为参数
  传递到方法中,这样代码就会变得简洁
语法:
    (parameters)->expression表达式
	或
	(parameters)->{statement代码块;}
  说明:
    -可选参数声明:不需要声明参数类型,编译器统一识别参数值
	-可选参数圆括号:一个参数无需定义圆括号,多个参数需要定义圆括号
    -可选大括号:如果主体包含了一个语句,就不需要使用大括号
	-可选返回关键字:如果主体只有一个表达式返回值,则编译器
	   会自动返回值,大括号需要指定返回了一个数据值
	   
  比如:
    //不要参数,返回值为5
    ()->5
	//接受一个参数(推断出数字类型),返回参数的2倍
	x->2*x
	//接受两个参数(推断出数字类型),返回值为参数差值
	(x,y)->x-y
    //接受两个参数,返回值为x-y
	(int x,int y)->x-y
	//接受一个参数,类型为String的参数,并输出参数的值
	//推断出没有返回值,相当于方法的返回值void
	(String str)->System.out.println(str)
	//接受两个参数(推断出数字类型,返回值为参数的差值)
	(x,y)->{return (x-y);}
	
  其实lambda表达式的本质就是接口的子实现
  lambda表达式简化了匿名内部类的写法
  lambda表达式另一个写法叫做函数式编程
  注意:
    就是把接口的实现是内部类,转换成函数式写法
使用lambda表达式需要注意变量的作用域问题:
-lambda表达式引用外层的成员变量
 如果外层的成员变量为final的,则在lambda内部不能修改成员变量的值
 如果外层的成员变量不是final的,则在lambda内部能修改成员变量的值
-lambda表示式的局部变量可以不用声明为final,但必须不可以被后面
  的代码修改(即隐式的final特性)
-lambda表达式不允许声明一个与局部变量同名的参数或局部变量
2.方法的引用:
  方法的引用方式用类名::方法名,其本质还是lambda表达式
  具体的写法有四种
  -构造器的引用   语法Class::new
  -静态方法的引用 语法 Class::静态方法的名称
  -特定类任意的对象引用  语法 Class::非静态方法名称
  -特定对象的方法引用    语法 instance对象::非静态的方法的的名称
3.函数式接口
  函数式接口(FunctionalInterface)就是一个有且只有一个抽象方法
  但是可以有多个非抽象方法的接口
  函数式接口可以用lambda表达式,也可以用方法的引用
  
  在java8之前已经有部分的函数式接口
  比如:
    java.lang.Runnable
	java.util.Comparator
	java.io.FileFilter
	等...
  java1.8之后新添加的函数式接口
  java.util.function 其中包含了很多的类
  比如:
    Consumer<T>
	Predicate<T>
	Supplier<T>
	等...
	

  总结:
    使用函数式接口,可以用如下方式实现
	  1.java7的匿名内部类
	  2.lambda表达式  
	  3.方法的引用   
	  4.lambda和方法的引用都是为了提高开发效率
4.默认方法
  在接口中可以放置有方法体的方法,但方法必须用default来修饰
  在接口添加默认方法,是用来给所有的的子类提供一个功能
  在接口中还可以放置静态的方法,但静态方法需要有方法体
5.Stream流管道
 在java8中添加了一个新的抽象,称之为流Stream ,可以让程序员
 以一种声明式的方式处理数据
 Stream流的处理方式,可以把要处理的元素看成一种流,
 流在管道种传输,并且开一在管道的节点上进行处理
 处理包括:
     筛选
	 排序
	 聚合
	 等等..
 元素流在管道中经过中的操作处理,最后由最终的操作得到前面的处理结果
 
 Stream流管道的几个名词解释
 -数据源:流的源头,可以是集合,数组,IO,其他的数据源
 -聚合操作:就是在流中筛选数据的操作
    比如:filter,map,reduce,find,match,sorted等...
	
-如何生成一个Stream的流的源头
  -stream()  生成一个串行流
  -parallelStream()  生成一个并行流
  比如:
    List<String> strings=Arrays.asList("abc","bc","cba","qaz","qwe","");
	List<String> filtered=
	  strings.stream().filter(str->!str.isEmpty()).collect(Collectors.toList());
	  
-用stream的forEach
 forEach方法用来迭代流中的每个数据
 Random random=new Random();
 random.ints().limit(10).forEach(System.out::println);
 
-map方法用于映射每个元素对应的结果
  List<Integer> numbers=Arrays.asList(3,2,3,3,7,3,5);
  List<Integer> 
     lists=numbers.stream().map((i)->i*i).distinct().collect(Collectors.toList());  
-filter方法用于通过设置条件过滤元素
  List<String> strings=Arrays.asList("abc","bc","cba","qaz","qwe","");
  long count=strings.stream().filter((str)->str.isEmpty()).count();
-limit方法,用户获取指定的数量的流
 Random random=new Random();
 random.ints(0,100).limit(10).sorted().forEach(System.out:println);
-sorted方法用于对流进行排序
 Random random=new Random();
 random.ints(0,100).limit(10).sorted().forEach(System.out:println);
 
-Collectors 类实现了很多的归约操作
  List<Integer> numbers=Arrays.asList(3,2,3,3,7,3,5);
  List<Integer> 
     lists=numbers.stream().map((i)->i*i).distinct().collect(Collectors.toList());  

  List<String> strings=Arrays.asList("abc","bc","cba","qaz","qwe","");
  String str=strings.stream().filter(str->!str.isEmpty()).collect(Collectors.joining(","));
6.java8的日期操作
  java8通过发布新的Date-Time api(规范JSR310)来进一步加强对日期与
  时间的处理
  在旧版中的日期和时间api存在很多问题
   -非线程安全,java.util.Date是非线程安全,所有日期类都是可变的
   -设计很差,java.util.Date和java.sql.Date类都是日期类,重复定义
   -时区处理很麻烦,在java.util.Date并没有提供处理时区的api
      用java.util.Calendar能够控制时区
	  java.util.TimeZone能控制时区 java8
 在java8中有一个包java.time包提供很多的新的api
   -local(本地) 简化了日期和时间的处理
   -zone(时区)  通过制定的时区处理日期和时间
  1. 项目的部署:
1.把项目打包
    a.java项目打成jar包
	b.web项目打成war包
    c.项目的打包方式
	  用maven方式打包
	    右键单击项目--run as--maven build...--goals添入"package"
		要求引入的jre是jdk中的jre
		war文件或jar文件是在target目录中出现
		
		右键单击项目--run as--maven install --会把jar或war包
		打到maven本地库中
	  用非maven方式打包
	    右键单击项目--exprot--jar或war--选定路径和文件名即可
2.把war包放在tomcat目录中的webapps目录中,tomcat启动后,会
    自动把war解压成一个目录
    tomcat的启动方式分类:
	  a.利用eclipse启动
	  b.利用tomcat目录中/bin/启动文件或停止文件
	    window系统:
		    tomcat8w.exe  windows窗口版本
			或
			startup.bat   windows的黑白界面
			shutdown.bat
		linux系统:
		    startup.sh
			shotdown.sh
      c.在window系统的服务中中启动或停止tomcat服务
        此时需要把tocmat的服务安装到window系统服务中
		1、软件和环境
           环境:JDK1.8 (确保jdk环境变量已经安装)
           应用服务:Tomcat7.0(非安装版)
           操作系统:Windows8

    2、设置Tomcat为系统服务
       win+R打开运行窗口,输入cmd打开dos窗口,
		   使用cd命令将位置切换到tomcat路径下的bin文件,
		   本机是F盘下。

       先输入F:回车进入F盘,
		   然后输入命令cd F:\apache-tomcat-5.5.26\bin,
		   进入到bin文件夹。输入service命令可以查看service.bat文件
		   的使用说明,输入service.bat install service_name就可以
		   安装服务,service_name就是给服务起的名字,可以自己命名,
		   我这里起的名字是TomcatService。
	
	tomcat在放在什么样的服务器中
	  1.tomcat项目放在自己的计算机服务器中
	    服务器计算机可能在本地网络中
		服务器计算机在在远程的机房中
		  托管方式
		  非托管方式
	  2.tomcat放在远程机房中
	     购买不是机房的主机,购买的机房的中服务器中的一个空间
3.选择第二步骤中的一个方式启动tomcat
      在浏览器中,直接访问项目即可