一、Servlet API:
1. Servlet API有以下4个Java包(主要学习前两个):
- javax.servlet,其中包含定义Servlet和Servlet容器之间契约的类和接口。
- javax.servlet.http,其中包含定义HTTP Servlet和Servlet容器之间契约的类和接口。
- javax.servlet.annotation,其中包含标注Servlet、Filter、Listener的标注。它还为被标注元件定义元数据。
- javax.servlet.descriptor,其中包含提供程序化登录web应用程序的配置信息的类型。
2. Servlet技术的核心是
Servlet是所有Servlet类必须直接或间接实现的一个接口,Servlet接口定义了Servlet与Servlet容器之间的契约。这个契约归结起来就是,Servlet容器将Servlet类载入内存,并在Servlet实例上调用具体的方法。在一个应用程序中,每种Servlet类型只能有一个实例。
过程操作:
- 用户请求致使Servlet容器调用Servlet的Service方法,并传入一个ServletRequest实例和一个ServletResponse实例
- ServletRequest中封装了当前的HTTP请求,因此,Servlet开发人员不必解析和操作原始的HTTP数据
- ServletResponse表示当前用户的HTTP响应,使得将响应发回给用户变得十分容易
- 对于每一个应用程序,Servlet容器还会创建一个ServletContext实例
- 这个对象中封装了上下文(应用程序)的环境详情。每个上下文只有一个ServletContext。
- 每个Servlet实例也都有一个封装Servlet配置的ServletConfig。
二、Servlet:
1.什么是Servlet:
Servlet是JavaWeb的三大组件之一,属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:
- 接收数据请求
- 处理请求
- 完成响应
2. Servlet接口中定义了以下5个方法:
void init(ServletConfig config) throws ServletException
生命周期方法,当该Servlet第一次被请求时,Servlet容器会调用这个方法。这个方法在后续请求中不会再被调用。我们可以利用这个方法执行相应初始化工作。调用这个方法时,Servlet容器会传入一个ServletConfig一般来说,你会将ServletConfig赋给一个类级变量,因此这个对象可以通过Servlet类的其他点来使用。
void service(ServletRequest request, ServletResponse response) throws ServletException, java.io.IOException
生命周期方法,每当请求Servlet时,Servlet容器就会调用这个方法。编写代码时,是假设Servlet要在这里被请求。第一次请求Servlet时,Servlet容器调用init方法和Service方法。后续的请求将只调用Service方法。
void destroy()
生命周期方法,当要销毁Servlet时,Servlet容器就会调用这个方法。当要卸载应用程序,或者当要关闭Servlet容器时,就会发生这种情况。一般会在这个方法中编写清除代码。
java.lang.String getServletInfo()
非生命周期方法,, 这个方法会返回Servlet的描述。你可以返回有用或为null的任意字符串。
ServletConfig getServletConfig()
非生命周期方法, 这个方法会返回由Servlet容器传给init方法的ServletConfig。但是,为了让getServletConfig返回一个非null值,必须将传给init方法的ServletConfig赋给一个类级变量。
3.特性:
- 单例,一个类只有一个对象,当然可能存在多个Servlet类
- 线程不安全,所以效率高
Servlet类由我们来写,但是对象由服务器来创建,并由服务器调用相应的方法
三、ServletRequest:
对于每一个HTTP请求,Servlet容器都会创建一个ServletRequest实例,并将它传给Servlet的Service方法。ServletRequest封装了关于这个请求的信息。
ServletRequest接口中有一些方法:
public int getContentLength()
返回请求主体的字节数。如果不知道字节长度,这个方法就会返回−1。
public java.lang.String getContentType()
返回请求主体的MIME类型,如果不知道类型,则返回null。
此方法是在ServletRequest中最常用的方法。该方法通常用于返回HTML表单域的值。
public java.lang.String getParameter(java.lang.String name)
返回指定请求参数的值。
public java.lang.String getProtocol()
返回这个HTTP请求的协议名称和版本。
四、ServletResponse:
ServletResponse接口表示一个Servlet响应。在调用Servlet的Service方法前,Servlet容器首先创建一个ServletResponse,并将它作为第二个参数传给Service方法。ServletResponse隐藏了向浏览器发送响应的复杂过程。
##### ServletResponse的getWriter方法:
它返回了一个可以向客户端发送文本的java.io.PrintWriter。默认情况下,PrintWriter对象使用ISO-8859-1编码。
PrintWriter writer = response.getWriter();
writer.print("<html><head></head><body>" +
"Admin:" + admin +"<br/>Email:" +
email +"</body></html>");
要注意的是,还有一个方法可以用来向浏览器发送输出,它就是getOutputStream。但这个方法是用于发送二进制数据的,因此,大多数情况使用的是getWriter,而不是getOutputStream。
注意:
在向客户端发送响应时,大多数时候是将它作为HTML发送。
在发送任何HTML标签前,应该先调用setContentType方法,设置响应的内容类型,并将“text/html”作为一个参数传入。这是在告诉浏览器,内容类型为HTML。在没有内容类型的情况下,大多数浏览器会默认将响应渲染成HTML。但是,如果没有设置响应内容类型,有些浏览器就会将HTML标签显示为普通文本。
五、ServletConfig:
当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init方法传入一个ServletConfig。ServletConfig封装可以通过@WebServlet或者部署描述符传给Servlet的配置信息。这样传入的每一条信息就叫一个初始参数。一个初始参数有key和value两个元件。
ServletConfig的一些方法:
java.lang.String getInitParameter(java.lang.String name)
为了从Servlet内部获取到初始参数的值,要在Servlet容器传给Servlet的init方法的ServletConfig中调用getInitParameter方法
例如://获取contactName参数值
String contactName = servletConfig.getInitParameter(“contactName”);
java.util.Enumeration
六、ServletContext(重要):
ServletContext表示Servlet应用程序。每个Web应用程序只有一个上下文。在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。
一个项目只有一个ServletContext对象!我们可以在多个Servlet中来获取这唯一的对象,使用它可以给多个Servlet传递数据!这个对象在Tomcat启动时就创建,在Tomcat关闭时死去。
1. 获取ServletContext的方法:
- 通过在ServletConfig中调用getServletContext方法
- GenericServlet中调用getServletContext方法
- HttpSession中调用getServletContext方法
ServletContextEvent中调用getServletContext方法
有了ServletContext,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。前者将对象保存在ServletContext中的一个内部Map中。保存在ServletContext中的对象被称作属性。
2. 域对象的功能:
域对象就是用来在多个Servlet中传递数据。
JavaWeb中有四大域对象:
PageContext;
ServletRequest;
- HttpSession;
- ServletContext
所有域对象都有存取数据功能,因为域对象内部有一个Map,用来存储数据。
3.ServletContext对象用来操作数据方法:
void setAttribute(String name, Object value)
用来存储一个对象,也可以称之为存储一个域属性
例如:servletContext.setAttribute(“xxx”, “XXX”),在ServletContext中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同;
Object getAttribute(String name)
用来获取ServletContext中的数据,当前在获取之前需要先去存储才行
例如:String value = (String)servletContext.getAttribute(“xxx”);,获取名为xxx的域属性;
void removeAttribute(String name)
用来移除ServletContext中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做;
Enumeration getAttributeNames()
获取所有域属性的名称;
4.获取应用初始化参数:
- Servlet标签中也有初始化参数,但它是局部的参数;也就是说,一个Servlet只能获取自己的初始化参数,不能获取别人的,即初始化参数只为一个Servlet准备!
- 可以配置公共的初始化参数,为所有Servlet而用!这需要使用ServletContext才能使用!
七、GenericServlet:
GenericServlet抽象类的出现。本着尽可能使代码简单的原则,GenericServlet实现了Servlet和ServletConfig接口,并完成以下任务:
- 将init方法中的ServletConfig赋给一个类级变量,以便可以通过调用getServletConfig获取。
- 为Servlet接口中的所有方法提供默认的实现,并且service方法是抽象的,子类继承需要重写。
- 提供方法,包围ServletConfig中的方法。
GenericServlet中的init方法如下:
//要注意,子类不能重写此方法,否则servletConfig不会被传入
public void init(ServletConfig servletConfig)
throws ServletException {
this.servletConfig = servletConfig;
this.init();
}
其中,this.init(); 是GenericServlet自己提供的
public void init() throws ServletException{
//NOOP by default
}
内容为空,是需要由子类覆盖的,不能子类覆盖生命周期方法 init(ServletConfig servletConfig)。
八、Http Servlets:
大多数应用程序都要与HTTP结合起来使用。这意味着可以利用HTTP提供的特性。javax.servlet.http中的许多类型都覆盖了javax.servlet中的类型。
HttpServlet类覆盖了javax.servlet.GenericServlet类。使用HttpServlet时,还要借助分别代表Servlet请求和Servlet响应的HttpServletRequest和HttpServletResponse对象。HttpServletRequest接口扩展
javax.servlet.ServletRequest,HttpServletResponse扩展javax.servlet.ServletResponse。
HttpServlet覆盖GenericServlet中的Service方法,并通过下列签名再添加一个Service方法:
//接受HttpServletRequest和HttpServletResponse,而不是ServletRequest和ServletResponse。
protected void service(HttpServletRequest request,HttpServletResponse response)throws ServletException, java.io.IOException
Servlet容器调用javax.servlet.Servlet中原始的Service方法。HttpServlet中的编写方法如下:
//原始的Service方法将Servlet容器的request和response对象分别转换成HttpServletRequest和 HttpServletResponse,并调用新的Service方法。
//javax.servlet.GenericServlet,也可以将传给Service方法的servlet request和
servlet response分别转换成HttpServletRequest和HttpServletResponse。
public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
然后,HttpServlet中的Service方法会检验用来发送请求的HTTP方法(通过调用request.getMethod),并调用以下方法之一:doGet、doPost、doHead、doPut、doTrace、doOptions和doDelete。这7种方法中,每一种方法都表示一个HTTP方法。doGet和doPost是最常用的。因此,不再需要覆盖Service方法了,只要覆盖doGet或者doPost,或者覆盖doGet和doPost即可。
九、HttpServletRequest:
HttpServletRequest表示HTTP环境中的Servlet请求。它扩展javax.servlet.ServletRequest接口,并添加了几个方法。
新增的部分方法如下:
java.lang.String getContextPath()
返回表示请求上下文的请求URI部分。
Cookie[ ] getCookies()
返回一个Cookie对象数组。
java.lang.String getHeader(java.lang.String name)
返回指定HTTP标题的值。
java.lang.String getMethod()
返回生成这个请求的HTTP方法名称。
java.lang.String getQueryString()
返回请求URL中的查询字符串。
HttpSession getSession()
返回与这个请求相关的会话对象。如果没有,将创建一个新的会话对象。
HttpSession getSession(boolean create)
返回与这个请求相关的会话对象。如果有,并且create参数为True,将创建一个新的会话对象。
十、HttpServletResponse:
新增的部分方法如下:
void addCookie(Cookie cookie)
给这个响应对象添加一个cookie。
void addHeader(java.lang.String name, java.lang.String value)
给这个响应对象添加一个header。
void sendRedirect(java.lang.String location)
发送一条响应码,将浏览器跳转到指定的位置。