Servlet规范为JavaWeb应用制定了对象模型,在这个对象模型中,不仅Servlet是对象,而且容器为它提供的各种功能也都是Java对象。
- 请求对象(ServletRequest和HttpServletRequest):Servlet从该对象中获取来自客户端的请求信息。
- 响应对象(ServletResponse和HttpServletResponse):Servlet通过该对象来生成响应结果。
- Servlet配置对象(ServletConfig):当容器初始化一个Servlet对象时,会向Servlet提供一个ServerConfig对象,Servlet通过该对象来获取初始化参数信息以及ServletContext对象。
- Servlet上下文(ServletContext):Servlet通过该对象来访问容器为当前Web应用提供的各种资源。
public class DispatcherServlet extends HttpServlet {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
String name = req.getParameter("name");
req.setAttribute("NAME", name);
ServletContext context = getServletContext();
RequestDispatcher dispatcher = context.getRequestDispatcher("/index.jsp");
dispatcher.forward(req, res);
}
}
Servlet API 的核心是javax.servlet.Servlet接口,所有的Servlet类都必须实现这一接口。在Servlet接口中定义了5个方法,其中有3个方法都由Servlet容器来调用,容器会在Servlet的生命周期的不同阶段调用特定的方法。
- init(ServletConfig config) 方法:负责初始化Servlet对象。容器在创建好Servlet对象后,就会调用该方法。
- service(ServletRequest req, ServletResponse res) 方法:负责响应客户的请求,为客户提供相应的服务。当容器接收到客户端要求访问特定Servlet对象的请求时,就会调用该Servlet对象的service()方法。
- destroy() 方法:负责释放Servlet对象占用的资源。当Servlet对象结束生命周期时,容器会调用此方法。
JavaWeb应用的生命周期由Servlet容器来控制,而Servlet作为JavaWeb应用的最核心的组件,其生命周期也由Servlet容器来控制。Servlet的生命周期可以分为3个阶段:初始化阶段、运行时阶段和销毁阶段,分别会调用Servlet的init、service和destroy方法。
Servlet接口还定义了两个返回Servlet的相关信息的方法。
- getServletConfig():返回一个ServletConfig对象,在该对象中包含了Servlet的初始化参数信息。
- getServletInfo():返回一个字符串,在该字符串中包含了Servlet的创建者、版本和版权等信息。
public interface Servlet {
void init(ServletConfig config) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest request, ServletResponse response) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
Servlet容器在启动一个Web应用时,会为它创建唯一的ServletContext对象。当Servlet容器终止一个Web应用时,就会销毁它的ServletContext对象。由此可见,ServletContext对象与Web应用具有同样的生命周期。由于ServletContext对象可以被Web应用中的所有组件共享,因此可以利用ServletContext对象来存取Web应用范围内的共享数据。
在ServletContext接口中常用的用于存取共享数据的方法包括:
- setAttribute(String name, Object object):向Web应用范围内存入共享数据。
- getAttribute(String name):根据参数给定的属性名,从Web应用范围内删除匹配的共享数据。
- removeAttribute(String name):根据参数给定的属性名,返回Web应用范围内匹配的共享数据。
在Servlet API中由一个ServletContextListener接口,它能够监听ServletContext对象的生命周期,实际上就是监听Web应用的生命周期。在Servlet容器启动或终止Web应用时,会触发ServletContextEvent事件,该事件由ServletContextListener来处理。在ServletContextListener接口中定义了处理ServletContextEvent事件的两个方法:
- contextInitialized(ServletContextEvent sce):当Servlet容器启动Web应用时调用该方法。在调用完该方法之后,容器再对Filter初始化,并且对那些在Web引用启动时就需要被初始化的Servlet进行初始化。
- contextDestroyed(ServletContextEvent sce):当Servlet容器终止Web应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet和Filter过滤器。
public interface ServletContextListener extends EventListener {
void contextInitialized(ServletContextEvent event);
void contextDestroyed(ServletContextEvent event);
}
javax.servlet.RequestDispatcher接口表示请求分发器,它有两个方法:
- forward()方法:把请求转发给目标组件。
- include()方法:包含目标组件的相应结果。
public interface RequestDispatcher {
void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException;
void include(ServletRequest request, ServletResponse response) throws ServletException, IOException;
}
Servlet容器为了保证能同时响应多个客户的要求访问同一个Servlet的HTTP请求,通常会为每个请求分配一个工作线程,这些工作线程并发执行同一个Servlet对象的service()方法。因此,在Servlet中需要注意局部变量和实例变量的作用范围;需要使用实例变量的地方,注意通过锁机制来处理潜在并发问题。
JSP
JSP是Java Server Page的缩写,它是Servlet的扩展,其作用是简化网站创建过程和维护动态网站。
JSP指令(在 “<%@” 和 “%>” 内)用来设置和整个JSP网页相关的属性,如网页的编码方式和脚本语言等。
<%@ 指令名 属性="值" %>
# page 和 include 两个指令
<%@ page 属性1="值1" 属性2="值2" %>
<%@ include file="被包含组件的绝对URL或相对URL" %>
<%@ taglib prefix="标签库别名" uri="标签库uri" %>
- page指令可以指定所使用的编程语言、与JSP对应的Servlet所实现的接口、所扩展的类及导入的软件包等。
- include指令用来包含其他文件的内容,被包含的文件可以是JSP文件或HTML文件。
- tablib指令用来定义一个标签库以及其自定义标签的前缀。
除了include指令,还可以使用include标签来包含其他文件:
<jsp:include page="被包含组件的绝对URL或相对URL" />
JSP声明(在 “<%!” 和 “%>” 内)用于声明与JSP对应的Servlet类的成员变量和方法。每个声明变量只在当前JSP文件中有效。
<%! declaration;[declaration;]... %>
在JSP文件中,可以在 “<%” 和 “%>” 标记间直接嵌入任何有效的Java程序代码,这种嵌入的程序片段称为Scriptlet。如果在page指令中没有指定method属性,那么这些程序片段默认为与JSP对应的Servlet类的service()方法中的代码块。
Java表达式的标记为 “<%=” 和 “%>”。如果在JSP文件的模板文件中使用该标记,那么它能把表达式的值输出到网页上。表达式中的int和float类型的值都自动转换成字符串再进行输出。
JSP可以不做任何变量声明,就直接通过固定的引用变量来引用一些隐含对象。
隐含对象的引用变量 | 隐含对象的类型 |
---|---|
request | javax.servlet.HttpServletRequest |
response | javax.servlet.HttpServletResponse |
pageContext | javax.servlet.jsp.PageContext |
application | javax.servlet.ServletContext |
out | javax.servlet.jsp.JspWriter |
config | javax.servlet.ServletConfig |
page | java.lang.Object(相当于Java中的this关键字) |
session | javax.servlet.http.HttpSession |
exception | java.lang.Exception |
JSP和Servlet一样,也能进行请求转发,转发的目标组件可以是HTML文件、JSP文件或者Servlet。
<jsp:forward page="转发的目标组件的绝对URL或相对URL" />
HttpSession
在Web开发领域,会话机制是用于跟踪客户状态的普遍解决方案。会话指的是在一段时间内,单个客户与Web应用的一连串相关的交互过程。在一个会话中,客户可能会多次请求访问Web应用的同一个网页,也有可能请求访问同一个Web应用中的多个网页。
会话并不是由HTTP协议制定的,而是服务端通过Cookie存储一个Session ID来实现的。使用JSP、PHP或ASP开发的Web应用都可以运用会话机制。
Servlet规范制定了基于Java的会话的具体运作机制。在 Servlet API 中定义了代表会话的 javax.servlet.http.HttpSession 接口,Servlet容器必须实现这一接口。当一个会话开始时,Servlet容器将创建一个HttpSession对象,在该对象中可以存放表示客户状态的信息。Servlet容器为每个HttpSession对象分配一个唯一标识符,称为 Session ID。
方法 | 描述 |
---|---|
getId() | 返回 Session ID |
invalidate | 销毁当前的会话,Servlet容器会释放HttpSession对象占用的资源 |
setAttribute(String name, Object value) | 将一对name/value属性保存在HttpSession中 |
getAttribute(String name) | 根据name参数返回保存在HttpSession对象中的属性值 |
getAttributeNames() | 以数组的方式返回HttpSession对象中所有的属性名 |
removeAttribute(String name) | 从HttpSession对象中删除name参数的指定属性 |
isNew() | 判断是否是新创建的会话 |
setMaxInactiveInterval(int interval) | 设定一个会话可以处于不活动状态的最长时间,以秒为单位。如果超过这个时间,Servlet容器会自动销毁会话。如果设置为负数,表示不限制会话处于不活动状态的时间,即会话永远不会过期 |
getMaxInactiveInterval() | 读取当前会话可以处于不活动状态的最长时间 |
getSevletContext() | 返回会话所属的Web应用的ServletContext对象 |
JSP默认情况下是支持会话的,也可以通过语句来显式地声明支持或不支持会话
<%@ page session="true" %>
<%@ page session="false" %>
Servlet容器在某些情况下会把创建的HttpSession对象从内存中转移到永久性存储设备(如文件系统或数据库)中,在需要访问HttpSession信息时再把它们加载到内存中。会话的持久化有两个好处:
- 节约内存空间。当有一万个连接时,就会创建一万个HttpSession对象,如果一直放在内存中,将是极大的消耗。因此可以把处于不活动状态的HttpSession对象转移到文件系统或数据库中,这样可以提供对内存资源的利用率。
- 确保在服务器重启或单个Web应用重启后,能恢复重启前的会话。比如在购物过程中,购物车信息对象保存在HttpSession,这样当服务器突发故障后,也能恢复之前的购物车状态,提高用户体验。
在Servlet API中定义了4个用于监听会话中的各种事件的监听器接口。
- HttpSessionListener 接口
- HttpSessionAttributeListener 接口
- HttpSessionBindingListener 接口
- HttpSessionActivationListener 接口
过滤器
过滤器能够对Servlet容器传给Web组件的ServletRequest对象和ServletResponse对象进行检查和修改。过滤器本身并不生成ServletRequest对象和ServletResponse对象,它只为Web组件提供如下过滤功能:
- 过滤器能够在Web组件被调用之前检查ServletRequest对象,修改请求头和请求正文的内容,或者对请求进行预处理操作。
- 过滤器能够在Web组件被调用之后检查ServletResponse对象,修改响应头和响应正文。
过滤器负责过滤的Web组件可以是Servlet、JSP或HTML文件。所有自定义的过滤器类都必须实现 javax.servlet.Filter 接口。
public interface Filter {
void init(FilterConfig config) throws ServletException;
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
void destroy();
}
网友评论