Lambda表达式

Lambda表达式:
Lambda表达式是Java8之后的新特性
Lambda表达式是函数式编程
Java-->面向对象语言 block代码块(闭包) 函数式编程(接近于面向过程) --> 面向对象
什么是函数式编程?函数式编程(英语:functional programming)或称函数程序设计,
又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数(cos sin tan)计算,
并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是λ演算(lambda calculus)。
而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。
ps:λ这个符号可以在搜狗输入法的符号中显示

而在面向对象编程中,面向对象程序设计(英语:Object-oriented programming,缩写:OOP)
是种具有对象概念的程序编程范型,同时也是一种程序开发的方法。它可能包含数据、属性、代码与方法。
对象则指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、
灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的数据。在面向对象程序编程里,
计算机程序会被设计成彼此相关的对象。

Lambda表达式能干什么
将接口的实现方式重匿名内部类的形式简化为了一个函数式表达式方式
简化接口实现

语法:
(形参参数) -> 表达式 或{方法体};
ps:
Lambds表达式就是实现了当前接口中的方法及简
void show();
() -> {System.out.println("我是Lambda表达式")};

1.形参列表
形参列表允许省略参数类型,若形参列表中只有一个参数,形参列表的原括号也可以省略
ps:形参列表 对应的是 接口中所需要实现方法的 形参列表
void show(int a, int b);
void display(int c);
(int a,int b) -> {实现};
(int a) -> {实现};
a -> {实现};

2.箭头(->)
必须是英文状态下的符号 减号(-) + 大于号(>) 指向实现代码块


3.代码块:
若代码块只包含一条语句,Lambda表达式允许允许省略花括号
若Lambda表达式中只有一条return,可以省略return关键字
若Lambda表达式中有多条语句(实现方法的逻辑)不能省略大括号

ps:Java中Lambda表达式的结合需要和接口完成
Stream API --> 流式编程
看Lambda包Test类

/**
 * 
 */
package com.qfedu.Day25.Lambda;

import java.util.ArrayList;

/**
 * Description: 实现Lambda表达式语法<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:Test.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class Test {
     public static void main(String[] args) {
         //void show();
        InteFaceB b = () ->{
            System.out.println("B接口中方法的实现");
        };
        b.showB();
        //简化版本
        InteFaceB b1 = () -> System.out.println("B中接口的实现");
        b1.showB();
        //void show(int a);
        InteFaceC c = (int a) ->{
            System.out.println("接口C中的方法:"+a);
        };
        c.showC(10);
        //简化版本 Lambda表达式会推断接口提供方法的数据类型
        InteFaceC c1 = (a) -> System.out.println("接口C中的方法:"+a);
        c1.showC(1);
        //ArrayList<Integer> array = new  ArrayList<>();
        InteFaceC c2 = a -> System.out.println("接口C中方法"+a);
        c2.showC(2);
        //void show(int a,int b)
        InteFaceD d = (int a, int bi) -> {
            System.out.println("接口D中的方法实现"+(a+bi));
        };
        //简化版本
        InteFaceD d1 = (a,bi) ->{
            System.out.println("接口D中的方法实现"+(a+bi));
        };
        //多参数的()坚决不能省略
        InteFaceD d2 = (a,bi) -> System.out.println("接口D中的方法实现"+(a+bi));
        
        //InteFaceD d3 = (a,bi) -> a+bi; 经常看到
        
    }

}


Lambda表达式还能作为参数传递
看Lambda包TestDemo类

/**
 * 
 */
package com.qfedu.Day25.Lambda;

/**
 * Description: Lambds表达式作为参数传递<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:TestDemo.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class TestDemo {
    public static void showInfosInteFaceB(InteFaceB b) {
        System.out.println("B接口");
        b.showB();
    }
    public static void showInfosInteFaceC(String message,InteFaceC c) {
        System.out.println("C接口"+message);
        c.showC(100);
    }
    public static void showInfosInteFaceD(int a,int b,InteFaceD d) {
        System.out.println("D接口");
        d.showD(a,b);
    }
    public static void main(String[] args) {
        //函数也是一种数据类型 --> 引用数据类型
        //通过一个变量来存当前函数的引用 
        //基本实现
//        showInfosInteFaceB(()->System.out.println("可以作为参数传递"));
//        showInfosInteFaceC(c -> System.out.println("可以作为参数"));
//        showInfosInteFaceD((a,b) -> System.out.println("可以作为参数"));
        
        showInfosInteFaceC("接口C的实现方式", c-> System.out.println("实现"));
        showInfosInteFaceD(300,200,(a,b)->System.out.println("实现+"+(a+b)));
    
        
    }

}

ps:Java8中若这个接口需要使Lambda表达式实现此时我们需要在这个接口上提供一个注解
@FunctionalInteFace

Lambda表达式引用全局变量和局部变量
看Lambda包TestDemo2类

/**
 * 
 */
package com.qfedu.Day25.Lambda;

/**
 * Description: Lambds表达式引用全局变量和局部变量<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:TestDemo2.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class TestDemo2 {
     static String ms1 = "Hello";
     String ms2 = "World";
     public static void main(String[] args) {
          VariableTest v = message -> {
              //引用全局变量 在Lambda中可以直接引用静态全局变量
              System.out.println(message + ms1);
              //若引用成员变量需要使用对象调用
              System.out.println(message + new TestDemo2().ms2);
              
          };
          v.sayMessage("Lambda表达式:");
          final String ms3 = "Hello World";
           VariableTest  v1  = message ->{
               //可以在Lambda表达式中直接调用局部变量
               //局部内部类-->引用局部变量时候,这个局部变量需要是final修改
               //匿名内部类是一个特殊的局部内部类
               //Lambda表达式是代替匿名内部类使用以上推断得出
               //在Lambda表达式中使用局部变量最好使用final修饰
               //虽然Java7之后可以不写final只要引用默认修饰,但是还是建议书写
              System.out.println(message + ms3);
           };
           
         
         
         
    }
}

Lambda式表达式引用构造方法和方法引用

1.引用类方法
在函数式接口中定义的抽象方法,而方法的实现是触发某个类方法实现此时我们就可以通过 :: 形式完成
看Lambda包TestDemo3

/**
 * 
 */
package com.qfedu.Day25.Lambda;

/**
 * Description: Lambda表达式引用类方法<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:TestDemo3.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class TestDemo3 {
    public static void main(String[] args) {
        //在Lambda表达式中引用静态方法
        //Lambda表达式中只有一个 return 可以省略不写
//        Converter c = (String str) ->{
//            
//            return Integer.valueOf(str);
//        };
        Converter c = str -> Integer.valueOf(str);
        Integer i = c.convert("69");
        System.out.println(i);
        
        //若Lambda不是的调用的是类方法并且参数可以进行方法传递
        // :: --> 需要有返回值 ,方法中有参数并可以应用到调用该方法,这个方法必须是静态方法
        Converter c2 = Integer::valueOf;
        Integer i2 = c.convert("72");
        System.out.println(i2);
        

    }

}

2.引用实例方法(成员方法)
在函数式接口中定义的抽象方法,而方法的实现是通过触发某类类创建的来完成时我们就可以 通过 :: 形式完成
看Lambda包TestDemo4;

/**
 * 
 */
package com.qfedu.Day25.Lambda;

/**
 * Description: Lambda表达式引用成员方法<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:TestDemo4.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class TestDemo4 {

    public static void main(String[] args) {
        //在Lambda表达式中引用成员方法
        ClassATest ca = message -> new A().show(message);
        ca.display("45");
        
        //:: --> 没有返回值, 接口中方法对参数也需要作用于调用方法中 ,当前对象
        ClassATest ca2 = new A()::show;
        ca2.display("17");
        
    }

}


版本二:
在函数式接口中定义的抽象方法,而方法上的实现是通过抽象方法中特定的对象参数来完成我们可以通过 :: 形式完成
不过 :: 之前是当前对象的数据了类型,而非 new出一个对象
看Lambda包TestDemo5;

/**
 * 
 */
package com.qfedu.Day25.Lambda;

/**
 * Description: 版本二引用成员方法<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:TestDemo5.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class TestDemo5 {

    public static void main(String[] args) {
        SubString str1 = (str,begin,end) -> str.substring(begin, end);
        String  val  = str1.sub("I LOVE U", 2, 6);
        System.out.println(val);
        //如何将当前上面Lambda转换为 :: 
        //因为当前接口中给的你方法使用的是参数作为对象调用方法
        //此时修改成 ::形式的时候就不能重新创建对象了,需要使用其对应的数据类型即可
        SubString str2 = String::substring;
        System.out.println(str2.sub("I LOVE U", 2, 6));
        
    }

}


3.引用构造方法
在函数式接口中定义的抽闲方法,而该方法的实现是通通过new 来创建对象,此时我们就可以使用 :: 形式来完成
ps:固定形式 构建对象的类型 :: new;
看Lambda包TestDemo6;

/**
 * 
 */
package com.qfedu.Day25.Lambda;

/**
 * Description: Lambda表达式引用构造方法<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:TestDemo6.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class TestDemo6 {
     public static void main(String[] args) {
        ClassBTest cb = (name,age) -> new B(name,age);
        B b1 = cb.getInstance("张三", 18);
        System.out.println(b1);
        
        //比较特殊的使用方式 引用的构造方法
        ClassBTest cb1 = B::new;
        B b2 = cb1.getInstance("李四", 20);
        System.out.println(b2);
        
    }
}


总结:
在上面两个案例中使用到了一个全新的形式 类或(对象) :: 静态方法/成员方法
若在Lambda表达式中引用了静态方法或成员方法时 只有一句话 ,可以使用 :: 形式进行简化
:: 之前 是这个方法主要的调用发起者 类/对象
:: 之后 静态方法/成员方法
ps:一定要主要 方法后面千万不要传入参数
调用方法的参数,会通过接口中方法的参数进行传递

Lambda表达式和匿名内部类的区别
1.匿名内部类可以为任意接口创建对象,不管接口中包含多少个抽象方法,只要匿名内部类实现所有方法即可
但是Lambda表达式只能为函数式接口创建对象(只能实现一个抽象方法)
2.匿名内部类可以为抽象类甚至是普通类创建对象
但是Lambda表达式只能为函数接口创建对象
3.匿名内内部类实现的抽象方法方法体允许调用接口定义默认(default)方法
但是Lambda表达式的实现是不允许调用默认方法的

Lambds的实际引用
看Lambda包TestDemo7;

/**
 * 
 */
package com.qfedu.Day25.Lambda;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * Description: Lambda表达式的实际应用<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:TestDemo7.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class TestDemo7 {
      public static void main(String[] args) {
        String[] name = {"张三","李四","王五"};
        List<String> players  = Arrays.asList(name);
        //遍历集合
        for(String str : players) {
            System.out.println(str);
        }
        //就可以这样写 流式编程方法
        players.forEach((player) -> System.out.println(player+";"));
        //最简版本
        players.forEach(System.out::println);
        
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                System.out.println("Hello Lambda");
                
            }
        }).start();
        
        new  Thread(()->System.out.println("Hello Lambda")).start();;
        
        Runnable ru = () -> System.out.println("Hello Lambda");
        new Thread(ru).start();
        
       
        //数组排序
        Arrays.sort(name, new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
            
                return o1.compareTo(o2);
            }
        });
        
        //Lambda表达式
        Comparator<String> sortByName  =  (String str1, String str2) ->{
              return str1.compareTo(str2);
            
        };
        Arrays.sort(name, sortByName);
        
        Arrays.sort(name, (str1,str2)->str1.compareTo(str2));
    
    }

}


ps:
1.需要记住形式为了Scala做准备
2.Lambda可以替换匿名内部类一次实现的方式
Lambda只能实现接口中一个抽方法.

注解:
Java5开始 Java支持对元数据的支持, 就是是Annotation(注解)
元数据: metadata描述数据的数据
注解:标签 Annotation
所有的Annotation都是java.Lang.annotation.Annotation接口的子接口
所有Annotation是一种特殊的接口

回顾注解:
@Override -->重写
@Deprecated --> 过时的
@SuppressWarings --> 压制警告
既可以放在方法上,放在变量上,放在类或接口上
使用注解需要注意:必须有三个参与才有意义
1.有注解的本身
2.被放置的位置(类,属性,方法,接口,参数上,包等等)
3.由第三方程序使用反射的手段赋予注解特殊的功能

Java5之前自带注解
Java5中提供的

@Override --> 限定子类重写父类的方法,只能在方法上
@Deprecated --> 标记当前方法已经过时,不推荐使用 只能用在方法上
@SuppressWarings --> 抑制编译器发出多种警告
@SuppressWarings(value="all") 可以应用在方法,类,属性上
Java7中提供了一个
@SafeVarargs 抑制堆污染
当方法使用可变参数和泛型参数,此时就会造成堆污染 Arrays.asList
Java8中提供一个
@FunctionalInteFace 函数式编程 -->所用在接口上


元注解:
描述注解的注解,用来限定注解可以贴在哪些程序元素上,还可以指定注解存在的周期
@Retention: 表示注解可以保存在哪一个代码时期. 保存的时期的值,封装在RetentionPolicy枚举类中:
注意:一般的,自定义的注解,使用RUNTIME.(使用反射赋予注解功能)
SOUECE:注解只能存在于源文件中,一旦编译,在字节码中就消失了.
CLASS:(缺省),注解可以存在于源文件和字节码文件中,一旦加载进JVM,在JVM中就消失了.
RUNTIME:注解可以存在于源文件,字节码文件,JVM中.

@Target:表示注解可以贴在哪些位置(类,方法上,构造器上等等).
位置的常量封装在ElementType枚举类中:
ElementType.ANNOTATION_TYPE只能修饰Annotation
ElementType.CONSTRUCTOR只能修饰构造方法
ElementType.FIELD只能修饰字段(属性),包括枚举常量
ElementType.LOCAL_VARIABLE只能修饰局部变量
ElementType.METHOD只能修饰方法
ElementType.PACKAGE只能修饰包(极少使用)
ElementType.PARAMETER只能修饰参数
ElementType.TYPE只能修饰类,接口,枚举

实现自己的注解:
语法格式:
@interface

@Retention(设置注解存储在的时间)
@Target(设置可以书写注解的位置)
public @interface 注解名{
注解中的成员:
抽象方法 --> (属性)
数据类型 方法名() default 默认值;

}

/**
 * 
 */
package com.qfedu.Day25.Annotation;

/**
 * Description: 描述类<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:Student.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
//若自定注解在注解中声明抽象方法(属性),使用注解时就需要给当前注解中的抽象方法(属性)赋值
//若注解中使用了默认值,可以修改也可以不修改
@VIP(Value="A",age=19,favs = {"你好","呵呵"})
public class Student {
    private String name;
    private int age;
    
}

/**
 * 
 */
package com.qfedu.Day25.Annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Description: 注解 <br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:VIP.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
@Retention(RetentionPolicy.RUNTIME)  //注解的声明周期就是源文件 ,编译文件和 JVM中
@Target(ElementType.TYPE) //注解可以书写的位置 类,方法和接口
public @interface VIP {
    // 抽象方法 --> 属性看
    //可以在注解中声明的数据类型:基本数据类型, String Class 数组,枚举,Annotation
    //声明的同时就赋值,此时在外部写书注解时就不需要赋值
    String  Value();
    int age() default 19;
    String[] favs();

}
/**
 * 
 */
package com.qfedu.Day25.Annotation;

import java.lang.annotation.Annotation;
import java.util.Arrays;

/**
 * Description: 如何取出注解中的值<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:VIPDemo.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class VIPDemo {

    public static void main(String[] args) {
        //1.获取Student上的所有注解(反射)
        Annotation[] as  =   Student.class.getAnnotations();
        for(int i = 0;i<as.length;i++) {
            System.out.println(as[i]);
        }
        //2.获取Student真正的注解
        //判断当前类是否存在指定注解
        if(Student.class.isAnnotationPresent(VIP.class)) {
             //获取注解对象
            VIP vip =  Student.class.getAnnotation(VIP.class);
            String str = vip.Value();
            String[] strs  = vip.favs();
            System.out.println(str);
            System.out.println(Arrays.toString(strs));
            
            
            
        }

    }

}


ps:Spring框架中--> 注解最多 --> 动态代理模式 --> 内省模式JavaBean和Map互转


什么是测试:
软件测试: 这是软件生命周期中的一部分.--->好的软件都不是开放出来的,都是测试出来的.黑盒测试: 软件测试工程师.
黑盒测试也称功能测试,它是通过测试来检测每个功能是否都能正常使用。
在测试中,把程序看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据而产生正确的输出信息。
黑盒测试着眼于程序外部结构,不考虑内部逻辑结构,主要针对软件界面和软件功能进行测试。
黑盒测试是以用户的角度,从输入数据与输出数据的对应关系出发进行测试的。
很明显,如果外部特性本身设计有问题或规格说明的规定有误,用黑盒测试方法是发现不了的。

作用:
黑盒测试法注重于测试软件的功能需求,主要试图发现下列几类错误。
功能不正确或遗漏;
界面错误;
输入和输出错误;
数据库访问错误;
性能错误;
初始化和终止错误等。

白盒测试:由软件开放工程师来测试,只有自己开放的东西自己才知道是怎么运作的..
又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。
它是按照程序内部的结构测试程序,通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进行,
检验程序中的每条通路是否都能按预定要求正确工作。 这一方法是把测试对象看作一个打开的盒子,测试人员依据程序内部逻辑结构相关信息,设计或选择测试用例,对程序所有逻辑路径进行测试,通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致。


白盒测试是一种测试用设计方法,盒子指的是被测试的软件,白盒指的是盒子是可视的,你清楚盒子内部的东西以及里面是如何运作的。
"白盒"法全面了解程序内部逻辑结构、对所有逻辑路径进行测试。测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。

单元测试(junit)属于白盒测试.
ps:无论哪种测试,都需要给当前工程添加Junit-->jar

Junit3
Junit3是针对Java5之前的版本,没有注解,需要按照规范的形式来书写测试
遵守如下规则:
1.需要先将JUnit3添加到当前项目中
2.定义一个测试类,并让该测试类继承于TestCase类,测试的类型XXXTest
看Junit包Junit3Test

/**
 * 
 */
package com.qfedu.Day25.Junit;

import junit.framework.TestCase;

/**
 * Description: 创建测试类<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:Junit3Test.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
//Junit使用的测试类必须继承TestCase
public class Junit3Test  extends TestCase{
     //定义测试方法
      /*
       *  访问权限修饰符必须是public
       *  无返回值
       *  必须以test作为方法名的前缀  testXXX 
       *  因为底层是用过反射来获取当前方法的
       *  所有异常都不要处理,一律抛出
       *  
       *  若需要执行测试类中的测试代码
       *  选中方法名 单机鼠标右键 选中 run as --> JUnit Test
       *  
       *  在某些时候在测试完成之后
       *  还对资源进行回收
       *  重写TestCase:
       *  setUp() -->测试方法之前执行
       *  tearDown() --> 测试方法之后之后
       */
        /* (non-Javadoc)
         * @see junit.framework.TestCase#setUp()
         */
        @Override
        protected void setUp() throws Exception {
             System.out.println("是在测试方法之前先执行");
        }
       
        /* (non-Javadoc)
         * @see junit.framework.TestCase#tearDown()
         */
        @Override
        protected void tearDown() throws Exception {
             System.out.println("是在测试方法执行之后执行");
        }
    
    
       //保存
       public void testSave()throws Exception{
           System.out.println("测试代码的操作了存储");
       }
       //删除
       public void testDelete()throws Exception{
           System.out.println("测试代码的操作了删除");
       }
    
    
}


Junit4
Junit4是针对Java5之后的版本,使用的是注解,推荐
步骤
1.将Junit4添加到工程中
2.定义一个测试类,不在继承TestCase类,类名必须是XXXTest
3.所有的测试方法使用的注解
看Junit包Junit4Test

/**
 * 
 */
package com.qfedu.Day25.Junit;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Description: Junit4测试类<br/>
 * Copyright (c) , 2018, JK <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name:Junit4Test.java <br/>
 * 
 * @author 千锋智哥
 * @version : 1.0
 */
public class Junit4Test {
     /*
      * Junit3中方法名必须是 testXXX
      * Junit4中不需要遵守这个规则,但是实际开发中保留这个书写形式的
      * 公有  无返回值  方法名保持和Junit3一致 testXXX  异常一律抛出
      * ps:因为为了防止冲突删除了Junit3这个测试jar包
      *    
      * 释放资源 -->Junit3中 setUp tearDownJunit4完全不需要
      * 使用   @Before @After释放资源
      * before --> 测试代码  ---> After
      * 若测代码使用BeforeClass 和 AfterClass 只会执行一次
      * BeforeClass --> before --> 测试方法  --> After --> AfterClass
      *  
      * 
      * 
      */
      //若这是一个测试方法只需在方法的上面添加注解即可
       //这两注解必须使用静态方法 只会执行一次 
       @BeforeClass
       public static void staticInit()throws Exception{
           System.out.println("Begin...");
       }
       @AfterClass
       public static void staticFinallzes()throws Exception{
           System.out.println("end...");
       }
       
      @Before
      public void init()throws Exception{
             System.out.println("初始化.....");
      }
      @After
      public void finallzes()throws Exception{
            System.out.println("销毁....");
      }
    
    
      @Test
      public  void  testSave() throws Exception{
          System.out.println("Junit4下的测试方法");
      }
      @Test
      public  void  testDelete() throws Exception{
          System.out.println("Junit4下的测试方法");
      }
     
    
}

使用断言:
一般而言,使用断言是用来做单元测试使用
什么是断言呢:期望的结果和真实结果是一样的
期望值: 执行某个方法可以得到什么效果
实际值: 执行某个方法的到的实际效果
断言成功: 实际值和期望值相同 ,显示绿色
断言失败: 实际值和期望值不同 ,显示红色


①:Assert.assertEquals(message, expected, actual):比较的值,比较两个对象值存储的数据.
三个参数:
message: 断言失败的提示信息,断言成功不会显示.
expected: 期望值
actual: 真实值
若真实值和期望值想等,则断言成功.--->绿条
②:Assert.assertSame(message, expected, actual):比较地址,是同一个对象
Assert.assertNotSame(message, expected, actual):断言不是同一个对象
③:Assert.assertTrue(message, condition):断言condition应该为TRUE.
④:Assert.assertFalse(message, condition):断言condition应该为FALSE.
⑤:Assert.assertNull(message, object):断言对象object为null.
⑥:Assert.assertNotNull(message, object):断言对象object不为null.

⑦:@Test(expected=ArithmeticException.class)
期望该方法报错,报错ArithmeticException.
⑧:@Test(timeout=400)
期望该方法在400毫秒之内执行完成.

XML
学习到目前为止我们所知道的资源文件只有一个Properties文件 键值对 并且继承于Hashtable
XML是一种可扩展标记语言和HTML类似
XML技术是W3C组织(WWW --> World Wide WEb)发布的目前通用的标准是2000年XML1.0规范
XML即可以作为一种配置文件存在,也可以作为数据传输文件

XML是一种通用的数据交换格式,许多系统都配备了XML格式文件
JSP文件档组件XML格式过度
可以知道什么是XML,如何书写正确的XML --> w3cschool ---> HTML CSS XML 菜鸟教程http://www.runoob.com/
看Info.xml
XML文件的语法:
XML文件的编码需要正式一致,一般都是UTF-8
一个XML文件必须有一对根节点,节点名需要区分大小写 节点中是不允许嵌套节点
<?xml version="1.0" encoding="UTF-8"?>
必须出现在文件的第一行而而且必须写,用来表示文件是XML文件
节点中可以书写子节点
标签<Students>中是可以添加属性

XML约束(了解)
可以对XML文件进行约束操作
dtd文件 schema 文件 --> xsd后缀名
XML中节点的创建

dtd约束文件:
<!ELEMENT contacts (linkman+)> contacts中必须有一个Linkeman节点 至少要有1个
+ 和 正则表达式是通用 ? 0或1 * 最少0个以上 :是一个1
<!ELEMENT linkman (name,email,address,group)> 在LinkeMan下需要出现以节点只能出现1个
<!ELEMENT name (#PCDATA)> p -> parse(解析) c-->Character(字符) --->解析字符串数据 只能传入字符串
<!ELEMENT email (#PCDATA)>
<!ELEMENT address (#PCDATA)>
<!ELEMENT group (#PCDATA)>
看content2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 最后一个位置是路径 因为文件已经在当前工程下了所以直接使用 -->
<!DOCTYPE contacts SYSTEM "constactsDtd.dtd">
<contacts>
   <!-- 节点中是可以书写属性 -->
    <linkman>
        <name>Jack</name>
        <email>ijack@sina.cn</email>
        <address>北京</address>
        <group>千锋教育</group>
    </linkman> 
    <linkman>
        <name>Sparrow</name>
        <email>sparrow@qq.com</email>
        <address>北京</address>
        <group>千锋教育</group>
    </linkman>
    <linkman>
        <name>Lily</name>
        <email>lily@163.com</email>
        <address>北京</address>
        <group>千锋教育</group>
    </linkman>
</contacts>

schema 文件 --> xsd后缀名
看content.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--xmlns 约束来源
    xmlns:xs 约束的依据
    xs:schemaLocation 约束的位置 -->
<contacts xmlns="http://qfedu.com"  
    xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
    xs:schemaLocation="http://qfedu.com contactsSchema.xsd">
    <linkman id="1" >
        <name>Jack</name>
        <email>ijack@sina.cn</email>
        <address>北京</address>
        <group>千锋教育</group>
    </linkman> 
    <linkman id="2">
        <name>Sparrow</name>
        <email>sparrow@qq.com</email>
        <address>北京</address>
        <group>千锋教育</group>
    </linkman>
    <linkman id="3">
        <name>Lily</name>
        <email>lily@163.com</email>
        <address>北京</address>
        <group>千锋教育</group>
    </linkman>
</contacts>

Web概述:
原始年代1990-1992:
1990年,HTML标记语言的出现标志Web开发时代的到来.
B/S架构开始在之后的岁月中不断的发展壮大,攻城略地蚕食传统C/S的领域。
如同所有的新生事物一样,在web的史前岁月,web的开发 技术在在html标记诞生后,
无论是在服务端还客户端都缓慢的发展着,在相当长的一个时间内,它并未像今天这样辉煌,
甚至于只是静态的文本标识.
关键字:HTML
技术特性:静态文本显示,表现力和交互能力不足。(hao123)
封建诸侯年代1993-1996:
1993年,NCSA提出了CGI1.0草案。Web开发终于迎来了它的第二次重大飞跃,伴随着CGI,
带来Web的动态处理能力,CGI就是这个时代的国王。(服务器端动态生成内容)
1994年,PHP
1996年,ASP
关键字:CGI(Common Gateway Interface )(Perl&&C&&Python)
技术特性:实现了客户端和服务器端的动态交互, 在程序代码中写html标记,
是面向过程的开发方式,用多进程运行
注:CGI是Web服务器端组件,都能产生Web动态页面输出
工业文明1996-1999:
1997年,Sun公司推出了Servlet规范。Java阵营终于迎来了自己的web英雄。
1998年JSP技术诞生,Servlet和JSP再加上JavaBean,
让JavaWeb开发者同时拥有了类似CGI程序的集中处理功能和类似于PHP 的HTML嵌入功能,
此外,Java的运行编译技术也大提高了Servlet和JSP的执行效率
1998年,Sun发布了EJB1.0标准
1999年,Sun正式发布了J2EE的第一个版本,紧接着,遵循J2EE,
为企业级应用提供支持平台的各类应用服务器争先恐后的涌现出来(WebSphere,WebLogic,JBoss),
(同时2001微软发布了ASP.NET技术)

查看HTTP数据规范格式:
请求消息的结构:
一个请求行、若干请求头、以及实体内容,其中的一些请求头和实体内容都是可选的,请求头和实体内容之间要用空行隔开。
Request:
常见的请求头:
<1>、Accept:浏览器可接受的MIME类型(Tomcat安装目录/conf/web.xml中查找)
MIME的英文全称是"Multipurpose Internet Mail Extensions" 多用途互联网邮件扩展,它是一个互联网标准,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。服务器会将它们发送的多媒体数据的类型告诉浏览器, 文件内容的类型:
MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型

<2>、Accept-Charset:告知服务器,客户端支持哪种字符集
<3>、Accept-Encoding:浏览器能够进行解码的数据编码方式
<4>、Accept-Language:浏览器支持的语言。
<5>、Referer:当前页面由哪个页面访问过来的。
<6>、Content-Type:通知服务器,请求正文的MIME类型。
取值:application/x-www-form-urlencoded默认值
对应的是form表单的enctype属性
<7>、Content-Length:请求正文的长度
<8>、If-Modified-Since:通知服务器,缓存的文件的最后修改时间。
<9>、User-Agent:通知服务器,浏览器类型.
<10>、Connection:表示是否需要持久连接。如果服务器看到这里的值为“Keep -Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接
<11>、Cookie:这是最重要的请求头信息之一(会话有关)


响应消息的结构:
一个状态行、若干响应头、以及实体内容 ,其中的一些消息头和实体内容都是可选的,响应头和实体内容之间要用空行隔开。
Response:
常见的响应头:
<1>、Location:制定转发的地址。需与302/307响应码一同使用
<2>、Server:告知客户端服务器使用的容器类型
<3>、Content-Encoding:告知客户端服务器发送的数据所采用的压缩格式
<4>、Content-Length:告知客户端正文的长度
<5>、Content-Type:告知客户端正文的MIME类型
Conent-Type:text/html;charset=UTF-8
<6>、Refresh:定期刷新。还可以刷新到其他资源
Refresh:3;URL=otherurl
3秒后刷新到otherurl这个页面
<7>、Content-Disposition:指示客户端以下载的方式保存文件。
Content-Disposition:attachment;filename=2.jpg
<8>、Expires:网页的有效时间。单位是毫秒(等于-1时表示页面立即过期)
Cache-Control:no-cache
Pragma:no-cache
控制客户端不要缓存
<9>、Set-Cookie:SS=Q0=5Lb_nQ; path=/search服务器端发送的Cookie(会话有关)


Get和Post
总结:
1.本质
Get是向服务器发索取数据的一种请求,而Post是向服务器提交数据的一种请求

2.服务器端获取值的方法
get方式提交的数据,服务器端使用request.QueryString获取变量的值
post方式提交的数据,服务器端使用request.Form获取数据

3.安全性
get方式安全性低,post方式较安全。但是post方式执行效率要比get方式差一些。

4.机制
get是把参数数据队列加到提交表单的action属性所指的URL中,
如:http://www.xxx.com?sessonid=db23434&name=hongten&age=20。
在URl中,值和表单南日各个字段一一对应,并且这些在URl中对用户来说是可见的,
即用户时可以看到的。如:name=hongten。
post是通过HTTP post机制,
将表单内各个字段与其内容放置在HTML HEADER内一起传送到action属性所指的URL地址,
对于用户来说,这是透明的。

5.大小
URL不存在参数上限的问题,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系统的支持。
理论上讲,POST是没有大小限制的,HTTP协议规范也没有进行大小限制,说“POST数据量存在80K/100K的大小限制”是不准确的,POST数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。

get方式的安全性较post方式要差一些,所以,包含一些重要的信息的话,简易使用post数据提交方式
在做查询统计的时候,使用get方式要更好一些;而在做数据的添加,修改或删除操作时,建议使用post数据提交方式


后记:
Java web中用到的技术
HTML:
超文本标记语言,标准通用标记语言下的一个应用。
“超文本”就是指页面内可以包含图片、链接,甚至音乐、程序等非文字元素。
超文本标记语言的结构包括“头”部分(英语:Head)、和“主体”部分(英语:Body),
其中“头”部提供关于网页的信息,“主体”部分提供网页的具体内容。
ps:静态网页 的组成

CSS:
层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)
或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可以静态地修饰网页,
还可以配合各种脚本语言动态地对网页各元素进行格式化。 
CSS 能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体字号样式,拥有对网页对象和模型样式编辑的能力。
ps:对静态或动态网页装饰用的

JavaScript
JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。
它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,
最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能
ps:添加特效

Servlet
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,
用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容。
ps:让网页与服务器之间具备传输数据的能力

JSP
JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计
它是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。
JSP技术有点类似ASP技术,它是在传统的网页HTML(标准通用标记语言的子集)
文件(*.htm,*.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件,后缀名为(*.jsp)。
用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能在其他操作系统上运行
ps:一种让Servlet简化的语言

AJAX
是一种用于创建更好更快以及交互性更强的Web应用程序的技术
ps:可以提高网页和服务器之间的连接效率

JQuery
JQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。
jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,
提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
ps:加强版JavaScript

Bootstrap
Bootstrap是美国Twitter公司基于HTML、CSS、JavaScript 开发的简洁、直观、强悍的前端开发框架,使得 Web 开发更加快捷。
ps:让HTML、CSS、JavaScript 更加便捷

框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;
另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。
  可以说,一个框架是一个可复用的设计构件,它规定了应用的体系结构,阐明了整个设计、协作构件之间的依赖关系、
责任分配和控制流程,表现为一组抽象类以及其实例之间协作的方法,它为构件复用提供了上下文(Context)关系。
因此构件库的大规模重用也需要框架。
  应用框架指的是实现了某应用领域通用完备功能(除去特殊应用的部分)的底层服务。
使用这种框架的编程人员可以在一个通用功能已经实现的基础上开始具体的系统开发。
框架提供了所有应用期望的默认行为的类集合。具体的应用通过重写子类(该子类属于框架的默认行为)或组装对象来支持应用专用的行为。
  应用框架强调的是软件的设计重用性和系统的可扩充性,以缩短大型应用软件系统的开发周期,提高开发质量。
与传统的基于类库的面向对象重用技术比较,应用框架更注重于面向专业领域的软件重用。应用框架具有领域相关性,
构件根据框架进行复合而生成可运行的系统。框架的粒度越大,其中包含的领域知识就更加完整。
  框架,即framework。其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。
简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。

框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;
另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。
  可以说,一个框架是一个可复用的设计构件,它规定了应用的体系结构,阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程,
表现为一组抽象类以及其实例之间协作的方法,它为构件复用提供了上下文(Context)关系。因此构件库的大规模重用也需要框架。
  应用框架指的是实现了某应用领域通用完备功能(除去特殊应用的部分)的底层服务。
使用这种框架的编程人员可以在一个通用功能已经实现的基础上开始具体的系统开发。
框架提供了所有应用期望的默认行为的类集合。
具体的应用通过重写子类(该子类属于框架的默认行为)或组装对象来支持应用专用的行为。
  应用框架强调的是软件的设计重用性和系统的可扩充性,以缩短大型应用软件系统的开发周期,
提高开发质量。与传统的基于类库的面向对象重用技术比较,应用框架更注重于面向专业领域的软件重用。
应用框架具有领域相关性,构件根据框架进行复合而生成可运行的系统。框架的粒度越大,其中包含的领域知识就更加完整。

框架,即framework。其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。

SSH 为 struts+spring+hibernate 的一个集成框架,是目前较流行的一种JAVA Web应用程序开源框架

Struts
Struts是一个基于Sun J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。
由于Struts能充分满足应用开发的需求,简单易用,敏捷迅速,在过去的一年中颇受关注。
Struts把Servlet、JSP、自定义标签和信息资源(message resources)整合到一个统一的框架中,
开发人员利用其进行开发时不用再自己编码实现全套MVC模式,极大的节省了时间,所以说Struts是一个非常不错的应用框架。

Spring
   Spring是一个解决了许多在JavaEE开发中常见的问题的强大框架。
Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。
Spring的架构基础是基于使用JavaBean属性的Inversion of Control容器。
然而,这仅仅是完整图景中的一部分:Spring在使用IOC容器作为构建完关注所有架构层的完整解决方案方面是独一无二的。
Spring提供了唯一的数据访问抽象,包括简单和有效率的JDBC框架,极大的改进了效率并且减少了可能的错误。
Spring的数据访问架构还集成了Hibernate和其他O/R mapping解决方案。
Spring还提供了唯一的事务管理抽象,它能够在各种底层事务管理技术,例如JTA或者JDBC事务提供一个一致的编程模型。
Spring提供了一个用标准Java语言编写的AOP框架,它给POJOs提供了声明式的事务管理和其他企业事务--如果你需要--还能实现你自己的aspects。
这个框架足够强大,使得应用程序能够抛开EJB的复杂性,同时享受着和传统EJB相关的关键服务。
Spring还提供了可以和IoC容器集成的强大而灵活的MVC Web框架。

Hibernate
  Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,
使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,
既可以在Java的客户端程序实用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,
Hibernate可以在应用EJB的JavaEE架构中取代CMP,完成数据持久化的重任。

SSM为 Spring+SpringMVC+MyBatis的一个集成框架,是目前较流行的一种JAVA Web应用程序开源框架
Spring 
    Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,
由Rod Johnson 在其著作Expert One-On-One JavaEE Development and Design中阐述的部分理念和原型衍生而来。
它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。
然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
SpringMVC     
    Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。
Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。
MyBatis
  MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。
MyBatis是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)MyBatis 
消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,
将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

原文地址:https://www.cnblogs.com/lijun199309/p/9664417.html