day05

01-servlet入门

1.Servlet简介

Servlet是sun公司提供的一门用于开发动态web资源的技术。
Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:
•编写一个Java类,实现servlet接口。
•把开发好的Java类部署到web服务器中。
快速入门,用servlet向浏览器输出“hello servlet”。
•阅读Servlet API,解决两个问题:
•输出hello servlet的java代码应该写在servlet的哪个方法内?
•如何向IE浏览器输出数据?
 
由于Servlet是sun公司提供的,所以我们要看api就必须看javaee的文档,又由于javaee文档的内容过于多,包含了java的13门技术,
所以我们可以单独查看servlet的帮助文档,我们查看servlet帮助文档中的servlet
这段话中它说了一个servlet就是一个运行在web服务器中中的小的java程序,servlet通常通过HTTP接受和响应web客户端的请求
这段话还说了可以继承javax.servlet.GenericServlet来创建一个普通的servlet,也可以继承javax.servlet.http.HttpServlet来创建一个HTTP servlet
当然还可以实现servlet这个接口来创建一个普通的servlet
还有Servelt这个接口定义了方法去初始化一个servlet,处理请求的方法,还有删除一个servelt的方法,这三个方法都是生命周期的方法,它们的调用顺序是
1.初始化方法
2.处理请求和响应的方法
3.销毁方法
除了生命周期内的方法外,这个接口还提供了获取serselet配置的方法getServletConfig,它可以获取到启动信息,然后后有一个getServletInfo方法,它可以返回
关于servelet的基本信息,比如作者,版本,版权
前面提的那个问题:输出hello servlet的java代码应该写在servlet的哪个方法内
这里我们就知道处理请求和响应的方法在方法中service(ServletRequest req, ServletResponse res),客户端的请求和响应都会通过这个方法传递,
其中ServletResponse表示响应,ServletRequest表示请求
这里我们要想浏览器输出hello servlet,就通过ServeltResponse的getOutputStream()这个方法
但是我们这里还要注意这里的ServletResponse是一个接口,
 
下面我们就来练习用servlet向浏览器输出"hello servlet",这里我们不是通过MyEclipse来写,而是用记事本写,以便熟悉过程
首先我们在Tomcat服务器的webapps文件下建立一个day05的web资源
根据web资源目录结构,我们需要将我们的servlet创建到classes目录下
我们将我们的servlet放到classes目录下
package cn.itcast;

import java.io.*;
import javax.servlet.*;
//这里继承GenericServlet成为一个Servlet
public class FirstServlet extends GenericServlet{
    public void service(ServletRequest req, ServletResponse res) throws ServletException,java.io.IOException
    {
        OutputStream out = res.getOutputStream();
        out.write("hello servlet!!!".getBytes());
        //其实这里可以不用关闭流的,因为servlet是给服务器调用的,当这个servlet结束后服务器会自动关掉这个流
        out.close();
    }
}

 写好servelt之后我们在cmd中编译

注意这里-d表示根据包编译,也就说将编译后的class存放到包里,这里的"."表示放到当前目录,也就是java所在目录
编译好之后
我们还要为这个servlet配置一个对外访问路径,也就是浏览器要访问这个资源的路径
我们就必须在web.xml文件中配置,对于web.xml的文件我们可以参照tomcat中其它web应用的web.xm来写
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5"> 
   <!--servlet的名字和路径-->
     <servlet>
        <servlet-name>FirstServlet</servlet-name>
        <servlet-class>cn.itcast.FirstServlet</servlet-class>
    </servlet>
  <!--servlet的名字和访问路径-->
    <servlet-mapping>
        <servlet-name>FirstServlet</servlet-name>
        <url-pattern>/servlet/FirstServlet</url-pattern>
    </servlet-mapping>
   
 </web-app>

 现在我们就可以在浏览器中输入http://localhost:8080/day05/servlet/FirstServlet访问这个servlet,就会在浏览器中显示hello serlvet!!!

总结:
1.这节课介绍了servlet接口的方法(包括生命周期内的方法和生命周期外的方法),以及它的实现类GenericServlet,HttpServlet
2.然后学习用记事本写第一个servelt程序,这里通过继承了GenericServlet成为一servelt,然后如何在cmd窗口打包编译这个servlet
3.如何在web.xml中为这个servlet配置对外访问路径
__________________________________________________________________________________________________________________________________

02-servlet调用uml图

1.Servlet的运行过程

我们这里通过Rational Rose来画servelt的运行过程
 
这里注意,servlet一旦被创建就会驻留在内存中方便其它客户端浏览器访问,所以在这张图中我们并没看见servlet的销毁
总结:
这节课要能会画访问servlet的流程图
 
————————————————————————————————————————————————————————————————————————————————————

 03-servlet实现类、eclipse创建servlet

 1.servlet的运行过程(祥哥版)

1.首先web浏览器想web服务器发送http请求
 
2.当web浏览器是首次方位servlet,这web服务器会将目标servlet实体创建出来
 
3.web服务器穿件出servlet实体后,还会将创建出请求和响应对象
 
 4.创建出请求和响应对象后,web服务器就会去调用servlet的service方法,把响应和请求对象作为参数传递进去
 
 5.在service方法中我们可以读取请求数据,然后再写入响应数据
 6.写入响应数据后,Servlet的service方法执行完返回给web服务器
 7.Servlet的service方法返回给web服务器之后,web服务器就会去读取响应对象中的信息
 8.如果响应对象中有数据,则web服务器会将数据回送给web浏览器

 2.在Eclipse中开发Servlet

 eclipse中新建一个web project工程,eclipse会自动创建下图所示目录结构
 
 当我们在MyEclipse中创建servlet时,由于servlet属于web资源,所以我们要创建web Project而不是创建一个java Project
 
 在创建web项目的时候,我们要注意这里的web root folder:WebRoot表示存放web资源的根目录,也就是映射到Context root URL:/day05
而这里的J2EE Specification Level表示要倒入j2ee的开发包(这是因为的j2se的开发并没有倒入J2ee的包,这里既然是web开发就属于j2ee的范畴)
,所以这里要倒入J2ee,这里我们建议倒入J2EE 1.4,因为它纯洁些,没有带任何第三方的包,在以后的开发中缺什么我们加什么,
java EE 5.0则倒入了一些第三方的包,不够纯洁,如果在以后的开发中我们倒入了相同的第三方包有可能要起冲突
下面的Maven和JSTL Support以后我们会讲到,这里不提
由于我们将J2EE改为了J2EE1.4,所以当我们点击确定之后MyEclipse要问我们是否也将编译器也改为1.4的,这里我们一定要选No
 
 之后我们就建立好了一个web工程项目,在这个web工程项目中已经倒入了javaee和javase的包
 这里的day05表示web工程,webRoot表示你的web应用,src表示我们要将web程序写入的目录,你的JRE System Library表示javase包,J2EE 1.4 Libraries表示javaee的包
 等会我们将web应用发送到服务器其实就是将WebRoot发送到服务器中
 
根据web应用的目录结构,我们创建的js,html,css,js都会放到WebRoot这个目录下,我们创建的java则放到WEB-INF的classes目录下
但是在MyEclipse中我们我们并不将java程序写道WEB-INF的classes目录中,而是写到src目录下,当我们发布之后,MyEclipse会自动将src中的
java程序编译之后存放到WEB-INF的classes目录下
 
 下面我们就在src目录下创建一个servlet程序
注意我们第一次创建servlet程序需要关联源码,在Tomcat的源码中就有servelt的源码
 没关联源码是这样的
 我们只要在按住Ctrl,然后点击GenericServlet,在根据源码是包还是文件的形式来关联
这里由于Tomacat中自带了servlet技术相关的源码,所以我们关联tomcat的源码就可以了
下面这张图就是tomcat自带的servlet相关技术的源码
 
由于源码是以文件形式存放的,所以我们选择External Folder
关联源码之后的代码 
 
 下面我们就开始写一个servlet
/day05/src/cn/itcast/servlet/FirstServlet.java
package cn.itcast.servlet;

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FirstServlet extends GenericServlet {
    
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        
        OutputStream out = res.getOutputStream();
        out.write("hello servelt".getBytes());
    }
}

 写完一个servlet之后我们还要为这个servelt映射一个访问路径,我们可以在web.xml中去做

 /day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <servlet>
      <servlet-name>FirstServlet</servlet-name>
      <servlet-class>cn.itcast.servlet.FirstServelt</servlet-class>
  </servlet>        
  <servlet-mapping>
      <servlet-name>FirstServlet</servlet-name>
      <url-pattern>/servlet/FirstServlet</url-pattern>
  </servlet-mapping>    
    
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 做好这些之后,我们还需要给MyEclipse配置一个服务器

Windows-Preferences然后我们搜索Tomcat,在这里我们只指定Tomcat6.0的目录

然后我们还可以为tomcat指定jdk,一般我们不指定,我们用MyEclipse默认的jdk

然后我们还要设置运行方式Launch,这里我们设置运行方式为debug方式,不然在以后的开发中无法调试

设置好服务器之后我们将程序发布到服务器中,由于之前我们手动创建了一个day05,所以这里重复了,我们需要将手动创建那个备份,我们选择第一个

然后开启服务器我们发现报错了

这个是由于我们开始手动创建的那个day05,也就是备份的那个java程序是用jdk 7.0编译的

然而我们这里MyEclipse中我们配置的tomcat服务器运行环境是jdk6.0的,高版本编译的程序,不能用低版本的虚拟机运行,所以就会报java.lang.UnsupportedClassVersionError

我们只需要将备份的那个day05删除就可以运行或者将MyEclipse中的服务器运行环境改成jdk7.0

我们这里选择删除备份,之后运行正常

删除之后我们在浏览器中访问这个servlet

http://localhost:8080/day05/servlet/FirstServlet

 则可以成功看到hello servlet
 
 

3.Servlet接口实现类

Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。
HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。
HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。
 
阅读HttpServlet API文档
由于HttpServlet是GenericServlet的子类,而GenericServlet是Servelt的实现类,又由于这里说了我们没有理由去重写service方法,service方法处理HTTP请求是通过将请求分发
给HttpServlet的对应的doxxx方法,比如doPost方法处理Post方式的请求,所以在创建一个servlet的时候我们通常继承HttpServlet,HttpServlet的子类至少要实现下面的一个方法
doGet,doPost,doPut,doDelete,init,destroy,getServletInfo
下面我们通过MyEclipse来来写一个Servlet
/day05/src/cn/itcast/servlet/SecondServlet.java
package cn.itcast.servlet;

import java.io.IOException;
import java.io.PrintWriter;

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

public class SecondServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.getOutputStream().write("hello servlet".getBytes());
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
      //无论是通过get还是post请求,我这里一律转给dogGet方法处理
        doGet(request,response);
        
    }

}

在MyEclipse中当我们创建一个Servlet,MyEclipse会自动会在web.xml中为我们映射这个资源

/day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <servlet>
      <servlet-name>FirstServlet</servlet-name>
      <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>
  </servlet>
  <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>SecondServlet</servlet-name>
    <servlet-class>cn.itcast.servlet.SecondServlet</servlet-class>
  </servlet>
        
  <servlet-mapping>
      <servlet-name>FirstServlet</servlet-name>
      <url-pattern>/servlet/FirstServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>SecondServlet</servlet-name>
    <url-pattern>/servlet/SecondServlet</url-pattern>
  </servlet-mapping>    
    
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

4.修改servlet模板

由于MyEclipse的默认servlet模板过于冗余,所以我们需要自己去修改模板
如果你用的是MyEclipse6.6则打开MyEclipse的安装目录,搜索Servlet.java文件,该文件就是servlet模板文件,我们可以自己修改
如果你用的MyEclipse8.5以后的版本则打开MyEclipse安装目录,搜索关键字"com.genuitec.eclipse.wizard",我这里是用的MyEclipse8.6
所以搜到的结果是com.genuitec.eclipse.wizards_8.6.0.me201007140905.jar
打开它,修改里面templates中的servlet.java
修改后的servlet模板
#---------------------------------------------#
# <aw:description>Template for Servlet</aw:description>
# <aw:version>1.1</aw:version>
# <aw:date>04/05/2003</aw:date>
# <aw:author>Ferret Renaud</aw:author>
#---------------------------------------------#

<aw:import>java.io.IOException</aw:import>
<aw:import>java.io.PrintWriter</aw:import>

<aw:import>javax.servlet.ServletException</aw:import>
<aw:import>javax.servlet.http.HttpServlet</aw:import>
<aw:import>javax.servlet.http.HttpServletRequest</aw:import>
<aw:import>javax.servlet.http.HttpServletResponse</aw:import>

<aw:parentClass>javax.servlet.http.HttpServlet</aw:parentClass>

<aw:constructor name="c1">
    public <aw:className/>() {
        super();
    }
</aw:constructor> 
 
<aw:method name="doGet">
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    }
</aw:method>

<aw:method name="doPost">
    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        doGet(request,response);
            
    }
</aw:method>

 这里要注意,在修改时要关闭MyEclipse

 ——————————————————————————————————————————————————————————————————

 04-servlet的7个小细节

1.Servlet的一些细节(1)

由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。
<servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name><servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。
一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name><url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。例如
 
这里要注意,一个servlet可以在web.xml中映射多个虚拟路径,下面就以FirstServlet来做一个例子
我们在web.xml中为FirstServlet添加多个<servlet-mapping>,并且这里注意,当我们修改了web.xml后
并不用重新部署到服务器中,因为服务器会自动将web.xml加载,这是由于在tomcat服务器conf的context.xml中有如下一段代码
服务器会自动去加载web.xml资源
 
 /day05/src/cn/itcast/servlet/FirstServlet.java
package cn.itcast.servlet;

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FirstServlet extends GenericServlet {
    
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        
        OutputStream out = res.getOutputStream();
        out.write("hello servelt".getBytes());
    }
}

 /day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <servlet>
      <servlet-name>FirstServlet</servlet-name>
      <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>
  </servlet>  
  <servlet-mapping>
      <servlet-name>FirstServlet</servlet-name>
      <url-pattern>/servlet/FirstServlet</url-pattern>
  </servlet-mapping>
  
  <servlet-mapping>
      <servlet-name>FirstServlet</servlet-name>
      <url-pattern>/1.html</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

 现在我们就可以通过http://localhost:8080/1.html访问FirstServlet
 

 2.Servlet的一些细节(2)

同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。
在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。
例如:
<servlet-mapping>
    <servlet-name>AnyName</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>AnyName</servlet-name>
    <url-pattern>/action/*</url-pattern>
</servlet-mapping>

 

下面还是以FirstServlet为例
/day05/src/cn/itcast/servlet/FirstServlet.java
package cn.itcast.servlet;

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FirstServlet extends GenericServlet {
    
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        
        OutputStream out = res.getOutputStream();
        out.write("hello servelt".getBytes());
    }
}

 /day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <servlet>
      <servlet-name>FirstServlet</servlet-name>
      <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>
  </servlet>
        
  <servlet-mapping>
      <servlet-name>FirstServlet</servlet-name>
      <url-pattern>/servlet/FirstServlet</url-pattern>
  </servlet-mapping>
  
  <servlet-mapping>
      <servlet-name>FirstServlet</servlet-name>
      <url-pattern>/*</url-pattern>
  </servlet-mapping>
  
  <servlet-mapping>
      <servlet-name>FirstServlet</servlet-name>
      <url-pattern>/1.html</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

这个时候我们在浏览器中输入http://localhost:8080/day05/任意输入,就可以访问
 
 

3.Servlet的一些细节(3)

既然一个servlet可以映射多个虚拟路径,那么当一个请求来了,多个servlet都匹配,那么到底哪个servlet响应?

比如如下的一些映射关系:

Servlet1 映射到 /abc/*
Servlet2 映射到 /*
Servlet3 映射到 /abc
Servlet4 映射到 *.do

问题:

当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应

  Servlet引擎将调用Servlet1,看谁长的最像那个就匹配,这里Servlet1的映射路径/abc/*长的最像

当请求URL为“/abc时,“/abc/*”,“/*”和“/abc”都匹配,哪个servlet响应

  Servlet引擎将调用Servlet3,这里Servlet3的映射路径/abc长的最像,随意匹配

当请求URL为“/abc/a.do时,“/abc/*”,“/*”和“*.do”都匹配,哪个servlet响应

  Servlet引擎将调用Servlet1,这里由于以“/*”开头的毕“*.xx”开头的优先级高,所以这里Servlet1优先级高

当请求URL为“/a.do时,“/*”和“*.do”都匹配,哪个servlet响应

  Servlet引擎将调用Servlet2,这里同样由于“/*”的优先级比“*.xx”高,所以选择Servlet2

当请求URL为“/xxx/yyy/a.do时,“/*”和“*.do”都匹配,哪个servlet响应

  Servlet引擎将调用Servlet2,同样由于“/*”比“*.xx”优先级高,所以选Servlet2

总结:当通配符都是以"/"或者"*."开头的通配符,则谁长的像就谁的优先级高,如果比较的通配符是一个是以“/”开头
一个是以“*.”开头,则以“/”开头的优先级高一些
 

4.Servlet的一些细节(4)

Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。
针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
Servlet的整个生命周期内,Servletinit方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servletservice方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servletservice()方法,service方法再根据请求方式分别调用doXXX方法。 
/day05/src/cn/itcast/servlet/ServletDemo1.java
package cn.itcast.servlet;

import java.io.IOException;

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

public class ServletDemo1 extends HttpServlet {
    
    public void init() throws ServletException {
        System.out.println("servlet创建了");
    }

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

    }

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


    public void destroy() {
        super.destroy();
        System.out.println("servlet销毁了");
    }
}

 /day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <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>ServletDemo1</servlet-name>
    <servlet-class>cn.itcast.servlet.ServletDemo1</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ServletDemo1</servlet-name>
    <url-pattern>/servlet/ServletDemo1</url-pattern>
  </servlet-mapping>     
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

从上面这个ServletDemo1种,当我们开启服务器第一次访问ServletDemo1的时候就会创建Servlet的实例对象,并驻留在内存中,下次浏览器访问这个ServeletDemo1的时候都只会用这一个Servlet对象,对于浏览器的每次访问都会都会创建独立的Request和Response对象,并且每次访问都会调用Servlet对象的service方法,service方法根据请求类型
将Request和Response对象派发给对应的doxxx方法,还要注意一点Request和Response对象的生命周期特别短,请求一结束Request和Response对象就会死去,这就是为什么服务器能够每天处理上亿的请求和响应,只要不是并发的请求,服务器就没事
 

5.Servlet的一些细节(5)

如果在<servlet>元素中配置了一个<load-on-startup>元素,那么服务器在启动时,就会装载并创建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>

 

用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据
   还有在学习struts的时候也会用到,struts其实就是一个大的servlet,如果我们要用到struts我们需要在在服务器开启时就在将struts加载到服务器中,所以我们需要改struts的web.xml,当我们在它的web.xml中配置了一个<load-on-startup>就会在服务器启动的时候将strust加载进来
另外还有一点在web.xml中配置了多个</load-on-startup>,到底谁先加载的问题,这里要看那个数字小就先加载那个,但是注意这里的数字是正整数
 

6.Servlet的一些细节(6)

如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。
凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。
在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。
当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。
 
注意:记住一句话,凡是在浏览器中输入的地址不管你访问的是什么资源,其实访问的都是servlet,即使这个地址不存在你访问的也是一个servlet
比如这里服务器中没有a.html这个资源,当我们访问则就会访问到报错的这个页面,报错的这个页面就是一个缺省的Servlet,这个是Tomcat中的一个全局缺省Servlet
这个缺省的Servlet是配置tomcat服务器conf下的web.xml

7.Servlet的一些细节(7)—线程安全

当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servletservice方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。
如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。
SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。 
对于实现了SingleThreadModel接口的ServletServlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。
实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)
/day05/src/cn/itcast/servlet/ServletDemo3.java
 
package cn.itcast.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//这个Servlet模拟多个浏览器并发访问这个servlet的同一个资源,从而来讨论servlet的多线程同步安全问题
public class ServletDemo3 extends HttpServlet {
    
    int i = 0;        //这个就相当于多线程共享的数据
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        i++;
        //这里休眠5秒,模拟多线程并发访问这个servlet,从而导致线程安全问题
        //还要注意,这里不能将异常抛出去,因为这个ServletDemo3继承自HttpServlet
        //子类不能抛比父类更多的异常,也就说子类抛的异常只能是父类异常的子集
        try {
            Thread.sleep(1000*5);        
        } catch (InterruptedException e) {
            e.printStackTrace();
        }    
        //当多浏览器访问这个servlet时,由于共享同一个i,所以会导致每个浏览器得到的数据都不是预期的结果
        //这个就是安全问题所在,为了避免安全问题
        response.getOutputStream().write(i);
    }

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

}

 我们这里有两种解决方案

第一种为操作共享数据的代码加上同步代码块,虽然添加同步代码块也可以解决同步安全问题,但是在实际开发中不要用,理由是,如果用这个同步代码块的话,你的网站效率会非常

低,当一个浏览器占整个这个servlet,其它的浏览器就只有等这个浏览器访问这个Servlet才能访问,这个就相当于单线程了

并且这里还要注意一点,这里的异常必须try...catch,因为子类抛出的异常必须是父类异常的子集

/day05/src/cn/itcast/servlet/ServletDemo3.java

package cn.itcast.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//这个Servlet模拟多个浏览器并发访问这个servlet的同一个资源,从而来讨论servlet的多线程同步安全问题
public class ServletDemo3 extends HttpServlet {
    
    int i = 0;        
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //为操作共享数据的代码加上同步代码块
        synchronized (this) {
            i++;
            try {
                Thread.sleep(1000*5);        
            } catch (InterruptedException e) {
                e.printStackTrace();
            }    
            response.getOutputStream().write(i);
        }
    }

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

}

 

第二种方案实现标记接口SingleThreadModel
但是这种方案并不建议,因为它的原理是当多个线程来访问共享资源时,如果共享资源在被别的线程在使用则web服务器会另外创建一个Servlet对象为这个线程服务,虽然这种
方法解决了线程安全问题,但是这种解决方案是通过单独创建Servlet实例对象来完成的,如果有成千上万的线程则需要创建成千上万的Servlet对象,这就会导致服务器内存溢出,所以
这个标记接口SingleThreadModel被废弃了
package cn.itcast.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//这个Servlet模拟多个浏览器并发访问这个servlet的同一个资源,从而来讨论servlet的多线程同步安全问题
public class ServletDemo3 extends HttpServlet implements SingleThreadModel{
    
    int i = 0;        
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
            i++;
            try {
                Thread.sleep(1000*5);        
            } catch (InterruptedException e) {
                e.printStackTrace();
            }    
            response.getOutputStream().write(i);
    }

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

}

 这里还要注意,所谓的标记接口就是只有接口名没有方法,类似的标记接口还有序列化标记接口Serializable,可以克隆标记接口Cloneable

标记接口的作用就是让某个类实现它,以让这个类具有某种特殊的行为,标记接口就好像现实生活中的特权卡,具有某些特权

——————————————————————————————————————————————————————————————————————————————————

05-servltConfig和servletConfig对象

 1.ServletConfig对象

在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。
当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。
阅读ServletConfig API,并举例说明该对象的作用:
•获得字符集编码
•获得数据库连接信息
•获得配置文件,查看struts案例的web.xml文件
 
这里的getSeveletName()方法时获取到web.xml中配置的Servlet名字
 
下面我们来做这些练习
这个练习就是ServletConfig的常见运用
/day05/src/cn/itcast/servlet/ServletDemo4.java
package cn.itcast.servlet;

import java.io.IOException;
import java.util.Enumeration;

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

public class ServletDemo4 extends HttpServlet {
    
    ServletConfig config = null;
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //通过ServeltConfig获取到字符集编码
        String character = this.config.getInitParameter("Character");
        System.out.println(character);
        //通过ServeltConfif获取到链接数据库的地址,用户名和密码
        String url = this.config.getInitParameter("url");
        System.out.println(url);
        String username = this.config.getInitParameter("username");
        System.out.println(username);
        String password = this.config.getInitParameter("password");
        System.out.println(password);
        //通过ServletConfig获取到要strust的配置文件
        String config = this.config.getInitParameter("config");
        System.out.println(config);
        
        //当然我们还可以通过getInitParameterNames来迭代出当前Servlet在web.xml中配置的所有初始化参数
        Enumeration e = this.config.getInitParameterNames();
        while(e.hasMoreElements()){
            String name = (String) e.nextElement();
            String value = this.config.getInitParameter(name);
            System.out.println(name+"->"+value);
        }
        
    }

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

    public void init(ServletConfig config) throws ServletException {
        
        this.config = config;
        
    }

}

 /day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <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>ServletDemo4</servlet-name>
    <servlet-class>cn.itcast.servlet.ServletDemo4</servlet-class>
    <!-- 这个是为Servlet配置的字符集 参数-->
    <init-param>
        <param-name>Character</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <!-- 这个是为Servlet配置的链接数据的一些 参数-->
    <init-param>
        <param-name>url</param-name>
        <!-- 表示要链接mysql数据库中的test库-->
        <param-value>dbc:mysql://localhost:3306/test</param-value>
    </init-param>
    <init-param>
        <param-name>username</param-name>
        <param-value>root</param-value>
    </init-param>
    <init-param>
        <param-name>password</param-name>
        <param-value>root</param-value>
    </init-param>
        <!-- 这个是为Servlet配置的要读取struts的配置文件-->
    <init-param>
        <param-name>config</param-name>
        <param-value>WEB-INF/struts-config.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>ServletDemo4</servlet-name>
    <url-pattern>/servlet/ServletDemo4</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 这里要明白一点,其实struts就是一个大大的Servlet,在struts的web.xml中就有<init-param>配置了需要读取的配置文件,要用到struts就要读取它的配置文件

 
下面这个练习是如何在HttpServlet中获取ServletConfig对象
由于服务器在创建Servlet实例对象的时候会自动将web.xml中的配置参数封装到ServletConfig的对象中,并在调用servlet的init方法时,将ServletConfig对象传递给serverlet
而我们这里创建的servlet实际上是继承成HttpServlet,而HttpServelt继承于GenericServlet
在GenericServlet中就已经通过init方法将ServletConfig对象拿到,所以我们这里可以通过getServletConfig
方法拿到ServletConfig对象,而不像ServletDemo4中那样亲自在init方法中获取ServletConfig对象
这里要注意,在GenericServlet中的ServletConfig有一个关键字transient,这个表示瞬时的,暂时的意思,加上这个关键字就表示这个变量不会序列化到硬盘当中
/day05/src/cn/itcast/servlet/ServletDemo5.java
package cn.itcast.servlet;

import java.io.IOException;

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

public class ServletDemo5 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //由于服务器在创建Servlet实例对象的时候会自动将web.xml中的配置参数封装到ServletConfig的对象中
        //并在调用servlet的init方法时,将ServletConfig对象传递给serverlet
        //而我们这里创建的servlet实际上是继承成HttpServlet,而HttpServelt继承于GenericServlet
        //在GenericServlet中就已经通过init方法将ServletConfig对象拿到,所以我们这里可以通过getServletConfig
        //方法拿到ServletConfig对象,而不像ServletDemo4中那样亲自在init方法中获取ServletConfig对象
        ServletConfig config = this.getServletConfig();
    }

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

}

 /day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <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>ServletDemo5</servlet-name>
    <servlet-class>cn.itcast.servlet.ServletDemo5</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ServletDemo5</servlet-name>
    <url-pattern>/servlet/ServletDemo5</url-pattern>
  </servlet-mapping>    
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

 2.ServletContext

WEB容器在启动时(也就是web应用在启动的时候),它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。
由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。
查看ServletContext API文档,了解ServletContext对象的功能
 
它的方法有如下
getAttribute(java.lang.String name)
getContext(java.lang.String uripath)  //通过给定servlet的url(字符串),返回一个ServletContext,这个方法用于多个web应用之间的交互
getInitParameter(java.lang.String name)
getMajorVersion()             //获取到Servelt的主要版本号
getMimeType(java.lang.String file)    //给定文件名(字符串),返回文件Servelt认定的文件类型,比如给定"1.jpg",返回"image/jpeg",这个在Tomcat的web.xml中可以查询
getMinorVersion()             //获取到Servlet的次要版本号
getNamedDispatcher(java.lang.String name)    //通过传递Servlet的名称(在web.xml中配置的名称)实现将数据转发给该Servelet
getRealPath(java.lang.String path)      //得到资源的绝对路径
getRequestDispatcher(java.lang.String path)    //得到请求转发对象
getResource(java.lang.String path)        //把资源当作URL返回
getResourceAsStream(java.lang.String path)      //把资源作为一个流
getResourcePaths(java.lang.String path)        //得到一个路径下所有的资源的路径,返回Set集合
getServerInfo()                    //得到Servlet的信息
getServlet(java.lang.String name)               Deprecated.
getServletContextName()              //获取到ServletContext的名称
getServlets()                         Deprecated.    
log(java.lang.Exception exception, java.lang.String msg)   Deprecated.
log(java.lang.String msg)                //输出日志
log(java.lang.String message, java.lang.Throwable throwable)     //输出日志
removeAttribute(java.lang.String name)        //移除属性
setAttribute(java.lang.String name, java.lang.Object object)     //设置属性
 

3.ServletContext应用

多个Servlet通过ServletContext对象实现数据共享。
获取WEB应用的初始化参数。
实现Servlet的转发。
利用ServletContext对象读取资源文件。
•得到文件路径
•读取资源文件的三种方式
•.properties文件(属性文件)
 
 
下面我们开始做练习

1.多个Servlet通过ServletContext对象实现数据共享。

 /day05/src/cn/itcast/context/ContextDemo1.java
package cn.itcast.context;

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//ServeltContext中常见运用,多个Servlet通过ServletContext对象实现数据共享
public class ContextDemo1 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //我们可以通过ServletConifig获取ServeletContext域对象
        //this.getServletConfig().getServletContext();
        //也可以直接获取ServletContext域对象
        ServletContext context = this.getServletContext();
        //ServletContext代表web应用,而ServletConfig代表当前Servlet的配置对象
        //我们可以在ServletContext中存入数据,这样在同一个web应用中实现各个Servlet之间的通信
        //比如下面我们将在ServletContext中存入一个name的属性,记住这里是向域中存入一个name的属性,而非对象
        //这是别人这么叫的,至于为什么就不知道了,这叫做专业术语
        context.setAttribute("name", "haha");
        //然后创建ContextDemo2来获取到ServletContext域中存入的数据
    }

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

}

 /day05/src/cn/itcast/context/ContextDemo2.java

package cn.itcast.context;

import java.io.IOException;

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

public class ContextDemo2 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //获取到ServletContext中存入的属性name
        String value = (String) this.getServletContext().getAttribute("name");
        System.out.println(value);
    }

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

}

 

 /day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <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>ContextDemo1</servlet-name>
    <servlet-class>cn.itcast.context.ContextDemo1</servlet-class>
  </servlet>
  <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>ContextDemo2</servlet-name>
    <servlet-class>cn.itcast.context.ContextDemo2</servlet-class>
  </servlet>

    <servlet-name>ContextDemo1</servlet-name>
    <url-pattern>/servlet/ContextDemo1</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ContextDemo2</servlet-name>
    <url-pattern>/servlet/ContextDemo2</url-pattern>
  </servlet-mapping>
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 2.获取WEB应用的初始化参数

/day05/src/cn/itcast/context/ContextDemo3.java
package cn.itcast.context;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//ServletContext域对象的常见运用之获取WEB应用的初始化参数。
//在ServletConfig中我们开始配置了单个Servlet链接数据库的信息
//但是在实际开发中要链接数据库的Servlet有很多个,如果都在各自的Servlet中配置这些链接信息就比较繁琐
//所以为了避免重复,我们可以再web域对象ServeltContext域对象中配置好这些链接信息,那么在整个web应用中
//我们就可以公用这些信息了,当web应用启动的时候就会将这些初始化参数封装到ServeltContext中
public class ContextDemo3 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
            Enumeration e = this.getServletContext().getInitParameterNames();
            while(e.hasMoreElements()){
                String name = (String) e.nextElement();
                System.out.println(name+"->"+this.getServletContext().getInitParameter(name));
            }
    }

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

}

 /day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <context-param>
      <param-name>url</param-name>
      <param-value>jdbc:mysql://localhost:3306/test</param-value>
  </context-param>    
  <context-param>
      <param-name>username</param-name>
      <param-value>root</param-value>
  </context-param>    
  <context-param>
      <param-name>password</param-name>
      <param-value>root</param-value>
  </context-param>    

  <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>ContextDemo3</servlet-name>
    <servlet-class>cn.itcast.context.ContextDemo3</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ContextDemo3</servlet-name>
    <url-pattern>/servlet/ContextDemo3</url-pattern>
  </servlet-mapping>    
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

 3.实现Servlet的转发

在实际开发中,Servlet用于响应数据请求的,但是显示数据却是在jsp页面,所以需要servlet将请求数据转发到jsp页面

/day05/src/cn/itcast/context/ContextDemo4.java
package cn.itcast.context;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//ServletContext应用:实现Servlet请求的转发。
public class ContextDemo4 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String data = "hahahaha";
        //将数据存入到ServletConext域对象中,但注意,在实际开发中我们并不将数据存入到ServeltContext中,因为它的作用范围是整个web应用内
        this.getServletContext().setAttribute("data", data);
        //通过ServletContext域对象获取一个请求转发对象
        //要知道这里由于是ServletContext在转发,ServletContext代表web应用,所以这里的"/"代表web应用
        RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/viewpage.jsp");
        //实现转发,然后我们到viewpage.jsp去接受处理数据
        rd.forward(request, response);
    }

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

}

 /day05/WebRoot/viewpage.jsp

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'viewpage.jsp' starting page</title>
  </head>
  
  <body>
    <h1>
        <font color="red">
            <% 
                String data = (String)this.getServletContext().getAttribute("data");
                out.write(data);
            %>
        </font>
    </h1>
  </body>
</html>

 

 /day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <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>ContextDemo4</servlet-name>
    <servlet-class>cn.itcast.context.ContextDemo4</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ContextDemo4</servlet-name>
    <url-pattern>/servlet/ContextDemo4</url-pattern>
  </servlet-mapping>    
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 这里要注意,在实际开发中我们并不会将请求数据存入到ServletContext中转发,因为ServletContext是域对象,存入的数据在整个web应用中通用

假如有多个用户同时请求这个web应用,当第一个用户请求的数据保存到名为data的变量中,然后将data保存到ServletContext中,还没来得及在jsp页面显示,另一个用户请求的数据d也保存到名为data的变量中,这个时候ServletContext中data变量就被覆盖了,第一个用户得到的数据却是第二个用户的数据,所以在实际开发中我们并不会讲请求数据保存到

ServletConext中而是保存到request容器中

这里我们演示ServletContext的转发是想说明ServletContxt可以实现在web应用组建之间转发数据,而并非是说我们要将请求数据保存到ServletContet中然后转发给jsp页面

 

4.利用ServletContext对象读取资源文件

/day05/src/cn/itcast/context/ContextDemo5.java
package cn.itcast.context;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//这个Servelt实现利用ServletContext对象读取资源文件
//在java中资源文件有两种方式存在,一种是xml文件,一种是propertier文件
//如果是xml则需要dom4j去读取xml文件,如果是properties文件则可以直接读取
//那什么时候用xml文件什么时候用properties,当我们的资源文件是由层次关系的则使用xml
//如果我们的资源文件没有层次关系则用properties
public class ContextDemo5 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //这里有很重要的一个问题,就是要分清web开发中,编译时的目录和运行时的目录是不同的
        //比如这里的db.propertier编译时的目录在src下,而当我们将其发布到服务器运行时则目录
        //在classes目录下,于是我们用传统的读取文件的方式去读取它
        //但是当我们发布之后我们去访问这个Servlet时发现出错了
        FileInputStream in = new FileInputStream("classes/db.properties");
        //读取properties文件的固定代码
        //其实Properties是map的孩子
        Properties p = new Properties();
        p.load(in);
        String url = p.getProperty("url");
        System.out.println(url);
    }

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

}

 /day05/src/db.properties

url=jdbc:mysql://localhost:3306/test
username=root
password=root

 

错误截图
这是为什么呢?这是因为虽然在classes目录下有db.properties这个文件,但是这里我们必须明白我们这里的classes/db.properties是采用的相对路径
我们知道classes中文件是java虚拟机在运行,所以我们这里的classes/db.properties是相对的java虚拟机的启动目录,由于java虚拟机的启动目录下没有
classes/db.properties这个文件,所以要报错
而我们这里的java虚拟机的启动是由tomcat的startup.bat这个文件开启的,当我们点击这个startup.bat时tomcat服务器开启,同时也开启了java虚拟机,所以进一步说这里的classes/db.propertier是相对tomcat的bin目录,而在这个目录下没有classes/db.properties这个文件所以要报错
 
这里一定要记住calsses中的文件的运行都是java虚拟机来运行的,所以classes中的文件中的路径都是相对于java虚拟机的启动目录
 
从上面我们可以知道,在web开发中读取资源文件不要采用传统的方式去读取,我们要通过ServletContext的去读取资源文件
在web工程的servlet中读取配置文件的方式有四种方式
/day05/src/cn/itcast/context/ContextDemo6.java
package cn.itcast.context;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;

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

public class ContextDemo6 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //使用ServletContext读取配置文件的第一种方法,我们通过它的getResourceAsStream()方法将资源转换成流然后载入Properties
        method1();
        //使用ServletContext读取配置文件的第二种方法,我们通过它的getRealPath()获取到资源的绝对路径,然后通过传统的方式去读取配置文件
        //这种方式很有好处,我们可以通过绝对路径将文件名抽取出来
        method2();
        //使用ServletContext读取配置文件的第三种方法,我们通过它的getResource()方法获取到资源的URL,然后通过URL的openStream()方法获取流
        //然后再通过固定格式读取配置文件
        method3();
        //使用ServletContext读取配置文件的第四种方法,我们通过他的getResourcePaths()方法获取到某个路径下的所有资源的路径,然后迭代出想要的路径
        //之后就可以用传统的方法读取配置文件了,注意这个方法返回的是一个set集合,这种方法不常用,这里就不演示了    
        //this.getServletContext().getResourcePaths(path)
    }

    public void method3() throws MalformedURLException, IOException {
        URL url = this.getServletContext().getResource("/WEB-INF/classes/db.properties");
        InputStream in = url.openStream();
        //然后用固定读取Properties文件的方式将流装载到Properties中读取
        Properties p = new Properties();
        p.load(in);
        String username = p.getProperty("username");
        System.out.println(username);
    }

    public void method2() throws FileNotFoundException, IOException {
        String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");
        System.out.println(path);
        //截取字符串最后一个'/'之后的字符串
        String fileName = path.substring(path.lastIndexOf("\\")+1);
        System.out.println(fileName);
        //然后通过传统方式读取配置文件
        FileInputStream in = new FileInputStream(path);
        //然后用固定读取Properties文件的方式将流装载到Properties中读取
        Properties p = new Properties();
        p.load(in);
        String driver = p.getProperty("driver");
        System.out.println(driver);
    }

    public void method1() throws IOException {
        //注意这里记住一点,凡是在servlet中涉及到写地址的,建议最好以"/"开头
        //这里由于是ServletContext调用db.properties(ServletContext代表web应用)所以这里的'/'代表web应用(相对于web应用)
        InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
        //读取properties类型的配置文件就是固定格式
        //要知道Properties是map的孩子
        Properties p = new Properties();
        //将输入流中的内容载入到Properties中
        p.load(in);
        //获取到配置文件中的地址
        String url = p.getProperty("url");
        System.out.println(url);
    }

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

}

 /day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <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>ContextDemo6</servlet-name>
    <servlet-class>cn.itcast.context.ContextDemo6</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ContextDemo6</servlet-name>
    <url-pattern>/servlet/ContextDemo6</url-pattern>
  </servlet-mapping>    
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

web工程中,资源文件在不同位置的读取方式,也就说该如何写地址
如上图,db.properties可以在这几个位置上,在web开发中我们该如何写地址了
我们从上到下编号为1234,
/day05/src/cn/itcast/context/ContextDemo7.java
package cn.itcast.context;

import java.io.IOException;

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

public class ContextDemo7 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //这里都要注意一下,这里路径中开始的"/"代表的是web应用
        //第一个db.properties路径为
        this.getServletContext().getResourceAsStream("/WEB-INT/classes/cn/itcast/context/db.properties");
        //第二个db.properties路径为
        this.getServletContext().getResourceAsStream("/WEB-INT/classes/db.properties");
        //第三个db.properties路径为
        this.getServletContext().getResourceAsStream("/WEB-INT/db.properties");
        //第二个db.properties路径为
        this.getServletContext().getResourceAsStream("/db.properties");
        
    }

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

}

 /day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <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>ContextDemo7</servlet-name>
    <servlet-class>cn.itcast.context.ContextDemo7</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ContextDemo7</servlet-name>
    <url-pattern>/servlet/ContextDemo7</url-pattern>
  </servlet-mapping>    
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

 
——————————————————————————————————————————————————————————————————————————————--

07-servletContext读取配置文件

1.在非Servlet中如何读取资源配置文件

上面我们讲解了在servlet中如何读取资源配置文件,但是在非servlet的文件中如何读取资源配置文件按呢?
比如servlet在处理请求数据的时候调用了dao层的方法,这里读取资源配置文件就由dao层去读取(比如dao层要添加删除数据就必须去连接数据库),
我们这里就必须用到类加载器去加载资源配置文件,这些配置文件就写有连接数据库的信息
这里要注意一点,由于在web应用中类加载器的指向路径时classes目录,所以在这个目录中文件才可以被类加载器加载,
其它路径的资源配置文件只能通过Sevlet读取之后然后传给dao层
 
 1.在非Servelt中读取资源文件的两种方式
/day05/src/cn/itcast/context/ContextDemo8.java
package cn.itcast.context;

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.itcast.dao.Student;

public class ContextDemo8 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Student student = new Student();
        student.add("student");
        
    }

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

}

/day05/WebRoot/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <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>ContextDemo7</servlet-name>
    <servlet-class>cn.itcast.context.ContextDemo7</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ContextDemo7</servlet-name>
    <url-pattern>/servlet/ContextDemo7</url-pattern>
  </servlet-mapping>    
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

 /day05/src/cn/itcast/dao/Student.java

package cn.itcast.dao;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;

public class Student {
    
    public void add(String student) throws IOException{
        //通过类加载器读取classes目录下资源文件的第一种方法
        //获取到类加载器,然后通过类加载器的getResourceAsStream()方法将资源文件读取到流中,然后在通过固定方式读取
        //这里要注意类加载器指向的路径时classes目录,只要在classes目录下的文件才能被加载,不在的就不行
        //所以这里的相对路径时classes目录,这里的/可以加也可以不加,但在开发中建议加上
        method1();
        //通过类加载器读取classes目录下资源文件的第二种方法
        //获得加载器之后,然后通过类加载器的getResource()方法将资源文件转成一个URL,然后通过URL的openStream()将
        //资源文件读取到流中,最后用固定读取资源文件的方式读取资源文件
        //同样这里要注意,类加载器执行的目录同样是classes目录,所以在有classes目录下的文件才能被加载
        //在Servlet中用URL读取资源文件的方式不常见,但是在这里却非常常用,因为用这种方式可以得到绝对地址
        method2();
        
    }

    public void method2() throws IOException {
        URL url = Student.class.getClassLoader().getResource("/db.properties");
        //获取绝对地址
        String path = url.getPath();
        System.out.println(path);
        InputStream in = url.openStream();
        //通过固定方式将流中的数据读取到Properties中
        Properties p = new Properties();
        p.load(in);
        String driver = p.getProperty("driver");
        System.out.println(driver);
    }

    public void method1() throws IOException {
        InputStream in = Student.class.getClassLoader().getResourceAsStream("/db.properties");
        //只要是在classes目录下就可以读取
        in = Student.class.getClassLoader().getResourceAsStream("/cn/itcast/context/db.properties");
        //通过固定方式将资源文件读取到Properties中
        Properties p = new Properties();
        p.load(in);
        String driver = p.getProperty("driver");
        System.out.println(driver);
    }
}

 2.在非Servelt中读取资源文件的注意事项

 在非Servlet中读取资源文件要注意两点:
第一点,由于读取资源文件是通关过类加载器加载的,所以要求被加载的问价不能过大,多大的话容易导致内存溢出
第二点,由于读取资源文件是通过类加载器加载的,类加载器第一次加载了文件之后就会将整个缓存到内存中不在修改,所以在读取变动的资源的时候这种方式就不行了
我们解决的方式是通过类加载器将资源文件的路径找到,然后通过传统方式去读取资源文件
/day05/src/cn/itcast/context/ContextDemo9.java
 
package cn.itcast.context;

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.itcast.dao.Student;

public class ContextDemo9 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Student s = new Student();
        s.delete();
    }

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

}

 /day05/src/db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root

 

/day05/WebRoot/WEB-INF/web.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
  <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>ContextDemo7</servlet-name>
    <servlet-class>cn.itcast.context.ContextDemo7</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ContextDemo7</servlet-name>
    <url-pattern>/servlet/ContextDemo7</url-pattern>
  </servlet-mapping>    
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 /day05/src/cn/itcast/dao/Student.java

package cn.itcast.dao;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Properties;

public class Student {
    
    public void add(String student) throws IOException{
        //通过类加载器读取classes目录下资源文件的第一种方法
        //获取到类加载器,然后通过类加载器的getResourceAsStream()方法将资源文件读取到流中,然后在通过固定方式读取
        //这里要注意类加载器指向的路径时classes目录,只要在classes目录下的文件才能被加载,不在的就不行
        //所以这里的相对路径时classes目录,这里的/可以加也可以不加,但在开发中建议加上
        //method1();
        //通过类加载器读取classes目录下资源文件的第二种方法
        //获得加载器之后,然后通过类加载器的getResource()方法将资源文件转成一个URL,然后通过URL的openStream()将
        //资源文件读取到流中,最后用固定读取资源文件的方式读取资源文件
        //同样这里要注意,类加载器执行的目录同样是classes目录,所以在有classes目录下的文件才能被加载
        //在Servlet中用URL读取资源文件的方式不常见,但是在这里却非常常用,因为用这种方式可以得到绝对地址
        method2();
        
    }

    public void method2() throws IOException {
        URL url = Student.class.getClassLoader().getResource("/db.properties");
        //获取绝对地址
        String path = url.getPath();
        System.out.println(path);
        InputStream in = url.openStream();
        //通过固定方式将流中的数据读取到Properties中
        Properties p = new Properties();
        p.load(in);
        String driver = p.getProperty("driver");
        System.out.println(driver);
    }

    public void method1() throws IOException {
        InputStream in = Student.class.getClassLoader().getResourceAsStream("/db.properties");
        //只要是在classes目录下就可以读取
        in = Student.class.getClassLoader().getResourceAsStream("/cn/itcast/context/db.properties");
        //通过固定方式将资源文件读取到Properties中
        Properties p = new Properties();
        p.load(in);
        String driver = p.getProperty("driver");
        System.out.println(driver);
    }
    public void delete() throws IOException{
        //对于在非Servlet中读取变动的资源文件的方式,我们需要先获取到资源文件的绝对地址
        //然后根据地址通过传统方式去读取资源文件按
        URL url = Student.class.getClassLoader().getResource("/db.properties");
        String path = url.getPath();
        //注意这里要转一下编码,得到的路径中可能有空格,空格都是用%20来代替的,所以需要转码,否则要报错
        path=URLDecoder.decode(path,"utf-8");
        System.out.println(path);
        //传统方式读取资源文件
        FileInputStream in = new FileInputStream(path);
        Properties p = new Properties();
        p.load(in);
        System.out.println(p.getProperty("driver"));
        
        //假设这里间隔10S,在这10s内我去修改资源文件
        try {
            Thread.sleep(1000*10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        //修改之后我们再去读取资源文件
        in = new FileInputStream(path);
        p = new Properties();
        p.load(in);
        System.out.println(p.getProperty("driver"));
        
    }
}

 —————————————————————————————————————————————————————————————————————————————————

最后说一下这里缺少一个总结:

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2013-12-13 15:21  ysfox  阅读(307)  评论(0)    收藏  举报