Servlet---JavaWeb技术的核心基础,JavaWeb框架的基石(一)

        初学JavaWeb开发,请远离各类框架,从Servlet开始。html

        Web框架是开发者在使用某种语言编写Web应用服务端是关于架构的最佳实践。不少Web框架是从实际的Web项目抽取出来的,仅和Web的请求和响应处理有关,造成一个基础,在开发别的应用项目的时候则能够从这个剥离出来的基础作起,让开发者更关注具体的业务问题,而不是Web的请求和响应的控制。
        框架不少,但套路基本相似,帮你隐藏不少关于HTTP协议细节内容,专一功能开发。
        但对于一个初学者来讲,过早的接触框架每每事倍功半!一样一个问题,换一种框架你可能须要从头开始研究。
        因此,做为Java Web技术的核心基础,Servlet的工做原理是必须掌握的,也是成为一名合格的Java Web技术开发人员的基本要求。
 
1、Servlet简介
        Servlet是Server与Applet的缩写,是服务端小程序的意思。是SUN公司提供的一门用于开发动态Web资源的技术。目前最新版本为3.1。
        Servlet本质上也是Java类,但要遵循Servlet规范进行编写,没有main()方法,它的建立、使用、销毁都由Servlet容器进行管理(如Tomcat)。
        Servlet是和HTTP协议是紧密联系的,其能够处理HTTP协议相关的全部内容。这也是Servlet应用普遍的缘由之一。
        提供了Servlet功能的服务器,叫作Servlet容器,其常见容器有不少,如Tomcat, Jetty, resin, Oracle Application server, WebLogic Server, Glassfish, Websphere, JBoss等。
 
2、Servlet工做原理解析
        一、一个HTTP请求的执行过程:
           客户端发出请求http://localhost:8080/xxx
           根据Web.xml文件的配置,找到<url-pattern>对应的<servlet-mapping>
           读取<servlet-mapping>中<servlet-name>的值
           找到<servlet-name>对应的<servlet-class>
           找到该class并加载执行该class
        二、Servlet的执行过程
           Servlet程序有Web服务器调用,当收到请求后,
           检查是否已装载并建立了该Servlet对象,若是没有则加载建立
           调用Servlet的init()方法初始化实例
           调用service()方法,处理请求并返回响应结果
           在服务器被中止或重启以前,调用destroy()方法释放资源
        三、Servlet接口实现类
           SUN公司定义了两个实现类,GenerricServlet和HttpServlet,其中后者是前者的子类,它在原有基础上添加了一些HTTP协议处理方法,它比GenerricServlet功能更强大,因此咱们通常将本身的类继承自HttpServlet,并重写doGet方法和doPost方法,不须要重写Service方法。
         四、Servlet的一些细节
               4.一、因为客户端是经过URL地址访问web服务器中的资源,因此Servlet程序弱项被外界访问,必须把Servlet程序映射到一个URL地址上,这个工做在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成(在Servlet3.0规范的新特性中,该功能可使用注解完成,不要求必须使用web.xml,只用注解更简单,该特性会在后文进行详细讲解)。
                    <servlet>元素用于注册Servlet,它包含两个主要的子元素:<servlet-name>和<servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。
                    <servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含两个子元素:<servlet-name>和<url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。
  1. <web-app>
        <servlet>
            <servlet-name>AnyName</servlet-name><!--自定义的逻辑名-->
            <servlet-class>HelloServlet</servlet-class><!--Servlet对应类的全类名-->
        </servlet>
        <servlet-mapping>
            <servlet-name>AnyName</servlet-name><!--上面定义的逻辑名-->
            <url-pattern>/demo/hello.html</url-pattern><!--匹配的URL-->
        </servlet-mapping>
    </web-app>

                 4.二、同一个Servlet能够被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值能够是同一个Servlet的注册名。java

                  在Servlet映射到的URL中也可使用*通配符,可是只能有两种固定的格式
                  一种是“*.扩展名”。
                  另外一种是以(/)开头并以(/*)结尾。
  1. <!--方式一用于匹配全部某一扩展名的文件-->
    <servlet-mapping>
        <servlet-name>AnyName</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    <!--方式二用于匹配某一文件夹下的全部文件-->
    <servlet-mapping>
        <servlet-name>AnyName</servlet-name>
        <url-pattern>/action/*</url-pattern>
    </servlet-mapping>

                       两个特色:能够精确匹配,就用精确匹配,最后使用范围最宽泛的匹配web

                                 /* 的优先级高于 *.扩展名 会先匹配
             4.三、若是某个Servlet的映射路径只有一个(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。
                    凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的请求访问都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理全部其余Servlet都不处理的访问请求。
                    在tomcat的安装目录/conf/web.xml中,注册了一个名称org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为缺省Servlet。
                    当访问Tomcat服务器中的某个静态HTML文件或图片等资源时,其实是在访问这个缺省Servlet。
          五、Servlet的生命周期
              Servlet没有main()方法,不能独立运行,它的运行彻底由Servlet引擎来控制和调度。
              针对客户端的屡次Servlet请求,一般状况下,服务器只会在第一次请求的时候建立一个Servlet实例对象,并驻留在内存中,为后续的其余请求服务,直至web容器退出,Servlet实例对象才会销毁。
              在Servlet的整个生命周期内,Servlet的init()方法只被调用一次,而对于每个请求都会调用一次Servlet的service()方法service根据请求方式调用doGet或doPost方法
              若是在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并建立实例对象、以及调用Servlet实例对象的init()方法。能够在启动的时候为整个WEB应用建立一些必要的的资源或链接。但若是全部的Servlet都启动加载,则会大大增长服务器负担,并且有些Servlet永远也不会被客户访问到,白白浪费资源,因此从性能角度,应合理利用该特性。
<servlet>
    <servlet-name>invoker</servlet-name>
    <servlet-class>
            org.apache.catalina.servlets.InvokerServlet
    </servlet-class>
    <load-on-startup>2</load-on-startup><!--数字表示启动加载的优先级,大于0-->
</servlet>

          六、ServletConfig对象apache

                在Servlet的配置文件中,可使用一个或对个<init-param>标签为Servlet配置一些初始化参数。
                当Servlet配置了初始化参数后,web容器在建立Servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用Servlet的init方法时,将ServletConfig对象传似给Servlet,开发者能够经过ServletConfig对象获得初始化参数信息。
           七、ServletContext对象
                WEB容器在启动时,它会为每一个WEB应用程序都建立一个对应的Servlet对象,它表明当前web应用。
                ServletConfig对象中维护了ServletContext对象的引用,开发者在编写Servlet是,能够经过ServletConfig.getServletContext方法得到该对象。
                因为一个WEB应用中的全部Servlet共享同一个ServletContext对象,所以Servlet对象之间能够经过ServletContext对象来实现通信。ServletContext对象一般也被称之为Context域对象
                 多个Servlet经过ServletContext对象实现数据共享。要确保注意线程安全。
                 能够经过ServletContext对象获取WEB应用的初始化参数。
                 能够实现Servlet的转发。getRequestDispatcher()方法
          八、Servlet经常使用容器Tomcat(左图:Tomcat容器;右图:Servlet的执行流程)
                
          九、Servlet体系结构
               
             从上图能够看出Servlet规范是基于这几个类运转的,与Servlet主动关联的是三个类:ServletConfig、ServletRequest、ServletResponse。这三个类都是经过容器传递给Servlet的。
             ServletConfig接口中的方法都是为了获取这个Servlet的一些配置属性,而这些配置属性可能在Servlet运行时被用到。
             ServletContext就是这些配置属性的上下文环境。
 
3、Servlet中的Session与Cookie
           Servlet可以给咱们提供两部分数据,一个是在Servlet初始化时调用init方法设置的ServletConfig,它基本包含了Servlet自己和Servlet所运行的Servlet容器中的基本信息。另外一个是ServletRequest提供的此次请求的HTTP协议信息,这部分须要很清楚HTTP协议。
           Session与Cookie的做用都是为了保持访问用户与后端服务器的交互状态,各有优缺点然而具备讽刺意味的是它们优势和它们的使用场景又是矛盾的,例如使用 Cookie 来传递信息时,随着 Cookie 个数的增多和访问量的增长,它占用的网络带宽也很大,试想假如 Cookie 占用 200 个字节,若是一天的 PV 有几亿的时候,它要占用多少带宽。因此大访问量的时候但愿用 Session,可是 Session 的致命弱点是不容易在多台服务器之间共享,因此这也限制了 Session 的使用。

           Session正常工做的实现方式:小程序

               基于URL Path Parameter,默认支持
               基于Cookie,若不修改Context中的cookie标识,默认支持
               基于SSL,默认不支持,只有connector.getAttribute("SSLEnabled")为true时才支持。
 
4、Servlet中的Listener
        整个Tomcat服务器中Listener使用的很是普遍,它是基于观察者模式的,Listener的设计对开发Servlet应用程序提供了一种快捷的手段,可以方便的从另外一个纵向惟独控制程序和数据,目前Servlet中提供了5中两类事件的观察者接口,他们分别是:4个EventListener类型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener 和 2 个 LifecycleListeners 类型的,ServletContextListener、HttpSessionListener。
           它们基本上涵盖了整个Servlet生命周期中,你感兴趣的每种事件,这些Listener的实现类能够配置在web.xml中的<listener>标签中,固然也能够在应用程序中动态添加Listener,可是ServletContextListener在容器启动以后就不能再添加新的,由于它监听的事件已经不会再出现。掌握这些Listener的使用,可以让咱们的程序设计的更加灵活。
 
5、Servlet3.0新特性注解
        前面介绍过Servlet3.0提供了注解(annotation),使得再也不须要在web.xml文件中进行Servlet的部署描述。
        开发者可使用@WebServlet注解将一个继承于javax.servlet.http.HttpServlet的类标注为能够处理用户请求的Servlet。   
  @WebServlet注解的相关属性
NO. 属性名 描述
1 asyncSupported 声明Servlet是否支持异步操做模式
2 description Servlet的描述信息
3 displayName Servlet的显示名称
3 initParams Servlet的初始化参数
5 name Servlet的名称
6 urlPatterns Servlet的访问URL
7 value Servlet的访问URL

         Servlet的访问URL是Servlet的必选属性,能够选择使用urlPatterns或者value定义。后端

         更多关于Servlet3.0的注解使用知识请参考博客: