【3】Servlet介绍、生命周期、HttpServlet创建、初始化、执行流程

1、Servlet介绍:

Servlet是运行在服务端的Java程序,是sun公司提供的一套规范,用来处理客户端的请求,响应给浏览器的动态资源。


2、Servlet规范简介,Web框架如何注入到Servlet当中:

Web框架一般是通过一个Servlet提供统一的请求入口,将指定的资源映射到这个servlet上,然后在这个servlet中进行框架的初始化配置,访问Web页面中的数据,进行逻辑处理后,将结果数据与表现层相融合并展现给用户。WEB框架想要在符合Servlet规范的容器中运行,同样也要符合Servlet规范。

将一个WEB框架注入到一个servlet中,主要涉及到Servlet规范中以下部分:部署描述符; 映射请求到Servlet;Servlet生存周期;请求分发;

部署描述符:

        部署描述符就是位于WEB应用程序的/WEB-INF目录下的web.xml的XML文件,是WEB应用程序不可分割的部分,管理着WEB应用程序的配置。部署描述符在应用程序开发人员,应用程序组装人员,应用程序部署人员之间传递WEB应用程序的元素和配置信息。

         XML声明:DTD约束

                <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web

                Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
 

        根据DTD约束典型的Servlet声明格式:

              <servlet>
                    <servlet-name>catalog</servlet-name>
                    <servlet-class>com.mycorp.CatalogServlet</servlet-class>
                    <init-param>
                          <param-name>catalog</param-name>
                          <param-value>Spring</param-value>
                    </init-param>
              </servlet>
              <servlet-mapping>
                    <servlet-name>catalog</servlet-name>
                    <url-pattern>/catalog/*</url-pattern>
              </servlet-mapping>

范德萨          通过上面方法,我们就声明了一个名称为catalog的Servlet,它的实现类为com.mycorp.CatalogServlet,并且带有一个catalog参数,参数值为Spring,所有向/catalog/*的请求都被映射到名称为catalog的Servlet。

映射请求到Servlet:

         接收到一个请求后,WEB容器要确定转到哪一个WEB应用程序。被选择的应用程序的最长的上下文路径必须和请求的URL开始部分匹配。URL匹配的部分是映射到Servlet的上下文路径。WEB容器下一步必须按照下面的程序定位处理请求的Servlet。

       用来映射到Servlet的路径是请求对象的URL减去上下文的路径。下面的URL路径映射规则按顺序执行,容器选择第一个成功的匹配并且不在进行下一个匹配:

Ø     容器试着对请求的路径和Servlet的路径进行精确匹配,如果匹配成功则选择这个Servlet。

Ø      容器会循环的去试着匹配最长的路径前缀:把’/’当作路径分隔符,按照路径树逐级递减的完成,选择最长匹配的Servlet。

Ø      如果这个URL路径的最后有扩展名(比如.jsp),Servlet容器会试着匹配处理这个扩展名的Servlet。

Ø      如果前面的没有与前面三条规则相匹配的Servlet,容器会试着为资源请求提供适当的资源,如果有“默认”的Servlet定义给这个应用程序,那么这个Servlet会被使用。

WEB容器允许显式的声明隐含映射以获得优先级,例如,*.shtml的隐含映射可以在服务器上被映射为包含功能。

                   映射实例:

path pattern

servlet

/foo/bar/*

servlet1

/baz/*

servlet2

/catalog

servlet3

*.bop

servlet4

  下面是实际请求映射的结果:

incoming path

servlet handling request

/foo/bar/index.html

servlet1

/foo/bar/index.bop

servlet1

/baz

servlet2

/baz/index.html

servlet2

/catalog

servlet3

/catalog/index.html

“default” servlet

/catalog/racecar.bop

servlet4

/index.bop

servlet4

请注意/catalog/index.html 和/catalog/racecar.bop这两种情况,因为是精确匹配,所以并没有映射到处理/catalog的servlet。


2、Servlet的生命周期:指Servlet的对象从被创建到被销毁的过程。

a:Servlet接口

在介绍Servlet的生存周期之前需要先介绍一下javax.servlet.Servlet接口。所有的Servlet必须实现或者间接实现这个接口,我们通常可以通过继承javax.servlet.GenericServlet或者javax.servlet.http.HttpServlet.类来实现这个接口。HttpServlet继承了GenericServlet;

b:Servlet接口中五个方法:

    void init(ServletConfig config) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest req, ServletResponse rsp) throws ServletException, IOException;

    String getServletInfo();

    void destroy();

构造器:

                - Servlet第一次处理请求时,会调用构造器,来创建Servlet实例(服务器创建,例如Tomcat)。

                - 只会调用一次,Servlet是单例模式,他是以多线程的方式调用service()方法.

                - Servlet不是线程安全,所以尽量不要再service()方法中操作全局变量。

init(ServletConfig config)方法:`

构造器调用之后马上被调用,用来初始化Servlet,init方法在容器装入Servlet 时执行,Servlet容器在实例化后只调用一次init方法, init方法必须在servlet接收到任何请求之前完成。这个方法通常用来进行一些资源的管理和初始化。读取配置文件中的配置数据,由Tomcat服务器创建ServletConfig对象,将ServletConfig对象传到init()方法中,进行Servlet的初始化。作用:从配置文件读取配置数据,读取初始化参数,初始化缓冲迟等一次性的操作。

getServletConfig()方法:

getServletConfig方法返回一个 ServletConfig 对象,该对象用来返回这个Servlet的初始化信息和启动参数。返回的是传递到init方法中的参数信息的对象ServletConfig。

Service(ServletRequest req, ServletResponse rsp)方法:

Servlet每次处理请求时服务器都会创建一个新的线程,访问service()方法,用来处理请求,会调用多次,在Service方法中决定调用get请求,还是post请求,然后响应的调用doXxx方法。Service方法是应用程序逻辑的进入点,是servlet方法的核心,WEB容器调用这个方法来响应进入的请求,只有servlet成功被init()方法初始化后,Service方法才会被调用。

getServletInfo()方法:

这个方法返回一个字符串对象,提供有关servlet 的信息,如作者、版本等。

destroy()方法:

Servlet对象销毁前(WEB项目关闭时,或者从服务器移除时)调用,用来做一些收尾工作,释放资源,destroy方法在容器移除Servlet 时执行,同样只执行一次。这个方法会在所有的线程的service()方法执行完成或者超时后执行,调用这个方法后,容器不会再调用这个servlet的方法,也就是说容器不再把请求发送给这个Servlet。 这个方法给servlet释放占用的资源的机会,通常用来执行一些清理任务。

c:执行顺序:

默认情况,当用户第一次发送请求,Servlet被服务器容器(Tomcat)创建(一种类型的Servlet只会创建一次!)!读取配置文件数据,服务器创建ServletConfig对象,对数据进行封装传递到init方法中,接着会调用init(ServletConfig config)方法来完成初始化!在整个Servlet生命周期中,该方法只会被调用一次!然后调用service(ServletRequest req,ServletResponse resp)方法来处理用户的请求,该方法在整个Servlet生命周期中会被调用
多次(用户发送一次请求就调用一次)!当我们正常关闭服务器的时候(关闭之前),会调用destroy()方法来进行销毁!该方法在整个Servlet生命周期中会被调用一次

3、请求分发:

请求分发可以让一个Servlet把请求分配到另外一个资源,RequestDispatcher接口提供了实现他的机制。可以通过下面两种方式从ServletContext中获得一个实现了RequestDispatcher接口的对象:

方法一:getRequestDispatcher(String url );接受一个指向目标资源的URL路径,

方法二:getNamedDispatcher(String name );接受一个Servlet名称,这个名称是在部署描述符中<servlet-name>元素指定的那个名称。

protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        //获取具有处理请求分发能力的实现了RequestDispatcher接口的对象
        RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher("/catlog");//指定一个url
        requestDispatcher.forward(request, response);
        
        RequestDispatcher catlog = getServletContext().getNamedDispatcher("catlog");//指定名称
        catlog.forward(request, response);

    }

RequestDispatcher接口有两个方法,允许你在调用的servlet完成初步处理后把请求响应分配到另外一个资源;

    void forward(ServletRequest req, ServletResponse rsp) throws ServletException, IOException;

    void include(ServletRequest req, ServletResponse rsp) throws ServletException, IOException;

forward方法上让你把请求转发到另外的Servlet或者jsp或者html等资源,由这个资源接下来负责响应。

include方法让你的Servlet响应中包含另外一个资源生成内容。

4、Servlet体系结构及Servlet运行流程:

1、Servlet简介: > Server + let,意为:运行在服务器端的小程序。

        > Servlet实际上是一个接口。

            - 狭义上的Servlet,指的就是Servlet接口

            - 广义上的我们认为凡是实现Servlet接口的类,我们都称他是一个Servlet

        > Servlet的作用:

            1:接收用户发送的请求

            2:调用其他的java程序来处理请求

            3:根据处理结果,返回给用户一个页面

        > Servlet的Demo

            1:创建一个类并实现Servlet接口,或继承一个已经实现了Servlet的类,example:HttpServlet

            2:在web.xml文件中对Servlet进行配置,配置具有处理请求能力的Servlet类,配置映射关系。

                 

        > Servlet的三个名字:

            <servlet-name>

                        - Servlet的别名,通过别名对Servlet进行配置

            <servlet-class>

                       - Servlet的全类名,服务器通过全类名来创建Servlet的实例

            <url-pattern>

                       - Servlet映射的请求地址,用户通过该地址访问Servlet

2、Servlet的生命周期:

        > Servlet的生命周期,指Servlet的对象从被创建到被销毁的过程。

        > Servlet的生命周期方法:

            1.构造器:

                - Servlet第一次处理请求时,会调用构造器,来创建Servlet实例。

                - 只会调用一次,Servlet是单例模式,他是以多线程的方式调用service()方法.

                - Servlet不是线程安全,所以尽量不要再service()方法中操作全局变量。

            2.init()方法:

                - 构造器调用之后马上被调用,用来初始化Servlet,只会调用一次。

            3.service()方法:

                - Servlet每次处理请求时都会调用service()方法,用来处理请求,会调用多次。

            4.destroy()方法:

                - Servlet对象销毁前(WEB项目卸载时)调用,用来做一些收尾工作,释放资源。

3、相关对象:

            ①ServletConfig:Servlet容器使用的Servlet配置对象,该对象在初始化期间将信息传递给Servlet。

                代表:当前Servlet的配置信息,每一个Servlet都有其唯一对应的ServletConfig。

         <servlet>
             <servlet-name>AServlet</servlet-name>
             <servlet-class>com.atguigu.servlet.AServlet</servlet-class>
             <init-param>
                 <param-name>user</param-name>
                 <param-value>root</param-value>
             </init-param>
             <init-param>
                <param-name>password</param-name>
                <param-value>123123</param-value>
             </init-param>
          </servlet>
//获得指定初始化参数的值(需要在web.xml文件中去配置!)
String getInitParameter(String name) 
		 
//获得所有的初始化参数名称(需要在web.xml文件中去配置!)
Enumeration getInitParameterNames() 
		 
//获得ServletContext对象(整个应用的上下文对象!)
ServletContext getServletContext() 
		 
//获得当前Servlet的名称!
String getServletName() 

获取:ServletConfig对象由Tomcat服务器创建,配置信息最终作为参数传递到init(ServletConfig conf)方法中,我们可以在init()方法直接使用。当我们通过继承HttpServlet创建Servlet时,由于父类已经实现ServletConfig接口,所以我们可以在Servlet中直接调用ServletConfig的方法。

            功能:

                【1】 获取Servlet的别名

                【2】 获取当前Servlet的初始化参数。

                          

                【3】 获取当前WEB应用的ServletContext对象。

        ②ServletContext

            代表:当前的WEB应用,一个WEB应用对应一个唯一的ServletContext对象ServletContext对象在项目启动时创建,在项目卸载时销毁。

            获取:通过ServletConfig的getServletContext()方法获取。

            功能:

                【1】 可以获取整个WEB应用的初始化参数                 

                【2】 可以获取资源的真实路径(物理路径),主要在文件的上传和下载时使用。

                【3】 可以作为一个域对象在不同的web资源之间共享数据。

              <context-param>
                   <param-name>phone</param-name>
                   <param-value>1388888888</param-value>
              </context-param>

4、GenericServlet:

        - 通用Servlet的父类

        - 相比Servlet接口GenericServlet更加简单一些,但是我们最终实际上使用的HttpServlet

5、HttpServlet:两个service方法。参数不同。

        - HttpServlet继承了GenericServlet,而GenericServlet实现Servlet接口,所以我们可以同构继承HttpServlet来创建一个Servlet。

        - HttpServlet重写service()方法:

            1:在该方法中先将ServletRequest和ServletResponse,强转为了HttpServletRequest和HttpServletResponse。

            2:然调用重载的service()方法,并将刚刚强转得到对象传递到重载的方法中。

            3:重载service(HttpServletRequest request , HttpServletResponse response)

                 

            1:在方法中获取请求的方式(get或post)

            2:在根据不同的请求方式去调用不同的方法:

                如果是GET请求,则调用doGet(HttpServletRequest request , HttpServletResponse response)

                如果是post请求,则调用doPost(HttpServletRequest request , HttpServletResponse response)

                

        - 结论:

            当通过继承HttpServlet来创建一个Servlet时,我们只需要根据要处理的请求的类型,来重写不同的方法。

                处理get请求,则重写doGet()

                处理post请求,则重写doPost()

6、HttpServletRequest:

            代表:浏览器发送给服务器的请求报文。

            获取:该对象由Tomcat服务器创建最终作为参数传递到doGet或doPost方法中,我们可以在这两个方法中直接使用。

           功能:

               【1】获取用户发送的请求参数

                        request.getParameter("username");

               【2】获取项目的名字(用来设置绝对路径)

                        request.getContextPath();

               【3】作为一个域对象,在不同的WEB资源之间共享数据。

               【4】请求的转发(相对路径

                        request.getRequestDispatcher("target.html").forward(request, response);

7、HttpServletResponse:

            代表:服务器发送给浏览器的响应报文。

            获取:该对象由Tomcat服务器创建,最终作为参数传递到doGet或doPost方法中,我们可以在这两个方法中直接使用。

            功能:

               【1】响应给浏览器一个网页或者是网页片段(设置的是响应报文的响应体)

                        response.getWriter("响应到页面");

               【2】请求的重定向(绝对路径

                        response.sendRedirect("target.html");

            转发和重定向:

                                                             转发                  重定向

                      请求的次数:                    1                         2

                      发生的位置:            服务器内部            浏览器

                      浏览器地址栏:            不改变                  改变

                     浏览器的感知:             未感知                  感知 

8、字符编码:

         > 当用户通过表单向Servlet发送中文请求参数时,Servlet获取到内容会产生乱码,当Servlet向浏览器响应中文内容时,也会产生乱码。

        > 浏览器和服务器之间通信时,中文内容时不能直接发送的,需要对中文进行编码。

        > 编码:

            - 将字符转换为二进制码的过程叫编码。

        > 解码:

            - 将二进制码转换为普通字符的过程叫解码。

        > 编码和解码所采用的规则我们称为字符集。常见的字符集:

           - ASCII、ISO8859-1、GBK、GB2312、UTF-8

        > 产生乱码问题的根本原因:

            编码和解码所采用的字符集不同。

        > 解决方法:

            统一编码和解码的字符集为UTF-8。

        > 请求编码

            - 请求是浏览器发送给服务器的。浏览器 --> 服务器,浏览器的会自动使用网页的字符集对参数进行编码

                  UTF-8的张三:%E5%BC%A0%E4%B8%89

                  GBK的张三:%D5%C5%C8%FD

             - 所以我们只需要统一网页的字符集为UTF-8即可。

        > 服务器解码

                 tomcat7以上的版本,对于path的内容,会自动用utf-8去解码。其也可以在server.xml中去配置。

                 而tomcat7以及以下的版本,默认的字符集依然是iso-8859-1。因此需要通过对应的格式去decode。

                post请求

                    > request解码时默认字符集时iso8859-1,但是iso压根就不支持中文

                    > post请求在servlet中解码,所以我们只需要指定request的字符集即可

                    > 我们可以通过如下方法,来设置request的字符集:

                             request.setCharacterEncoding("utf-8");

                    > 注意:

                             该方法要在request.getParameter()第一次调用之前调用

                get请求

                    > get请求是通过url地址传递请求参数,url中的请求参数将会被Tomcat服务器自动解码。

                    > Tomcat的默认编码是iso8859-1,但是iso压根就不支持中文,所以必然乱码。

                    > 只需要修改Tomcat的解码的默认字符集,修改配置文件server.xml

                    > 在server.xml的Connector标签中(改端口号的那个标签)添加如下属性:

                              URIEncoding="utf-8"

                       

                    > 修改完配置文件以后,get请求的编码就不用再处理的,但是post请求还是老样子。

        > 响应编码

            - 响应是服务器发送给浏览器 - 服务器 --> 浏览器

                > 指定服务器的编码字符集为UTF-8。

                > 指定response的字符集

                           response.setCharacterEncoding("utf-8");

                > 虽然我们已经指定了response的字符集为utf-8,但是浏览器并不是用utf-8解码。

                    浏览器默认使用gb2312解码的,所以依然乱码,只不过没有那么乱。

        > 浏览器 解码

                > 浏览器的解码字符集可以通过浏览器来设置(不靠谱)

                > 我们可以通过服务器来告诉浏览器,我们的内容的编码格式为utf-8

                > 我们可以通过一个响应头来告诉浏览器,内容的编码格式:

                        Content-Type:text/html;charset=utf-8

                > 通过response的方法,来设置响应头:

                        response.setHeader("Content-Type", "text/html;charset=utf-8");

            解决方案:

                1.设置响应头

                    response.setHeader("Content-Type", "text/html;charset=utf-8");

                2.设置response的编码格式

                    response.setCharacterEncoding("utf-8");

                > 当我们设置Content-Type这个响应头时,服务器会自动使用响应头中的字符集为内容编码

                > 最终方案:

                    response.setContentType("text/html;charset=utf-8");

        <<总结>>

              post请求:

                  - 在request.getParameter()方法第一次调用之前,调用如下代码:

                      request.setCharacterEncoding("utf-8");

              get请求:

                - 修改server.xml配置文件

                - <Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

            响应:

                - 设置一个Content-Type响应头

                    response.setContentType("text/html;charset=utf-8");

10、路径问题:

          > URI和URL

                      - URL是URI的一种实现,也是URI最常见的实现方式。

                      - URI有两种实现方式URL和URN,URN用的很少

                      - 我们说URL和URI实际上可以理解为一个意思

        > URL地址的格式

                     http://主机名:端口号/项目名/资源路径/资源名

        ①相对路径和绝对路径

            > 相对路径:所谓的相对路径指相对于当前资源所在路径:

                    http://主机名:端口号/项目名/资源路径/

            - 由于转发的出现,相对路径会经常发生变化,容易出现错误的链接

                     所以在开发中我们一般不使用相对路径,而是使用绝对路径。

            > 绝对路径:- 绝对路径使用/开头,

                   - 由浏览器解析的绝对路径中的/代表的是服务器的根目录:

                             http://主机名:端口号/项目名/

                              注意:需要加上项目名

                  - 由服务器解析的绝对路径中的/代表的项目的根目录:

                              http://主机名:端口号/

                              注意:不要加项目名

                  - 转发的路径由服务器解析,设置绝对路径时不需要加项目名

                 - 重定向的路径由浏览器解析,设置绝对路径时需要加上项目名

        ②常见的路径:

            url-pattern:

                - url-pattern和转发中的路径都是由服务器解析的,

                    根目录是项目的根目录:

                        http://主机名:端口号/

                  - 所以这两个路径不需要加项目名

            重定向的路径:

                - 重定向和页面中的路径(HTML标签中的路径),由浏览器解析的,

                    根目录是服务器的根目录:

                        http://主机名:端口号/项目名

                - 所以这个两个路径必须加上项目名

11、运行流程:

12、HttpServlet:

        

 部分转自:http://www.cnblogs.com/libingbin/,修改,理解。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值