Java联系人案例 jsp版 ---- Java进阶篇

引入

1.JavaBean      本质是一个满足下面条件的Java类

  • 必须有一个无参构造方法(无参构造方法也叫无参构造器/无参构造函数)
  • 所有属性必须私有化  private
  • 必须提供公开的getter和setter方法

2.mvc开发模式  (servlet+jsp + javabean的开模式)

  • M:Model(模型层)             JavaBean实现          封装业务数据
  • V:View(视图层)                 jsp实现                     显示数据
  • C:Controller(控制器层)     servlet实现               接收参数,调用业务逻辑

3.三层结构开发

  •  dao层:数据访问对象。实现对数据的相关操作    
  • service层:业务逻辑对象,实现对项目的业务逻辑处理的相关操作
  • web层:表现层。处理和用户直接相关的,接收参数,处理参数,跳转视图,展示数据

 dao层+service层

web层

 

 

实体类(entity)  javaBean实现    model模型层    

package cn.itcase.entity;
/**
 * 联系人实体类
 * @author Administrator
 *实体注意事项:
 *一、实体类的名字尽量和数据库的表的名字对应相同。
     二、实体类应该实现java.io.Serializable接口。
     三、实体类应该有个无参的构造方法。
     四、实体类应该有个有参(所有的参数)的构造方法。
    五、实体类有属性和方法,属性对应数据库中表的字段,方法主要有getter和setter方法。
    六、实体类还应该有个属性serialVersionUID。
   例如:private static final long serialVersionUID = -6125297654796395674L;
    七、属性一般是private类型,方法为public类型,对于数据库自动生成的ID字段对应的属性的set方法为private。
 */

public class Contact {
	
	private String id;
	private String name;
	private String gender;
	private int age;
	private String phone;
	private String email;
	private String qq;
	/**
	 * get和set方法就是为了能以得到和设置实体类中的私有属性值,
	 * 而一个类中至少要有一个构造方法,当没有人为添加的时候,
	 * 编译器会自动加入一个隐式的无参构造方法,当有人为添加时,编译器就不会自动添加了。
	 * 无参构造方法的作用是为了比较方便的new出一个对象
	 */
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getQq() {
		return qq;
	}
	public void setQq(String qq) {
		this.qq = qq;
	}
	/*有参构造方法(构造器):初始化属性(成员变量/实例变量)
	 * Java初始化:个人理解定义代码执行顺序,面向对象中的概念
	 * 非静态成员的初始化,发生在任何方法(包括构造器)被调用之前。并且它们定义的顺序,决定了初始化的顺序
	 * */
public Contact(String id,String name, String gender,int age,String phone,String email,String qq){
	super(); // 调用父类构造方法,这里调用的是无参构造方法
	this.id =id;
	this.name=name;
	this.gender=gender;
	this.age=age;
	this.phone = phone;
	this.email = email;
	this.qq=qq;
}
/*创建对象的过程叫实例化对象
 * 创建对象(new) 调用的是无参数的构造方法(无参构造器)
 * 
 * 如果写了有参数的构造方法,必须显示的写出无参数的构造方法
 * 
 * 如果没有有参构造方法则不一定要写出,因为Java 虚拟机会帮我们隐式的出来
 * 
 * 
 * */
public Contact(){
	
}
/*
 * (non-Javadoc)
 * @see java.lang.Object#toString()
 * 重写toString的目的:
 * 便于输出一些想要的信息
 * 
 * 跳过set方法
 */
@Override
	public String toString() {
		return "Contact [id=" + id + ", name=" + name + ", gender=" + gender
				+ ", age=" + age + ", phone=" + phone + ", email=" + email
				+ ", qq=" + qq + "]";
	}
}
/*
	 * 知识点复习:自定义类创建对象三个步骤: 
	 * 1.自定义类    
	 *  Class 类名{ 
	 *  事物的公共属性 成员变量描述 
	 *  事物的公共行为 函数描述 
	 *  }
	 * 
	 * 2.通过自定义创建对象 
	 * 类名 变量名 = new 类名():
	 * 
	 * 3.访问(设置)对象的属性或者对象的功能 
	 * 访问对象的属性:对象.属性名 
	 * 设置对象的属性:对象.属性 = 数据 调用对象的功能: 对象.函数名();
	 * 
	 * 封装:忽略内部具体实现,提供访问的方法 getXXX(), 提供设置的方法setXXX();
	 * 
	 * 局部变量与成员变量定义位置上的区别: 
	 * 成员变量是定义在方法之外,类之内的 
	 * 局部变量是定义在方法之内的
	 * 
	 * 作用上的区别:
	 * 成员变量的作用是描述一类事物的公共属性 
	 * 局部变量的作用是提供一个变量给方法内部使用
	 * 
	 * 生命周期的区别: 成员变量是默认的初始值 
	 * 数据类型         默认初始值 
	 * Boolean   False Char‘\000’(空字符) 
	 * Byte      0(byte) 
	 * Short     0(Short) 
	 * Int       0 
	 * Long      0L 
	 * Float     0.0f 
	 * Double    0.0
	 * 局部变量是没有默认的初始值的,必须要先初始化才能使用。
	 * 
	 * 
 * 构造函数
 * 作用:给对应的对象进行初始化
 * 
 * 构造函数的格式:
 * 修饰符 函数名(形式参数){
 * 函数体
 * }
 * 
 * 构造函数的说明:
 * 构造函数 是没有返回值类型的
 * 构造函数的函数名必须与类名相同
 * 构造函数不是由手动调用,在创建对象是时jvm主动调用构造函数
 * 如果一个类没有显示的写上一个构造方法时,java编译器会为该类添加一个无参构造函数
 * 如果一个类显示的写上了一个构造方法,那么Java编译器则不会为该类添加一个无参的构造函数
 * 构造函数可以在一个类中以函数重载的形式存在多个
 * 
 * JDK提供一个Java开发工具(java.exe)给我们进行反编译
 * 
 * javap 反编译的使用格式:
 * javap -c -1 -private 类名
 * 
 * java编译器添加的无参构造函数的权限修饰符 是什么
 *    与类的权限修饰符是一致的。
 *    
 *   构造函数与普通函数的区别:
 *   返回值类型:
 *      构造函数没有返回值类型
 *      普通函数是有返回值类型的,即使函数没有返回值,返回值类型也要写上void
 *      
 *     函数名
 *     构造函数的函数名必须与类名相同
 *     普通函数只要符合标识符的命名规则即可
 *     
 *     调用方式
 *     构造函数是在创建对象的时候由JVM调用
 *     普通函数是由我们使用对象调用的,一个对象可以调用多次普通函数
 *     
 *     作用不同
 *     构造函数的作用是初始化一个对象
 *     普通函数是用于描述一类公共事物的行为
 *     
	 * this关键字与super关键字
 *  this关键字:
 * this关键字代表了所属函数的调用者对象    谁调用我 我就调用谁      this.qq =qq;  初始化成员变量
 * 
 * this关键字的作用
 *  如果存在同名成员变量与局部变量,在方法内部默认是访问局部变量的数据,可以通过this关键字指定访问成员变量的数据。
 *  在一个构造函数中可以调用另外一个构造函数初始化对象
 *  
 *  this关键字调用其他构造函数的注意事项:
 *  this关键字调用其他构造函数,this关键必须要位于构造函数的第一个语句
 *  this关键字在构造函数中不能出现相互调用的情况,这是一个死循环
 *  
 *  this关键字要注意的事项:
 *  存在同名成员变量与局部变量时,在方法内部访问的事局部变量(java 采用的是”就近原则“ 访问的)
 *  如果在一个方法中访问了一个变量,该变量只存在成员变量的情况下,那么java编译器会在该变量的 前面添加this关键字。
	 */

联系人操作接口   dao层

package cn.itcase.dao;

import java.util.List;

import cn.itcase.entity.Contact;

/**
 * 存放crud操作 联系操作方法接口
 * 
 * @author Administrator
 * 
 */
public interface ContactDao {

	public void addContact(Contact contact); // 添加联系人

	public void updateContact(Contact contact); // 修改联系人

	public void deleteContact(String id); // 删除联系人

	public List<Contact> findAll(); // 查询所有联系人

	public Contact findByid(String id); // 根据id编号查询联系人

	public boolean checkContact(String name); //姓名重复检索

	

	
}
/*知识点复习:
 * 
 * 
* 一.static(静态 修饰符)
 * static修饰成员变量:数据需共享给对象时,可以用static修饰成员变量
 * 静态成员:  在类加载的时候,类加载完成,就分配完空间;直到类被卸载时空间被回收
 * 非静态成员: 创建对象的时候分配空间; 对象变为垃圾空间被回收的时候被销毁
 * 
 * 静态成员变量的访问方式
 *  方式1: 使用对象进行访问
 *        格式:  对象.变量名
 *        
 *  方式2: 可以使用类名进行访问
 *      格式:  类名.变量名;
 *      
 *   注意:
 *   非静态的成员变量只能使用对象进行访问,不能使用类名进行访问
 *   不要为方便访问数据而是用static修饰成员变量,只有成员变量数据是真正需要被共享的时候才使用static修饰。
 * 
 * static修饰成员变量的使用场景:如果一个数据需要被所有对象共享时,使用static修饰成员变量
 * 
 * static可以修饰成员函数
 * 
 * static静态,修饰符)
 * static修饰成员变量时:被static修饰的成员变量是共享数据
 * 
 * 静态成员变量访问方式:
 *      方式一:使用对象访问
 *            对象.属性名
 *      方式二:使用类名进行访问
 *            类名.属性名
 *    注意:
 *    非静态成员变量不能使用类名进行访问,只能使用对象进行访问
 *    不能为了访问方便而使用static修饰成员变量,一定该数据是共享数据 时才使用static修饰。
 * 
 * 二.static修饰方法(静态的成员方法)
 * 方式一: 对象.静态方法(函数)名();
 * 方式二: 类.静态函数ming()  推荐使用
 * 
 * 静态成员变量与非静态成员变量的区别
 * 1. 作用上的区别:
 * 		1. 静态的成员变量的作用共享一个 数据给所有的对象使用。
 * 		2. 非 静态的成员变量的作用是描述一类事物的公共属性。
 * 	2. 数量与存储位置上的区别:
 * 		1. 静态成员变量是存储方法 区内存中,而且只会存在一份数据。
 * 		2. 非静态的成员变量是存储在堆内存中,有n个对象就有n份数据。
 * 	3. 生命周期的区别:
 * 		1. 静态的成员变量数据是随着类的加载而存在,随着类文件的消失而消失。
 * 		2.非静态的成员数据是随着对象的创建而存在,随着 对象被垃圾回收器回收而消失。
 * 
 * 静态函数要注意的事项:
 *	1. 静态函数是可以通过类名或者对象进行调用的,而非静态函数只能使用对象进行调用。
 *	2. 静态的函数可以直接访问静态的成员,但是不能直接访问非静态的成员。	
 *		原因:静态函数是可以使用类名直接调用的,这时候可能还没有存在对象,
 *		而非静态的 成员数据是随着对象 的存在而存在的。
 *
 *	3. 非静态的函数是可以直接访问静态与非静态的成员。
 *		原因:非静态函数只能由对象调用,当对象存在的时候,静态数据老早就已经存在了,而非静态数据也随着对象的创建而存在了。
 *
 *	4. 静态函数不能出现this或者super关键字。
 *		原因:因为静态的函数是可以使用类名调用的,一旦使用类名调用这时候不存在对象,而this关键字是代表了一个函数 的调用者对象,这时候产生了冲突。
 *
 *静态的数据的生命周期:静态的成员变量数据是优先于对象存在的。
 *
 *static什么时候修饰一个函数?
 *	如果一个函数没有直接访问到非静态的成员时,那么就可以使用static修饰了。 一般用于工具类型的方法
 * 
 *静态函数不能访问非静态的成员?
 * 静态函数只要存在有对象,那么也可以访问非 静态的数据。只是不能直接访问而已。
 * 
 * 分类
 * 静态成员函数
 * 静态函数
 * 
 * static修饰的函数,被限定在本类的源文件中,不能被其他源文件的类调用
 * 
 * 三.抽象类:
抽象类的应用场景:
	我们在描述一类事物的时候,发现该种事物确实存在着某种行为,
但是这种行为目前是不具体的,那么我们可以抽取这种行为 的声明,但是
不去实现该种行为,这时候这种行为我们称作为抽象的行为,我们就需要使用抽象类。

抽象类的好处: 强制要求子类一定要实现指定的方法。

抽象类要注意的细节:
	1. 如果一个函数没有方法体,那么该函数必须要使用abstract修饰,把该函数修饰成抽象 的函数。。
	2. 如果一个类出现了抽象的函数,那么该类也必须 使用abstract修饰。
	3. 如果一个非抽象类继承了抽象类,那么必须要把抽象类的所有抽象方法全部实现。
	4. 抽象类可以存在非抽象方法,也可以存在抽象的方法.
	5. 抽象类可以不存在抽象方法的。 
	5. 抽象类是不能创建对象的。
		疑问:为什么抽象类不能创建对象呢?
		因为抽象类是存在抽象方法的,如果能让抽象类创建对象的话,那么使用抽象的对象
		调用抽象方法是没有任何意义的。
	6. 抽象类是存在构造函数的,其构造函数是提供给子类创建对象的时候初始化父类的属性的。

abstract不能与以下关键字共同修饰一个方法:
	1. abstract不能与private共同修饰一个方法。
	2. abstract 不能与static共同修饰一个方法。
	3. abstract 不能与final共同修饰一个方法。
	
	四.接口
 接口:拓展功能的。 
 举例:电脑的usb接口.。。

 接口的定义格式:
 interface 接口名{
 }

 接口要注意的事项 :
 1. 接口是一个特殊的类。
 2. 接口的成员变量默认的修饰符为: public static final 。那么也就是说接口中的成员变量都是常量。
 3. 接口中 的方法都是抽象的方法,默认的修饰符为: public abstract。
 4. 接口不能创建对象。
 5. 接口是没有构造方法的。
 6. 接口是给类去实现使用的,非抽象类实现一个接口的时候,必须要把接口中所有方法全部实现。

 实现接口的格式:

 class  类名 implements 接口名{

 }

 类与接口之间关系: 实现关系。
 接口与接口之间关系: 继承关系。

 类与接口要注意的事项:
 1. 非抽象类实现一个接口时,必须要把接口中所有方法全部实现。
 2. 抽象类实现一个接口时,可以实现也可以不实现接口中的 方法。
 3. 一个类可以实现多个接口 。

 java不支持多继承(类),但支持多实现(接口)
 * */

联系人接口实现类   ContactDaoImp   dao层    

package cn.itcase.dao_imp;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import cn.itcase.dao.ContactDao;
import cn.itcase.entity.Contact;
import cn.itcase.util.XMLUtil;

/**
 * 联系人接口实现类
 * 
 * @author Administrator
 * 
 */
public class ContactDaoImp implements ContactDao {
	/* 添加联系人 */
	@Override
	public void addContact(Contact contact) {

		try {
			
			File file = new File("c:/contact.xml");
			Document doc = null;
			Element rootElem = null;
			if (!file.exists()) {
				// 没有文件则创建文件
				doc = DocumentHelper.createDocument();
				rootElem = doc.addElement("ListContact");
			} else {
				// 存在文件,读取文件
				doc = XMLUtil.getDocument();
				// 存在文件,读取跟标签
				rootElem = doc.getRootElement();
			}
			// 添加标签
			Element contactElem = rootElem.addElement("contact");

			/**
			 * 有系统生成且唯一的ID值,赋值给联系人
			 */
			String uuid = UUID.randomUUID().toString().replace("-", "");
			// 設置id属性
			contactElem.addAttribute("id", uuid);
			// 添加标签及其内容
			contactElem.addElement("name").setText(contact.getName());
			contactElem.addElement("gender").setText(contact.getGender());
			contactElem.addElement("age").setText(contact.getAge()+"");
			contactElem.addElement("phone").setText(contact.getPhone());
			contactElem.addElement("email").setText(contact.getEmail());
			contactElem.addElement("qq").setText(contact.getQq());
		    
			// 从内存中写出数据到xml文件
			XMLUtil.write2xml(doc);
		
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	
	}

	/**
	 * 修改联系人
	 */
	@Override
	public void updateContact(Contact contact) {
     
		try {
			// 1.读取文件
			Document doc = XMLUtil.getDocument();
			
			// 2.查询需要查询的id的联系人

			Element contactElem = (Element)doc.selectSingleNode("//contact[@id='"+contact.getId()+"']");
			// 3.修改内容
			contactElem.element("name").setText(contact.getName());
			contactElem.element("gender").setText(contact.getGender());
			contactElem.element("age").setText(contact.getAge()+"");
			contactElem.element("phone").setText(contact.getPhone());
			contactElem.element("email").setText(contact.getEmail());
			contactElem.element("qq").setText(contact.getQq());
   
			// 4.从内存中写出文件到xml文件
			XMLUtil.write2xml(doc);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		
		
	}

	/**
	 * 删除联系人
	 */
	@Override
	public void deleteContact(String id) {
		try {
			//1.读取xml文件
			Document doc = XMLUtil.getDocument();
			//2.查询需要删除id的contact
			Element contactElem = (Element)doc.selectSingleNode("//contact[@id='"+id+"']");
			//删除标签
			if(contactElem!=null){
				contactElem.detach();
			}
			
			//3.把Document写出到xml文件
			XMLUtil.write2xml(doc);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}

	}

	/**
	 * 查询所用联系人
	 */
	@Override
	public List<Contact> findAll() {
		// 读取xml文件
		Document doc = XMLUtil.getDocument();
		
		//2.创建List对象
		List<Contact> list = new ArrayList<Contact>();
	
	   // 3.读取contact标签
		@SuppressWarnings("unchecked")
		List<Element> conList = (List<Element>)doc.selectNodes("//contact");
		for(Element e:conList){
			//创建Contact对象
			Contact c = new Contact();
			c.setId(e.attributeValue("id"));
			c.setName(e.elementText("name"));
			c.setGender(e.elementText("gender"));
			c.setAge(Integer.parseInt(e.elementText("age")));
			c.setPhone(e.elementText("phone"));
			c.setEmail(e.elementText("email"));
			c.setQq(e.elementText("qq"));
			//把Contact放入list中
			list.add(c);
		}
		return list;
	
	}

	/**
	 * 根据id查询联系人
	 */
	@Override
	public Contact findByid(String id) {
		// 1.读取文件
		Document doc = XMLUtil.getDocument();
		
		// 2.查询id
		Element e = (Element)doc.selectSingleNode("//contact[@id='"+id+"']");
		
		// 3.根据id查询联系人
		Contact c = null;
		if(e!=null){
			//创建Contact对象
			c = new Contact();
			c.setId(e.attributeValue("id"));
			c.setName(e.elementText("name"));
			c.setGender(e.elementText("gender"));
			c.setAge(Integer.parseInt(e.elementText("age")));
			c.setPhone(e.elementText("phone"));
			c.setEmail(e.elementText("email"));
			c.setQq(e.elementText("qq"));
		}
		return c;
	}
	public static void main(String[] args) {
		//测试UUID
		String uuid = UUID.randomUUID().toString().replace("-","");
		System.out.println(uuid);
	}

	/**
	 * true 重复
	 * false 不重复
	 */
	@Override
	public boolean checkContact(String name){
		//查询name标签的内容与传入的值是否一致
		Document doc = XMLUtil.getDocument();
		Element nameElem = (Element)doc.selectSingleNode("//name[text()='"+name+"']");
		if(nameElem!=null){
			return true;
		}else{
			return false;
	}
	}
}
/*
 *二.xml加强
Dom4j修改XML文档
	写出xml文档:
		XMLWriter writer = new XMLWriter()
		writer.wrtite(doc);   

	增加:
	    DocumentHelper.createDocument()  增加新文档
	    Element.addElement("name");  增加子标签
		Element.addAtrribute(“name”,“value”) 增加属性
	修改:
	    Attribute.setValue("value");  修改属性值
		Element.setText("value");  修改文本内容
	删除:		
		Element.detach();   删除标签
		Attribute.detach();  删除属性
				
XPath技术: 快速找到xml元素(标签,属性,文本)
		dom4j使用xpath:
			List<Node> list = Element.selectNodes("xpath表达式");		 	多个节点对象
			Node node = Element.selectSingleNode("xpath表达式");         一个节点对象

				xpath表达式:
						/       表示根位置 或者  子标签
						//      表示后代标签(不分层次结构)
						*       表示所有元素
						[ ]      表示条件
						@      表示选择属性
						text()    表示选择文本
						and     表示与条件

SAX解析: 原理: 加载一点,解析一点,处理一点,对内存要求不高!!!(基于事件)
				
	SAXPasser 类:
		parser(File file, DefaultHandler handler):该方法使用sax解析方式去解析xml文档
					
		DefaultHandler类:重写该类中的一些方法,用于处理xml文档
		startElement( ....  String qName): 读到开始标签时调用
		characterrs(char[] ch,int start,int length);  读到文本内容时调用(包括空格和换行)
		endElement(.....String qName): 读到结束标签时调用
 * */

联系人接口实现的测试类  testContactDaoImp

package cn.itcase.test;

import java.util.List;

import org.junit.Before;
import org.junit.Test;

import cn.itcase.dao.ContactDao;
import cn.itcase.dao_imp.ContactDaoImp;
import cn.itcase.entity.Contact;

/*
 * 联系人操作实现类的测试类
 */
public class TestContactDaoImp {
ContactDao operator = null;
	
	/**
	 * 初始化对象实例
	 */
	@Before
	public void init(){
		operator = new ContactDaoImp();
	}
	

	@Test
	public void testAddContact(){
		Contact contact = new Contact();
		//contact.setId("2");
		contact.setName("张三2");
		contact.setGender("男");
		contact.setAge(20);
		contact.setPhone("134222233333");
		contact.setEmail("eric@qq.com");
		contact.setQq("33334444");
		
		operator.addContact(contact);
	}
	
	@Test
	public void testUpdateContact(){
		Contact contact = new Contact();
		contact.setId("1"); //修改的ID
		contact.setName("李四");
		contact.setGender("女");
		contact.setAge(30);
		contact.setPhone("135222233333");
		contact.setEmail("zhangsan@qq.com");
		contact.setQq("33334444");
		operator.updateContact(contact);
	}
	
	@Test
	public void testDeleteContact(){
		operator.deleteContact("2");
	}
	
	@Test
	public void testFindAll(){
		List<Contact> list = operator.findAll();
		for (Contact contact : list) {
			System.out.println(contact);
		}
	}
	
	@Test
	public void testFindById(){
		Contact contact = operator.findByid("1");
		System.out.println(contact);
	}
	
	@Test
	public void testCheckContact(){
		System.out.println(operator.checkContact("王五1"));
	}
}

联系人逻辑处理接口  ContactService    service层    

package cn.itcase.service;
/**
 * web 操作接口
 */
import java.util.List;

import cn.itcase.entity.Contact;
import cn.itcase.exception.NameRepeatException;

public interface ContactService {
public void addContact(Contact contact)throws NameRepeatException; // 添加联系人
public void updateContact(Contact contact);//修改联系人
public void deleteContact(String id);//删除联系人
public List<Contact> findAll();  //查询所有联系人
public Contact findById(String id);//根据编号查询联系人
}

联系人逻辑处理接口实现类 ContactServiceImp

package cn.itcase.service.imp;

import java.util.List;

import cn.itcase.dao.ContactDao;
import cn.itcase.dao_imp.ContactDaoImp;
import cn.itcase.entity.Contact;
import cn.itcase.exception.NameRepeatException;
import cn.itcase.service.ContactService;

/**
 * 
 * 
 */
public class ContactServiceImp implements ContactService {

	ContactDao dao = new ContactDaoImp();// 多态:接口引用类型变量 执行 接口实现类
    // 添加联系人
	@Override
	public void addContact(Contact contact) throws NameRepeatException {
		
		// 执行业务逻辑 检查姓名是否重复
		if (dao.checkContact(contact.getName())) {
			
			// 姓名重复抛出异常
			throw new NameRepeatException("姓名重复,不可使用");
		}
		// 如果姓名不重复则执行添加操作
		dao.addContact(contact);
	}
   //修改联系人
	@Override
	public void updateContact(Contact contact) {
          dao.updateContact(contact);
	}
   // 根据id删除联系人
	@Override
	public void deleteContact(String id) {
        dao.deleteContact(id);
	}
    // 查询所有联系人
	@Override
	public List<Contact> findAll() {
		return  dao.findAll();
	}
  // 根据id查询联系人
	@Override
	public Contact findById(String id) {
		return dao.findByid(id);
	}

}
/*
 知识点梳理
 一.多态
 多态:一个对象具备多种形态。(父类的引用类型变量指向了子类的对象或者是接口 的引用类型变量指向了接口实现类的对象)

 多态的前提:必须存在继承或者实现 关系。

 动物  a  = new   狗();

 多态要注意 的细节:
 1.  多态情况下,子父类存在同名的成员变量时,访问的是父类的成员变量。
 2.  多态情况下,子父类存在同名的非静态的成员函数时,访问的是子类的成员函数。
 3.  多态情况下,子父类存在同名的静态的成员函数时,访问的是父类的成员函数。
 4.  多态情况下,不能访问子类特有的成员。

 总结:多态情况下,子父类存在同名的成员时,访问的都是父类的成员,除了在同名非静态函数时才是访问子类的。

 编译看左边,运行不一定看右边。

 编译看左边:java编译器在编译的时候,会检查引用类型变量所属的类是否具备指定的成员,如果不具备马上编译报错。

 多态的应用:
 1. 多态用于形参类型的时候,可以接收更多类型的数据 。
 2. 多态用于返回值类型的时候,可以返回更多类型的数据。

 多态的好处: 提高了代码的拓展性。
 
 二.多态中的数据转型
 多态情况下不能访问子类特有的成员。
 如果需要访问子类特有的成员,那么需要进行类型强制转换.
 
 基本数据类型的转换
 小数据类型-------->大的数据类型      自动类型转换
 大数据类型--------->小数据类型       强制类型转换     小数据类型  变量名 = (小数据类型)大数据类型;

 引用数据类型的转换
 小数据类型--------->大数据类型     自动类型转换。
 大数据类型--------->小数据类型      强制类型转换

 类型转换最场景的问题: java.lang.ClassCastException。 强制类型转换失败
 
 三.内部类
 内部类:一个类定义在另外一个类的内部,那么该类就称作为内部类。
 内部类的class文件名: 外部类$内部类.  好处:便于区分该class文件是属于哪个外部类的。

 内部类的类别:
 1. 成员内部类:
 成员内部类的访问方式:
 方式一:在外部类提供一个方法创建内部类的对象进行访问。
 方式二:在其他类直接创建内部类的对象。 格式:外部类.内部类  变量名 = new 外部类().new 内部类();
 注意: 如果是一个静态内部类,那么在其他类创建 的格式:
 外部类.内部类  变量名 = new 外部类.内部类();


 内部类的应用场景: 我们在描述A事物的时候,发现描述的A事物内部还存在另外一个比较复杂的事物B时候,
 而且这个比较复杂事物B还需要访问A事物的属性等数据,那么这时候我们就可以使用内部类描述B事物。

 比如: 人--->心脏
 class 人{
 血
 氧气
 等....
 class 心脏{
 }		
 }

 内部类的好处:内部类可以直接访问外部类的所有成员。

 内部类要注意的细节:
 1. 如果外部类与内部类存在同名的成员变量时,在内部类中默认情况下是访问内部类的成员变量。
          可以通过"外部类.this.成员变量名" 指定访问外部类的 成员。
 2. 私有的成员内部类只能在外部类提供一个方法创建内部类的对象进行访问,不能在其他类创建对象了。
 3. 成员内部类一旦出现了静态的成员,那么该类也必须 使用static修饰。

局部内部类: 在一个类 的方法内部定义另外一个类,那么另外一个类就称作为局部内部类。

局部内部类要注意的细节:
	1. 如果局部 内部类访问了一个局部变量,那么该局部变量必须使用final修饰、


匿名内部类:没有类名的类就称作为匿名内部类。
匿名内部类的好处:简化书写。
匿名内部类的使用前提:必须存在继承或者实现关系才能使用。
匿名内部类一般是用于实参。

四.模板模式   工具类
模板模式 :解决某类事情的步骤有些是固定的,有些是会发生变化的,那么这时候我们可以为这类事情提供一个模板代码,从而提高效率 。
 
 五.集合
 Collection接口: 单列集合       集合的顶级父类
 Collection提供的方法(list和set适用  list和set是Collection的子类)
 增加:
		1:add()	将指定对象存储到容器中
                      add 方法的参数类型是Object 便于接收任意对象
		2:addAll() 将指定集合中的元素添加到调用该方法和集合中
删除:
		3:remove() 将指定的对象从集合中删除
		4:removeAll() 将指定集合中的元素删除
修改
		5:clear() 清空集合中的所有元素
判断
		6:isEmpty() 判断集合是否为空
		7:contains() 判断集合何中是否包含指定对象
            
		8:containsAll() 判断集合中是否包含指定集合
                            使用equals()判断两个对象是否相等  
获取:   9:int size()    返回集合容器的大小

转成数组10: toArray()   集合转换数组

			List接口: 有存储顺序, 可重复
				ArrayList:	数组实现, 查找快, 增删慢
					                由于是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 所以慢。数组是可以直接按索引查找, 所以查找时较快
				LinkedList:	链表实现, 增删快, 查找慢  由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个元素,
                                                                     后一个元素记住前一个元素. 这样的增删效率较高但查询时需要一个一个的遍历, 所以效率较低   单线程使用
list集合的特有方法:
1:增加
        void add(int index, E element) 指定位置添加元素            
        boolean addAll(int index, Collection c) 指定位置添加集合  
2:删除
E remove(int index) 删除指定位置元素

3:修改
		E set(int index, E element)    返回的是需要替换的集合中的元素
4:查找:
        E get(int index)             注意: IndexOutOfBoundsException
		int indexOf(Object o)         // 找不到返回-1
		lastIndexOf(Object o) 
5:求子集合
		 List<E> subList(int fromIndex, int toIndex) // 不包含toIndex
		 
迭代器
    Itreator	该接口是集合的迭代器接口类,定义了常见的迭代方法
	1:boolean hasNext() 判断集合中是否有元素,如果有元素可以迭代,就返回true。
	2: E next()  返回迭代的下一个元素,注意: 如果没有下一个元素时,调用next元素会抛出NoSuchElementException
	3: void remove()从迭代器指向的集合中移除迭代器返回的最后一个元素(可选操作)。


			Vector:	和ArrayList原理相同, 但线程安全, 效率略低 和ArrayList实现方式相同, 但考虑了线程安全问题, 所以效率略低    多线程使用
			
			Set接口: 无存储顺序, 不可重复
			        HashSet    哈希表边存放的是哈希值。HashSet存储元素的顺序并不是按照存入时的顺序(和List不同) 是按照哈希值来存的所以取数据也是按照哈希值取得。
				    TreeSet   红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。
				   LinkedHashSet
Map: 键值对   将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值
		HashMap       采用哈希表实现,所以无序
		TreeMap       可以对健进行排序
		HashTable     底层是哈希表数据结构,线程是同步的,不可以存入null键,null值。效率较低,被HashMap 替代。
		LinkedHashMap 底层是哈希表数据结构,线程是不同步的,可以存入null键,null值。要保证键的唯一性,需要覆盖hashCode方法,和equals方法。
map特有方法
1、添加:
	1、V put(K key, V value)    (可以相同的key值,但是添加的value值会覆
盖前面的,返回值是前一个,如果没有就返回null)                                          
	2、putAll(Map<? extends K,? extends V> m)  从指定映射中将所有映射关
系复制到此映射中(可选操作)。
2、删除
	1、remove()    删除关联对象,指定key对象
	2、clear()     清空集合对象
3、获取
     1:value get(key); 可以用于判断键是否存在的情况。当指定的键不存在的时候,返
回的是null。

3、判断:
	1、boolean isEmpty()   长度为0返回true否则false
    2、boolean containsKey(Object key)  判断集合中是否包含指定的key
3、boolean containsValue(Object value)  判断集合中是否包含指定的value
4、长度:
Int size()

六.流概念
高级流(字符流)   低级流(字节流)
Reader        OutputStream
Writer        Inputstream
其他流都由这几个流派生而来
对流进行操作时,必须把低级流转换为高级流

I/O流按类型分类
一.Memory
从/向内存数组读写数据:CharArrayReader,CharArrayWriter,ByteArrayInputStream,ByteArrayOutputStream
从/向内存字符串读写数据:StringReader,StringWriter,StringBufferInputStream,StringBufferOutStream

二.Pipe管道
实现管道的输入和输出(进程间通信):PipedReader,PipeWriter,PipedInputStream,PipedOutputStream

三.File文件流
对文件进行读写操作:FileReader,FileWriter,FileInputStream,FileOutputStream

四.ObjectSerialization
对象输入,输出:ObjectInputStream,ObjectOutputStream

五.DataConversion数据流
按基本数据类型读,写(处理的数据是Java的基本数据类型):DataInputStream,DateOutputStream

六.Printing
包含方便的打印方法:PrintWriter,PrintStream

七.Buffering 缓冲区
在读入,写出时 对数据进行缓存,以减少I/O的次数:BufferedReader,BufferedWriter,BufferedIputStream,BuffereOutputStream

八.Filtering  滤流
在数据进行读写时进行过滤:FilterReader,FilterWriter,FilerInputStream,FilterOutputStream

九.Concatenation
合并输入并把多个输入流连成一个输入流:SequenceInputStream

十.Conunting
在读入数据时对行记数:LineNumberReader,LineNumberInputStream

十一.Peeking Ahead
通过通过缓存机制进行预读:PushBackReader,PushBackInputStream

十二.Converting between Bytes and Characters
按照一定的编码/解码标准将字节流转换为字符流,或反向转换(Stream到Reader,Writer的转换类):InputStreamReader,OutputStreamWriter


 
 * 
 * */

自定义姓名异常类

package cn.itcase.exception;

/**
 * 自定义 姓名异常 继承 Exception
 * 
 * @author Administrator
 * 
 */
public class NameRepeatException extends Exception {
	
	private static final long serialVersionUID = 1L;

	public NameRepeatException(String msg) {
		super(msg);
	}
}
/**
 * throw 在方法体内部 创建异常处理
 * 
 * throws 在方法上抛出异常
 * 
 * try{可能出现异常的代码(捕获异常)}catch(Exception e){处理异常}
 * 
 */
package cn.itcase.util;

import java.io.File;
import java.io.FileOutputStream;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * 模板模式 工具类
 * 
 * @author Administrator
 * 
 */
public class XMLUtil {
 /**
  * 读取方法
  * @return
  */
	public static Document getDocument() {
		try {
			Document doc = new SAXReader().read(new File(
					"c:/contact.xml"));
			return doc;
		} catch (DocumentException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 数据从内存写出到xml文件的方法
	 */
	public static void write2xml(Document doc){
		
		try {
			FileOutputStream  out = new FileOutputStream("contact.xml");
		   //输出格式
			OutputFormat format = OutputFormat.createPrettyPrint();
		   format.setEncoding("utf-8");
		   XMLWriter writer = new XMLWriter(out,format);
		   writer.write(doc);
		   writer.close();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
}
/*知识点梳理
 一.xml基础
 * 1)XML的作用
		1.1 作为软件配置文件
		1.2 作为小型的“数据库”
	2)XML语法(由w3c组织规定的)
		标签:  
			标签名不能以数字开头,中间不能有空格,区分大小写。有且仅有一个根标签。
		属性:		
			可有多个属性,但属性值必须用引号(单引号或双引号)包含,但不能省略,也不能单						双混用。
		文档声明:
			<?xml version="1.0" encoding="utf-8"?>	
			encoding="utf-8": 打开或解析xml文档时的编码
				注意:
				保存xml文档时的编码 和 解析xml文档时的编码要保持一致,才能避免中文乱码问题!
	3)XML解析
			程序读取或操作xml文档
			两种解析方式:   DOM解析   vs   SAX解析
			DOM解析原理:一次性把xml文档加载成Document树,通过Document对象得到节点对象,通过节点对象访问xml文档内容(标签,属性,文本,注释)。

			Dom4j工具(基于DOM解析原理):
				读取xml文档:
					Document doc = new SAXReader().read("xml文件"); 
				节点:
					nodeIterator();  所有节点
				标签:
					element("名称")   指定名称的第一个子标签对象
					elementIterator("名称");  指定名称的所有子标签对象
					elements();  所有子标签对象
				属性:
					attributeValue(“名称”) 指定名称的属性值
					attribute("名称")   指定名称的属性对象
					getName()  属性名称
					getValue()  属性值
					atributeIterator()   所有属性对象(Iterator)
					attributes()       所有属性对象(List)
				文本:
					getText()  得到当前标签的文本
					elementText("子标签名称")  得到子标签的文本


三.Schema约束  DTD约束 (了解知道有这个东西 能看懂约束)
*/

AddContactServlet

package cn.itcase.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.itcase.entity.Contact;
import cn.itcase.exception.NameRepeatException;
import cn.itcase.service.ContactService;
import cn.itcase.service.imp.ContactServiceImp;

public class AddContactServlet extends HttpServlet {


	private static final long serialVersionUID = 1L;


	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
      // 1.设置编码格式
		request.setCharacterEncoding("utf-8");
     
		//2.接收参数   getParameter(); 根据参数名获取参数值
		String name = request.getParameter("name");
		
	  	String gender = request.getParameter("gender");
	    String age =request.getParameter("age");
	    String phone = request.getParameter("phone");
	    String email = request.getParameter("email");
	    String qq = request.getParameter("qq");
	    
	    // 3.封装成Contact对象
	    Contact contact = new Contact();
	    contact.setName(name);
	    contact.setGender(gender);
	    contact.setAge(Integer.parseInt(age));
	    contact.setPhone(phone);
	    contact.setEmail(email);
	    contact.setQq(qq);
	    
	    ContactService service = new ContactServiceImp();
	     // 4.调用添加方法
	     try {
			service.addContact(contact);
		} catch (NameRepeatException e) {
		// 自定义异常处理
		request.setAttribute("msg", e.getMessage());
		request.getRequestDispatcher("/addContac.jsp").forward(request, response);
		return;
		}
	     
	    // 5.跳转到查询联系人页面
	     response.sendRedirect(request.getContextPath()+"/ListContactServlet");
	
	}

	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        doGet(request,response);
		
	}

}
/*
    Servlet梳理
1.Servlet生命周期(重点)
		构造方法: 创建servlet对象。默认情况下,第一次访问servlet对象时。只调用1次。
		
		init方法(有参): 创建完servlet对象后调用。只调用1次。
				注意: 会调用无参的init方法。
		service方法: servlet提供服务的方法。每次发出请求调用。
				注意: request对象 ,response对象
		destroy方法: tomcat服务器停止或web应用重新部署,servlet对象销毁,destroy方法被调用。
		
2.ServletConfig对象
			获取servlet的初始化参数:
				getInitParameter("name	");
				getInitParameterNames();
				
3.ServletContext对象
得到web应用路径:
	context.getContextPath();
	request.getContextPath();  等价于上面的代码
得到web应用参数:
	context.getInitParameter("name");
	context.getInitParameterNames();
域对象:
	context.setAttribute("name",Object): 保存数据
	context.getAttribute("name")   得到数据
	context.removeAttribue("name")  清除数据
转发
		context.getRequestDispatcher("路径").forward(request,response);
		request.getRequestDispacher("路径").forward(request,response);  等价于上面的代码
得到web应用中的资源文件
    context.getRealPath("路径")
	context.getResourceAsStream("路径");

 */

DeleteContactServlet

package cn.itcase.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.itcase.service.ContactService;
import cn.itcase.service.imp.ContactServiceImp;
/**
 * 删除联系人逻辑
 * @author Administrator
 *
 */
public class DeleteContactServlet extends HttpServlet {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;


	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//在火狐浏览器中以Get方式提交带参数的数据,会重复提交两次。
		System.out.println("刪除联系人");
		
		//1.接收Id
		String id = request.getParameter("id");
		
		// 2.调用Service删除联系人的方法
		ContactService service = new  ContactServiceImp(); // 接口引用数据类型 执行 接口实现类  多态
		service.deleteContact(id);
		
		//3.跳转到查询联系人的页面
		response.sendRedirect(request.getContextPath() + "/ListContactServlet");
		
		
		
	}

	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request,response);
	}
	/*
	 * 
	 一.http协议:浏览器客户端和服务器端之间数据传输的格式规范
 请求报文  浏览器->服务器端
	HttpServletRequest对象: 请求对象。获取请求信息。
		请求行:request.getMethod()   request.getRequestURI/getRequestURL()  request.getProtocol();
		请求头: request.getHeader("name")    request.getHeaderNames()  
		实体内容: request.getInputStream() 

		获取参数数据:(GET或POST)
				request.getParameter("name")  一个值的参数
				request.getParameterValues("name"); 多个值的参数
				request.getParameterNames()    所有参数
 
 响应报文    服务器->浏览器端
       HttpServletResponse对象: 响应对象。设置响应信息。
			响应行: response.setStatus();
			响应头: response.setHeader("name","value")
			实体内容: 
				(PrintWriter) response.getWriter().writer(); 字符内容
				(OutputStream)response.getOutputStream().writer();  字节内容

	二会话管理: 管理浏览器和服务器之间的会话过程中产生的会话数据
      1.Cookie技术: 会话数据保存在浏览器客户端。
			Cookie核心的API:
				2.1 在服务器端创建Cookie对象
					Cookeie cookie = new Cookie("name","value");
				2.2 把cookie发送给浏览器端(通过响应头:set-cookie)
					response.addCookie(cookie);
				2.3 浏览器带着cookie信息访问服务器(通过请求头:cookie),服务器得到cookie信息
					Cookie[] cookies = request.getCookies();
			局限: 
					1)只能保存字符串类型,不能保存中文
					2)一个cookie不能超过4kb
		2.Session技术:会话数据保存在服务器端。(内存)
				Session核心的API:
					3.1 创建或得到session对象	
						HttpSession session = request.getSession(); //创建或得到session对象
						request.getSession(false); //得到session对象
					3.2 会话数据保存session对象中,和得到会话数据
						session.setAttribute("name",Object);  保存数据
						session.getAttribute("name")   得到数据
				注意:
						1)session.setIntactiveInterval(时间);   设置session过期时间
						2)session.invalidate()  手动销毁session对象

	 *
	 */

}
package cn.itcase.servlet;
/**
 * 显示所有联系人
 */
import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.itcase.entity.Contact;
import cn.itcase.service.ContactService;
import cn.itcase.service.imp.ContactServiceImp;

public class ListContactServlet extends HttpServlet {

	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;


	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
     // 1.从xml中读取数据
		ContactService service = new ContactServiceImp();
		List<Contact> list = service.findAll(); // 对象.方法名
		
	//2.把结果保存到对象域中
		request.setAttribute("contacts", list);
		
   // 3.跳转到Jsp页面
		request.getRequestDispatcher("/listContact.jsp").forward(request,response);
		
	}

	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request,response);
	}

}
/*
 * 
 一.Jsp基础
	Jsp的执行过程
		tomcat服务器完成:jsp文件->翻译成java文件->编译成class字节码文件-> 构造类对象-> 调用方法tomcat的work目录下存放jsp运行时的临时文件!
		
		Jsp语法:
			1)jsp表达式:<%=变量或表达式%> 向浏览器输出变量或表达式计算的结果
			2)jsp脚本: <% java代码 %> 执行java代码  原理:翻译到_jspService()方法中
			3)jsp声明: <%! 变量或方法 %> 声明jsp的成员变量或成员方法
			4)jsp注释: <%!-- jsp注释 --%> 用于注释jsp代码,不会翻译到java文件中,也不会执行。

	    jsp的三大指令
				1.include指令:用于包含其他页面。原理:先合并再翻译,叫静态包含
				 
				2. page指令:告诉tomcat服务器如何把jsp文件翻译成java文件
					 language: 翻译的动态语言。
					 import: 类导入
				
				jsp文件编码问题:
					pageEncoding: 告诉tomcat服务器使用什么编码翻译jsp文件(jsp->java文件)
					contentType: tomcat服务器发送给浏览器的数据编码(tomcat服务器->浏览器)

				 异常错误相关的:
					errorPage:  指定当前jsp页面的错误处理页面。
					isErorrPage:  指定当前页面是否为错误处理页面。false,不是错误处理页面,则不能使用								exception内置对象;true,是错误处理页面,可以使用exception内置对象。
					session:  是否开启session功能。false,不能用session内置对象;true,可以使用session内								置对象。
					buffer:  jsp页面的缓存区大小。
					isELIgnore: 是否忽略EL表达式。
               
                3.taglib:导入JSTL标签库
     
  二.jsp加深
    
	Jsp的9大内置对象
	                   内置对象                    数据类型(复杂数据类型)
			request       HttpServletRequet
			response     HttpServletResponse
			config         ServletConfig
			application     ServletContext
			exception      Throwable
			page          Object
			pageContext    PageContext
			out              JspWriter
			session        HttpSession

	Jsp的4个域对象
			request    
			session
			application
			pageContext
			作用范围:
				pageContext : 处于当前jsp页面中有效的!!
				request:      处于同一个请求中有效的!!
				session:      处于同一个会话中有效的!
				application:   处于同一个web应用中有效的!
		
EL表达式
			替代jsp表达式,用于向浏览器输出域对象中的变量值和表达式计算的结果。
			语法:
					${变量}
				  1 输出普通字符串: ${name}
				  2 输出对象属性:  ${student.name}  注意: .name 相当于  .getName()方法
				  3 输出List集合:   ${list[0].name }   注意: [0]  相当于 get(下标)方法
				  4 输出map集合:  ${map[key].name}  注意: [key]相当于get(key)方法

jsp标签
			替代jsp脚本,用于在jsp页面中执行java代码
			 内置标签:
					<jsp:foward/>   request.getRequesetDipsacher("/路径").foward(request,response);
		  			<jsp:param/>   参数标签    ?name=eric
					<jsp:include/>   包含其他页面 ,动态包含
							静态包含: 先合并再翻译。不能传递参数
							动态包含: 先翻译再合并。可以传递参数
			 jstl标签库 (java标准标签库)
					使用步骤:
							1)确保jstl支持的jar包存在于项目中
							2)在jsp页面中导入标签库
 								<%@taglib uri="标签库声明文件tld文件的标记" prefix="前缀"%>
							3)使用标签库中的标签
				
			核心标签库:
							<c:set />     保存数据到域对象中
							<c:out/>     从域中取出数据
							<c:if/>       单条件判断
							<c:choose/> + <c:when/> + <c:otherwise/>  多条件判断
							<c:forEach />  遍历数据 
							<c:forTokens/>  遍历特殊字符串
							<c:redirect/>   重定向


 */

QueryContactServlet

package cn.itcase.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.itcase.entity.Contact;
import cn.itcase.service.ContactService;
import cn.itcase.service.imp.ContactServiceImp;

public class QueryContactServlet extends HttpServlet {


	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;


	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
  // 接收id
		String id = request.getParameter("id");
		
 // 调用service 根据id查询联系
		ContactService service = new ContactServiceImp();
		Contact contact = service.findById(id);
		
// 把查询结果保存到request域中
		request.setAttribute("contact",contact);

//跳转到修改联系人的页面
	request.getRequestDispatcher("/updateContact.jsp").forward(request, response);
		
	}

	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
doGet(request,response);
		doGet(request,response);
	}

}

updateContactServlet

package cn.itcase.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.itcase.entity.Contact;
import cn.itcase.service.ContactService;
import cn.itcase.service.imp.ContactServiceImp;

public class UpdateContactServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		// 1.接收参数
		String id = request.getParameter("id");
		String name = request.getParameter("name");
		String gender = request.getParameter("gender");
		String age = request.getParameter("age");
		String phone = request.getParameter("phone");
		String email = request.getParameter("email");
		String qq = request.getParameter("qq");

		// 封装成Contact对象
		Contact contact = new Contact();
		contact.setId(id);
		contact.setName(name);
		contact.setGender(gender);
		contact.setAge(Integer.parseInt(age));
		contact.setPhone(phone);
		contact.setEmail(email);
		contact.setQq(qq);

		// 2.调用service修改联系人的方法
		ContactService service = new ContactServiceImp();
		service.updateContact(contact);

		// 3.跳转到查询联系人的页面
		response.sendRedirect(request.getContextPath() + "/ListContactServlet");

	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

	}

}

addContact.jsp

<%@ page language="java" import="java.util.*,cn.itcase.entity.*"
	pageEncoding="utf-8" errorPage="error.jsp" isErrorPage="true" session="true"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>addcontact</title>

<!--编码格式-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--时间脚本-->

<script language="javascript" src="js/DateTime.js"></script>
<!--bootstrap样式库-->
<link href="bootstrap/css/bootstrap.css" rel="stylesheet"
	type="text/css">
<link href="bootstrap/css/bootstrap-theme.css" rel="stylesheet"
	type="text/css">
<!--页面样式-->
<link href="css/.addcontactcss" rel="stylesheet" type="text/css">


</head>

<body>
	<div class="panel panel-default">
		<center>
			<h1>添加联系人</h1>
			<p style="font-size:14px;">
				北京时间: <span id="clock" style="font-size:14px;"></span>
			</p>
		</center>
		<div class="panel-heading">
			<ul class="nav nav-tabs">
				<li role="presentation" ><a href="#top">Home</a></li>
				<li role="presentation" class="active"><a
					href="${pageContext.request.contextPath }/AddContact.jsp">AddContact</a></li>
				<li role="presentation"><a
					href="${pageContext.request.contextPath }/listContact.jsp">FindAllContact</a></li>
				<li role="presentation"><a href="${pageContext.request.contextPath }updateContact.jsp">UpdateContact</a></li>
			</ul>
		</div>
		<div class="panel-body">
			<!-- ${pageContext.request.contextPath }
   绝对路径,解决不同部署方式的差别,在所有非struts标签的路径前加
 ${pageContext.request.contextPath},如原路径为:
  /project07/src/AddContactServlet
    -->
			<form action="${pageContext.request.contextPath }/AddContactServlet"
				method="post">

				<ul class="list-group">
					<li class="list-group-item list-group-item-success">姓名: <input
						type="text" name="name" /> <font color="red">${msg }</font> <span>*</span>姓名以字母开头,4-16位字母、数字,下划线组成
					</li>

					<li class="list-group-item">性别: <input type="radio"
						name="gender" value="男" />男 <input type="radio" name="gender"
						value="女" />女
					</li>

					<li class="list-group-item list-group-item-info">年龄:<input
						type="text" name="age" "/> <span>*</span>由数字组成
					</li>

					<li class="list-group-item">电话:<input type="text" name="phone" />
						<span>*</span>由数字组成
					</li>

					<li class="list-group-item list-group-item-danger">邮箱:<input
						type="text" name="email" /> <span>*</span>由数字组成
					</li>

					<li class="list-group-item">QQ:<input type="text" name="qq" />
						<span>*</span>由6到12位的数字组成
					</li>
					<li class="list-group-item list-group-item-warning"><input
						type="submit" value="保存" class="btn btn-primary" />&nbsp; <input
						type="reset" value="重置" class="btn btn-default" /></li>
				</ul>
			</form>
		</div>
		<div class="panel-footer">
			<center>@版权所有2020-2030</center>
		</div>
	</div>
	<br>
</body>
</html>
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="jquery/jquery-3.4.1.min.js"></script>
<!--组件库-->
<script src="bootstrap/js/bootstrap-tab.js"></script>

ListContact.jsp

<%@ page language="java" import="java.util.*,cn.itcase.entity.*"
	pageEncoding="utf-8" errorPage="error.jsp" isErrorPage="true"%>
<!--使用JSTL标签 需要导入两个包jstl.jar  standard.jar  web3.0以上版本自动导入-->
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>查询所有联系人</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--bootstrap样式库-->
<link href="bootstrap/css/bootstrap.css" rel="stylesheet"
	type="text/css">
<link href="bootstrap/css/bootstrap-theme.css" rel="stylesheet"
	type="text/css">
<style type="text/css">
table td {
	/*文字居中*/
	text-align: center;
}

/*合并表格的边框*/
table {
	border-collapse: collapse;
}
</style>
</head>

<body>
	<!--标题-->
	<div class="panel panel-default">
		<center>
			<h1>查询所有联系人</h1>
		</center>
		<!--导航栏-->
		<div class="panel-heading">
			<ul class="nav nav-tabs">
				<li role = "presentation"><a href="#top">Home</a></li>
				<li role = "presentation"><a
					href="${pageContext.request.contextPath }/AddContact.jsp">AddContact</a></li>
				<li role="presentation"  class="active"><a
					href="${pageContext.request.contextPath }/listContact.jsp">FindAllContact</a></li>
				<li role="presentation"><a href="${pageContext.request.contextPath }updateContact.jsp">UpdateContact</a></li>
			</ul>
		</div>
		<!-- 主要内容 -->
		<table align="center" border="1" width="850px" height="210px">
			<tr>
				<th>编号</th>
				<th>姓名</th>
				<th>性别</th>
				<th>年龄</th>
				<th>电话</th>
				<th>邮箱</th>
				<th>QQ</th>
				<th>操作</th>
			</tr>
			<c:forEach items="${contacts}" var="con" varStatus="varSta">
				<tr>
					<td>${varSta.count }</td>
					<td>${con.name }</td>
					<td>${con.gender }</td>
					<td>${con.age }</td>
					<td>${con.phone }</td>
					<td>${con.email }</td>
					<td>${con.qq }</td>
					<td>
					<a href="${pageContext.request.contextPath }/QueryContactServlet?id=${con.id}">修改</a>
					<a href="${pageContext.request.contextPath }/DeleteContactServlet?id=${con.id}">删除</a>
					</td>
				</tr>
			</c:forEach>
			<tr>
				<td colspan="8" align="center">
				<a href="${pageContext.request.contextPath }/AddContact.jsp">[添加联系人]</a>
				
				</td>
			</tr>
		</table>
		<div class="panel-footer">
			<center>@版权所有2020-2030</center>
		</div>
</body>
</html>
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="jquery/jquery-3.4.1.min.js"></script>
<!--组件库-->
<script src="bootstrap/js/bootstrap-tab.js"></script>

updateContact

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
errorPage="error.jsp" isErrorPage="true"
%>
<!--使用JSTL标签 需要导入两个包jstl.jar  standard.jar  web3.0以上版本自动导入-->
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>修改联系人</title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<!--bootstrap样式库-->
<link href="bootstrap/css/bootstrap.css" rel="stylesheet"
	type="text/css">
<link href="bootstrap/css/bootstrap-theme.css" rel="stylesheet"
	type="text/css">



</head>

<body>
	<!--标题-->

	<div class="panel panel-default">
		<center>
			<h1>修改联系人</h1>
		</center>
		<!--导航栏-->
		<div class="panel-heading">
			<ul class="nav nav-tabs">
				<li role="presentation"><a href="#top">Home</a></li>
				<li role="presentation"><a
					href="${pageContext.request.contextPath }/AddContact.jsp">AddContact</a></li>
				<li role="presentation"><a
					href="${pageContext.request.contextPath }/listContact.jsp">FindAllContact</a></li>
				<li role="presentation"  class="active"><a href="${pageContext.request.contextPath }updateContact.jsp">UpdateContact</a></li>
			</ul>
		</div>
		<!--主要内容-->
		<div class="panel-body">
			<form
				action="${pageContext.request.contextPath }/UpdateContactServlet"
				method="post">
				<input type="hidden" name="id" value="${contact.id }" />
				<ul class="list-group">
					<li class="list-group-item list-group-item-success">姓名: <input
						type="text" name="name" value="${contact.name }" /> <font
						color="red">${msg }</font> <span>*</span>姓名以字母开头,4-16位字母、数字,下划线组成
					</li>

					<li class="list-group-item">性别: <input type="radio"
						name="gender" value="男"
						<c:if test="${contact.gender=='男' }">checked="checked"</c:if> />男
						<input type="radio" name="gender" value="女"
						<c:if test="${contact.gender=='女' }">checked="checked"</c:if> />女
					</li>

					<li class="list-group-item list-group-item-info">年龄:<input
						type="text" name="age" value="${contact.age }" /> <span>*</span>由数字组成
					</li>

					<li class="list-group-item">电话:<input type="text" name="phone"
						value="${contact.phone }" /> <span>*</span>由数字组成
					</li>

					<li class="list-group-item list-group-item-danger">邮箱:<input
						type="text" name="email" value="${contact.email }" /> <span>*</span>由英文、数字、@符号组成
					</li>

					<li class="list-group-item">QQ:<input type="text" name="qq"
						value="${contact.qq }" /> <span>*</span>由6到12位的数字组成
					</li>
					<li class="list-group-item list-group-item-warning">
						<!--<input type="submit" value="保存" />&nbsp;
				<input type="reset" value="重置" />-->
						<p>
							<a href="#" class="btn btn-primary" role="button">保存</a> <a
								href="#" class="btn btn-default" role="button">重置</a>
						</p>
					</li>
				</ul>
			</form>
		</div>
		<div class="panel-footer">
			<center>@版权所有2020-2030</center>
		</div>
	</div>
</body>
</html>
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="jquery/jquery-3.4.1.min.js"></script>
<!--组件库-->
<script src="bootstrap/js/bootstrap-tab.js"></script>

截图

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《21天学通Java-第7 入门到精通》是由林信良编著的一本Java编程教材。这本书主要适合初学者学习Java编程语言。 首先,本书介绍了Java编程的基础知识,包括Java环境的安装和配置、Java基本语法、面向对象编程等。读者可以通过丰富的实例和案例,掌握Java编程中的基本概念和技巧。 其次,本书还详细介绍了Java的高级特性,如异常处理、IO操作、多线程编程、网络编程等。这些内容不仅能帮助读者进一步提高Java编程的能力,还能够应用于实际项目开发中。 此外,书中还介绍了Java的GUI编程、数据库编程以及JavaWeb开发等内容。这使得读者可以在学习完基础知识后,进一步深入学习Java编程的各个方向。 这本书的特点是结构清晰,内容丰富,既适合作为Java编程的入门教材,也适合作为进阶学习的参考。书中还提供了大量的练习题和案例,读者可以通过实际动手编写代码来巩固所学知识。 总之,《21天学通Java-第7 入门到精通》是一本很好的Java编程教材,无论是初学者还是有一定编程基础的读者,都可以通过学习这本书快速掌握Java编程技能。 ### 回答2: 《21天学通Java-第7 入门到精通PDF》是一本专门介绍Java编程语言的书籍。Java是一种跨平台的高级编程语言,广泛应用于各种类型的软件开发中。 这本书的第7涵盖了从入门到精通的内容,适合初学者和有一定基础的读者。书中的内容分为21个章节,每天学习一个章节,需要大约三周的时间。通过阅读本书,读者可以系统地掌握Java的语法、基本概念和编程技巧。 本书的特点是结合理论和实践,通过丰富的实例和练习,帮助读者加深对Java的理解。每个章节都有清晰的学习目标和总结,讲解内容简洁明了,易于理解。此外,书中还介绍了Java的常见开发工具和常用的第三方库,帮助读者提高编程效率。 值得一提的是,本书提供了附带学习资源,包括源代码、习题答案和额外的学习资料。读者可以通过这些资源进行实践和进一步学习,巩固所学知识。 总的来说,《21天学通Java-第7 入门到精通PDF》是一本适合初学者入门学习Java的好书。通过认真阅读和实践,读者可以逐步掌握Java编程的基本技能,并逐渐提升到精通的水平。这本书是学习Java编程的良好起点,也是提升编程能力的重要工具。 ### 回答3: 《21天学通Java-第7 入门到精通》是一本针对Java编程语言入门学习的教材。它是以21天为单位进行组织的,每天学习一个特定的主题,帮助读者逐步掌握Java编程的基础知识和技术。 这本书以简明易懂的方式介绍了Java的基本语法、数据类型、运算符、控制结构、方法等基础知识,并通过实例解析帮助读者理解和掌握。每天的学习内容都有相应的练习题,读者可以通过动手实践加深对知识点的理解,并培养编程能力。 《21天学通Java-第7 入门到精通》不仅涵盖了Java的基础知识,还介绍了面向对象编程、异常处理、多线程编程、GUI编程、数据库编程等高级主题。通过学习这本书,读者可以系统地了解Java的核心特性和常用类库,为进一步深入学习和应用Java打下坚实的基础。 此外,这本书还涵盖了一些实际应用和项目实践,帮助读者将学到的知识应用到实际开发中。它介绍了如何使用Eclipse和Java开发工具进行开发,以及如何使用Java编写Web应用程序和Android应用程序。 总之,如果你想从零开始学习Java编程,这本《21天学通Java-第7 入门到精通》是一个很好的选择。它不仅具备全面的内容,而且以简单易懂的方式呈现,适合初学者快速上手。无论是自学还是作为教材,这本书都能帮助你掌握Java编程技能,成为一名优秀的Java开发人员。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旭日初扬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值