java深入探究05
通讯录小程序
需求说明:
功能:
添加联系人
修改联系人
删除联系人
查询所有联系人
要求:
console控制
数据保存在xml
1.创建联系人类
/** * 联系人实体对象 * @author APPle * */ public class Contact { private String id; private String name; private String gender; private int age; private String phone; private String email; private String qq; 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; } @Override public String toString() { return "Contact [age=" + age + ", email=" + email + ", gender=" + gender + ", id=" + id + ", name=" + name + ", phone=" + phone + ", qq=" + qq + "]"; } }
2.通讯录功能接口,实现类
/** * 该接口用于存放联系人相关操作的方法。 * @author APPle * */ public interface ContactOperator { public void addContact(Contact contact);//增加联系人 public void updateContact(Contact contact);//修改联系人 public void deleteContact(String id);//根据ID删除联系人 public List<Contact> findAll();//查询所有联系人 }
/** * 实现联系人操作接口 * @author APPle * */ public class ContactOperatorImpl implements ContactOperator { /** * 添加联系人 */ @Override public void addContact(Contact contact) { try { File file = new File("e:/contact.xml"); Document doc = null; Element rootElem = null; if(!file.exists()){ /** * 需求: 把contact对象保存到xml文件中 */ //如果没有xml文件,则创建xml文件 doc = DocumentHelper.createDocument(); //创建根标签 rootElem = doc.addElement("contactList"); }else{ //如果有xml文件,则读取xml文件 doc = XMLUtil.getDocument(); //如果有xml文件,读取根标签 rootElem = doc.getRootElement(); } //添加contact标签 /** * <contact id="1"> <name>eric</name> <gender>男</gender> <age>20</age> <phone>1343333</phone> <email>eric@qq.com</email> <qq>554444</qq> </contact> */ Element contactElem = rootElem.addElement("contact"); contactElem.addAttribute("id", contact.getId()); 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()); //把Document写出到xml文件 XMLUtil.write2xml(doc); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 修改联系人 */ @Override public void updateContact(Contact contact) { /** * 需求: 修改id值为2的联系人 * 1)查询id值为2的contact标签 * 2)修改contact标签的内容 */ try { //1.读取xml文件 Document doc = XMLUtil.getDocument(); Element contactElem = (Element)doc.selectSingleNode("//contact[@id='"+contact.getId()+"']"); //2.修改contact标签内容 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()); //3.把Document写出到xml文件 XMLUtil.write2xml(doc); } catch (Exception e) { 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+"']"); //删除标签 contactElem.detach(); //3.把Document写出到xml文件 XMLUtil.write2xml(doc); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 查询所有联系人 */ @Override public List<Contact> findAll() { //1.读取xml文件 Document doc = XMLUtil.getDocument(); //2.创建List对象 List<Contact> list = new ArrayList<Contact>(); //3.读取contact标签 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; } }
3.XML操作工具类
/** * xml操作的工具类 * @author APPle * */ public class XMLUtil { /** * 用于读取xml文件 * @return */ public static Document getDocument(){ try { Document doc = new SAXReader().read(new File("e:/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("e:/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); } } }
4.主函数
/** * 主程序 * @author APPle * */ public class MainProgram { public static void main(String[] args) { try { /*Scanner scanner = new Scanner(System.in); String command = scanner.next();*/ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); ContactOperator operator = new ContactOperatorImpl(); //不断接收输入 while(true){ //1.看到菜单 printMenu(); //2.接收用户输入的命令 String command = br.readLine(); //3.根据用户的输入执行不同的操作 if("1".equals(command)){ //添加联系人 //获取用输入的数据 Contact contact = new Contact(); //获取ID System.out.println("请输入编号:"); String id = br.readLine(); //获取姓名 System.out.println("请输入姓名:"); String name = br.readLine(); //获取性别 System.out.println("请输入性别:"); String gender = br.readLine(); //获取年龄 System.out.println("请输入年龄:"); String age = br.readLine(); //获取电话 System.out.println("请输入电话:"); String phone = br.readLine(); //获取邮箱 System.out.println("请输入邮箱:"); String email = br.readLine(); //获取QQ System.out.println("请输入QQ:"); String qq = br.readLine(); contact.setId(id); contact.setName(name); contact.setGender(gender); contact.setAge(Integer.parseInt(age)); contact.setPhone(phone); contact.setEmail(email); contact.setQq(qq); operator.addContact(contact); }else if("2".equals(command)){ //修改联系人 //获取用输入的数据 Contact contact = new Contact(); //获取ID System.out.println("请输入需要修改的编号:"); String id = br.readLine(); //获取姓名 System.out.println("请输入修改后的姓名:"); String name = br.readLine(); //获取性别 System.out.println("请输入修改后的性别:"); String gender = br.readLine(); //获取年龄 System.out.println("请输入修改后的年龄:"); String age = br.readLine(); //获取电话 System.out.println("请输入修改后的电话:"); String phone = br.readLine(); //获取邮箱 System.out.println("请输入修改后的邮箱:"); String email = br.readLine(); //获取QQ System.out.println("请输入修改后的QQ:"); String qq = br.readLine(); contact.setId(id); contact.setName(name); contact.setGender(gender); contact.setAge(Integer.parseInt(age)); contact.setPhone(phone); contact.setEmail(email); contact.setQq(qq); operator.updateContact(contact); }else if("3".equals(command)){ //删除联系人 //获取需要删除的ID System.out.println("请输入删除的编号:"); String id = br.readLine(); operator.deleteContact(id); }else if("4".equals(command)){ //查询所有联系人 List<Contact> list = operator.findAll(); //打印输出 for (Contact con : list) { System.out.println(con); } }else if("Q".equals(command)){ break; }else{ System.out.println("输入的命令有误!"); } } } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } private static void printMenu() { System.out.println("===================="); System.out.println("[1]添加联系人"); System.out.println("[2]修改联系人"); System.out.println("[3]删除联系人"); System.out.println("[4]查看所有联系人"); System.out.println("[Q]退出系统"); System.out.println("===================="); } }
Servlet编程
1.如何开发一个Servlet程序
1)步骤
编写java类,继承HttpServlet类
重新doGet和doPost方法
Servlet程序交给tomcat服务器运行!!
servlet程序的class码拷贝到WEB-INF/classes目录
在web.xml文件中进行配置
2)web.xml中配置Servlet
<!-- 配置一个servlet --> <!-- servlet的配置 --> <servlet> <!-- servlet的内部名称,自定义。尽量有意义 --> <servlet-name>FirstServlet</servlet-name> <!-- servlet的类全名: 包名+简单类名 --> <servlet-class>gz.itcast.a_servlet.FirstServlet</servlet-class> </servlet> <!-- servlet的映射配置 --> <servlet-mapping> <!-- servlet的内部名称,一定要和上面的内部名称保持一致!! --> <servlet-name>FirstServlet</servlet-name> <!-- servlet的映射路径(访问servlet的名称) --> <url-pattern>/first</url-pattern> </servlet-mapping>
3)url如何访问,访问原理
在day10的web.xml中查找是否有匹配的url-pattern的内容(/first)
如果找到匹配的url-pattern,则使用当前servlet-name的名称到web.xml文件中查询是否相同名称的servlet配置
如果找到,则取出对应的servlet配置信息中的servlet-class内容:
字符串: gz.itcast.a_servlet.FirstServlet
通过反射:
构造FirstServlet的对象
然后调用FirstServlet里面的方法
2.映射路径
<servlet-mapping> <!-- servlet的内部名称,一定要和上面的内部名称保持一致!! --> <servlet-name>FirstServlet</servlet-name> <!-- servlet的映射路径(访问servlet的名称) --> <url-pattern>/first</url-pattern> </servlet-mapping>
1)精确查询
url-pattern 浏览器输入
/first http://localhost:8080/day10/first
/aaa/first http://localhost:8080/day10/aaa/frist
2)模糊查询
/* http://loaclhost:8080/day10/任意路径
/aaa/* http://localhost:8080/day10/aaa/任意路径
*.后缀名 http://localhost:8080/day10/任意路径.do
*.action
*.html(伪静态)
3)注意:
url-pattren要么以/开头,要么以*开头,例如aaa是非法路径
不能同时用两种模糊查询。例如/aaa/*.do是非法路径
当输入的url有多个Servlet同时被匹配的情况下:
a.精准配备优先(长得像的优先)
b.以后缀名结尾的模糊url-parttern优先级最低!!
3.缺省路径
缺省路径是在tomacat服务器内置的一个路径。改路径对应的default(缺省Servlet)。这个缺省的Servlet的作用是用于解析web应用的静态资源文件
问题:URL输入http://localhost:8080/day10/index.html如何读取文件
1)先到web.xml文件中查找是否有匹配的url-pattern,-》2)如果没有匹配到就交给tomcat内置的DefaultServlet处理-》3)DefaultServlet程序到day10应用的根目录下查找是否存在一个index.html的静态文件-》4)如果找到,则读取返回给浏览器-》5)找不到就放回404错误页面
结论:先找动态资源再找静态资源
4.Servlet生命周期
1)4个重要的生命周期方法
构造方法:创建servlet对象时调用。默认情况下第一个访问Servlet时创建Servlet对象i只调用一次。证明Servlet对象在tomcat是单列模式。
init方法:创建servlet对象时候调用,只调用一次。
service方法:每次发生请求时调用。调用n次
destroy方法:销毁Servlet对象时调用。停止服务器或者重新部署web应用时销毁Servlet对象。只调用1次
2)伪代码演示servlet生命周期
Tomcat内部代码运行:
a.通过映射找到servlet-class内容-》b.通过反射构造FirstServlet对象
1.得到字节码对象:Class clazz=class.forName("aa.FirstServlet");
2.调用无参构造对象:Object obj=class.newInstance() --、构造方法被调用了
c.创建ServletConfig对象通过反射调用init方法
1.Method m=class.getDeclareMethod("init",ServletConfig.class);
2.m.invoke(obj,cconfig); --、init方法被调用了
d.创建request,response对象,通过反射调用service方法
1.Method m=class.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);
2.m.invoke(obj,request,response); --、service方法被调用了
e.当tomcat服务器停止或者web重写部署的时候,通过放射调用destory方法
1.Method m=class.getDeclareMethod("destory",null);
2.m.invoke(obj,null); --、destory方法被调用了
5.自动加载
默认情况下,第一次访问Servlet时创建Servlet对象,如果Servlet的构造方法或init方法中执行较多的逻辑代码,那么导致用户第一次访问Servlet的时候比较慢降低了用户体验
改变Servlet创建时间:提前到加载web应用的时候
在Servlet配置中加上<load-on-startup>即可
<servlet> <servlet-name>LifeDemo</servlet-name> <servlet-class>gz.itcast.c_life.LifeDemo</servlet-class> <!-- 让servlet对象自动加载 --> <load-on-startup>1</load-on-startup> 注意: 整数值越大,创建优先级越低!! </servlet>
6.servelt的多线程并发问题
Servlet对象在tomcat服务器是单例多线程的,当多个Servlet对象访问共享资源的时候,可能会发生线程安全问题,
解决方法:1.sysnchronized关键字进行同步,尽量缩小成员变量,避免因同步而导致的并发效率低下
8.Servlet的学习
HttpServletRequest,HttpServletResponse,ServletConfig,ServletContext
1)HttpServletRequest
2)HttpServletResponse
3)ServletConfig:servet配置对象
1.定义:一个servlet对应一servletConfig对象,主要用于加载servlet的初始化参数,一个web应用中可以有多个ServletConfig对象
2.对象创建和获得
在创建完Servlet对象后,在调用init方法之前创建-》再从有参数的init方法中获得
3.初始化参数的配置
<servlet> <servlet-name>ConfigDemo</servlet-name> <servlet-class>gz.itcast.f_config.ConfigDemo</servlet-class> <!-- 初始参数: 这些参数会在加载web应用的时候,封装到ServletConfig对象中 --> <init-param>
<param-name>path</param-name>
<param-value>e:/b.txt</param-value>
</init-param>
</servlet>
注意:Servlet的参数只有当前的Servlet才能获得
ServletConfig的API:
java.lang.String getInitParameter(java.lang.String.name):根据参数名获得参数值
java.util.Enumeration getInitParameterNames() 获得所有的参数
java.lang.String getServletName() 获得Servlet的名称
4)ServletContext:servlet上下文对象
一个web应用只有一个上下午对象ServletContext对象
2)对象的创建和获得
在有参的init方法获得ServletCongfig对象的getServletContext方法得到
创建ServletConfig对象
我们自己设计
public void init(ServletConfig config,ServletContext context){//这里是多加了一个参数
得到ServletConfig对象,得到ServletContext对象
}
sun公司设计
1.创建ServletContext对象 :ServletContext context=new ServletContext();
2.创建ServletConfig对象:ServletConfig config=new ServletConfig();
config.setServletContext(context);
class ServletConfig{
ServletContext context;
public ServletContext getServletContext(){
return context;
}
}
public void init(ServletConfig config){
得到ServletConfig对象
再从ServletConfig对象中得到ServletContext对象
ServletContext context = config.getServletContext();
}
3)核心api
java.lang.String getContextPath() --得到当前web应用的路径 用在请求重定向的资源名称中
java.lang.String getInitParameter(java.lang.String name) --得到web应用的初始化参数
java.util.Enumeration getInitParameterNames()
void setAttribute(java.lang.String name, java.lang.Object object) --域对象有关的方法
java.lang.Object getAttribute(java.lang.String name)
void removeAttribute(java.lang.String name)
RequestDispatcher getRequestDispatcher(java.lang.String path) --转发(类似于重定向)
java.lang.String getRealPath(java.lang.String path) --得到web应用的资源文件
java.io.InputStream getResourceAsStream(java.lang.String path)
4)域对象
作用:就是用于保存数据,获取数据,可以在不同动态资源之间共享数据
案例:response.sendRedirect("/Servlet?name=eric")--保存到域对象中
String request.getParameter("name"); --从域中获取对象
这里例子传递参数只能 字符串;域对象共享数据可以共享 任意类型
ServletContext就是一个域对象
保存数据:void setAttribute(String name,Object object)
获得数据:void getAttribute(String name)
删除数据:removeAttribute(String name)
所有的域对象:
HttpServletRequest域对象;
ServletContext域对象;
httpSession 域对象;
PageContext 域对象;