Servlet:
狭义上servlet是Java语言提供的接口,广义上认为是实现Servlet接口的类。
Servlet API下包含四个包分别是
servlet:包含定义servlet和servlet容器(Tomcat、JBoss、Jetty)之间契约的类和接口
servelet.http: 包含定义Http Servlet与Servlet容器之间的关系
servlet.annotation: 包含定义Servlet、Filter、Linstener的标注,它还被标注元件定义元数据
servlet.description: 包含提供程序化登录Web应用程序的配置信息的类型
Servlet接口的源码:
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo(); // 会返回由Servlet容器传给init()方法的ServletConfig对象。
void destroy();
}
ServletConfig类的源码:
public interface ServletConfig {
String getServletName();
ServletContext getServletContext();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
}
Servlet接口定义了Servlet与servlet容器之间的契约,这个契约是:Servlet容器将Servlet类载入内存,并产生Servlet实例和调用它具体的方法。
在一个应用程序中,每种Servlet类型只能有一个实例。
用户请求致使Servlet容器(如Tomcat)调用servlet的service()方法,并传入一个ServletReuest对象和ServletResponse对象,
这两个对象都是有Servlet容器(如Tomcat)封装好的,不需要我们去实现,我们可以直接使用这两个对象。
对于每一个应用程序,Servlet还会创建一个ServletContext对象,用来封装上下文的环境信息,每一个应用程序只能有一个ServletContext,
每一个Servlet对象也都有一个封装的Servlet配置的ServletConfig对象。
GenericServlet抽象类实现了Servlet接口和ServletConfig接口
GenericServlet抽象类相比于直接实现Servlet接口,有以下几个好处:
1.为Servlet接口中的所有方法提供了默认的实现,不再需要把所有的方法都自己实现了。
2.提供方法,包围ServletConfig对象中的方法。
3.将init()方法中的ServletConfig参数赋给了一个内部的ServletConfig引用从而来保存ServletConfig对象,不需要自己去维护ServletConfig了。
然而,虽然GenricServlet是对Servlet一个很好的加强,但是也不经常用,因为他不像HttpServlet那么高级。
HttpServlet:
HttpServlet有两个特性是GenericServlet所不具备的:
1.不用覆盖service方法,而是覆盖doGet或者doPost方法。在少数情况,还会覆盖其他的5个方法。
2.使用的是HttpServletRequest和HttpServletResponse对象。
HttpServletResponse接口:
继承自ServletResponse接口,专门封装HTTP响应消息,由于Http请求分为状态行、响应消息头、响应消息体三部分,
所以在HttpServletResponse接口中定义了向客户端发送响应状态码、响应消息头、响应消息体的方法。
方法:
PrintWriter getWriter():获得字符流,通过字符流的write(String s)方法可以将字符串设置到response缓冲区中,
随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。
ServletOutputStream getOutputStream():获得字节流(ServletOutputStream类型),通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,
再由Tomcat服务器将字节内容组成Http响应返回给浏览器。因为它可以直接输出字节数组中的二进制数据,因此要输出二进制响应的正文,就需要使用getOutputStream()方
法。
虽然response对象的getOutSream()和getWriter()方法都可以发送响应消息体,但是他们之间相互排斥,不可以同时使用,否则会发生异常。
response的乱码问题:
response缓冲区的默认编码是iso8859-1,此码表中没有中文。所以需要更改response的编码方式:
response.setCharacterEncodig("utf-8")
通过更改response的编码方式为UTF-8,任然无法解决乱码问题,因为发送端服务端虽然改变了编码方式为UTF-8,
但是接收端浏览器端仍然使用GB2312编码方式解码,还是无法还原正常的中文,
因此还需要告知浏览器端使用UTF-8编码去解码。
response.setHeader("Content-Type", "text/html;charset=utf-8")
上面通过调用两个方式分别改变服务端对于Response的编码方式以及浏览器的解码方式为同样的UTF-8编码来解决编码方式不一样发生乱码的问题。
实际应用中只需要调用response.setContentType("text/html;charset=UTF-8")即可,该方法包含上述两个方法的调用。
ServletContextListener
ServletContex翻译成中文是Servlet上下文或者叫Servlet全局。其实ServletContext就是一个“域对象”,它存在于整个应用中,并在整个应用中有且仅有一份。
他表示了当前整个应用的状态,可以理解为某个时刻的servletContext代表了这个应用在某个时刻的一张快照,这张快照包含了有关应用的许多信息,应用的所有组件
都可以从ServletContext获取当前应用的状态信息。
小结:当Servlet容器启动时,ServletContext对象被初始化,
当ServletContext创建时我们可以创建applicationContext对象,当ServletContext销毁时,我们可以销毁applicationContext对象。