zoukankan      html  css  js  c++  java
  • jsp技术

      1.JSP简介

      JSP是一种动态网页技术标准。它是在传统的网页HTML文件(*.htm,*.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件,后缀名为(*.jsp)。

      将内容的生成和显示进行分离。

      用JSP技术,Web页面开发人员可以使用HTML或者XML标识来设计和格式化最终页面,并使用JSP标识或者小脚本来生成页面上的动态内容(内容是根据请求变化的,例如请求账户信息或者特定的一瓶酒的价格等)。生成内容的逻辑被封装在Servlet和JavaBeans组件(两个都是.java)中,并且捆绑在脚本中,所有的脚本在服务器端运行。由于核心逻辑被封装在标识和JavaBeans中,所以Web管理人员和页面设计者,能够编辑和使用JSP页面,而不影响内容的生成。
      在服务器端,JSP引擎解释JSP标识和脚本,生成所请求的内容(例如,通过访问JavaBeans组件,使用JDBC技术访问数据库或者包含文件),并且将结果以HTML(或者XML)页面的形式发送回浏览器。这既有助于作者保护自己的代码,又能保证任何基于HTML的Web浏览器的完全可用性。
      弦外:*Servlet控制器,接收请求封装‘Type1’(下行解释)的JavaBean、调用‘Type2’的JavaBean的相应业务逻辑方法、向客户端发出响应
          @WebServlet(urlPatterns={"authImg.jsp"})       

          public class AuthImg extends HttpServlet 然后在其中重写service等方法,对其响应。(假如在里面生成一张图片)。

          @注解中指向的url即是Servlet的访问入口,在jsp中可以通过<img name="d" src="authImg">来访问。

         *JavaBean:普通的java类,模型,逻辑事务,数据访问。
           1)只有属性声明和该属性对应的setXxx和getXxx方法不包含业务逻辑;这种JavaBean可以简单地理解为“数据对象”即可。
          2)还有一种JavaBean,其内包含业务处理逻辑,用于处理特定的业务数据。
         *JSP视图,
          1)仅仅是视图,只是表现层角色,拿到数据后显示出来。(MVC推荐)
          2)除了表现层,还包括一些逻辑处理。

      MVC(模型Model-视图View-控制器Controller)是一种设计模式,
      M(Model)在Java Web里说的是JavaBean,在JavaBean中除了其属性和字段,还可以有行为及其事件,JavaBean可以理解为普通Java对象。Java普通对象,就是符合Java规范的所有对象,这和实体类完全是两回事。业务逻辑和数据访问应该放在Model层,也就是V负责展示数据,Controler除了转发不做业务逻辑。真正的逻辑事务,数据访问,甚至算法都放到Model去。
      Controller是控制器的意思,所谓控制器,就是将用户请求转发给模型层,经过处理后把结果返回到界面层展现的一个中间层,那么Controller到底管什么工作呢?先不说.先来看下在Java Web中这三个层一般的定义,一般在Java Web里,JSP充当V,Servlet充当C,JavaBean充当M,这里的Servlet管什么工作呢?接受输入,转到Model层去处理,处理结果保存后转发到JSP,然后展现数据。所以它的功能就是控制器的基本功能,它就管转发,在V和M之间转来转去。在Struts中,还包括它独有的控制器—Action。
      MVC没有把业务的逻辑访问看成两个层,这是采用三层架构或MVC搭建程序最主要的区别。当然了。在三层中也提到了Model,但是三层架构中Model的概念与MVC中Model的概念是不一样的,“三层”中典型的Model层是实体类(数据对象)构成的,而MVC里,则是由业务逻辑与访问数据组成的。

      2.JSP分析

      1.HelloWorld.jsp代码:
        <%
         String message = "Hello World!";
        %>
        <%=message%>

      这个文件非常简单,仅仅定义了一个String的变量,并且输出。把这个文件放到Tomcat的webapps/ROOT/目录下,启动Tomcat,在浏览器中访问http://localhost:8080/HelloWorld.jsp,浏览器中的输出为“HelloWorld!”

      2.HelloWorld_jsp.java代码:

     import javax.servlet.*;
     import javax.servlet.http.*;
     import javax.servlet.jsp.*;
     import org.apache.jasper.runtime.*;
    
        public class HelloWorld_jsp extends HttpJspBase {
    
            private static java.util.List _jspx_dependants;
    
            public Object getDependants() {
                return _jspx_dependants;
            }
            public void _jspService(HttpServletRequest request, 
            HttpServletResponse response)throws java.io.IOException,         ServletException{
                JspFactory _jspxFactory = null;
                javax.servlet.jsp.PageContext pageContext = null;
                HttpSession session = null;
                ServletContext application = null;
                ServletConfig config = null;
                JspWriter out = null;
                Object page = this;
                JspWriter _jspx_out = null;
    
                try {
                 _jspxFactory = JspFactory.getDefaultFactory();//调用JspFactory的getDefaultFactory()方法获取容器实现的一个JspFactory对象的引用
                 response.setContentType("text/html;charset=ISO-8859-1");
                 pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);//填充一个PageContext返回,并赋给内置变量 pageConext
                 application = pageContext.getServletContext();
                 config = pageContext.getServletConfig();
                 session = pageContext.getSession();
                 out = pageContext.getOut();
                 _jspx_out = out;
    
                 String message = "Hello World!";
                 out.print(message);
                } catch (Throwable t) {
                 out = _jspx_out;
                 if (out != null && out.getBufferSize() != 0)
                  out.clearBuffer();
                 if (pageContext != null) pageContext.handlePageException(t);
                } finally {
                if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
                }
              }
       } 

          转到Tomcat的/work/Standalone/localhost/_目录下,可以找到如下的HelloWorld_jsp.java,这个文件就是Tomcat解析HelloWorld.jsp时生成的源文件。由此可见,HelloWorld.jsp在运行时首先解析成一个Java类HelloWorld_jsp.java,该类继承 于org.apache.jasper.runtime.HttpJspBase基类,HttpJspBase实现了HttpServlet接口。因此,JSP在运行前首先将编译为一个Servlet,这就是理解JSP技术的关键。

          首先,调用JspFactory的getDefaultFactory()方法获取容器实现的一个JspFactory对象的引用。JspFactory是javax.servlet.jsp包中定义的一个抽象类,其中定义了两个静态方法setDefaultFactory()/getDefaultFactory()。set方法由JSP容器(Tomcat)实例化该页面Servlet(即 HelloWorld_jsp类)的时候置入,所以可以直接调用JspFactory.getDefaultFactory()方法得到这个JSP工厂的 实现类。Tomcat是调用org.apache.jasper.runtime.JspFactoryImpl类。

      然后,调用这个JspFactoryImpl的getPageContext()方法,填充一个PageContext返回,并赋给内置变量 pageConext。其它内置对象都经由该pageContext得到。具体过程见上面的代码,这里不再赘述。该页面Servlet的环境设置完毕,开始对页面进行解析。HelloWorld.jsp页面仅仅定义了一个String变量,然后直接输出。解析后的代码如下:

           String message = "Hello World!";
           out.print(message);

      所以说其实所有jsp都被编译成.java文件,所以在jsp中可以直接实例化其它.java文件,并调用它就行。

      eg:

    1 <%
    2     Person p1 = new Person();//实例化Person类
    3     //把p1实例放入session生存范围中,并取名为"p1"
    4     session.setAttribute("p1",p1); 
    5     p1.setName("jslee"); //调用方法
    6 %>
    7 <!-- 调用方法来输出p1中的name属性值 -->
    8 <%=p1.getName()%>

      3.JSP特殊接口

      1)3个编译指令

      通知Servlet引擎的处理消息。

      <%@ 指令 指令的属性= "属性值" %> 

      *include JSP语法中的include指令语句指示在JSP语句被解释的过程中包含一个静态文件,同时解析这个被包含文件中的JSP语句。

      *page 当前jsp页面的相关属性

      *taglib 用于定义和访问自定义标签

      2)7个动作指令

      运行时的动作。

      <jsp:指令 指令的属性= "属性值"  />

      *include动作指令在于在一个JSP页面包含另一个文件。如果被包含的文件是一个静态文件 ,则功能和include指令相同,它将被包含的文件直接发送给客户端浏览器,由浏览器负责显示。如果被包含的文件是一个动态文件(扩展名为.jsp),则被包含的文件在运行结果包含在一起,再发送给客户端浏览器。

      *param动作指令用来向目标JSP页面传参数,在目标页面中可以用request对象的getParameter()等方法获取传来的参数的值。

      *useBean动作指令用来在JSP页面中创建一个JavaBean组件,创建后即可使用这个组件。相比于直接new 对象,用useBean可以通过setProper和getProperty动作指令来设置scope属性. 相当于实例的作用域.

      *forward动作指令类似于response.sendRedirect(),都是用来重定向页面。不同的是jsp:forward动作指令可以为目标页面指定参数

      *plugin:用于下载JavaBean或Applet到客户端执行。

      *Forword和SendRedirect区别     
      前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址; 
      后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。 
      所以,前者更加高效,在前者可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。但在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用sendRedirect()方法。 
      forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。 
      redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。
     

      3)9个内置对象

      用法: jsp中,<% 对象名.对象方法 %> ,直接用

          .java中,ServletContext sc = getServletConfig().getServletContext();

               sc.setAttribute("");          此例是获得application对象。

      *request对象封装了客户端的请求信息,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。request对象具有请求域,即完成客户端的请求之前,该对象一直有效。
      *response对象包含了响应客户请求的有关信息,但在JSP中很少直接用到它。它是HttpServletResponse类的实例。response对象具有页面作用域,即访问一个页面时,该页面内的response对象只能对这次访问有效,其它页面的response对象对当前页面无效。
      *session对象指的是客户端与服务器的一次会话,从客户端连到服务器的一个WebApplication开始,直到客户端与服务器断开连接为止。它是HttpSession类的实例。Session对象是一个JSP内置对象,它在第一个JSP页面被装载时自动创建,完成会话期管理。从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。当一个客户访问一个服务器时,可能会在这个服务器的几个页面之间切换,服务器应当通过某种办法知道这是一个客户,就需要Session对象。session对象具有会话作用域
      *out对象是JspWriter类的实例,是向客户端输出内容常用的对象
      *page对象就是指向当前JSP页面本身,有点象类中的this指针,它是java.lang.Object类的实例
      *application对象实现了用户间数据的共享,可存放全局变量。它开始于服务器的启动,直到服务器的关闭,在此期间,此对象将一直存在;这样在用户的前后连接或不同用户之间的连接中,可以对此对象的同一属性进行操作;在任何地方对此对象属性的操作,都将影响到其他用户对此的访问。服务器的启动和关闭决定了application对象的生命。它是ServletContext类的实例。
      *exception对象是一个例外对象,当一个页面在运行过程中发生了例外,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。他实际上是java.lang.Throwable的对象
      *pageContext对象提供了对JSP页面内所有的对象及名字空间的访问,也就是说他可以访问到本页所在的SESSION,也可以取本页面所在的application的某一属性值。
      *config对象是在一个Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象)

      4.JSP容器与Filter(过滤器)

      Servlet容器:

      负责处理客户请求、把请求传送给Servlet(运行前首先将JSP编译为一个Servlet)并把结果返回给客户不同程序的容器实际实现可能有所变化,但容器与Servlet之间的接口是由Servlet API定义好的,这个接口定义了Servlet容器在Servlet上要调用的方法及传递给Servlet的对象类。

      Servlet生命周期:

      1、Servlet容器创建Servlet的一个实例

      2、容器调用该实例的init()方法

      3、如果容器对该Servlet有请求,则调用此实例的service()方法

      4、容器在销毁本实例前调用它的destroy()方法

      5、销毁并标记该实例以供作为垃圾收集

      一旦请求了一个Servlet,就没有办法阻止容器执行一个完整的生命周期。
      容器在Servlet首次被调用时创建它的一个实例,并保持该实例在内存中,让它对所有的请求进行处理。容器可以决定在任何时候把这个实例从内存中移走。在典型的模型中,容器为每个Servlet创建一个单独的实例,容器并不会每接到一个请求就创建一个新线程,而是使用一个线程池来动态的将线程分配给到来的请求,但是这从Servlet的观点来看,效果和为每个请求创建一个新线程的效果相同。

      filter使用户可以改变一个request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在response离开servlet时处理response.换种说法,filter其实是一个“servlet chaining“(servlet 链).
    包括
      1. 在servlet被调用之前截获;
      2. 在servlet被调用之前检查servlet request;
      3. 根据需要修改request头和request数据;
      4. 根据需要修改response头和response数据;
      5. 在servlet被调用之后截获.
      filter和listener都配置在web.xml文件中。
      它和Struts中的拦截器不同,过滤器是在JSP和生成servlet之间过滤,而拦截器是在执行Action方法前或后调用(AOP)!

      5.Listener

      在Web项目中,我们可以使用Listener接口来监听Container的中一些对象状态的变化,并且根据这些对象的状态的变化做出相应的响应。

      Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。当增加一个HttpSession时,就激发sessionCreated(HttpSessionEvent se)方法,这样就可以给在线人数加1。

      6.Servlet生命周期

      servlet的定义及其生命周期

      1)init()方法
          在Servlet的生命周期中,仅执行一次init()方法。它是在服务器装入Servlet时执行的,可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init();

      2)service()方法
          它是Servlet的核心。每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。

      3)destroy()方法
          仅执行一次,在服务器端停止且卸载Servlet时执行该方法,有点类似于C++的delete方法。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。

      Tomcat服务器在如下时刻加载和实例化Servlet:

               a) 如果已配置自动装入选项,则在启动服务器时自动载入。
               b) 在服务器启动后,客户机首次向Servlet发出请求时。
               c) 重新装入Servlet时。

      当启动Servlet容器时,容器首先去查找一个配置文件web.xml,这个文件中记录了可心提供服务的Servlet。每个Servlet被指定一个Servlet名,也就是这个Servlet实际对应的Java的完整class文件名。Servlet容器会为每个自动装入选项的Servlet创建一个实例。所以,每个Servlet类必须有一个公共的无参数的构造器。

      Servlet Engine可以随时随意使用或释放Servlet。因此,你不能依赖Servlet class或其成员存储信息。

      当Servlet Engine判断一个Servlet应当被释放时(比如说Engine准备Shut down 或需要回收资源),Engine必须让Servlet 能释放其正在使用的任何资源,并保存持续性的状态信息。这些可以通过调用Servlet的destroy方法实现。 

      在Servlet Engine 释放一个Servlet 以前,必须让其完成当前实例的service方法或是等到timeout(如果Engine定义了timeout)。当Engine释放一个Servlet以后,Engine将不能再将请求转发给它,Engine必须彻底释放该Servlet并将其标明为可回收的(给garbage collection)。 

    参考:百科
      轻量级javaEE企业应用实战
  • 相关阅读:
    Shiro(三):Spring-boot如何集成Shiro(下)
    Shiro(二):Spring-boot如何集成Shiro(上)
    Shiro踩坑记(一):关于shiro-spring-boot-web-starter自动注解无法注入authorizer的问题
    Shiro(一):Shiro介绍及主要流程
    Netty(七):EventLoop学习前导——Reactor模式
    java基础
    nginx,tomcat,apache三者分别用来做什么,有何区别
    python之yagmail发送邮件
    python之文件的读写
    python之字符串方法
  • 原文地址:https://www.cnblogs.com/jslee/p/3439441.html
Copyright © 2011-2022 走看看