Servlet

272 阅读15分钟

1.概览

  • 1.1 什么是 Servlet?

      Servlet 是基于 Java 技术的 web 组件,容器托管的,用于生成动态内容。像其他基于 Java 的组件技术一样,
      Servlet 也是基于平台无关的 Java 类格式,被编译为平台无关的字节码,可以被基于 Java 技术的 web server
      动态加载并运行。容器,有时候也叫做 servlet 引擎,是 web server 为支持 servlet 功能扩展的部分。客户端
      通过 Servlet 容器实现的请求/应答模型与 Servlet 交互。
    
  • 1.2 什么是 Servlet 容器?

      Servlet 容器是 web server 或 application server 的一部分,提供基于请求/响应发送模型的网络服务,解码基
      于 MIME 的请求,并且格式化基于 MIME 的响应。Servlet 容器也包含了管理 Servlet 生命周期。
    
      所有 Servlet 容器必须支持基于 HTTP 协议的请求/响应模型,比如像基于 HTTPS(HTTP over SSL)协议的
      请求/应答模型可以选择性的支持。容器必须实现的 HTTP 协议版本包含 HTTP/1.0 和 HTTP/1.1。因为容器
      或许支持 RFC2616 (HTTP/1.1)描述的缓存机制,缓存机制可能在将客户端请求交给 Servlet 处理之前修改它
      们,也可能在将 Servlet 生成的响应发送给客户端之前修改它们,或者可能根据 RFC2616 规范直接对请求
      作出响应而不交给 Servlet 进行处理。
    
  • 1.3 一次典型的事件序列:

      1、客户端(如 web 浏览器)发送一个 HTTP 请求到 web 服务器;
      2、Web 服务器接收到请求并且交给 servlet 容器处理,servlet 容器可以运行在与宿主 web 服务器同一个进
      程中,也可以是同一主机的不同进程,或者位于不同的主机的 web 服务器中,对请求进行处理。
      3、servlet 容器根据 servlet 配置选择相应的 servlet,并使用代表请求和响应对象的参数进行调用。
      4、servlet 通过请求对象得到远程用户,HTTP POST 参数和其他有关数据可能作为请求的一部分随请求一
      起发送过来。Servlet 执行我们编写的任意的逻辑,然后动态产生响应内容发送回客户端。发送数据到客户
      端是通过响应对象完成的。
      5、一旦 servlet 完成请求的处理,servlet 容器必须确保响应正确的刷出,并且将控制权还给宿主 Web 服务
      器。
    

2.Servlet

  • 2.1 Servlet 接口

      Servlet 接口是 Java Servlet API 的核心抽象。所有 Servlet 类必须直接或间接的实现该接口,或者更通常做法
      是通过继承一个实现了该接口的类从而复用许多共性功能。目前有 GenericServlet 和 HttpServlet 这两个类实
      现了 Servlet 接口。大多数情况下,开发者只需要继承 HttpServlet 去实现自己的 Servlet 即可。
          具体步骤:
          1)创建类继承HttpServlet类
          2)覆盖doGet和doPost
          3)在web.xml中进行servlet的配置
    
  • 2.1 请求处理方法

      Servlet 基础接口定义了用于客户端请求处理的 service 方法。当有请求到达时,该方法由 servlet 容器路由到
      一个 servlet 实例。
      Web 应用程序的并发请求处理通常需要 Web 开发人员去设计适合多线程执行的 Servlet,从而保证 service
      方法能在一个特定时间点处理多线程并发执行。(注:即 Servlet 默认是线程不安全的,需要开发人员处理
      多线程问题)
      通常 Web 容器对于并发请求将使用同一个 servlet 处理,并且在不同的线程中并发执行 service 方法。
    
  • 2.2 Servlet 生命周期

      1.Servlet 是按照一个严格定义的生命周期被管理,该生命周期规定了 Servlet 如何被加载、实例化、初始化、
      处理客户端请求,以及何时结束服务。该声明周期可以通过 javax.servlet.Servlet 接口中的 init、service 和
      destroy 这些 API 来表示,所有 Servlet 必须直接或间接的实现 GenericServlet 或 HttpServlet 抽象类。
      2.由 Servlet 容器初始化的某个 Servlet实例在服务期间,可以在其生命周期中不处理任何请求
      
           1)Servlet何时创建
              默认第一次访问该servlet时该servlet创建
                  为什么是“默认”?
                  因为存在<load-on-startup>配置,可以让服务器一起动就创建servlet对象
                  语法:<load-on-startup>正整数</load-on-startup>
                  其中  正整数越小创建对象优先级越高  建议不要将1占用
    
              该servlet对象创建执行init方法
              Servlet对象有一个
          
          2)Servlet何时销毁
              服务器关闭/从服务器中将web应用移除
              销毁servlet对象之前执行destroy方法
          
          3)每次访问必然执行的方法
              service方法---每次访问该servlet资源都会执行的方法
    
  • 2.3 web.xml配置servlet

<servlet>
  	<servlet-name>ServletDemo</servlet-name>
	<servlet-class>com.servlet.ServletDemo</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>ServletDemo</servlet-name>
  	<url-pattern>/servlet</url-pattern>
  </servlet-mapping>
url-pattern的配置方式:
    三种配置方式:
    1) 完全匹配  客户端的访问资源的地址与配置的地址完全一致
    2) 目录匹配  语法:以/开始  以*结束
    示例:/aaa/bbb/*    --- 代表访问/aaa/bbb下的任何资源都匹配
    3) 扩展名匹配 语法:以*开始  以扩展名结束
    示例:*.abc
    
    注意:第二种与第三种不能混合使用
    例如:/aaa/bbb/*.abc  ---- 错误的
    
    缺省Servlet(了解)
    缺省的servlet:当所有的servlet匹配都不成功时,缺省servlet负责响应
    当url-pattern配置成/时,那么该servlet就是缺省的servlet
    其实 所有的资源的响应都是通过servlet
  • 2.4 ServletContext

      1.什么是ServletContext对象
          ServletContext:直译servlet的上下文对象,ServletContext就代表一个web应用
          ServletContext内部维护着该web应用的一些相关信息
      
      2.怎样获得ServletContext对象
          ServletContext context = config.getServletContext()
          ServletContext context = this.getServletContext();
      
      3.ServletContext的作用
          1.初始化信息
          <context-param>
              <param-name>name</param-name>
              <param-value>servlet</param-value>
          </context-param>
          
          ServletContext servletContext = getServletContext();
          String name = servletContext.getInitParameter("name");
          
          2.获取文件绝对地址(web应用的下的文件)
          String realPath = servletContext.getRealPath("WEB-INF/simple.txt");
          
          3.获取类路径(src)下的文件的绝对地址
          String path = ServletDemo.class.getClassLoader().getResource("simple.txt").getPath();
          
          4.域对象,存储对象
          servletContext.setAttribute("key", "value");
          String str = (String) servletContext.getAttribute("key");
          servletContext.removeAttribute("key");
    

3.Request

  • 3.1.Http请求

      Http请求分为部分:请求行,请求头,请求体
      请求行:请求方式;请求资源;http协议版本
      请求头:http协议参数
      请求体:get请求无请求体,post的请求参数存在请求体中
    
  • 3.2.request是对请求参数的封装对象,api中大多数get方法

  • 3.3.get和post请求中文乱码的解决方式

         request默认查询iso-8859-1码表
         post处理方式:
              request.setCharacterEncoding("UTF-8"),只设置请求体中的编码,所以只能结局post请求中的参数中文乱码情况。
         get处理方式
             String Key = new String(req.getParameter("Key").getBytes("iso8859-1"),"UTF-8");
    
  • 3.4.域对象

       request.setAttribute("key", "value");
		String str = (String) request.getAttribute("key");
		request.removeAttribute("key");
  • 3.5.转发(转发与重定向不能一起使用)
    RequestDispatcher requestDispatcher =request.getRequestDispatcher("/servlet2");
    requestDispatcher.forward(request, respoinse);
  • 3.6.注意
注意:ServletContext域与Request域的生命周期比较?
	ServletContext
		创建:服务器启动就创建context对象
		销毁:服务器关闭
		作用范围:整个web应用
	Request
		创建:请求时创建
		销毁:请求结束销毁
		作用范围:一次请求链中
	注意:转发与重定向的区别?

	注意:客户端地址与服务器端地址的写法?
    	什么是客户端地址:客户端直接访问服务器的地址是客户端地址通过客户端访问web应用 地址必须加上web应用的名称
    	什么是服务器端地址:web应用内部访问的地址服务器端地址特点,访问时,不用写web应用名称
    
    	写地址时怎么区分是否加上web应用的名称看在web应用内还是外
    
    	1)直接在地址栏中写url地址 --- 客户端地址
    	2)a标签的href --- 客户端地址
    	3)form表单的action-----客户端地址
    	4)location.href ---- 客户端地址
    
    	目前记住一个服务器端地址:转发 --- 服务器端地址

4.Response

  • 4.1.Http响应

      Http请求分为部分:响应行,响应头,响应体
      响应行:http协议版本;返回的状态码;状态码描述
      响应头:http协议参数
      响应体:请求的响应内容
    
  • 4.2.response是对请求参数的封装对象,api中大多数set,add方法

  • 4.3.重定向

    1.  response.set(302);
        response.setHeader("Localhost","/servlet2")
    2.  response.sendRedirect("/servlet2");
  • 4.4.解决中文乱码问题
    1.response缓冲区的默认编码是iso8859-1
    2.response.setCharacterEncoding("UFT-8") ;设置响应体编码,但是页面还是乱码,是因为页面是GBK解析的
    3.response.setContentType("text/html;charset=UTF-8");设置页面解析方式,并包含了response.setCharacterEncoding("UFT-8"),实际开发中只用这一句就可以了
  • 4.5 注意

      response细节点:
      1)response获得的流不需要手动关闭,Tomcat容器会帮助我们关闭
      2)getWriter和getOutputStream不能同时调用
    

5.Cookie&Session

    1.Http协议是无状态的,无法记录状态,所有需要会话技术记录状态,所以有了Cookie和Session
    2.Cookie:数据存储在客户端本地,减少服务器端的存储的压力,安全性不好,客户端	可以清除cookie
    3.Session:将数据存储到服务器端,安全性相对好,增加服务器的压力
    4.session基于cookie技术,session内存区域借助于cookie存储内存编号id

cookie

    1.Cookie cookie = new Cookie(String cookieName,String cookieValue);
    示例:
    Cookie cookie = new Cookie("key","vlaue");
    那么该cookie会以响应头的形式发送给客户端:Set-Cookie:"key=value"
    注意:cookie只能设置非中文
    
    2.设置Cookie在客户端的持久化时间:
    cookie.setMaxAge(int seconds);
    注意:如果不设置持久化时间,cookie会存储在浏览器的内存中,浏览器关闭cookie信息销毁,如果设置持久化时间,cookie信息会被持久化到浏览器的磁盘文件里
    示例:
         cookie.setMaxAge(10*60);
        设置cookie信息在浏览器的磁盘文件中存储的时间是10分钟,过期浏览器自动删除该cookie信息
        
    3.设置Cookie的携带路径:
    cookie.setPath(String path);
    注意:如果不设置携带路径,那么该cookie信息会在访问产生该cookie的资源所在的路径下的任何资源都携带cookie信息
    示例:
        cookie.setPath("/Path");
        代表访问Path应用中的任何资源都携带cookie

    4.向客户端发送cookie:
    response.addCookie(Cookie cookie);

    5.删除客户端的cookie:
    如果想删除客户端的已经存储的cookie信息,那么就使用同名同路径的持久化时间为0的cookie进行覆盖即可

    6.服务器端怎么接受客户端携带的Cookie
    cookie信息是以请求头的方式发送到服务器端的:
    1)通过request获得所有的Cookie: Cookie[] cookies = request.getCookies();
    2)遍历Cookie数组,通过Cookie的名称获得我们想要的Cookie
    
    7.浏览器(客户端)具有自动保存和发送cookie的能力
      cookie默认是会话级别的,设置持久化时间是会持久化到磁盘上

session

Session技术是将数据存储在服务器端的技术,会为每个客户端都创建一块内存空间存储客户的数据,但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间。所以说Session的实现是基于Cookie,Session需要借助于Cookie存储客	户的唯一性标识JSESSIONID
1.获得Session对象
HttpSession session = request.getSession();
此方法会获得专属于当前会话的Session对象,如果服务器端没有该会话的Session	对象会创建一个新的Session返回,如果已经有了属于该会话的Session直接将已有的Session返回

2.session是一个域对象
Session也是存储数据的区域对象,所以session对象也具有如下三个方法:
session.setAttribute(String name,Object obj);
session.getAttribute(String name);
session.removeAttribute(String name);

3.Session对象的生命周期(重点)
创建:
    当客户端携带id与服务器端的session区域都对不上号 就创建
销毁:
    1)服务器关闭时
    2)session过期/失效(默认30分钟)
何时开始计时?
    从最后一次访问该web应用计算
可以在工程的web.xml中进行配置
    <session-config>
            <session-timeout>30</session-timeout>
    </session-config>
3)手动销毁session
    session.invalidate();
作用范围:
    默认在一次会话中,也就是说在,一次会话中任何资源公用一个session对象


4.、三个域对象的生命周期的比较?
ServletContext
创建:服务器启动
销毁:服务器关闭
作用范围:整个web应用

session
创建:本质jsessionid与服务器端的任何session都不匹配时,调用	request.getSession()就创建
销毁:服务器关闭 session失效 手动关闭
作用范围:默认一次会话

request
创建:请求
销毁:请求结束
作用范围:一次请求链

浏览器关闭 对应的session就销毁了?不对

6.listener

1.什么是监听器?

监听器就是监听某个对象的的状态变化的组件 监听器的相关概念:

事件源:被监听的对象,三个域对象 request  session  servletContext

监听器:监听事件源对象  事件源对象的状态的变化都会触发监听器

响应行为:监听器监听到事件源的状态变化时 所涉及的功能代码

八大监听器:

 ServletContext:
        域对象创建和销毁: ServletContextListener
        域对象属性的变化: ServletContextAttributeListener
 HttpSession:
        域对象创建和销毁: HttpSessionListener
        域对象属性的变化: HttpSessionAttributeListener
 ServletRequest:
        域对象创建和销毁: ServletRequestListener
        域对象属性的变化: ServletRequestAttributeListener
session中的绑定的对象相关的监听器(对象感知监听器)
    即将要被绑定到session中的对象有几种状态
        绑定状态:就一个对象被放到session域中
        解绑状态:就是这个对象从session域中移除了
        钝化状态:是将session内存中的对象持久化(序列化)到磁盘
        活化状态:就是将磁盘上的对象再次恢复到session内存中
    
    绑定与解绑的监听器HttpSessionBindingListener
    钝化与活化的监听器HttpSessionActivationListener
    注意:对象感知监听器不需要在web.xml中进行配置


2.监听三大域对象的创建与销毁的监听器

举例:监听ServletContext域的创建与销毁的监听器ServletContextListener

Servlet域的生命周期
    何时创建:服务器启动创建
    何时销毁:服务器关闭销毁
    作用范围:整个web应用
HttpSession对象的生命周期
    何时创建:第一次调用request.getSession时创建
    何时销毁:服务器关闭销毁  session过期  手动销毁
    作用范围:默认一次会话中
ServletRequest的生命周期
    创建:每一次请求都会创建request
    销毁:请求结束
域对象的通用的方法:
    setAttribute(name,value)
         --- 触发添加属性的监听器的方法   
         --- 触发修改属性的监听器的方法 
    getAttribute(name)
    --- 无触发
    removeAttribute(name)  
        --- 触发删除属性的监听器的方法 


2)监听器的编写步骤:
    a、编写一个监听器类去实现监听器接口
    b、覆盖监听器的方法
    c、需要在web.xml中进行配置
1.ServletContextListener, HttpSession, ServletRequest

public class ListenerContent implements ServletContextListener{
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("init");
	}
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("destory");
	}
}

web.xnl配置文件
  <listener>
  	<listener-class>cn.servlet.ListenerContent</listener-class>
  </listener>
  
  
 2.钝化与活化的监听器HttpSessionActivationListener
 可以通过配置文件 指定对象钝化时间 --- 对象多长时间不用被钝化在META-INF下创建一个context.xml
 <Context>
	<!-- maxIdleSwap:session中的对象多长时间不使用就钝化 -->
	<!-- directory:钝化后的对象的文件写到磁盘的哪个目录下  配置钝化的对象文件在work/catalina/localhost/钝化文件 -->
	<Manager className="org.apache.catalina.session.PersistentManager" 																				maxIdleSwap="1">
	 	<Store className="org.apache.catalina.session.FileStore" directory="itcast205" />
	</Manager>
</Context>


7.Filter

filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行

步骤:
    1)编写一个过滤器的类实现Filter接口
    2)实现接口中尚未实现的方法(着重实现doFilter方法)
    3)在web.xml中进行配置(主要是配置要对哪些资源进行过滤)
filter生命周期及其与生命周期相关的方法
    Filter接口有三个方法,并且这个三个都是与Filter的生命相关的方法
    1.init(Filterconfig):代表filter对象初始化方法 filter对象创建时执行
    2.doFilter(ServletRequest,ServletResponse,FilterCha):代表filter执行过滤的核心方法,如果某资源在已经被配置到这个filter进行过滤的话,那么每次访问这个资源都会执行doFilter方法。FilterChain:过滤器链对象,通过该对象的doFilter方法可以放行该请求
    3.destory():代表是filter销毁方法 当filter对象销毁时执行该方法
Filter对象的生命周期:
    Filter何时创建:服务器启动时就创建该filter对象
    Filter何时销毁:服务器关闭时filter销毁
public class FilterDemo implements Filter{

	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)
			throws IOException, ServletException {
		filterChain.doFilter(req, resp);
	}

}

<filter>
  	<filter-name>filterDemo</filter-name>
  	<filter-class>cn.servlet.FilterDemo</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>filterDemo</filter-name>
  	<url-pattern>/servlet</url-pattern>
  </filter-mapping>
  
  url-pattern配置时
    1)完全匹配  /sertvle1
    2)目录匹配  /aaa/bbb/* ----最多的
    /user/*:访问前台的资源进入此过滤器
    /admin/*:访问后台的资源时执行此过滤器
    3)扩展名匹配  *.abc  *.jsp

注意:url-pattern可以使用servlet-name替代,也可以混用

dispatcher:访问的方式(了解)
REQUEST:默认值,代表直接访问某个资源时执行filter
FORWARD:转发时才执行filter
INCLUDE: 包含资源时执行filter
ERROR:发生错误时 进行跳转是执行filter