java web知识点总结


 JAXP - DOM 
     1.XML解析           (1) XML解析方式
XML文档一般用来配置文件 , 其有两种解析方式 , 分别是 DOM 解析和 SAX 解析 , DOM是W3C组织推荐的标准(由于内存问题 , 没有被采用) , SAX是事实上的使用标准 .
           (2)XML解析器
        Crimson(Sun) , Xerces(IBM) , Aelfred2(dom4j)
           (3)XML解析开发包
        Jaxp(Sun) , Jdom , dom4j , pull(android 的sdk 自带)
     2.JAXP介绍
      Jaxp是Sun公司提供的一套XML解析API ;
      Jaxp很好的支持 DOM 和 SAX 解析 ;
      Jaxp开发包是J2SE的一部分 , 包括以下包或子包 , javax.xml , org.w3c.dom , org.xml.sax
      在Jaxp包中定义了几个工厂类 , 程序员调用这几个工厂类 , 可以得到对xml文档进行解析的DOM 或 SAX 解析对象 .
   3.相应的API解析
   4.
 JAXP – SAX解析 XML
 DOM4J解析 XML     1.dom4j介绍
      Dom4j 是 简单 灵活 开放的源代码库 , 其是由早起的JDOM开发团队分离出来的 , 与JDOM不同的是 , dom4j使用接口和抽象类 , 虽然API较为复杂 , 但是其提供了比JDOM更好的灵活性 .
      Dom4j是非常优秀的java xml api , 具有性能优异 , 功能强大 , 极易使用的特点 .
      采用dom4j的软件 , Hibernate , Sun的Jaxm .
      使用dom4
     2.怎样使用dom4j开发包
      (1)解压dom4j压缩包 , 在根目录下有一个 dom4j-1.6.1.jar 这是dom4j的jar包 ;
      (2)在MyEclipse中的工程的根目录下创建一个文件夹 , 命名为 lib , 将dom4j-1.6.1.jar 文件复制到 lib文件夹中 ;
(3)右键点击 dom4j-1.6.1.jar , 选择Build Path | Add to Build Path , 这样这个jar包就导入到了这个工程中 , 我们就可以使用dom4j中的类和方法了 ;
(4)在一些时候我们使用dom4j中的类和方法的时候 , 会报出 类没有找到异常 , 我们还需要导入一些其他的包 , 这些包在dom4j文件下的 lib 文件夹下 , 根据报错信息 , 找到相应的jar包 , 复制到工程下的lib文件夹下 , 然后设置 Build Path .
     3.API介绍           (1)SAXReader [read()]_org.dom4j.SAXReader , Document [getXMLEncoding()]_org. dom4j.Document
        这是dom4j提供的解析器 , 该解析器提供了一个方法 ,
read() (从一个已知的文件中读取一个Document对象) , 传入一个文件 , 返回Document对象 , 可以用来获取Document对象 .
这里注意了 , Document是一个接口 , 没有构造函数 , 不能通过构造函数获取Document对象 , 只能通过其他方法获取 .
获取Document对象的方法 : 先获取SAXReader解析器 , 即创建一个SAXReader对象 ; 然后解析xml文档 , 就是调用read()方法 , 获取Document文档 .
其中解析器read()方法 , 传入的参数是一个文件对象 , 这里可以新建一个文件 , new File(“books.xml”) ;
为了验证是否成功获取Document对象 , 我们使用Document类下的getXMLEncoding()方法 , 该方法返回的是Document对象所对应的XML文档的编码码表 , 例如UTF-8 , GBK等 , 这个码表值是在XML的第一行的标注中的.
一般XML文档的第一行都是<?xml version=”1.0” encoding=”UTF-8”?> , 这里的encoding就是 getXMLEncoding()方法获得的返回值 .
( 返回文档的码表值 , 这个码表值是XML文档的一部分 , 当编码未指明或者未知或者系统不支持这个码表的时候其返回值为null) .
*****************************************************************************
一个获取document对象的方法:
Import java.io.File;
Import org.dom4j.Document;
Import org.dom4j.io.SAXReader;
Public static Document getDocument(){
   //获取解析器
   SAXReader  reader = new SAXReader();
   //解析XML文档
   Document  document = reader.read(new File (“books.xml”));
   //验证是否成功获取Document对象
   System.out.println(document.getXMLEncoding());
   //返回Document对象
   return document;
}
***************************************************************************
注意上面的方法导入了三个包 :
   当使用到Document的时候需要导入包 org.dom4j.Document;
   当使用到SAXReader的时候需要导入包org.dom4j.io.SAXReader ;
   当使用到File的时候 , 需要导入包 java.io.File;
           (2)Document[getRootElement()]_org.dom4j.Document , Element[]_org.dom4j.Element
        Document类下的getRootElement()方法 , 是返回根节点 .
        (返回文档的根节点) , 返回值是Element对象 , 是个XML 文档的元素 .
        Element类定义了一个XML文档的元素 , 使用Element需要提前导入包 org.dom4j.Element .
        这里注意了 : Document 和 Element 都是接口 , 都没有构造函数 , 只能通过其他方法获得 .
         ******************************************************************************
        遍历所有节点的方法 :
        (粉色的字体为要导入包的类)
        Import java.util.List;
        
        Import org.dom4j.Document;
        Import org.dom4j.Element;
        Public static void getAllBooks() throws Exception{
   //获取Document对象 , 其中的getDocument是调用的上面(1)中的方法
   Document document = getDocument();
   //获取根节点
   Element rootElement = document.getRootElement();
   //获得所有的书
   List bookList = rootElement.Elements();
   //遍历所有的书
   For(int i = 0 ; I < bookList.size() ; i++){
   //获得每一本书 , 注意从集合中获取元素 , 涉及到强转
   Element book = (Element)bookList.get(i);
   List childList = book.Elements();
   //获取每一本书的子节点
   For(int j = 0 ; j < childList.size() ; j++){
   Element child = (Element)childList.get(j);
   System.out.println(child.getName() + ”:” + child.getText());
}
}
}
****************************************************************************
        代码解析 :
           A.Element调用的getName()和getText()方法 .
              getName()和getText()方法并不是Element类下定义的方法 , Element类是Node类的子类 , 这两个方法是从Node类中继承的 .
              (返回这个结点的名字) ;
              (返回这个结点的文本) ;
           B.导入包的介绍:
              当使用Document类的时候需要导入包 org.dom4j.Document ;
              当使用Element类的时候需要导入包 org.dom4j.Element ;
              当使用List类的时候需要导入包 java.util.List .
           C.代码思想
              从根节点之后 , 调用Element()方法 , 将结点的子节点放入一个集合中 .
然后遍历这个集合 , 将元素从集合中取出 , 注意从集合中取出元素 , 集合并不知道取出的是什么类型 , 取出的类型一律为Object  , 这里我们需要将取出的元素强转为Element类型 .
然后在调用Element()方法 , 获取从集合中取出的Element类型的子节点 , 以此类推 .
最后是将元素的名称和文本输出 , 树有几层 , 有要嵌套几层循环 , 只在最内层的循环中输出元素名称和文本 .
   `      
根节点rootElement , 在XML文档中是<books>标签 ;
获取根节点的子节点book , rootElement.element() , 获取的就是<books>标签下的子标签<book> ;
获取book的子节点child , book.element() , 获取的就是<book>标签下的子标签<title>和<price>;
获取<title>标签的标签名的方法  getName()  , 获取<title> 标签文本的方法 getText .
       (3)Element[attributeValue(qName)]_org.dom4j.Element , String[equalsIgnoreCase()]
        AttributeValue(qName)是Element下的方法 , 其返回值是 , 返回名称为qName属性的属性值 .
        equalsIgnoreCase()是String类下的方法 , 目的是判断两个String类死否相等 , 不区分大小写 .
         *******************************************************************************
        获取实体类集合的方法:
        Import java.util.List;
        Import java.util.ArrayList;
        Import java.io.File;
        
        Import org.dom4j.Document;
        Import org.dom4j.io.SAXReader;
        Import org.dom4j.Element;
        Public static List getBooks() throws Exception{
   //获取document , 先获取解析器 , 再通过解析器获得document
   SAXReader reader = new SAXReader();
   Document document = reader.read(new File(“books.xml”));
   //获取根节点
   Element rootElement = document.getRootElement();
   //获取根节点的子节点的集合
   List bookList = rootElement.elements();
   //创建存取书的实体类集合 , 该实体类已在本包中定义
   List returnBook = new ArrayList();
   //将xml文档中的信息存到Book实体类中 , 然后将Book实体类存入到returnBook集合中
   For(int i = 0 ; i < bookList.size() ; i ++){
   //获得每一本书
   Element book = (Element)bookList.get(i);
   //创建Book实体类
   Book bookBean = new Book();
   //设置id
   bookBean.setId(book.attributeValue(“id”));
   //获取书的子标签集合
   List childList = book.elements();
   //获取每一个标签 , 将标签的文本放到Book实体类中
   For(int j = 0 ; j < childList.size() ; j ++){
      Element child = (Element)childList;
      If(“title”.equalsIgnoreCase(child.getName())){
   bookBean.setTitle(child.getText());    //设置titile字段
}else if(“price”.equalsIgnoreCase(child.getName())){
   bookBean.setPrice(child.getText());    //设置price字段
}
}
returnBook.add(bookBean);
}
Return returnBook;
}
********************************************************************************
代码解析 :
A.  Book类是在这个包中定义的一个存放xml文档信息的实体类 , 其有三个字段 , id , title 和 price , 以及有相应的get set方法 .
设置字段的时候直接使用其set方法即可 .
B.  该代码中Element类中所调用的getName()和getText()方法 , getName()方法是返回xml文档元素的标签名 , getText()方法是返回xml文档元素的标签内的文本 .
C.  导入包介绍
当使用 List 类的时候需要导入包 java.util.List ;
当使用 ArrayList 类的时候需要导入包 java.util.ArrayList ;
当使用 File 类的时候需要导入包 java.util.io.File ;
当使用 SAXReader 类的时候需要导入包 org.dom4j.io.SAXReader ;
当使用 Document 类的时候需要导入包 org.dom4j.Document ;
当使用 Element 类的时候需要导入包 org.dom4j.Element ;
        D. 代码思想
通过SAXReader解析器获取document , 然后通过document方法获取根节点<books> , 获取到根节点之后 , 就可以获得二级节点 book , 然后就可以获取book下的子标签 child的标签名和文本 , 将book的属性id 和 book的子标签的标签名和文本名设置到Book的实体类bookBean中 .
这里涉及到了两层嵌套循环 , 第一层循环获取book标签 , 第二层循环获取book标签下的子标签 .
 JDK新特性     1. 静态导入 Static Import           (1)静态导入介绍
           静态导入就是导入某个类的静态属性或静态方法 .
           (2)语法:
        A. 导入指定的单个静态属性
           import static 包名.类名.静态属性 ;
           例如 :
              Import static java.lang.System.out ;
        B. 导入指定静态方法
           import static 包名.类名.静态方法 ;
           例如 :
              Import static java.lang.Math.max ;
              注意导入静态方法的时候 , 只写上方法名 , 括号/修饰符/参数列表/方法体等不带 .
        C. 导入指定类全部静态属性和方法
           import static 包名.类名.* ;
           例如:
              Import static java.lang.Math.* ;
              注意: 加上了static , 后面有*的话导入的全是静态的属性和静态方法 ;
如果没有加上static , 那么导入的就是所有的属性和方法 , 包括静态的和非静态的 .
           (3)代码示例:
        ****************************************
        import java.lang.Math.PI ;
        import java.lang.Math.max ;
        public static void main(String[] args){
           //导入静态字段 , 属性
   double a = Math.PI ;
   System.out.println(a) ;
   System.out.println(PI) ;
   //导入静态方法
   Int b = Math.max(1, 2) ;
   System.out.println(b);
   System.out.println(max(1,2));
}
*******************************************
代码思想 :
如果没有导入静态字段和方法 , 不能直接使用PI和max()方法 , 如果使用了就会报错 .
     2. 自动装箱,拆箱 AutoBoxing/Unboxing
      (1)
     3. 泛型 Generics           (1)泛型介绍
        A. Jdk5.0之前 , 对象保存到集合中就会失去其特性 , 取出时通常要程序员手工进行类的强制转化 , 这样就不可避免的引发一些程序上的安全性问题 .
        B. 泛型格式 : 类型<T>
        C. 泛型的基本术语
              以ArrayList<E>为例 , 念作 ArrayList type of E ;
              ArrayList<E> , E称为类型参数变量 ,
              ArrayList<Integer> , Integer成为实际类型参数 ;
              ArrayList<E> 整个称为泛型类型 ;
              ArrayList<Integer>成为参数化的类型ParameterizedType .
           (2)泛型的作用
        Jdk5中的泛型 , 允许程序员在编写集合代码的时候 , 就限制集合的处理类型 , 从而将运行时可能发生的问题 , 转变为编译时的问题 , 从而提高程序的可读性和稳定性 .
        这个作用在大型程序中尤为突出 .
           (3)类型擦出
        泛型是提供给javac编译器使用的 , 它用于限定集合的输入类型 , 让编译器在源码级别上挡住向集合中插入非法数据 .
        编译器编译完带有泛型的java源文件之后 , 生成的class文件不再带有泛型信息 , 这个过程称为类型擦出(type erasure) .
        
        public void print(List<String> list){}
        public void print(List<Integer> List){}
        上面两个方法不能同时存在 , 由于类型擦出效果 , 这两个方法在编译之后生成的class文件是没有区别的 , 这样两个函数就完全相同了 .
           (4)泛型的典型应用
        
     4. 增强for循环 (for - each)  Enhanced for Loop
      (1)
      (2)
      (3)
     5. 可变参数  Varargs
     6. 枚举 Typesafe Enums
 反射      1. 反射介绍
      反射就是通过字节码文件 , 获得类中的构造函数 , 方法 , 字段 .
      注意 :
      Class下的api  , 获得公共的构造函数 , 方法 : getConstructor() , getMethod() ;
      获得声明的构造函数 , 方法 : getDeclareConstructor() , getClareMethod() , 这里获得的构造函数或者方法不一定是公共的 , 私有的也可以获得 .
     2. 获得Class           (1)通过类名获得Class对象
注意这个类名不带 .class 后缀
Class clazz = Class.forName(“my.cn.itcast.reflect.ReflectTest”);
           (2)通过已知类获得Class对象
        直接将字节码文件赋给Class对象
        Class clazz2 = ReflectTest.class ;
           (3)通过已知对象获得Class对象
        Object object = new ArrayList();
         Class clazz3 =  object.getClass();
           (4)实例化
        Clazz.newInstance() ; 是调用获得的Class对象默认的构造函数创建相应的实例 .
     3. Constructor           (1)获得公共的构造函数
        Clazz是Class类对象 .
        Constructor con = clazz.getConstructor();
        这样con就是返回的构造函数 , 如果想要调用这个构造函数创建实例 , 可以使用 con.newInstance()创建实例 .
        使用clazz.newInstance()调用默认的构造函数创建实例 .
           (2)获得声明的构造函数(可获得私有构造函数)
        Constructor con = clazz.getDeclaredConstructor(String.class , Integer.class) ;
   在类中这个构造函数是私有的 , 我们如果使用con.newInstance()调用这个方法 , 就会吧报出异常 , 我们如果想要调用这个私有的构造方法创建实例 , 就要将该构造函数设置为可访问的 .
   Con.setAccessible(true);
   进行了以上设定之后 , 我们就可以使用con.newInstance()方法创建实例了 .
      4. Field           (1)获得公共的字段
        Class类中有可以获取Filed类对象的方法 .
        Class clazz = Class.forName(“cn.itcast.reflect.ReflectData”);   //获得Class类对象
        Object obj = clazz.newInstance();   //调用默认函数实例化
        //获得公共字段
        Field field = class.getField(“name”) ;
        System.out.println(field.get(obj));
        Field类下的get(Object object) 方法 , 将指定对象上该Field字段值返回 .
           (2)获得私有的字段
        Field field = clazz.getDeclaredField(“age”) ;
        使用Class类下的getDeclaredField()方法可以获取私有的字段值 , 传入的参数是字段值的名称 .
        注意 , 私有的字段值不能被访问 , 如果强行访问就会报出异常  , 若想要正常访问 , 需要将其设置为可访问 .
        Field.setAccessible(true) ;
        这个Accessible默认为false , 我们设置其为true , 之后就能访问相应的字段 .
     5.Method           (1)获得公共方法
        Class clazz = Class.forName(“cn.itcast.”) ;     //根据名称获取Class对象
         Object obj = clazz.newInstance();   //调用默认的构造函数创建Class对象实例
        //getMethod()是Class类下的方法
        Method method = Clazz.getMethod(“print”) ;
        注意 , 这个方法传入的参数情况 , 必须传入的参数是方法名 , 后面还可以传入方法的参数类型类别 , 注意这个类型格式是 类型名.class .
        例如 : 原来的方法是 public void print(int i , List list){} 如果想要获得这个方法就要使用下面的代码:
Method method = clazz.getMethod(“print” , int.class , List.class) , 后面的是一个可变参数 , 可变参数就是可以使任意个参数 , 参数个数和类型由方法的参数决定 , 如果原来的方法没有参数 , 在getmethod()方法中只传入方法名 , 如果原来的方法中有n个参数 , 那就在获取这个方法的时候 , 除了传入方法名之外 , 还要传入那n个变量类型 , 注意变量类型格式 , 类型名.class .
        method.invoke(obj);
   invoke()方法是Method下的方法 , Method对象调用这个方法 , 传入一个字段所在类的对象 , 和一个可变参数(就是方法自身的参数 , 格式仍然是 参数类型名.class) , 相当于传入的对象调用这个方法 , 调用方法的同时传入后面的可变参数 .
           (2)获得私有方法
        Method method = clazz.getDeclaredMethod(“print” , int.class);
        Method类下有一个getDeclaredMethod()方法 , 传入的参数与getMethod()方法传入的参数相同 , 一个方法名称字符串 , 一个可变参数 , 可变参数是方法参数类型 .
        这个方法也能调用 method.invoke(obj , 1234) 执行 , 执行前必须将这个方法设置成可访问 , 否则就会报出异常 .
        method.accessiableValue(true) ;
        method.invoke(obj , 1234);
        这样就相当于执行了原来的私有方法 , 传入参数1234 .
        
     6.反射总结
      (1)获得构造函数(Constructor) , 字段(Field)的方法都是在Class类中定义的 , 这几种方法都不是静态的 , 需要通过对象实例调用 ,
      (2)获得公共构造函数和公共字段 : getConstructor() , getField()
        getConstructor()中传入类型.class 参数类型列表 , 例如 String.class , int.class 等 .
        getField() 中传入的是字符串 , 如果字段名(成员变量名)为 name , 那么就将 “name” 传入到方法中 .
      (3)获得私有的构造函数和私有字段 : getDeclaredConstructor() , getDeclaredField() , 传入的参数与获得公共的构造函数和公共字段方法传入的参数相同 .
        私有的构造函数和私有的字段不能直接被调用 , 如果想要调用私有的构造函数和私有字段 , 需要将相应的私有构造函数和私有字段设置为可访问的 .
        在Constructor和Field下有setAccessible()方法 , 传入一个布尔值 , 默认的为false , 传入true , 就可以调用相应的私有构造函数和私有字段了 .
(4)注意使用Constructor类和Class类下的newInstance方法创建的实例 , 其类型为Object类型的 , 系统不知道其原来的类型是什么 , 如果要将实例赋值给原来的类型, 就需要强制转换类型 , 这里跟从集合中取出对象是一个道理的 .
 单例
(1)单例描述
单例就是一个类在整个程序中只有一个实例 , 不能存在第二个该类的实例 .
           (2)单例模式的实现方法
        A. 私有化构造方法 , 由于只能存在一个实例 , 那么就不能调用构造方法 , 使用户不能通过构造函数创建实例 .
        B. 获取方法:
           通过公共静态方法创建单一的实例 ;
           通过静态工厂方法获取实例 .
           (3)单例模式代码实例
        *************************************************
        饿汉模式:
        Public class SingletonTest{
   Private SingletonTest(){    //私有化构造函数
}
Private static SingletonTest sing = null ;      //声明一个私有的对象 , 并赋值null
Static{
   Sing = new SingletonTest()     //在静态代码块中创建对象
}
Public static SingletonTest getInstance(){      //公共静态方法返回这个单例对象
   Return sing;
}
}
*************************************************
        代码分析:
A.    方法以及变量的修饰符分析
构造函数私有化是为了避免用户调用构造函数 , 创建出实例 , 由于只能创建一个实例 , 所以我们只能在类内部创建这个实例 , 不能在外部创建实例 ;
声明一个私有的对象 , 这个对象不能被外部调用 , 这是为了专门提供给共有的方法来调用的 ;
静态代码块在类第一次加载的时候执行 , 且只执行一次 , 一旦执行过了 , 下一次在加载类就不会执行这个静态太代码块了 , 这也是饿汉模式的原因 ;
该类中只有一个公有的方法 , 这个方法提供给外部调用 , 用来获得唯一的一个实例 .
        B. 为什么叫饿汉模式
           由于创建实例是放在静态代码块中执行的 , 仅执行一次 , 不管取出多少次 , 就仅将第一次创建的实例返回 .
        
         ********************************************************************************************
        懒汉模式 :
        Public class SingletonTest2{
   Private SingletonTest2(){   //私有化构造函数
}
Private static SingletonTest2 sing = null;      //声明实例对象 私有静态
Public static SingletonTest2 getInstance(){     //设置公共静态的方法 , 供用户调用唯一的实例对象
   If(sing == null){
   Sing = new SingletonTest2();
}
Return sing ;
}
}
*********************************************************************************************
        代码分析:
A.    构造函数私有化 , 避免用户调用构造函数 , 创建多余的实例 ;
B.    懒汉模式 : 不管之前有没有创建实例 , 都调用这个方法 , 如果没有创建就创建 , 如果创建了就直接返回 .
 Web入门     1. Web开发相关知识            (1)B/S模式
        Web采用B/S模式 , 通过超文本传输协议(HTTP , Hypertext transport protocol)进行通信 , 是无状态通信 .
        B/S是 Browser / Server , 浏览器服务器架构 ;
        C/S是 Client / Server , 客户端服务器架构 ;
           (2)Web特点
        A. 用超文本标记语言 ( HTML , Hypertext Markup Language ) 来表达信息 ;
        B. 用统一资源定位 ( URL , Uniform Resource Locator ) 来对来自网络上的信息进行精确的定位 ;
        C. 用DNS来解析域名 , 用以方便记忆 ;
        D. 用网络应用层之间的协议HTTP来实现与Web服务器之间的通信 , 底层为 TCP/IP协议 .
           (3)静态资源与动态资源
        A. Internet上供外界访问的Web资源分为静态资源和动态资源两种 ;
        B. 静态Web资源开发技术是Html ;
        C.    常用的动态Web开发技术有 JSP/Serverlet , ASP , PHP ;
        D. 在Java中 , 动态Web开发技术统称为JavaWeb .
     2. 开发企业级应用介绍(1)ERP
(Enterprise Resource Planning) : 企业资源计划 , 针对物资资源管理(物流) , 人力资源管理(人流) , 财务资源管理(财流) , 信息资源管理(信息流) 集成一体化的企业管理软件 .
(2)CRM
   (Customer Relationship Management) : 客户关系管理 , 是指用计算机自动化分析销售 , 市场营销 , 客户服务以及应用支持等流程的软件系统 .
(3)BPM
   (Business Process Management) : 是一套达成企业各种业务环节整合的全面管理模式 .
(4)OA
   (Office Automation) : 办公自动化 , 是将现代化办公和计算机网络结合起来的一种新型的办公方式 .
     3. Web系统通信方法
      客户端发出请求 , 客户端请求包含用户要访问的资源路径和名称 ;
      服务器端接到请求 , 可以将 页面 , 图片 , 媒体 , 等很多的资源内容发送给客户端 ;
      如果客户端请求没有得到正确处理 , 服务端会响应一个所悟状态码 .
     4. URL格式
      http://www.baidu.com:80/liyanhong/web/1.html
      http://  是协议 , 采用哪种协议进行本次网络访问 ;
      www.baidu.com  是服务器 , 服务器的唯一域名 , 映射到一个IP地址 ;
      :80 端口 , 访问服务在服务器端绑定的端口号 , 如果没有指定端口 , 默认为80 ;
      /liyanhong/web/ 路径 , 由零个或多个 / 隔开的字符串 , 一般表示主机上一个目录或文件的地址 ;
      1.html 资源名称 , 资源是本地计算机上的文件 .
常见服务器简介           (1)WebLogic
      是Oracle公司的产品 , 是目前应用最广泛的服务器 , 支持J2EE规范 .
           (2)WebSphere
      是IBM公司的产品 , 支持J2EE规范 .
           (3)apache
      Tomcat , 支持全部Jsp与Servlet规范 .
 Tomcat安装与启动     1.下载并安装Tomcat
      (1)下载Tomcat
        Tomcat官方站点  :  http://archive.apache.org/dist/tomcat/  ;
        在上面的网站获取Tomcat , tar.gz文件是Linux系统下的安装版本 , exe文件是Windows下的安装版本 , zip文件是Windows下的压缩版本 .
      (2)安装Tomcat
        这里我们下载的是apache-tomcat-6.0.35.zip , 解压缩到E盘的DevelopPakage , 一些开发包文件都放在这里 .
     2.启动Tomcat
      双击Tomcat/bin/startup.bat , 就可以启动Tomcat .
      打开浏览器 , 输入   http://localhost:8080/   能条转入Tomcat服务器界面 .
      
 Tomcat配置     1.Tomcat常见问题           (1)启动闪了一下并消失
如果启动的时候 , 仅仅是闪了一下 , DOS界面就消失了 , 此时Tomcat并没有启动成功 , 这是因为我们没有配置 JAVA_HOME 环境变量 .
        这是我们右键点击 我的电脑|属性|高级|环境变量|新建Administrator环境变量| 在弹出的对话框中的变量名选项输入 JAVA_HOME , 在变量值选项输入jdk的根目录路径 .
        
           (2)地址占用异常
        如果报出了地址被占用异常 , 我们需要查看到底是那个程序占用了Tomcat需要的8080端口 , 并终止这个程序 .
        查找端口的方法 :
        A. cmd新建一个DOS命令窗口 , 输入 netstat –abo (注意中间是一个空格) , 会将端口使用情况列出 , 如果端口过多 , 一部分信息就不会显示出来 .
        B. 使用Fport.exe工具查看 , 这个工具不能直接双击运行 , 需要在DOS命令窗口运行 , 将其方法 E:/DevelopPakage 文件夹下 ;
           Cmd一个DOS命令窗口 , 将操作目录变为 E:/DevelopePakage , 然后输入 Fport.exe , 执行这个文件 , 与javac类似 .
           
        C. 使用360安全卫士中的 网络连接查看器 , 可以在这里查看端口使用情况 , 并且这个功能更强大 , 能终止被使用的端口 .
               
           
           微软的SQLServerServersServer.exe SQLServer服务器报表服务宿主程序占用了次8080端口 , 我们将Tomcat的端口改为18080 .
           修改端口方法 :
              打开根目录下的conf文件 , 打开server.xml , 其中只有一处8080 , 将其改为18080 .
              <Connector port="18080"  protocol="HTTP/1.1"  connectionTimeout="20000"   redirectPort="8443" />
              Connector 标签下的port 是端口 .
              Protocol 是协议 , 使用的是http协议 , 版本是 1.1的 .
           (3)MyEclipse中配置Tomcat
        打开MyEclipse , 选择 Window|Preference|MyEclipse|Servers|Tomcat|Tomcat 6.x
        因为我这里用的是apache-tomcat-6.0.35.zip , 因此选的也是 Tomcat 6.x ;
        Tomcat Server 选择 Enable , 然后在第一个 Tomcat Home directory 浏览选择Tomcat的根目录 .
        这样就成功在MyEclipse中成功配置了Tomcat .
        
        此时的Tomcat在Server中 , Server就是我们平时打印东西的地方Console旁边 .
        
        我们可以选择Server中的Tomcat服务器 , 右键选择Run  , Tomcat就成功启动了起来 .
        如果在Windows中启动的话 , 如果启动失败 , 这个DOS命令窗口就会消失 , 就不能在DOS命令窗口查看具体出了什么错误 , 在MyEclipse中显然可以查看启动过程供出现的错误 .
           (4)Tomcat服务器和Servlet版本之间的关系
           Tomcat  7.0.x Servlet 3.0  Jsp 2.2 Java EE 6.0
           Tomcat  6.0.x Servlet 2.5  Jsp 2.1 Java EE 5.0
           Tomcat  5.5.x Servlet 2.4  Jsp 2.0 Java EE 1.4
           Tomcat  4.1.x Servlet 2.3  Jsp 1.2 Java EE 1.3
           Tomcat  3.3.x Servlet 2.2  Jsp 1.1 Java EE 1.1
        1.3的xml文件是dtd的 , 1.4之后的xml文件是schema的 .
           (5)MyEclipsejdk先安装
        如果使用的MyEclipse安装了以后 , 将之前的jdk卸载了 , 重新安装的 , 这是在启动Tomcat就会启动不成功 , 这时我们需要在下面进行配置 :
        MyEclipse | Window | Preferences | MyEclipse | Servers | Tomcat | Tomcat 6.x | JDK 下进行设置 , 设置完毕之后就能正常启动Tomcat了 .
     2. Tomcat目录结构和权限设置           (1)Tomcat目录层次结构
        A. bin目录中存放启动和关闭Tomcat的脚本程序 ;
        B. conf 存放Tomcat中各种配置文件
        C. lib 存放的是Tomcat程序和所有的Web应用程序所访问的jar文件 ;
              tomcat-i18n-es.jar 是与国际化有关的文件 ,
              servlet-api.jar , jsp-api.jar Tomcat处理servlet和jsp相关的文件 .
        D. logs 存放Tomcat的日志文件 .
        E. temp 存放tomcat运行时产生的临时文件 ;
        F. webapps当发布web应用程序时通常把web应用程序的目录及文件放到这个目录下 ;
        G. work Tomcat将JSP生成的servlet源文件和字节码文件放到这个目录下 .
           (2)第一次在Tomcat下创建项目
        在tomcat的webapps目录下 , 创建一个文件夹 , 命名为day01 , 然后在里面创建一个html文件 , 随便写上一些内容 .
        我们启动Tomcat服务器 ,
        文件的路径为 : E:\DevelopPakage\apache-tomcat-6.0.35\webapps\day01
        在浏览器中我们输入  :  http://localhost:18080/day01/1.html   就能访问到刚才创建的html文件
        这就说明了一个问题 http://localhost:18080/   与E:\DevelopPakage\apache-tomcat-6.0.35\webapps\  映射是一样的 .
         http://localhost:18080/   对应的是Tomcat服务器的webapps目录 .
           (3)Tomcat中打开Jsp页面(浏览器Jsp页面生成的原理)
在MyEclipse中创建一个Web项目 , 从中将Jsp复制到刚才在webapps文件夹下创建的day01文件夹下 , 然后在浏览器中输入 http://localhost:18080/day01/index.html  ,  就能访问到这个页面 .
我们在浏览器中打开源文件 , 在打开Jsp的源文件 , 发现两个源文件并不是完全一模一样的 , 其中有很多地方有改动 .
Jsp页面源码发生改变的原因:
A. 在work文件夹下存放的是Jsp生成的servlet源文件和字节码文件 , Jsp页面并不是直接就能在浏览器中显示出来 .
B. 打开E:\DevelopPakage\apache-tomcat-6.0.35\work\Catalina\localhost\day01\org\apache\jsp 目录 , 下面有两个文件 , 分别是index_jsp.class 和index_jsp.java , 其中的index_jsp.java 中的程序中有很多行的 out.write() , 浏览器中的代码就是这里的Java代码一行一行写出来的 .
           (4)Tomcat Manager 的使用
A. 如果查看当前的所有项目的信息 , 我们可以再Tomcat中查看这些信息 , Tomcat Manger 在我们使用 http://localhost:18080   在浏览器中登陆的页面 , 选择在小猫下的第二个连接就是 Tomcat Manager , 但此时我们登陆的时候需要账号密码才能登陆 .
B. 设置登陆口令
   在弹出的口令的界面 , 我们连续点3次确定 , 就会跳入一个界面 , 在这个界面给我们一个建议 .
   我们按照建议操作 :
   进入conf目录下的tomcat-user.xml文件中 , 在<tomcat-users> 标签中添加下面的内容
   <role rolename="manager-gui"/>
<user username="admin" password="admin" roles="manager-gui"/>
rolename 是管理权限 , 这里有四种权限 , manager-gui是最高的权限 . 在第二行的标签中我们设置了账号和密码 .
四种权限介绍 :
   manager-gui - allows access to the HTML GUI and the status pages(状态页)
                 允许访问管理页面和状态信息页面
   manager-script - allows access to the text interface and the status pages
                 允许访问文本接口和状态信息页面
   manager-jmx - allows access to the JMX proxy and the status pages
                 允许访问Java管理扩展代理和状态信息页面
   manager-status - allows access to the status pages only
                 允许访问状态信息页面
        C. 管理页介绍
进入的Tomcat manager 界面是对所有webapps下的项目的管理页 .
1)其中的/doc 是Tomcat的文档 , 我们可以在这里查询Tomcat 相关的文档,信息 .
2)我们点击我们的/day01 项目 , 发现会进入 index.jsp 页面 , 这是因为在conf 目录下的web.xml 中设置了欢迎文件 .
   在web.xml中有这样一个标签(1220行) :
   <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
在这里设置了项目的欢迎文件 , 欢迎文件当我们打开一个项目的时候 , 第一个弹出的页面 , 根据上面的标签 , 我们可以了解到 : 在打开一个项目的时候 , 会首先查看有没有index.html文件 , 有的话就作为欢迎文件 , 没有的话就去找 index.htm 文件作为欢迎文件 , 如果在没有就去找index.jsp作为欢迎文件 .
 Java EE 体系结构      1. 客户层
      包含于用户交互的程序 ,  这些程序提示用户进行输入 , 然后把用户的响应转化成请求 , 发往到服务端组件 , 并接收服务端处理的结果 .
     2. 表示层(web)
      为Java EE 应用程序提供Internet功能 , 在Web层运行的组件 , 使用http协议接收客户端的各种请求 , 并将对请求的响应返回给客户端 . 例如 Servlet , jsp .
     3. 业务层
      包含javaEE应用程序的业务路几层 .
     4. EIS(信息系统层)
      是JavaEE应用程序与其它技术的直接或者间接接口 .
十一 Servlet简介      1. 什么是Servlet
      A. Java编写的服务器端程序
        主要功能在于交互式的浏览和修改数据 , 生成动态web内容 ;
        狭义的servlet是指Java语言实现的一个接口 ;
        广义的servlet是指任何实现了这个Servlet接口的类别 , 一般情况下按照广义理解 .
      B. Servlet运行于支持Java的服务器中 . 从现实上讲 , Servlet可以响应任何形式(ftp,svn等类型也可以)的请求 , 但绝大多数情况下servlet只用来扩展基于http协议的web服务器 .
     2. Servlet的优缺点
      (1) 优点
      (2) 缺点
     3. Servlet容器就是Tomcat 十二 Servlet运行过程     1. 浏览器发出请求
Web浏览器向Web容器发出http请求 , 之后Web容器会创建Servlet , 只有首次访问才创建Servlet ;
     2. 创建servlet(1)创建请求(request)和响应(response)对象
   此时Web容器会创建请求和响应对象 , 并将相应的数据填充进去 , 创建的请求头和请求体有实际的数据填充 , 但是响应头和响应体都为空 ;
   请求有7中 , 分别是 get , post , put , delete , head , option .
(2)调用service方法
   Service方法是servlet的一个方法 , 这个方法读取请求信息 , 并向空白的响应头和响应体写入响应信息 , 并生成servlet ;
     3. 浏览器收到响应
      Servlet的service方法将servlet返回给Web容器 , Web容器在读取响应信息 , 并向Web浏览器发出http响应 .
十三 Servlet编程      1. 配置Servlet虚拟路径           (1)配置路径原理
浏览器是通过URL地址来访问Web服务器的资源 , 如果servlet程序想要被外界访问 , 必须将servlet程序映射到一个URL地址上 , 这个工作在WebRoot | WEB-INF | 中的web.xml中完成 .
           (2)如何配置
        Servlet是通过两组标签来完成虚拟路径的配置的 .
        A. <servlet>标签用来注册Servlet , 其主要包含两个子元素 , <servlet-name>和<servlet-class> , 前者用于设置Servlet注册名称 , 后者用来存放Servlet完整类名 .
        B. <servlet-mapping> 用于映射一个已注册的Servlet的一个对外访问路径 , 它包括<servlet-name>和<url-pattern>两个子标签 , 分别用于指定注册名称和对外访问路径 .
           (3)配置实例
        <web-app>
           <servlet>
              <servlet-name>ServletDemo</servlet-name>
              <servlet-class>cn.itcast.servlet.ServletDemo</servlet-class>
           </servlet>
           <servlet-mapping>
              <servlet-name>ServletDemo</servlet-name>
              <url-pattern>/servletdemo</url-pattern>
           </servlet-mapping>
        </web-app>
        
        假设我们的工程名字叫day05 , 那么我们使用   http://localhost:18080/day05/servletdemo  ,  就可以访问刚才的servlet页面了 .
           (4)虚拟路径访问过程
浏览器中端口工程名后面跟着 url , 在服务器中会自动根据 url 到web.xml 文件中查找 <servlet-mapping> 标签的<url-pattern> , 如果找到匹配的 , 找到本<servlet-mapping>标签下的<servlet-name> , 在去<servlet> 标签中找到相应的<servlet-name> 符合的标签 .
           (5)servletservlet-mapping可以一对多
        同一个servlet可以被映射到多个URL上 , 即多个<servlet-mapping>元素的<servlet-name>子元素的设置 , 可以使同一个servlet注册名 .
           (6)servlet-mapping中的url-pattern 可以使用通配符
        Servlet映射到url中可以使用 * 通配符 , 但是只能由两种固定的格式 : 一种格式是 *.扩展名 ; 另一种是以 / 开头 , 并以 /* 结尾 .
        总结 : 只能使用 / 或 * 开头 , *开头的时候后面就没东西了 ; / 和 *. 不能同时存在 ( 意思是/*.不行 ) ; / 或 /* 表示任意 ; 只有 *. 才表示通配符 .
     2. 创建一个简单的Servlet程序           (1)创建一个Web Project           (2)创建servlet页面
A. 包名填写 my.cn.itcast , 名字上填写 hello , 修饰符选择 public , MyEclipse自动选好了继承的父类    javax.servlet.http.HttpServlet , 我们就不需要选了 , 选择一 个要用的模板  Default temple for Servlet , 创建的方法 勾上 doGet() 和 doPost() ;
B. 进入创建的第二页 , ClassName不能修改 , 这是我们之前输入好的 , 在此不作修改 , name 和 maping url 可以直接设置web.xml文档中的信息 , 那么相当于<servlet-name>标签中的信息 , mapping url 相当于 <url-pattern>标签中的信息  , 第三个是设置的创建servlet文件的路径 , 第四第五个是描述信息 , 可写可不写 .
   
C.  创建好了之后 , 我们去查看web.xml文件的配置 :
    <servlet>
      <description>This is the description of my J2EE component</description>
      <display-name>This is the display name of my J2EE component</display-name>
      <servlet-name>Hello</servlet-name>
      <servlet-class>my.cn.itcast.Hello</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>Hello</servlet-name>
      <url-pattern>/servlet/Hello</url-pattern>
  </servlet-mapping>
   其中的<servlet>标签下的<description>和<display-name> 是我们创建servlet第二页设置的最后两项 .
D. 发布servlet并启动Tomcat
   选中项目 , 然后选择发布按钮 , 左边的是发布按钮 , 右边的是启动Tomcat按钮 .
   在Project选项中选择项目 , 然后点右侧的Add添加Tomcat , 然后点右侧的Redeploy发布 , 在最下面的信息框中出现successfully deployed , 说明发布成功 .
   然后点ok退出 .
E. 打开浏览器 , 在浏览器地址栏输入 http://localhost:18080/day05_exercise/servlet/Hello  ,  就可以访问这个Servlet页面
   
     3. Servlet页面中的乱码问题           (1)乱码现象
        在上面的页面中添加 out.println(“中文”);
        就会在生成的html页面中将 “中文” 两个字添加进去 , 但是我们添加进去的时候 , 在浏览器中显示的是乱码 .
           
           (2)产生乱码的原因
Servlet源文件中直接输出 “中文” 两个汉字 , 这些信息发送到Tomcat服务器之后 , Tomcat就会按照ISO-8859-1 进行转码 , 显然 , 转码以后就变成了乱码 , ISO-8859-1码表中没有中文 , 只有英文 .
“中文” à 按照ISO-8859-1编码 à “??”
           (3)解决乱码
        String str = “中文” ;
        str = new String( str.getBytes(“GBK”) , “ISO-8859-1” ) ;
        由于浏览器默认的码表为GBK , 我们最终得到的字符串是用GBK解析的 , 我们直接得到 “中文” 的GBK码表数据 .
   将GBK格式的字符串使用 “ISO-8859-1”进行编码得到一个新的字符串 str , 将这个str发送到Tomcat服务器进行解析 , Tomcat将会用 “ISO-8859-1” 对齐进行解析 , 得到的是原来的 GBK码的字符串 , 浏览器最终用GBK码表解析这个字符串 , 我们最终能够看到中文 .
   
     4. servlet注册和编写映射           (1) servlet注册
        使用servlet标签实现servlet注册 , 注册的目的是将servlet提供给别人使用 ;
        <servlet-name> 为自己起名 , 命名自定义 , 但不能重复 ;
        <servlet-calss> 选择要注册的servlet的完整路径 , 这个class路径从源文件的包名开始 , 到不带后缀的servlet文件名 ;
           例如: 如果servlet是在cn.itcast 包下的 Servlet.java , 那么此时的<servlet-calss> 中的路径为 cn.itcast.Servlet .
(2) servlet配置初始化
在Servlet的配置文件中 , 可以使用一个或多个<init-param>标签为servlet配置一些初始化 .
        在web.xml文档中 , 注册servlet的时候 , 在<servlet>标签中除了有<servlet-name>和<servlet-calss>子标签之外 , 还可以有*个<init-param> 标签 ;
        初始化参数设置 , 设置一个参数名和参数值 , 参数名<param-name>和参数值<param-value>是<init-param>的子标签 ;
        例如 :
           <init-param>
              <param-name>ServletName</param-name>
              <param-value>ServletContex</param-value>
           </init-param>
           上面在servlet中设置了初始化参数 , 参数名为 servletname , 参数值为 ServletContex .
           (3)编写映射
        编写映射就是配置虚拟路径 , 详见 四 Servlet编程 | 1. 配置servlet虚拟路径 .
     5. init方法中的ServletConfig对象            (1) 配置初始化参数
在Servlet配置文件中 , 可以使用一个或多个<init-param>标签 , servlet配置一些初始化参数  , 详见上面 4 .
(2) 如何获得初始化信息
当servlet配置了初始化参数后 , web容器在创建servlet实例对象时 , Tomcat会自动将这些初始化参数封装到ServletConfig对象中 , 并在调用Servlet的init()方法的时候 , 将ServletConfig对象传递给servlet , 进而 , 程序员就可以通过ServletConfig对象就可以得到当前的servlet初始化信息 .
(3)ServletConfig API介绍
   ServletConfig接口定义了一个对象 , 通过这个对象 , Servlet容器允许Servlet获得一个有关ServletContex接口说明 .
A.     getInitParameteerNames()
public Enumeration getInitParamNames() , 这个方法返回一个枚举集合 , 其中放的是String对象 , 这些字符串是初始化的参数名 .
Enumeration就是老版本的迭代器 .
   Enumeration有两个方法 :
      HasMoreElements() , 返回一个布尔类型 , 是否有下一个元素 , 如果有就返回true , 反之返回false .
      nextElement() , 返回下一个枚举 , 返回的是枚举中的元素 .
   这个枚举的使用方法 :
   Enumeration<String> names = config.getInitParameterNames() ;
   While ( names.hasMoreElements() ){
   String name = names.nextElement() ;
   System.out.println( name ) ;
}
上面的代码可以将所有的参数打印出来 .
B.     getInitParameter()
public String getInitParameter(String str) , 返回初始化参数名为str所对应的参数值 .
        C. getServletContex()
           Public ServletContex getServletContex() , 返回这个servlet的ServletContex对象 .
           获得上下文对象 , 一个项目只有一个该对象 .
           以后会讲 , 关于四大作用域 , ServletContex是最大的作用域 .
        D. getServletName()
           返回的是一个字符串 , 如果这个servlet文件的文件名是ServletDemo.java , 那么返回的就是 ServletDemo .
     4. Servlet生命周期           (1) init()方法
服务器调用该方法初始化servlet , 该方法只在servlet第一次被请求加载的时候调用一次 , 当有客户在请求servlet服务时 , 这个方法就不再执行了 , 服务器将启动一个新的线程 , 在该线程中 , 调用service方法响应用户的请求 ;
           (2) service()方法
        初始化完毕 , 服务器调用该方法响应客户的请求 ;
        
           (3) destroy()方法
        服务器调用该方法消灭servlet .
     5. 配置Servlet自动加载
如果在web.xml文件中 , 在注册servlet的时候 , 在其子标签配置了一个<load-on-startup>元素 , 那么Web应用程序在启动时 , 就会装载并创建Servlet实例对象 , 以及调用Servlet实例对象的init()方法 . 设置了自动加载 , 这个servlet就会在服务器启动的时候就会加载 .
例如 :
   <servlet>
      <servlet-name>invoker</servlet-name>
      <servlet-class>
        org.apache.catalina.servlets.InvokerServlet
      </servlet-class>
      <load-on-startup>2</load-on-startup>
   </servlet>
在上面的servlet注册标签中 , 除了servlet-name 和 servlet-calss 两个子标签外 , 还有一个 load-on-startup 标签 , 这个标签值为 0 – 6 , 数字越小优先级越高 , 配置的时候 , 那个数字越小 , 服务器启动的时候就先加载哪一个 .
     6. 错误页面替换
      我们使用浏览器浏览页面的时候 , 会出现各种错误 , 为了使界面友好 , 我们使用一些出错页替换相应的错误码页面 .
      在WebRoot目录下创建一个error文件夹 , 在里面创建相应错误的Jsp页面 , 一般都用 错误码.jsp 作为出错页面 , 例如错误404 相应的页面 404.jsp .
      然后在 web.xml 文档中加入以下标签 .
        <error-page>
           <error-code>404</error-code>
           <location>/error/404.jsp</location>
        </error-page>
      当我们访问出现404错误之后 , 就会自动跳转到这个页面 .
如果我们使用html页面作为出错页面 , 但是IE浏览器会过滤html页面 , 需要在IE | Internet 选项中选中 显示友好的错误信息 , 这样就能显示html出错页面了 , 正因为这样我们不适用html页面作为出错页面 , 我们使用jsp页面作为出错页面 .
     7. 缺省servlet
      如果某个servlet的映射路径仅仅为一个正斜杠(/) , 那么这个Servlet就成为当前web应用程序的的缺省servlet .
   凡是在web.xml 文件中找不到匹配的<servlet-mapping>元素的url , 它们的访问请求都将交给缺省的servlet处理 , 也就是说 , 缺省Servlet处理用于处理其他servlet都不处理的访问请求 .
     8. Servlet接口实现类            (1)Servlet接口简介
A. SUN公司为Servlet接口定义了两个实现类 , GenericServlet 和 HttpServlet , GenericServlet 是 HttpServlet的父类 .
        B. Servlet是一个接口 , 所有的servlet都必须实现这个接口 , 或者是实现这个Servlet接口的子类 .
        C. GenericServlet类实现了Servlet接口 , 有一点要注意 , GenericServlet类不是Servlet的子类 , 它是Object的子类 .---?
        D. HttpServlet类继承了GenericServlet类 , 是GenericServlet类的子类 .
           (2)Servlet
        A. 介绍
           这个接口定义了一个Servlet , Servlet是一个在Web服务器上继承了这个功能的java类 .
        B. 方法
           1) init()方法
              Public void init(ServletConfig config) throws ServletException
              被servlet容器调用 , 表名一个servlet被置入服务 .
              这个方法是在浏览器访问servlet的java类之后 , 调用service()方法之前执行的 , 在服务器启动之后 , 该init()方法只调用一次 , 并且在调用service之前必须退出 .
           2) service()方法
              Servlet容器调用这个方法 , 允许servlet响应请求 .
           3) destroy()方法
              Servlet容器调用这个方法 , 将servlet从服务器中移出 .
           4) getServletConfig()方法
              返回一个ServletConfig对象 , 这个对象包括这个这个servlet的初始化和启动参数 .
           5) getServletInfo()方法
              返回这个servlet信息 , 例如作者 , 版本 , 版权等信息 .
      (3)
      (3) GenericServlet实现类
        
      (3) HttpServlet实现类
                     
十四 四大作用域      1. Context
      一个应用(项目)拥有唯一的一个ServletContex对象 , 访问此应用的任何浏览器 , 共享一个ServletContex .
      一个应用是从服务器开启 , 到服务器关闭 , 指的是一个项目 .
      获取方式 , servletConfig.getServletContex()方法 ,
     2. session
      为每一个浏览器创建一个独有的会话 , 当前的用户访问任意的servlet都可以保存自己的数据 .
      类 : HttpSession , 获取该类的方式 , httpServletRequest.getSession() .
      每一个HttpSession对象都有自己唯一的ID值 .
     3. request
      用户请求Servlet , 当请求结束的时候request消失 .
      类 HttpServletRequest .
     4. PageContext
      
     5. 相同点
      ServletContex , HttpSession , HttpServletRequest 三个类都有以下两种方法 :
        setAttribute(key , value) , 用于将数据存在此范围内 ,
        getAttribute(key) , 用于将数据从某范围内取出 .
     6. 比较
      ServletContex , HttpSession , HttpServletRequest , PageContext 作用范围依次减小 , 但它们没有包含关系 .
      ServletContex一个项目中有一个 , HttpSession 一个会话有一个 , HttpServletRequest 一次请求有一个 , PageContext 一个页面有一个 .
十五 jdbc入门1.jdbc概念
    Jdbc Java Database Connectivity .
    这是Sun公司的对数据库进行操作的一套api , 都是由接口组成 , Sun公司没有实现 .
    这些接口都是由数据库厂商进行实现的 , 这些实现的类 , 我们称之为驱动 .
2.jdbc步骤详解(1). 注册驱动
DriverManger类介绍 :
DriverManger使java.sql包下的类 , 作用使管理jdbc驱动用的 , 下面用到了DriverManger类的集中方法 , 其中 registerDriver()为注册驱动程序 ,  getConnection()为获得数据库连接 .
DriverManager.registerDriver( new com.mysql.jdbc.Driver() ) ;
    上面的语句会导致驱动加载两次 , com.mysql.jdbc.Driver 中由一个静态的代码块 , 该代码块中的语句是java.sql.DriverManager.registerDriver(new Driver());
    在com.mysql.jdbc.Driver()中的静态代码块就将该驱动注册了 , 我们只需要加载这个类就可以了 , 不用在外部在使用一次 DriverManager.registerDriver(new com.mysql.jdbc.Driver())了 , 这样在静态代码块中加载了一次驱动 , 在外部我们又执行了一次加载 , 这样驱动就加载了两次了 .
    我们只需要使类加载就可以了 , 我们使用 Class.forName(“com.mysql.jdbc.Driver”); 就可以实现驱动的注册了 .
(2)创建数据库的连接
    Connection conn = DriverManager.getConnection(url , user , password) ;
    上面是获得数据库连接的语句 , Connecttion对象就是数据库的连接 , 我们使用java.sql.DriverManger下的getConnection()方法可以获取数据库连接 , 传入的三个值都是字符串形式的 .
    1)url : 是数据库的地址 ;
       格式范例 :
jdbc:mysql://localhost:3306/test?参数名1=参数值1&参数名2=参数值2
url个字段介绍 :
              jdbc : 主协议
              mysql : 子协议
              localhost : 主机名 , 可以为ip地址
               3306 : 数据库的端口号
              Test : 数据库名称
              参数名和参数值常为 数据库的用户名 , 密码 或者编码类型 , 常用的参数示例 user=root&password=root&characterEncoding=UTF-8
    2)user : 是数据库的用户名
    3)password : 数据库的密码
    如果在url中带了用户名和密码的参数 , 可以不写 user和password .
    getConnection()可以传入两种参数 , 一个是 url , user, password 三个参数 ; 另一种是传入一个带用户名和密码的uri .
    Connecttion conn = DriverManger.getManager(“jdbc:mysql://localhost:3306/test” , root , root) ;
    Connecttion conn = DriverManger.getManager(“jdbc:mysql://localhost:3306/test?user=root&password=root”);
(3)几个重要的类及其主要方法1)Connecttion
    作用 : Connecttion对象用于表示对某个数据库的连接 , 所有的对数据库的操作都需要Connecttion对象来完成 .
    createStatement() 创建向数据库发送sql语句的数据库对象 ;
     prepareStatement(sql)  创建向数据库发送预编译sql的PrepareStatement对象 ;
2)Statement
    作用 : 用于向数据库发送sql语句 并返回生成的结果对象.
    Execute(String sql) 用于向数据库发送任意sql语句 ;
    executeQuery(String sql) 用于向数据库中发送查询sql语句 ;
    executeUpdate(String sql) 用于向数据库总发送增删改sql语句;
    上面的三个方法返回的都是ResultSet对象 .
3)PreparedStatement
    作用 : 表示预编译的sql语句对象 , 也有Statement对象的三个方法 , 方法遇上面的Statement对象方法基本相同 .
4)ResultSet
    作用 : 这个类的对象用于封装查询到的结果集 , 这个结果与我们看到的dos窗口查询到的结果一样 ;
       指针一开始指向的位置是第一行 , 就是表头 , 第一行只是列名 , 没有数据 , 取出数据要从第二行开始 .
    Next() : 指针指向下一行 , 如果没有下一行就返回false , 如果有就返回true ;
    get()方法 , 当我们将指针指向一行的时候 ,可以获取当前行某列的数据 ,
       getBoolean()方法 , 获得数据库中的bit类型的数据 , 返回类型为boolean ;
       getByte()方法 , 获得数据库中的tinyint类型的数据 , 返回类型为byte ;
       getShort()方法 , 获得数据库中的smallint类型的数据 , 返回类型为short ;
       getInt()方法 , 获得数据库中的int类型的数据 , 返回类型为int ;
       getLong()方法 , 获得数据库中的bigint类型的数据 , 返回类型为long ;
       getString()方法 , 获得数据库中的char , varchar , longvarchar类型的数据 , 返回类型为String ;
       getClob()方法 , 获得数据库中的clob类型的数据 , 返回类型为clob ;
       getBlob()方法 , 获得数据库中的blob类型的数据 , 返回类型为blob ;
       getDate()方法 , 获得数据库中的date类型的数据 , 返回类型为java.sql.Date ;
       getTime()方法 , 获得数据库中的time类型的数据 , 返回类型为java.sql.Time ;
       getTimeStamp()方法 , 获得数据库中的timestamp类型的数据 , 返回类型为java.sql.Timestamp ;
    其中可以将列的信息当作参数传入上面的get方法中 :
       get(int index) 获得第几列的数据, 列数从1开始 ;
       get(String columnName) 根据列名获得 ;
    previous() : 指针移到上一行 ;
    absolute(int index) : 移到指定行 ;
    beforeFirst() : 移动到ResultSet的最前面 ;
    afterLast() : 移动到ResultSet的最后面 ;
   
    用上面三个类处理对数据库的各种操作以及获得的结果 .
(4)释放数据库资源
    上面用于数据库连接和操作以及结果处理创建的对象必须要释放掉 .
    需要释放的对象 :
Connecttion对象 conn , 这个对象必须释放掉 , 因为数据库有并发连接数 , 如果一个连接没有释放 , 就会被占用这个连接 .
    Statement 对象 stmt ;
    ResultSet 对象 rs ;
    上面的三个对象都需要释放掉 .
    将释放对象的语句放在finally语句中
   
    语释放语句技巧 , 先判断是否为空 , 如果不为空我们就将其关闭 , 如果出现异常 , 打印之 , 执行完之后将conn=null ;
   
    Try{
}finally{
    If(conn != null){
       Try{
       Conn.close()
}catch(SQlException e){
       E.printStackTrace();
}
Conn = null ;
       }
    If(stmt != null){
       Try{
       stmt.close()
}catch(SQlException e){
       E.printStackTrace();
}
stmt = null ;
       }
    If(rs != null){
       Try{
       rs.close()
}catch(SQlException e){
       E.printStackTrace();
}
rs = null ;
       }
}
   
下面是jdbc案例十六 JDBC案例介绍1.需求
实现一个简单的员工信息管理系统 , 并实现对其的增删改查
id varchar(40)
name varchar(20)  
gender varchar(4)
birthday date
idcard varchar(20)
degree vachar(20)
entrydate date
position varchar(40)
department varchar(20)
2.步骤简介(1)模式选择
    java开发两种模式 :
    jsp+javabean 只适合小型应用 ;
    servlet + jsp + javabean  mvc模式 jsp 用来显示 , 其中禁止调用方法 , 调用的方法都放在servlet中 .
    这里我们选择mvc模型 .
(2)搭建开发环境
    1) 建工程 建包
    2) 导入相关jar包
       BeanUtils先关jar包  commons-beanutils-1.8.0.jar 和 commons-logging.jar
       jstl标签库 (这个包是自带的)
       mysql 相关jar包 mysql-connector-java-5.0.8-bin.jar
    将上面的三个包复制到WEB-INF下面的lib文件夹下 , MyEclipse会自动将路径加到工程上 . 这个lib文件夹是工程自带的 .   
    3)创建数据库和表
   
    create database day12_employee;
       use day12_employee;
       create table employee
       (
              id varchar(40) primary key,
              name varchar(20),
              gender varchar(6),
              birthday date,
              idcard varchar(20),
              degree varchar(20),
              entrydate date,
              department varchar(20),
              position varchar(40)
       );
(3)设计bean
    employee.java
(4)实现dao(5)实现service
简单的原封不动的调用dao中的方法
(6)实现web .3按照步骤进行详解(1)设计javabean
创建一个cn.itcast.myemp.domain 包 , 我们在后面包名统一前面加上 cn.itcast.myemp ;
1)employee实体类
将上面的九个字段一一实现 , 获得getter setter方法即可 .
   
     private String id;
     private String name;
     private String gender;
     private String idcard;
     private String degree;
     private String department;
     private String position;
     private Date birthday;
     private Date entrydate;
    注意这个Date导入的是 java.util.Date包
2)Page实体类
     private  List pageData;   // 分页显示的数据
     private int pageNum; // 当前页码
     private int totalRecord; // 总记录数
     private int totalPageNum;   // 总页数
     private int firstPageNum;   // 起始页码
     private int lastPageNum; // 结束页码
    设置上面的一系列私有变量 , 获得getter和setter方法 .
(2)创建配置文件
    在src下创建一个jdbc.properties 的文件
    输入以下数据
    driverClass=com.mysql.jdbc.Driver
uri=jdbc:mysql://localhost:3306/emp
user=root
password=root
    上面的四行是数据库连接相关的数据 .
   
    这个配置文件的四个键值对 是jdbc的四要素 .
(3)实现工具类1)WebUtils工具类 request2Bean()方法的概述 :
a.    先创建一个实体类对象 ;
b.    注册转换器 , 如果我们需要自动转换类型就需要这一步 , 在调用BeanUtils.setProperty()方法的时候会自动调用
c.    获得request中的参数名枚举 ;
d.    遍历枚举 , 获得参数名和参数值 , 然后调用 BeanUtils.setProperty()方法 , 将参数值按照参数名封装到bean实体类中 ,
e.    返回封装好的bean实体类 .
注册日期转换器 :
a.    先创建一个日期转换器对象 ;
b.    设置这个转换器对象的格式 ;
c.    注册这个转换器 .
      a. 先私有化构造函数
    private WebUtils(){}
    然后创建两个方法 request2Bean()方法 和 forward()方法 , 一个是用来将表单提交数据封装到javabean中 , 第二个是转发全据消息页面 .
      b. 创建request2Bean()方法 :
    public static <T> T request2Bean(HttpServletRequest request , Class<T> beanClass ){
       try{
           //先创建一个bean对象
           T bean = beanClass.newInstance();
           //封装一个uuid作为其id , 这里是为了使id不会重复
           BeanUtils.setProperty(bean , “id” , UUID.radomUUID().toString());
           //注册转换器 , 这个转换器可以在调用BeranUtils.setProperty()方法的时候 , 自动调用
           DateConvert convert = new DateConvert();
           convert.setPattern(“yyyy-MM-dd”);
           ConvertUtils.register(convert , Date.class)   //由字符串转换为date的时候调用这个方法 .
           //获得request中的参数名枚举
           Enumeration e = request.getParameterNames();
           //便利枚举 , 并调用request.getParameter()方法得到参数值 , 再将参数封装到bean中
           while(e.hasMoreElement){
    String name = (String)e.nextElement();
    String value = request.getParameter(name);
    BeanUtils.setProperty(bean , name , value);
}
           //将bean返回
           return bean ;
       }catch(Exception e){
    throw new RuntimeException(e);
}
}
      c. 转发全据消息页面方法 :
     注意转发的时候的路径是绝对地址 , 从应用的根目录开始 , / 表示应用的根目录 , 页面是在根目录下的 .
    public static void forward(HttpServletRequest request , HttpServletResponse response , String message) throws ServletException , IOException{
       request.setAttribute(“message” , message);
       request.getRequestDispatcher(“/WEB-INF/pages/message.jsp”).forward(request , response);
}
      验证WebUtils工具类是否可用
    验证request2Bean()方法可行性 :
       a. 一个jsp页面不能跳转到另一个jsp页面 , 如果想要跳转 , 必须使用一个UiServlet进行跳转 ;
       b. 在首页中创建一个链接 , 直接链接到 “${pageContext.request.contextPath}/servlet/UiWebUtilsTest” ,
           el表达式不用导入标签库就可以使用 .
servlet/UiWebUtilsTest是一个中转页面 , 在这个页面中只有一句
request.getRequestDispatcher(“/WEB-INF/pages/webutilstest.jsp”).forward(request , response)语句 , 直接跳转到测试页面 .
d.    创建一个Person类 , 有三个属性 name , birtjday , age ; 从表单提交这三个属性 , 其中birthday是Date类型的 .
e.    wenutilstest.jsp表单页 , 提交上面三个属性到WebUtilsTest页面 , 调用WebUtils.request2questBean()方法 , 看是否能将表单中的数据封装到Person实体类中 , 包括日期属性 , 如果成功 , 就说明验证成功了 .
验证全局消息转发页面可行性 :
    a. 在上面的servlet/WebUtilsTest中调用forward()方法 ,传入request , response , “验证全局消息页面” , 如果最后提交完表单后 , 自动跳转到这个页面 , 说明验证成功
2)JdbcUtils工具类从配置文件中获取jdbc四要素步骤 :
a.    设置静态代码块 , 在该类加载的时候就获取四要素 , 只获取依次就可以 , 以后就没必要调用了 .
b.    创建Properties类的对象 , 用来接受配置文件中的数据 ;
c.    使用 JdbcUtils.class.getClassLoader.getResourceAsStream(“”)方法将配置文件传入输入流中 .
d.    关联Properties对象和输入流
e.    从Properties对象中取数据 , 并进行操作 , 加载驱动也是在这一步完成的 .
释放资源方法 :
a.    一个if语句是一组 , 一共yao释放三个对象 , 这三个方法都是差不多的 , 只是变量不同 ;
b.    在每个if语句中 , 先判断变量是否为空 , 如果不为空就关闭 , 然后为了以防万一在将其指向null .
导包问题 :
    注意 , 这个方法中的 Connection , PreparedStatement , ResultSet 类导入的包均为java.sql包下的 , 不是mysql下的 .
a. 先私有化构造函数 , 工具类不允许创建对象 .
private JdbcUtils(){}
b. 设置全局变量
将数据库路径 uri , 账号 uer , 密码 password 设置为类的全局变量 . 因为这些变量是在静态代码块中读取到的 , 然后在下面的数据库连接方法中还要使用 , 因此要设置为全局变量 .
static{
   
}
c. 设置静态代码块 , 处理四要素
设置一个静态代码块 , 在静态代码块中读取配置文件 , 注册驱动 .
Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
    static{
    try{
       //读取配置问文件 , 获取四要素
    Properties props = new Properties();   //创建一个Properties对象
    //将jdbc.Properties文件读取到输入流中
    InputStream in = JdbcUtils.class.getClassLoader().getRespurceAsStream(“jdbc.Properties”);
    //相当于将文件与props对象关联 , 将文件中的键值对存到props对象中
props.load(in);
//取出驱动名字 , 加载驱动
String driverClassName = props.getProperty(“DriverClass”);
Class.classForName(driverClassName);
//取出数据库路径
uri = props.getProperty(“uri”);
//取出数据库的用户名
user = props.getProperty(“user”);
//取出数据库密码
password = props.getProperty(“password”);
}catch(Exception e){
    throw new
}
}
d.创建连接方法
注意这里的Connection需要导入的包是 java.sql.Connection .
    public static Connection getConnection() throws SQLException{
    return DriverManger.getConnection(uri , user , password);
}
e.释放资源方法
    public static void release(Connecttion conn , Statement stmt , ResultSet rs){
    if(conn != null){
    try{
    conn.close();
}catch(Exception e){
    e.printStackTrace ;
}
conn = null ;
       }
    if(stmt != null){
    try{
    stmt.close();
}catch(Exception e){
    e.printStackTrace ;
}
stmt = null ;
       }
    if(rs!= null){
    try{
    rs.close();
}catch(Exception e){
    e.printStackTrace ;
}
rs = null ;
       }
}
(4)实现Dao1)获得所有的员工流程介绍
a.    将Connecttion , PreparedStatement , ResultSet 对象放到方法的全局变量中 , 并赋值null , 这是因为在try finally两个区域都要用到这些对象 .
b.    获得连接 , 调用 JdbcUtils.getConnection()来获得 , 得到conn对象;
c.    预编译sql语句 , 调用conn.PreparedStatement(sql语句字符串)方法获得 stmt对象 ;
d.    发送sql语句 , 调用stmt.executeQuery()方法 , 得到rs对象 ;
e.    处理rs对象中的数据 .
异常处理
    在Dao中出现的异常 , 我们都将其抓起来 , 然后转为一个运行时异常抛出 .
    先写一个异常 ,然后会报错 , 我们就ctrl+1 处理错误 , 创建这个异常 , 然后就将异常制定创建在Exception包中 , 继承RuntimeException , 并且继承所有的方法 .
代码
public List getAll(){
       //由于有try catch 语句 , 这些变量除了在try中使用以外 , 还要在finally中使用 .
    Connecttion conn = null;
    PreparedStatement stmt = null ;
    ResultSet rs = null ;
    try{
    conn = JdbcUtils.getConnection();  //获得连接
    //预编译sql语句
    String sql = “select * from employees” ;
    stmt = conn.PreparedStatement(sql);
    //发送sql语句
    rs = stmt.executeQuery();
    //处理结果集 , 我们将取出的数据封装在employee对象中 , 将employee对象都放在list中 .
    List list = new ArrayList();
    //遍历rs
    while(rs.next()){
    Employee e = new Employee(); //创建一个employee对象 , 用来封装结果
    e.setBirthday(rs.getDate(“birthday”));
    e.setEntryDate(rs.getDate(“entrydate”));
    e.setdegree(rs.getString(“degree”));
    e.setDepartment(rs.getString(“department”));
    e.setGender(rs.getString(“gender”));
    e.setId(rs.getString(“id”));
    e.setIdcard(rs.getString(“idcard”));
    e.setName(rs.getString(“name”));
    e.setPosition(rs.getString(“position”));
    list.add(e);  //将封装好的对象加入到list中
}
return list;  //将list返回
}catch(Exception e){
    throw
}finally{
    JdbcUtils.release(conn , stmt , rs);
}
}
2)根据id查找      流程介绍
a.    将Connecttion , PreparedStatement , ResultSet 对象设置为方法的全局变量 , 因为在try 和 finally区域中要使用这些变量 ;
b.    获得连接 , 调用JdbcUtils.getConnection()方法 , 得到Connecttion对象 ;
c.    预编译sql语句 , 调用conn.preparedStatement(sql语句)方法 , 预编译sql语句 , 得到PreparedStatement对象 ;
d.    发送sql语句 , 调用 stmt.executeQuery()方法 , 执行sql语句 , 返回ResultSet对象 ;
e.    处理结果集 ;
代码
public Employee find(String id){
    Connecttion conn = null;
    PreparedStatement stmt = null ;
    ResultSet rs = null ;
    try{
    conn = JdbcUtils.getConnection();  //获得连接
    //预编译sql语句
    String sql = “select * from employees where id=?” ;
    stmt = conn.PreparedStatement(sql);
    //替换占位符
    stmt.setString(1,id);
    //发送sql语句
    rs = stmt.executeQuery();
    //遍历rs
    while(rs.next()){
    Employee e = new Employee(); //创建一个employee对象 , 用来封装结果
    e.setBirthday(rs.getDate(“birthday”));
    e.setEntryDate(rs.getDate(“entrydate”));
    e.setdegree(rs.getString(“degree”));
    e.setDepartment(rs.getString(“department”));
    e.setGender(rs.getString(“gender”));
    e.setId(rs.getString(“id”));
    e.setIdcard(rs.getString(“idcard”));
    e.setName(rs.getString(“name”));
    e.setPosition(rs.getString(“position”));
    return e ;
}
return null;  //将list返回
}catch(Exception e){
    throw
}finally{
    JdbcUtils.release(conn , stmt , rs);
}
}
3)添加employee对象到数据库流程介绍
a.    将Connecttion , PreparedStatement , ResultSet 对象设置为方法的全局变量 , 因为在try 和 finally 两个区域都用到了这三个对象 ;
b.    获得连接 , 调用 JdbcUtils.getConnection()方法 , 得到conn ;
c.    预编译sql语句 , 调用conn.PreparedStatement(sql语句)方法 ,得到PreparedStatement对象 ;
d.    替换占位符
e.    发送sql语句 , 调用stmt.executeUpdate()方法 , 得到一个int型数据 .
关于替换占位符
    先进行预编译 , 先执行conn.preparedStatement(sql)方法 , 将sql语句与pstmt关联起来 , 我们才能使用PreparedStatement类下的替换占位符方法 ,
如果是字符串形式 , 我们可以使用setString(1 , “张三”) , 如果是日期形式 , 我们可以使用 setDate(1 , java.sql.Date对象) ;
    替换占位符的方法一般是 : set被替换的类型(占位符的索引 , 被替换的实体) ;
    如果被替换的是字符串  ,那么被替换的类型就是String , 方法就是 setString() ; 如果被替换的是日期 , 被替换的类型就是Date类型 , 不过这个Date是java.sql.Date , 一定要区分java.utils.Date , 方法就是setDate() ;
    关于替换Date的处理 :
       我们使用setDate(index , new java.sql.Date(dateStamp)); 新建一个sql的Date对象 , 在构造函数中传入一个时间戳 , 时间戳就是从1970年到现在的毫秒数 ,在本程序中 , 我们是这样处理的 , 先取出utils的Date , 然后获得时间戳 , 再将时间戳传入sql的Date构造函数 .
    setDate(index , new java.sql.Date(bean.getDate().getTime()));
代码
    public boolean save(employee bean){
    Connecttion conn = null ;
    PreparedStatement pstmt = null ;
    ResultSet rs = null ;
    try{
       //获得连接
    conn = JdbcUtils.getConnection();
    //预编译sql语句
    String sql = “insert into employees (id,name,gender,birthday,idcard,degree,entrydate,department,position) values(?,?,?,?,?,?,?,?,?)”
    pstmt = conn.PreparedStatement(sql);
    //替换占位符
    pstmt = conn.preparedStatement(sql);
    pstmt.setString(1 , bean.getId());
    pstmt.setString(2 , bean.getName());
    pstmt.setString(3 ,bean.getGenter());
    pstmt.setDate(4 , new java.sql.Date(bean.getDate().getTime()));
    pstmt.setString(5 , bean.getIdcard());
    pstmt.setString(6 , bean.getDegree());
    pstmt.setDate(7 , new java.sql.Date(bean.getEntrydate().getTime()));
    pstmt.setString(8 , bean.getDepartment());
    pstmt.setString(9 , bean.getPosition());
    //发送sql语句
    int num = stmt.executeUpdate();
    if(num > 0)
       return true ;
    return false;
}catch(Exception e){
    Throw
}finally{
    JdbcUtils.release();
}
}
4)修改数据库中的employee数据流程介绍
a.    将Connecttion , PreparedStatement  , ResultSet ,三个类的对象 conn , pstmt , rs的声明提为该方法的全局变量 , 因为在try和finally两个区域中都要用到这三个对象 , 在try中是对数据库操作的需要 , 在finally中是在释放资源的时候 , 将这三个对象全部释放 .
b.    获得数据库连接 , 调用JdbcUtils.getConnection()方法 , 获得conn对象 ;
c.    预编译sql语句 , 调用conn.PreparedStatement(sql)方法 , 获得PreparedStatement对象 ;
d.    替换占位符
e.    发送sql语句 , 返回是否成功修改得到一个布尔值 .
代码
    public boolean update(employee bean){
    Connecttion conn = null ;
    PreparedStatement pstmt = null ;
    ResultSet rs = null ;
    try{
       //获得连接
    conn = JdbcUtils.getConnection();
    //预编译sql语句
    String sql = “update employees set name , gender=? , birthday=? , idcard=? , degree=? , entrydate=? , department =?, position where id =?”;
    pstmt = conn.PreparedStatement(sql);
    //替换占位符
    pstmt = conn.preparedStatement(sql);
    pstmt.setString(1 , bean.getName());
    pstmt.setString(2 ,bean.getGenter());
    pstmt.setDate(3 , new java.sql.Date(bean.getDate().getTime()));
    pstmt.setString(4 , bean.getIdcard());
    pstmt.setString(5 , bean.getDegree());
    pstmt.setDate(6 , new java.sql.Date(bean.getEntrydate().getTime()));
    pstmt.setString(7 , bean.getDepartment());
    pstmt.setString(8 , bean.getPosition());
    pstmt.setString(9 , bean.getId());
    //发送sql语句
    int num = stmt.executeUpdate();
    if(num > 0)
       return true ;
    return false;
}catch(Exception e){
    Throw
}finally{
    JdbcUtils.release();
}
}
5)删除一个员工流程介绍
a.    将Connecttion , PreparedStatement , ResultSet 对象设置为方法的全局变量
b.    获得数据库连接 , 调用JdbcUtils.getConnection()方法 , 获得conn ;
c.    预编译sql , conn.PreparedStatement(sql) , 得到pstmt对象 ;
d.    替换占位符
e.    发送sql语句 .
代码
    public boolean update(int id){
    Connecttion conn = null ;
    PreparedStatement pstmt = null ;
    ResultSet rs = null ;
    try{
       //获得连接
    conn = JdbcUtils.getConnection();
    //预编译sql语句
    String sql = “delete from employees where id =?”;
    pstmt = conn.PreparedStatement(sql);
    //替换占位符
    pstmt = conn.preparedStatement(sql);
    pstmt.setString(1 , id);
    //发送sql语句
    int num = stmt.executeUpdate();
    if(num > 0)
       return true ;
    return false;
}catch(Exception e){
    Throw
}finally{
    JdbcUtils.release();
}
}
6)查询记录数流程介绍
a.    将Connecttion , PreparedStatement , ResultSet 对象设置为方法的全局变量  , 在try中需要这3个变量进行数据库操作  , 在finally中需要将这三个变量释放掉 .
b.    得到数据库连接 , 调用JdbcUtils.getConnection()方法 , 得到conn对象 ;
c.    预编译sql语句 , 调用 conn.PreparedStatement(sql)方法 , 得到 pstmt对象 ;
d.    发送sql语句 , 调用pstmt.executeQuery()方法 , 得到rs对象 ;
e.    处理结果集
注意
    凡是查询返回的都是rs对象 , 增删改返回的都是int对象 .
    获得查询的数据 , 以dos窗口中的列名为准 , 例如这次查询 count(*) , 我们最后从rs中获取的时候也是用
rs.getString(“count(*)”)方法 .
   
代码
    public int getotalRecord(){
    Connecttion conn = null ;
    PreparedStatement pstmt = null ;
    ResultSet rs = null ;
    try{
       //获得连接
    conn = JdbcUtils.getConnection();
    //预编译sql语句
    String sql = “select count(*) from employees”;
    pstmt = conn.PreparedStatement(sql);
    //发送sql语句
    rs = stmt.executeQuery();
    //处理结果集
    if(rs.next()){
    return getInt(“count(*)”);
}
return 0;
}catch(Exception e){
    Throw
}finally{
    JdbcUtils.release();
}
}
7)查询分页显示数据流程介绍
a.    将Connecttion , PreparedStatement , ResultSet 对象设置为方法的全局变量 ;
b.    获得连接 , 调用JdbcUtils.getConnection()方法 , 得到conn对象 ;
c.    预编译sql语句 , 调用conn.PreparedStatement(sql)方法 ,得到pstmt对象 ;
d.    发送sql语句 , 调用 pstmt.executeQuery()方法 ,得到rs对象 ;
e.    处理结果集 .
代码
public List getPageData(int start , int len){
       //由于有try catch 语句 , 这些变量除了在try中使用以外 , 还要在finally中使用 .
    Connecttion conn = null;
    PreparedStatement stmt = null ;
    ResultSet rs = null ;
    try{
    conn = JdbcUtils.getConnection();  //获得连接
    //预编译sql语句
    String sql = “select * from employees limite ?,?” ;
    stmt = conn.PreparedStatement(sql);
    //替换占位符
    stmt.setInt(1, start);
    stmt.setInt(2, len);
    //发送sql语句
    rs = stmt.executeQuery();
    //处理结果集 , 我们将取出的数据封装在employee对象中 , 将employee对象都放在list中 .
    List list = new ArrayList();
    //遍历rs
    while(rs.next()){
    Employee e = new Employee(); //创建一个employee对象 , 用来封装结果
    e.setBirthday(rs.getDate(“birthday”));
    e.setEntryDate(rs.getDate(“entrydate”));
    e.setdegree(rs.getString(“degree”));
    e.setDepartment(rs.getString(“department”));
    e.setGender(rs.getString(“gender”));
    e.setId(rs.getString(“id”));
    e.setIdcard(rs.getString(“idcard”));
    e.setName(rs.getString(“name”));
    e.setPosition(rs.getString(“position”));
    list.add(e);  //将封装好的对象加入到list中
}
return list;  //将list返回
}catch(Exception e){
    throw
}finally{
    JdbcUtils.release(conn , stmt , rs);
}
}
8)验证是否可用      a. 验证findAll()JdbcUtils()方法
       第一种方法
a.    在首页中链接到servlet/UiWebUitlsTest页面中去 , 我们在这个页面测试这个方法 .
b.    在servlet/UiWebUitlsTest中调用JdbcUtils.findAll()方法 , 将返回的list打印出来 , 这种方法不好 , 验证起来很麻烦 , 我们只需要看看getAll()方法能不能将数据全部取出 .
第二种方法(推荐)
我们创建一个主函数类Test类 , 在主函数中调用getAll()方法 , 这样有很明显的提示 , 在这里出现了两个错误 , 第一个是将jdbc.properties配置文件中的url写错了 , 写成uri , 在这里注意 , 另外将sql语句中的表名写错了 , 改完这两个错误 , 成功将方法返回的list打印出来 , 并且能在list中查看相关的变量 .
   
      b. 验证getById()方法是否可用
        在Test中输入下面的代码 :
       Employee bean =  dao.getById("1");
       System. out.println("test--> getById() : " + bean);
       执行 , 如果能打印出取出的代码 , 就说明该方法可行
      c. 验证insert()方法是否可用
       在Test中输入以下代码 :
       Employee bean2 =  new Employee();
       bean2.setId("2");
       bean2. setBirthday( new Date());
        bean2.setEntrydate( new Date());
        boolean b =  dao.insert(bean2);
       System. out.println("test--> insert() : " + b);
       这里只有id是必须的 , 不过在这里必须写上日期 , 我们在替换占位符的时候 , 使用的 new java.sql.Date(bean.getBirtiday().getTime())方法 , 如果我们不输入日期 , 那么就会出现空指针调用 , 抛出空指针异常 , 因此我们将两个日期加上去 .
       这个方法我们不用的时候 , 将其注释掉 , 因为这个每次执行都要修改以下传入的参数 , 我们插入了id为1  ,下一次就不能再插入1 了 , 因为id是主键, 如果插入逐渐重复就会出现异常 .
      d. 验证update()方法是否可用
       //测试EmployeeDao类中的update()方法是否可用
       Employee bean3 =  new Employee();
       bean3.setId("000fb8a5-7d13-460f-9ffb-f17cd8aa59b6");
        bean3.setBirthday( new Date());
       bean3.setEntrydate( new Date());
        boolean b1 =  dao.update(bean3);
       System. out.println("test--> update() : " + b1);
       使用上面的方法来验证是否更新成功 .
         e. 验证delete()方法是否可用
       //测试EmployeeDao类中的delete()方法是否可用
        boolean b2 =  dao.delete("2");
       System. out.println("test--> delete() : " + b2);
      f.验证getTotalRecord()方法是否可用
       //测试EmployeeDao类中的getTotalRecord()方法是否可用
        int totalRecord =  dao.getTotalRecord();
       System. out.println(totalRecord);
   g. 验证getPageData()方法是否可用
       //测试EmployeeDao类中的getPageData()方法是否可用
        List pageData =  dao.getPageData(1, 5);
       System. out.println(pageData);
(5)实现service
    service是业务逻辑层 , 这层代码起着承上启下的作用 , web层调用service , service调用dao层的方法和成员 .
    在service中 , 代码很简单 ,我们只需要创建一个私有的EmployeeDao成员变量 , 通过这个私有的对象调用EmployeeDao中的方法 .
    代码 :
    public class service{
       //创建一个EmployeeDao实体类 , 我们通过这个实体类调用EmployeeDao中操作数据库的方法
       private EmployeeDao dao = new EmployeeDao();
       //得到所有员工信息
       public List getAll(){
    return dao.getAll();
}
//根据id查找员工信息
public Employee getById(String id){
    return dao.getById(id) ;
}
//插入员工信息
public boolean insert(Employee bean){
    return dao.insert(bean);
}
//修改员工信息
public boolean update(Employee bean){
    return dao.update(bean);
}
//删除员工信息
public boolean delete(String id){
    return dao.delete(id);
}
}
(6)几个页面链接
    我们使用浏览器首先登陆的是首页 , 我们通过首页跳转到UiServlet , 在通过UiServlet跳转到其它页面 .
    首页中所有的跳转都是跳转向UiServlet中 .
    在index.jsp首页中设置两个链接 , 分别连接到查看所有的员工页 , 和添加员工页 .
    首页中的代码 :
       <a href = “${pageContext.request.contextPath}/servlet/UiGetAllServlet”>查看所有的员工 </a>
       <a href = “${pageContext.request.contextPath}/servlet/UiAddServlet”>添加员工 </a>
    通过上面的链接能到相关的UiServlet页面 .
   
    UiGetAllServlet页面代码
       这个页面中我们调用service中的getAll()方法 , 将获得的List对象存入request中 .  跳转代码如下 :
       request.getRequestDispather(“/WEB-INF/pages/getalldata.jsp”).forward(request , response);
       通过执行上面的语句 , 可以直接跳转到查看所有员工页面 .
    UiAddServlet页面代码
       这个是一个纯跳转页面 , 只实现跳转功能 . 代码如下 :
       request.getRequestDispather(“/WEB-INF/pages/add.jsp”).forward(request , response);
    页面连接做完之后 ,我们就能够登陆首页 , 进行相应的页面跳转了 .
(7) 分页实现1)分页需求
由于数据库中的数据量过大 , 在一个页面显示所有的数据用户体验不够好 , 因此我们使用了分页 .
   
    实现上图所示的需求 , 我们来逐条分析 .
a.    除了上面的图片之外 , 我们还需要有显示的数据 , 这里每页显示10条信息 , 显示的数据都放在一个List中 , 显然我们需要一个List变量 , pageData来存放要显示的数据 .
b.    显示当前的页数 , 当前第几页 , 我们根据页数来从数据库中查询相关信息 , 这个用一个String变量pageNum来表示 ;
c.    总记录数 , 我们使用count(*)可以得到 , String totalRecord ;
d.    总页数 , 总记录数 除以每页显示的数据条数count , 注意这里的算法 totalPageNum = ( totalRecord + (count - 1) )/count ;
e.    起始页码 , 总共显示10页的编号 , 一般来说 , 起始页码就是当前页减去5 , 如果当前页小于5 , 那就显示1-10 编号 ;
f.    终止页码 , 当前页加上4 , 如果当前页是大于totalPageNum-4 , 那么就显示 totalPageNum-9 – totalPageNum编号 ;
2)创建page实体类
     private  List pageData;   // 分页显示的数据
     private int pageNum; // 当前页码
     private int totalRecord; // 总记录数
     private int totalPageNum;   // 总页数
     private int firstPageNum;   // 起始页码
     private int lastPageNum; // 结束页码
    获得其getter和setter方法 .
3)分页service实现底层dao实现
分页的底层是基于EmployeeDao的getTotaoRecord()方法和getPageDate()方法实现的 .
    其中getTotaoRecord()方法是获得数据库中该表的总记录数 ;
    getPageDate()方法是获得从一个起始位置 , 制定长度的记录数 .
    这里主要解析service实现 , 分页的service主要是封装page .
流程介绍
a.    创建Page对象 , 这个对象是要返回的 ;
b.    设置count , 这个很重要 , 表示每页显示数据条数 ;
c.    查询总记录数 , 创建一个EmployeeDao对象 , 通过这个对象调用getTotaoRecord()方法 ;
d.    计算总页数 , 使用 ( TotalRecord + ( count - 1 ) ) / count 方法 .
e.    查询分页显示的数据 , 开始位置是 ( PageNum – 1 ) * count , 长度为count ;
f.    计算起始页码和结束页码 , 起始页码为当前页-5 , 终止页码为当前页+4 , 如果当前页是前5页 , 那么显示前10页页码 , 如果当前页是后4页 , 那么显示后10页页码 , 如果页面不足10页 , 那就第一页是当前页 , 最后一页是终止页 ;
g.    PageNum是通过参数传递进来的 , 将上面的所有的数据封装起来返回 .
代码
    public Page getPage( int pageNum ){
       //创建Page对象
       Page page = new Page();
       //设置count
       int count = 10 ;
       //创建EmployeeDao对象 , 使用该对象操作数据库
       EmployeeDao dao = new EmployeeDao() ;
       //查询总记录数
       int totalRecord = dao.getTotaoRecord();
       //计算总页数
       int totalPageNum = ( totalPageNum + ( count - 1 ) ) / count ;
       //查询分页显示数据
       int start = ( pageNum – 1 ) * 10 ;
       int len = count ;
       List list = getPageDate( start , len ) ;
       //计算页码显示起始页和终止页
       int firstPage = pageNum - 5 ;
       int lastPage = pageNum + 4 ;
       //将三种特殊情况筛选出来
       if(firstPage < 1){   //这种情况是当前页是前5页的情况
    firstPage = 1 ;
    lastPage = 10 ;
}
if(lastPage > pageNum){  //这种情况是当前页是后四页的情况
    firstPage = totalPageNum -9 ;
    lastPage = totalPageNum ;
}
if(totalPageNum < 10){   //这种情况是总页数不足10页的情况
    firstPage = 1 ;
    lastPage = totalPageNum ;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值