通过伪代码演示servlet的生命周期(tomcat服务器中进行)
1)通过映射找到servlet-class的内容,字符串:cn.jinshuo.ServletDemo.FirstServlet
2)通过反射构造FirstServlet对象
得到字节码对象:Class clazz=class.forName("cn.jinshuo.ServletDemo.FirstServlet");
调用无参数的构造方法来构造对象:clazz.newInstance(); ----1.servlet的构建方法被调用
3)创建ServletConfig对象,通过反射调用init方法
得到方法对象:Method m=clazz.getDeclareMethod("init",ServletConfig.class);
调用方法:m.invoke(obj,config); ----2.servlet的init方法被调用
4)创建request,response对象,通过反射调用service方法
得到方法对象 :Method m=clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);
调用方法:m.invoke(obj,request,response); ----3.servlet的service方法被调用
5)当tomcat服务器停止或者web应用重新部署,通过反射调用destory方法
得到方法对象:Method m=clazz.getDeclareMethod("destory",null);
调用方法:m.invoke(obj,null); ----4.servlet的destory方法被调用。
1、Servlet的自动加载:
在默认情况下,第一次访问servlet的时候创建servlet对象。如果servlet的构造方法或init方法执行了比较多的逻辑代码,那么导致用户第一次访问servlet的时候比较慢。
改变servlet创建对象的时机:提前到加载web应用的时候。
在servlet的配置信息中,加上一个<load-on-startup>即可。
<servlet>
<!--servlet的内部名称,自定义。尽量有意义-->
<servlet-name>FirstServlet</servlet-name>
<!--serlvet的类全名:包名+简单类名-->
<servlet-class>FirstServlet</servlet-class>
<!--让servlet自动加载-->
<load-on-startup>1</load-on-startup> 注意:整数值越大,创建时优先级越小。
</servlet>
2、init方法
有参数的init方法
* 该方法是servlet的生命周期方法,它一定会被tomcat服务器调用。
* 不需要覆盖有参数的init方法。
无参数的init方法,自动被调用(只要没有覆盖有参数的init方法)
* 该方法是servlet的编写初始化代码的方法。是sun公司设计出来专门给开发者进行覆盖,
* 然后再里面编写servlet的初始化逻辑代码的方法。
3、线程并发安全
servlet对象在tomcat服务器中是单实例多线程的。
因为servlet是多线程的,所以当servlet的线程同时访问servlet的共享数据,如成员变量,可能引发线程安全问题。
解决办法:把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)。
建议在servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步。而且尽量缩短同步代码块的范围。(哪里使用到了成员变量,就同步哪里),以避免因同步而导致并发效率降低。
HttpServletRequest 请求对象:获取请求信息。
HttpServletResponse 响应对象:设置响应对象。
ServletConfig对象 servlet配置对象。
ServletContext对象 servlet的上下文对象。
4、servletconfig对象。
1>作用:ServletConfig对象:主要用于加载servlet的初始化参数。一个web中可以有多个servletconfig对象,一个servlet对应一个servletconfig
2>对象的创建的获得:
在创建完servlet对象之后,在调用init方法之前创建。
获得:直接从有参的init方法中得到
3>servlet的初始化参数配置
<servlet>
<servlet-name>ConfigDemo</servlet-name>
<servlet-class>ConfigDemo</servlet-class>
<!--初始参数:这些参数会在加载web应用的时候,封装到ServletConfig对象中-->
<init-param>
<param-name>path</param-name>
<param-value>e:/a.txt</param-value>
</init-param>
</servlet>
servlet的参数只能由当前的这个servlet获取。
ServletConfig的API
java.lang.String.getInitParameter(java.lang.String name) 根据参数获取参数值
java.until.Enumeration.getInitParameterNames() 获取所有参数
ServletContext.getServletContext() 得到servlet上下文对象
java.lang.String.getServletName() 得到servlet的名称
//查询当前servlet的所有初始化参数
Enumeration<String> enums=this.getServletConfig().getInitParameterNames();
while(enums.hasMoreElements()){
String paramName=enums.nextElement();
String paramValue=this.getServletConfig().getInitParameter(paramName);
System.out.println(paramName+"="+paramValue);
}
5、ServletContext对象:叫做servlet的上下文对象,表示一个当前的web应用环境。一个web应用中只有一个servletcontext
1>ServletContext对象的核心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);
创建时间和得到:
时间:加载web应用时创建ServletContext对象
得到:从servletconfig对象的getServletContext方法得到
1)创建ServletContext对象 ServletContext context=new ServletContext()
2)创建ServletCofig对象 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();
}
1>得到web应用的路径
java.lang.String getContextPath(); 用于请求重定向的资源名称中。
2>得到web应用的初始化参数(全局)
java.lang.String getInitParameter(java.lang.String name); --得到web应用的初始化参数
java.util.Enumeration getInitParameterNames();
web应用参数可以让当前web应用的所有servlet获取
3>域对象有关的方法
域对象:作用是用于数据的保存、获取。可以在不同的动态资源之间共享数据。
案例:
Servlet1 Servlet2
name=eric
response.sendRedict("/Servlet2?name=eric") String request.getParameter("name");
保存到域对象中 从域中获取
student
方案1:可以通过传递参数的形式,共享数据。局限:只能传递字符串类型。
方案2:可以通过域对象共享数据,好处:可以共享任何类型的数据。
ServletContext就是一个域对象
保存数据:void setAttribute(java.lang.String name,java.lang.Object object);
获取数据:java.lang.Object getAttribute(java.lang.String name);
删除数据:void removeAttribute(java.lang.String name);
ServletContext域对象:作用范围在整个web应用中
所有域对象:
HttpServletRequest域对象
ServletContext域对象
HttpSession域对象
Pagecontext域对象
4>转发:跳转页面
RequestDispatcher getRequestDispatcher(java.lang.String path);
1)转发
a)地址栏不会改变
b)不能转发当前web应用以外的资源
c)可以在转发过程中把数据保存到request中
2)跳转
a)地址栏变为重定向到的地址
b)可以跳转到web应用内,或者其他web应用,甚至其他外部域名
c)不能在重定向过程中把数据保存到request中。
结论:如果使用request域对象进行数据共享,只能使用转发技术。
得到web应用的资源文件
. 表示相对路径中的当前路径。相对于Java运行命令的目录
结论:
在Java项目中, . 代表在Java项目的根目录下开始。
在JavaWeb项目中, . 代表tomcat的bin目录开始,所以不能使用这种相对路径。
File file = new File("./src/db.properties");
所以用:
this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");
得到web应用的资源文件的方法:getRealPath(path);
java.io.InputStream getResourceAsStream(java.lang.String path);