1、servlet的生命周期
(1)容器最终要调用service方法为客户进行服务。(此处“容器”指java运行的环境,tomcat是jsp/servlet的容器)
==> 在内存中一个Servlet只有一个实例。针对不同的用户请求,容器采用多线程的机制调用service方法的。
(2)Servlet接口中的常用方法:
==> public void init():初始化。Servlet类被实例化后就执行,且执行一次。由容器进行调用。启动服务器时还没有创建,当第一个人通过浏览器访问某个servlet时调用此方法
==> public void destroy():销毁Servlet对象。由容器进行调用。服务器关闭是,摧毁对象
==> Servlet实例对象和初始化方法,默认情况下,只有第一次访问时才执行,且只执行一次。
(3)利用load-on-startup在应用被Tomcat加载完毕后(此时还没有任何人访问),就实例化并完成初始化Servlet的工作,其中的数字越小代表越先执行
<servlet>startup</servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.smalle.servlet.HelloServlet</servlet-class>
<load-on-startup>2</load-on-startup>
2、模板方法设计模式
==> 如果设计与HTTP协议有关的Servlet,一般选择集成javax.servlet.http.HttpServlet==> 不要覆盖其中的service(ServletRequest req,ServletResponse resp)方法,而应该覆盖掉,doXXX方法(doGet、doPost),doXXX就是根据你的请求方式来的。==> HttpServlet中的service方法是典型的模板方法设计模式的具体应用。
3、Servlet配置:url-pattern
(1)一个Servlet可以被映射到多个URL地址上(2)URL地址映射还支持通配符*==> 方式一:以*开头,以扩展名结尾。比如<url-pattern>*.html</url-pattern>==> 方式二:以/前缀开头,以*结尾。 比如<url-pattern>/action/*</url-pattern>(3)多个Servlet使用通配符时,有可能有多==> 以"/"开头(方式二)要比"*"开头(方式一)优先级高==> 都以"/"开头,还是有多个匹配,找最匹配的(4)如果一个Servlet的映射为一个"/",就称之为缺省的Servlet,它负责处理没有映射路径的URL请求的响应。(5)当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。所以无特殊要求在web.xml中尽量不要有缺省的Servlet
4、Servlet中的线程安全问题
==> 在Servlet中定义变量,除非特殊要求,尽量使用局部变量。==> 如果有需要实例变量时,应做同步处理,且同步代码块尽量包围少的代码。==> 解决思路:用synchronized处理,但在实际中不会用,不可能让同一时刻访问网站的用户排队访问
5、拦截器:使用时要实现Filter接口
当用户访问Web工程时就调用拦截器,并且每次访问servlet时还会调用一次拦截器
==> java代码
public class CharacterEncodingFilter implements Filter{ private FilterConfig config; @Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
} @Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 获取filter初始化的参数值
String encoding = config.getInitParameter("encoding");
if (null != encoding && !"".equalsIgnoreCase(encoding)) {
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
System.out.println("从拦截器获得的参数encoding = " + encoding + ", 在servlet执行之前已经设置了字符编码哦。");
}
// 把请求和响应传给过滤链中的下一个调用者或servlet
chain.doFilter(request, response);
} @Override
public void destroy() {
}
} ==> web.xml代码
<!-- 定义一个拦截器CharacterEncodingFilter -->
<filter>
<!-- 过滤器的标识名 -->
<filter-name>characterEncodingFilter</filter-name>
<!-- 过滤器对应的实现类 -->
<filter-class>com.smalle.filter.CharacterEncodingFilter</filter-class>
<!-- 配置初始化参数 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<!-- 过滤器的标识名 -->
<filter-name>characterEncodingFilter</filter-name>
<!-- 过滤器的URL匹配模式 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
6、监听器:使用时要实现某些接口
(1)Servlet监听器可以使你的应用对某些事情做出反应。每一个监听器都定义了一个回调方法,当对应的事件发现前或发生后,Web容器会自动调用对应监听器实现类中的相应方法。
(2)在ServletApi提供了以下的监听接口:
==> ServletContextListener:应用上下文生命周期的监听器。用于监听Web应用的启动和销毁事件。
==> ServletContextAttributeListener:应用上下文属性事件监听器。用于监听Web应用上下文的属性改变的事件。
==> ServletRequestListener:请求生命周期监听器,用于监听请求的创建和销毁事件。
==> HttpSessionListener:会话生命周期监听器,用于监听会话的创建和销毁事件。
==> HttpSessionActivationListener:会话集合和钝化事件监听器,用于监听会话的激活和钝化的事件。
==> HttpSessionAttributeListener:会话属性事件监听器。用于监听会话中的属性改变事件。
==> HttpSessionBindingListener:会话值绑定事件监听器,知识唯一不需要在web.xml中设定的监听器。
(3)实例
package com.smalle.listener; import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener; public class DemoListener implements ServletContextListener { private ServletContext application = null; //应用上下文初始时会回调的方法
@Override
public void contextInitialized(ServletContextEvent e) {
//初始化一个application对象
System.out.println("DemoListener");
application = e.getServletContext();
this.application.setAttribute("key", "可以在其他地方调用到我");
} public void contextDestroyed(ServletContextEvent e) {}
}
-------------------------------------------------------
package com.smalle.listener; 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 DemoServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String value = (String) getServletConfig().getServletContext().getAttribute("key");
System.out.println("DemoServlet" + value);
}
}
------------------------------------------------------------
<!-- 注册一个监听器 -->
<listener>
<listener-class>com.smalle.listener.DemoListener</listener-class>
</listener> <servlet>
<servlet-name>DemoServlet</servlet-name>
<servlet-class>com.smalle.listener.DemoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DemoServlet</servlet-name>
<url-pattern>/demoListener</url-pattern>
</servlet-mapping>
(4)利用监听器实现用户在线人数监测:查看项目源代码