l 一个Servlet程序就是一个实现了特殊接口的Java类,它由支持Servlet(具有Servlet引擎)的WEB服务器调用和启动运行。Web服务器可以把一个或一组URL地址的访问请求交给某个的Servlet程序去处理,Servlet可以接收到客户端的请求信息和产生响应内容。
l在WEB-INF下的文件是无法访问的。是一个私有目录无法通过浏览器访问。所以把lib,class,web.xml这三个东西,放在这下面,因为这三个完全不需要用户访问,并且是高度保密的,这三个东西是让tomcat看的。所以它会把其它要用户要访问的放在外面。
用户一旦访问网站tomcat会把class目录下的字节码文件在tomcat里面运行,然后把结果通过tomcat返回给用户,这是过程。
http://localhost:8888/day06_servlet_01/xxx.html?username=23
寻找servlet jar包
部署前,对着tomcat自带的例子应用说清楚javaweb应用程序的目录结构(并画一个图关系结构图),然后解释开发环境和运行环境的区别,说清楚MyEclipse是如何发布web应用的,通过修改web虚拟目录的名字来强调。
最后按照后面的ppt总结下用手工方式如何做,因为面试时要试探你的工作是真的明白,还是照猫画虎,就会考这个问题。
在myelclipse里面找web可以修改虚拟路径。
我们发布的是什么呢,就是在开发环境中把WebRoot下的所有文件文件到搬到tomcat里面去。如果是静态页面直接就搬过去,如果是java要部署后才能发搬过去。
l 同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。
l 同一个Servlet类可以被注册多次,即创建出这个Servlet类的多个实例对象。
l 在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。带扩展名的*前不能有“/”,即不能设置为“/action/*.xx”形式。
如果没有通配符,那么url-pattern必须以/开头。十分重要!
<servlet>
<servlet-name>dog</servlet-name>
<servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>
</servlet>
同一个Servlet类可以被注册多次,即创建出这个Servlet类的多个实例对象
<servlet>
<servlet-name>cat</servlet-name>
<servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>
</servlet>
同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名
<servlet-mapping>
<servlet-name>dog</servlet-name>
<url-pattern>/xxx.html</url-pattern>
<url-pattern>/yyy.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cat</servlet-name>
<url-pattern>/abc.html</url-pattern>
<url-pattern>/yt.html</url-pattern>
</servlet-mapping>
对于如下的一些映射关系:
l /abc/* 映射到
Servlet1
l /* 映射到
Servlet2
l /abc 映射到
Servlet3
l *.do 映射到
Servlet4
将发生如下一些行为:
l 当请求URL为“/abc/a.html”,“/abc/*”和“/*”都可以匹配这个URL,
Servlet引擎将调用Servlet1。
l 当请求URL为“/abc”时,“/abc/*”和“/abc”都可以匹配这个URL,
Servlet引擎将调用Servlet3。
l 当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都可以匹配这个URL,
Servlet引擎将调用Servlet1。
l 当请求URL为“/a.do”时,“/*”和“*.do”都可以匹配这个URL,
Servlet引擎将调用Servlet2。
l 当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都可以匹配这个URL,
Servlet引擎将调用Servlet2。
Servlet的运行过程:
① Servlet引擎检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。
② 装载并创建该Servlet的一个实例对象。
③ 调用Servlet实例对象的init()方法。
④ 创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
⑤ WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。
Servlet程序查询数据库的工作过程:
Servlet的运行过程à特殊说明:
l 在<servlet>元素中嵌套一个<load-on-startup>子元素,WEB应用程序在启动时就可以装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。
举例:
<servlet>
<servlet-name>invoker</servlet-name>
<servlet-class>
org.apache.catalina.servlets.InvokerServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
l 在Servlet的整个生命周期内,它的init方法只被调用一次,而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法。
l Tomcat也提供了是否自动重新装载被修改的Servlet的配置选项。在<Tomcat安装主目录>/conf/server.xml文件中,可以将<Context>元素的reloadable属性设置为true,这样,Tomcat将监视该WEB应用程序的/WEB-INF/classes和/WEB-INF/lib目录下的类是否发生了改变,然后自动重新装载那些发生了改变的类。
举例:
<Context path="/it315"docBase="d:\myweb" debug="0"reloadable="true"/>
其实有更为简单的方法:只对本程序起作用,在META-INF下。建立一个Context.xml文件。
<Context
reloadable="true">
</Context>
Servlet API就是接口,只是在开发编译的时间需要这个接口编译成功,然后在运行的时间具体的实现类是在容器中的。这才是它们之间的重要关系,
就像request的具体实现类是org.apache.catalina.connector.RequestFacade在我们开发的包中里面根本没有,只是在容器中调用的时间才有的。我们开发用的环境和API中没有,只有它父类的一个接口,只要保证编译成功就行。
Servlet是一个并不是一个单例,如果一个servlet映射一个文件,那么是单例,如果不是那么就不是。
<load-on-startup>1</load-on-startup> 是指,没有它,就是在用户第一次访问时间调用 init方法,如果加上了就是在服务器启动过程中就调用了(先是构造方法,再是init)。
如果没有就是等到第一次调用时间。
ServletConfig:可以得到servlet的配置信息,非常好。
l Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外部的资源,所以,Serlvet引擎需要将表示Servlet容器的对象传递给Servlet。另外,在web.xml文件中为某个Servlet设置的友好名称和初始化参数等信息也需要传递给该Servlet。
listings Shoulddirectory listings be produced if there -->
<!-- is no welcome file in this directory?
[false] -->
<!-- WARNING: Listings fordirectories with many -->
<!-- entries can be slow andmay consume
也就是说如果没有找到那个文件是进行404还是进行目录列表。
//在这里写成GBK和UTF-8都行,只要是汉字编码,因为这样服务器才会把这些字符以中文的编码送出去。这个东西有两个方面的作用,第一个,告诉以什么的编码传过去,第二、告诉浏览器我是什么编码,让浏览器用相应的东西解码。
response.setContentType("text/html;charset=GBK");
response.getWriter().println(config.getInitParameter("Corporation")+"欢迎你");
Enumeration<String> enumeration =
config.getInitParameterNames();
while (enumeration.hasMoreElements()) {
String param = (String) enumeration.nextElement();
String value =
config.getInitParameter(param);
response.getWriter().println("param:"+param+"
"+"value:"+value);
}
ServletCofig四个方法:
l getInitParameterNames
l getInitParameter
l getServletName
getServletContext
ServletContext(Servlet的环境):它的范围就是一个webapp,一个webapp只有一个ServletContext.,你就把它看成jsp中的application就行了。
servlet与ServletContext的关系时,画图说明一个站点(一个Tomcat服务器,也即Servlet容器)下有多个ServletContext(一个ServletContext就是一个Web应用程序),每个ServletContext下又有多个Servlet,可以认为ServletContext对象就是Servlet的环境。
l Servlet引擎为每个WEB应用程序都创建一个对应的ServletContext对象,ServletContext对象被包含在ServletConfig对象中,调用ServletConfig.getServletContext方法可以返回ServletContext对象的引用。
l 由于一个WEB应用程序中的所有Servlet都共享同一个ServletContext对象,所以,ServletContext对象被称之为application
对象(Web应用程序对象)。
ServletContext可以通过ServletConfig获得,ServletContext的应用:
可以得到这个webapp的真实路径(getRealPath
),还可以从webapp中读取某个文件
以流的形式(getResourceAsStream
)。
程序中相对路径都是相对于当前工作目录。在tomcat里面就是指那个tomcat下面的
Bin目录下,因为服务器在这里启动。
ServletContext接口
l 功能:
ü 获取WEB应用程序的初始化参数
ü 记录日志
ü application域范围的属性
ü 访问资源文件,牢牢记住三种访问方式:classpath、webapp、FileSystem(打死你也不要用相对路径)。
ü 获取虚拟路径所映射的本地路径
ü WEB应用程序之间的访问
ServletContext的其他方法
十分重要:(要会默写)
ServletContext application =
config.getServletContext();
// getRealPath(java.lang.Stringpath)
// Returns a String containing the realpath for a given virtual path.
String realpath = application.getRealPath("/WEB-INF/downloads");
File download = new File(realpath);
if (!download.exists()) {
download.mkdir();
}
String fileName = request.getParameter("filename");
FileOutputStream out =
new FileOutputStream(realpath+"/"+fileName);
out.close();
你直接写个newFileoutputStream(“db.properties”)它是到tomcat的binhhiv gh
去找这个文件,这就是相对路径的坏处,在哪里面执行的,就去哪里找。
访问资源文件,牢牢记住三种访问方式:
classpath、(是类加载器目录,在src目录下)
webapp、(在web应用中读取/WEB-INF/c.txt)
FileSystem(在d:/32.txt).
只有这有三种,且记。
我们要知道,不能把我们配置文件放在项目的根目录下面,因为这样用户可以通过浏览器访问,之所以要出现WEB-INF这个私密目录,就是为了让程序访问,而用户不能够访问,所以可以把它放在这下面,通过获得真实路径的filesystem方法访问和通过ServletContext访问。
当然也可以在src目录下面,通过类加载器的方法访问。
//访问文件的三种方式(
//第一种:通过获得真实路径是访问的文件系统
String dbRealpath = application.getRealPath("/WEB-INF/db.properties");
System.out.println(dbRealpath);
InputStream inputStream =
new FileInputStream(dbRealpath);
Properties properties =
new Properties();
// properties.load(inputStream);
// properties.list(response.getWriter());
//第二种是通过webapp来访问的
// properties.load(
// application.getResourceAsStream("/WEB-INF/db.properties")
// );
// properties.list(response.getWriter());
//第三种是通过classpath访问的,要把它放在src目录下。就是在运行的环境的classes目录下。
properties.load(
FirstServlet.class.getResourceAsStream("/db.properties")
);
properties.list(response.getWriter());
ServeletContext. getResourceAsStream()这个方法与我们所说的类加载器的getResourceAsStream方法是不同的,类加载器中我们只能访问src目录下的东东,然后这个
ServletContext却可以访问webapp中任何地方的资源 ,包括WEB-INF。
This method isdifferent from java.lang.Class.getResourceAsStream
, which uses aclass loader. This method allows servlet containers to make a resource availableto a servlet from any location, without using a class loader.
我们所说的WEB-INF是不能被用户通过浏览器直接访问,而可以被应用程序本身访问。
ServletContext获取WEB应用程序的初始化参数
在ServletConfig中获得初始化参数:
<servlet>
<servlet-name>dog</servlet-name>
<servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>
<init-param>
<param-name>Corporation</param-name>
<param-value>北京传智播客公司</param-value>
</init-param>
<init-param>
<param-name>site</param-name>
<param-value>itcast.cn</param-value>
</init-param>
</servlet>
只有在说这个servlet被访问时间才能访问到它的初始化变量。
但是我们想要全局访问,任何一个serlvet都想访问,怎么办?就是用设置一个全局的初始化参数,然后用全局的ServletContext访问。
在web.xml里面写上:
<context-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</context-param>
你可能平常不用,但是在spring里面有大量这样的配置,要看得懂。
//获得全局初始化参数
String
debug= application.getInitParameter("debug");
response.getWriter().println(debug);
HttpServlet:
public abstract class HttpServlet
extends GenericServlet
public abstract class GenericServlet
extends java.lang.Object
implements Servlet,ServletConfig,java.io.Serializable
在GenericServlet里面封装了getServletConfig
()
和getServletContext()方法,
service
(ServletRequest req,
ServletResponse res)
Called by theservlet container to allow the servlet to respond to a request.
两个方面,以后在HttpServlet可以直接用上面两个方法,获得config
和ServletContext太有用了,对吧。但是这个里面的Service方法,的参数类型
不太好,如果是HttpServletRequest就好了,
那么我们在HttpServlet方法中实现了两者的完美结合:
service
(HttpServletRequest req,HttpServletResponse resp)
不但不用再转型 ,而可以直接通过上面两个get方法获得想要的东东。