Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 279|回复: 0

[jsp学习]深入理解Servlet和JSP原理

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-2 01:36:53 | 显示全部楼层 |阅读模式
    一、什么是Servlet       Servlet是由Sun公司制定的服务器端组件规范。它不但指定了作为一个Servlet组件的特征,同时也指定了作为运行Serlvet的系统(称之为Servlet容器)应具备的特征。
         Servlet组件运行在Servlet容器下,由Servlet容器负责诸如“实例化并管理Servlet对象”、“调用Servlet生命周期方法”、“解析及封装特定协议的请求和响应”等工作。
        Servlet类应实现javax.servlet.Servlet接口并实现其生命周期方法。其中最主要的是
        public void service(ServletRequest request, ServletResponse response)
             throws ServletException, IOException {        ... ... ...
        }
      
       
       
         
       

         
       
      
        容器收到请求后即会调用该方法。面对大量的用户访问,Servlet容器一般采用“单实例,多线程”的方式管理Servlet,即Servlet容器只会创建一个Servlet实例,针对不同的用户访问将开启不同的线程运行service方法,Servlet容器一般会维护一个线程池去管理这些线程。鉴于Servlet容器的这种管理方式,对于service方法而言应注意线程安全的问题。
        一般在实际中常常使用的是基于HTTP协议的Servlet,作为基于HTTP协议的Servlet可以通过继承javax.servlet.HttpServlet得到。HttpServlet类实现了Servlet接口,并在service方法中根据不同的请求(get或post等)调用相应的方法(doGet或doPost)。一般情况下,作为HttpServlet的子类可以重写其doGet方法用于处理Get请求,重写doPost方法用于处理Post请求。 另外HttpServlet可以重写init()和destory()方法

    init()方法用于定义初始化逻辑,Servlet一创建后即会被调用。
    destory()方法将在Servlet实例销毁前调用。  
        一个HttpServlet需要有特定的部署描述符(web.xml,置于应用的/WEB-INF中)指定其特征:其定义如下:
         <servlet>
           <servlet-name>Tst</servlet-name>
           <servlet-class>test.TestServlet</servlet-class>
           <init-param>
             <param-name>someKey</param-name>
             <param-value>someValue</param-value>
           </init-param>
           <load-on-startup>0</load-on-startup>
         </servlet>
      
         <servlet-mapping>
            <servlet-name>Tst</servlet-name>
            <url-pattern>/test</url-pattern>
         </servlet-mapping>

    子元素指定Serlvet的名称,作为该Servlet的唯一标识。
    子元素用于指定Servlet的类名。
      
       
       
       
        的子元素用于定义所谓基于键-值对的初始化参数,Servlet对象可以通过调用ServletConfig对象的getInitParameter(String name)获取制定指定键的对应值。
         
          可以有多个元素,用于定义Servlet在工作时要获取的某些初始化信息(如:要读取的某些属性文件的路径等
          
          )。
          
         
      
       
       
        的子元素用于指定是在Servlet容器启动时即创建该Servlet对象,还是在Serlvet容器接收到针对该Servlet的请求后再实例化该Servlet对象。的值为负数时采取后一种策略,的值为0或正数时采取前一种策略。web.xml中可能会定义多个为正数的Servlet,Servlet容器会根据其值得大小决定其实例化顺序,值小的先实例化,值大的后实例化。
          

         元素用于把特定的Servlet映射到一个URI地址,当Servlet容器收到针对该地址发出的请求时即会实例化相应的Servlet对象,并调用其特定方法。例如某个Servlet的url-pattern为"/test"则当在浏览器的地址栏输入".../应用名/test"时,Servlet容器将会访问
    该Servlet。     作为Tomcat服务器,还可以通过其他的方式访问Servlet,在其安装目录的conf子目录下有也有一个web.xml该web.xml中定义了一些Servlet,这些Servlet属于Tomcat内置的Servlet,在Tomcat服务器一启动时即会实例化这些Servlet对象。
        其中InvokerServlet的配置信息如下:
          <servlet>
             <servlet-name>invoker</servlet-name>
             <servlet-class>
               org.apache.catalina.servlets.InvokerServlet
             </servlet-class>
             <init-param>
                 <param-name>debug</param-name>
                 <param-value>0</param-value>
             </init-param>
             <load-on-startup>2</load-on-startup>
         </servlet>       <servlet-mapping>
             <servlet-name>invoker</servlet-name>
             <url-pattern>/servlet/*</url-pattern>
         </servlet-mapping>        该Servlet用于访问其他的Servlet,其默认的url-pattern配置为/servlet/*。当我们在浏览器的地址栏输入“.../servlet/其他Servlet的类名” 时,则Tomcat容器将通过InvokerServlet访问该Servlet(即使该Servlet没有在web.xml进行定义)
        例如:在浏览器的地址栏输入".../应用名/servlet/servet.TestServlet时,Servlet容器即会对test.TestServlet进行访问。这种访问方式将便于对Servlet的测试。
        我们可以关注Tomcat另外的一个内置Servlet:DefaultServlet可以用于列出应用下某个目录的内容,该Servlet的配置信息如下:
           <servlet>
             <servlet-name>default</servlet-name>
             <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
             <init-param>
                 <param-name>debug</param-name>
                 <param-value>0</param-value>
             </init-param>
             <init-param>
                 <param-name>listings</param-name>
                 <param-value>true</param-value>
             </init-param>
             <load-on-startup>1</load-on-startup>
         </servlet>        更改其配置信息的名为listings的初始化参数值为true时,当输入某个应用的目录时DefaultServlet可以用下图的方式列出该目录中的内容并可实现链接导航。这样的功能会对测试有一定的帮助。       二、什么是JSP?
         准确的说,JSP就是Servlet,JSP是一个标准的文本文件,在第一次访问时,Servlet会将该文件“翻译”成Servlet,然后再实施调用。不同的应用服务器会有不同的翻译方式。     针对于Tomcat服务器而言,我们可以在conf/web.xml中关注定义的另外一个内置Servlet:JspServlet,该Servlet的功能在于“翻译”JSP并对其实施访问,该Servlet的定义如下:
            <servlet>
             <servlet-name>jsp</servlet-name>
             <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
             <init-param>
                 <param-name>fork</param-name>
                 <param-value>false</param-value>
             </init-param>
             <init-param>
                 <param-name>xpoweredBy</param-name>
                 <param-value>false</param-value>
             </init-param>
             <load-on-startup>3</load-on-startup>
         </servlet>     <servlet-mapping>
             <servlet-name>jsp</servlet-name>
             <url-pattern>*.jsp</url-pattern>
         </servlet-mapping>     注意该Servlet的url-pattern为“*.jsp”及所有后缀为“.jsp”等请求将会访问该Servlet,例如:在浏览器地址栏输入“.../应用名/test.jsp”将访问该Servlet
         而该Servlet将首先获取名为test.jsp文件的内容将其编译成并实施调用。     可以做一个小的实验,在conf/web.xml中替换JspServlet对应的url-pattern(例如:改成hey),重启Tomcat服务器,访问内容如下所示的hello.jsp(地址为".../应用名/hello.jsp")
         <HTML>      <head>
            <title>hello.jsp</title>
            </head>        <body>
            <%
             for (int i = 0; i <= 100; i++) {
               out.println("helloworld");
             }
            %>
           </body>
         </html>     通过在浏览器中"单击右键->查看源文件"的方式可以看到浏览器你收到的内容为:
          <html>        <head>
              <title>hello.jsp</title>
            </head>        <body>
            <%
             for (int i = 0; i <= 100; i++) {
               out.println("helloworld");
             }
            %>
           </body>
         </html>     可见该jsp并没有被解析,而是以静态文本的方式原样输出。     在Tomcat安装目录下的workCatalina下可以找到JSP经过“翻译”后的Java源文件和编译后类文件,对于上面hello.jsp而言,“翻译”后的Servlet源文件为:workCatalinalocalhost        storgapachejsphello_jsp.java 该文件的主要内容如下: package org.apache.jsp; import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.jsp.*; public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
         implements org.apache.jasper.runtime.JspSourceDependent {   ... ... ...   public void _jspService            (HttpServletRequest request, HttpServletResponse response)
                 throws java.io.IOException, ServletException {     JspFactory _jspxFactory = null;
         PageContext pageContext = null;
         HttpSession session = null;
         ServletContext application = null;
         ServletConfig config = null;
         JspWriter out = null;
         Object page = this;
         JspWriter _jspx_out = null;
         PageContext _jspx_page_context = null;
         try {       ... ... ...
           out.write("<html>
    ");
           out.write("        <head>
    ");
           out.write("                <title>hello.jsp</title>
    ");
           out.write("        </head>
    ");
           out.write("
    ");
           out.write("        <body>
    ");
           out.write("                ");         for (int i = 0; i <= 100; i++) {
             out.println("helloworld");
          }
       
           out.write("
    ");
           out.write("        </body>
    ");
           out.write("</html>");       ... ... ...
         }
    }     可以看出hell.jsp经过“翻译”后的类名为hello_jsp 该类继承了org.apache.jasper.runtime.HttpJspBase类,而HttpJspBase类又是HttpServlet的子类。HttpJspBase在其service方法中调用了_jspService方法,针对特定的jsp页面,Tomcat的JSP引擎将其“翻译”成HttpJspBase的子类并重写其_jspService方法。该类的很多初始化内容有JSP引擎完成。     在上面的_jspService方法中可以看到hello.jsp的“影子”,在JSP中使用<%...%>所书写的Java代码被原样的置于_jspService方法中;另外在JSP中的HTML脚本通过流对象out原样输出...当然,JSP的“翻译”不可能如此简单,因为JSP页面还可能写有指令、标签等复杂的结构。     从上面的_jspService方法还可以看出,所谓JSP内建对象(request、reponse、application、session等)其实并不神秘,它们或是_jspService方法的参数变量,或是由JSP引擎在_jspService方法中预先定义好的变量,我们在JSP的<%...%>中可以直接使用。

      
      
       
       

         
       

         
       
      
    复制代码
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-20 01:14 , Processed in 0.423675 second(s), 50 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表