jsp的实现和原理理解

2021-05-30 00:04

阅读:715

标签:将不   范围   convert   需要   目录   一个人   run   base   初始化   

JSP介绍

JSP全称java server pagesservlets一样都是sun公司定义的一种用于开发动态web资源的技术。

JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据。

 

JSP运行原理

浏览器向服务器发请求,不管访问的是什么资源,其实都是在访问Servlet,所以当访问一个jsp页面时,其实也是在访问一个Servlet,服务器在执行jsp的时候,首先把jsp翻译成一个Servlet,所以我们访问jsp时,其实不是在访问jsp,而是在访问jsp翻译过后的那个Servlet

 技术图片

当我们通过浏览器访问index.jsp时,服务器首先将index.jsp翻译成一个index_jsp.class,在Tomcat服务器的work\Catalina\localhost\项目名\org\apache\jsp目录下可以看到index_jsp.class的源代码文件index_jsp.java。代码如下:

 技术图片技术图片

从上面的代码可以发现b_jsp是继承org.apache.jasper.runtime.HttpJspBase的,但是这个类其实是继承HttpServlet的,所以其本质上访问b.jsp还是在访问servlet

 

JSP的排版标签是如何发送到浏览器的 

技术图片

jsp中编写的java代码和html代码都会被翻译到_jspService方法中去,在jsp中编写的java代码会原封不动地翻译成java代码,如直接翻译成out.print("Hello Jsp”);,而HTML代码则会翻译成使用out.write("标签>\r\n");的形式输出到浏览器。在jsp页面中编写的html排版标签都是以out.write("标签>\r\n");的形式输出到浏览器,浏览器拿到html代码后才能够解析执行html代码。

JSP页面中的java代码服务器是如何执行的

 

jsp中编写的java代码会被翻译到_jspService方法中去,当执行_jspService方法处理请求时,就会执行在jsp编写的java代码了,所以Jsp页面中的java代码服务器是通过调用_jspService方法处理请求时执行的。

 

web服务器在调用jsp的时候会提供jsp8个对象使用

PageContext pageContextHttpSession sessionServletContext applicationServletConfig configJspWriter outObject page=nullHttpServletRequest requestHttpServletResponse response。这8个对象是可以直接在jsp页面中使用的。

 

其中的requestresponsepage是已经完成了初始化,而其它的5个通过下面的代码完成初始化。

 技术图片

jsp的整个运行流程。

 

1.浏览器对服务器发送请求,请求是动态的。连接器将请求交给Servlet容器处理,

2.servlet容器查找要执行的.jsp文件

3.jsp转为.java,

4.在编译为.class

5.最终服务器要加载这个class文件,最后调用这个servlet实例。

 

注意:第二次执行的时候,如果内容没有发生变化,则直接执行原来的class文件。

JSP模版元素

 

jsp页面中的HTML内容称之为jsp模版元素。

jsp模版元素定义了网页的基本骨架,即定义了页面的结构和外观。

 

JSP表达式

 

JSP脚本表达式(expression)用于将程序数据输出到客户端。

语法:变量或表达式 %>

例如:%= 5 %> 将会将5输出到客户端。

 

JSP脚本片段

JSP脚本片断(scriptlet)用于在JSP页面中编写多行Java代码。

语法:

             多行java代码

     %>

中可以定义变量、编写语句,不能定义方法。

注意:

1.jsp脚本片段中只能出现java代码不可以出现其他jsp模版元素。

2.jsp脚本片段中的所有代码必须遵循java语法规范。

3.一个jsp中可以有多个jsp脚本片段,之间可以加其它的元素。

4.多个脚本片段中的代码可以互相访问。

5.单个脚本片段中的代码可以是不完整的,但是多个脚本片段组合后必须是完整的。

 

JSP声明

 

JSP页面中编写的所有代码,默认会翻译到servlet_jspservice方法中, Jsp声明中的java代码被翻译到_jspService方法的外面。

语法:

        java代码

   %>

所以,JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法   

 技术图片技术图片

 

 

JSP指令

JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。JSP中定义了三个指令,分别是pageincludetaglib

JSP指令的基本语法格式:指令 属性名="" %>

 

page指令

 

page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。

—Language属性:指定在页面中的脚本语言。

—contentType:表示JSP输出的MIME类型和编码。

—pageEncoding:表示jsp的输出编码方式。

 

page指令的import属性

可以在一条page指令的import属性中引入多个类或包,其中的每个包或类之间使用逗号,分隔.

% @ page import="java.util.*,java.net" %>

 

page指令的errorPage属性

 

该属性用于页面出错的时候,指明跳转到哪一个页面。

—errorPage属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前Web应用程序的根目录(注意不是站点根目录),否则,表示相对于当前页面。

可以在web.xml文件中使用元素为整个Web应用程序设置错误处理页面。

元素有3个子元素,

子元素指定错误的状态码,例如:404

子元素指定异常的类的完全限定名

子元素指定以“/”开头的错误处理页面的路径。即/ErrorPage/404Error.jsp类似。

如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。

 

使用page指令的的isErrorPage属性显式声明页面为错误页面

如果一个页面为系统的错误页面,应该用属性isErrotPagetrue显示的声明。使用该属性后,jsp引擎在将error.jsp转为servlet的时候,会在jspservice方法中生成一个exception对象,通过调用exception.getErrorMessage()可以获取到错误的具体信息。 

 include的指令

 @include可以包含任意的文件,当然,只是把文件的内容包含进来。

语法:  —静态包含。

include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP在翻译阶段合并成一个java文件。所以include指令引入通常也称之为静态引入。

 

 一、JSP运行原理

  每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ,然后按照servlet的调用方式进行调用。
  由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。
  JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。

 

 

 


out
对象

该对象是通过pageContextgetout方法获得,其类似于PrintWriter,但是它在PrintWriter基础上增加了自己的一个out缓存区,意味着调用out.write并不会直接将数据写入response的缓存区,而是将数据写入out的缓存区,当出现下面3种情况时out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中。

—page指令将buffer区关闭了。

—JSP页面加载结束了。

—out对象的缓冲区满了。 

技术图片

pageContext对象

 

pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象(容器),可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。

 

通过pageContext获得其他对象

—getException方法返回exception隐式对象

—getPage方法返回page隐式对象

—getRequest方法返回request隐式对象

—getResponse方法返回response隐式对象

—getServletConfig方法返回config隐式对象

—getServletContext方法返回application隐式对象

—getSession方法返回session隐式对象

—getOut方法返回out隐式对象

 

pageContext封装其它8大内置对象的意义

如果在编程过程中,把pageContext对象传递给一个普通java对象,那么这个java对象将可以获取8大隐式对象,此时这个java对象就可以和浏览器交互了,此时这个java对象就成为了一个动态web资源了,这就是pageContext封装其它8大内置对象的意义,把pageContext传递给谁,谁就能成为一个动态web资源,那么什么情况下需要把pageContext传递给另外一个java类呢,什么情况下需要使用这种技术呢,在比较正规的开发中,jsp页面是不允许出现java代码的,如果jsp页面出现了java代码,那么就应该想办法把java代码移除掉,我们可以开发一个自定义标签来移除jsp页面上的java代码,首先围绕自定义标签写一个java类,jsp引擎在执行自定义标签的时候就会调用围绕自定义标签写的那个java类,在调用java类的时候就会把pageContext对象传递给这个java类,由于pageContext对象封装了对其它8大隐式对象的引用,因此在这个java类中就可以使用jsp页面中的8大隐式对象(requestresponseconfigapplicationexceptionSessionpageout)了,pageContext对象在jsp自定义标签开发中特别重要。

 

pageContext作为域对象

  pageContext对象可以作为容器来使用,因此可以将一些数据存储在pageContext对象中。

  pageContext对象的常用方法

public void setAttribute(java.lang.String name,java.lang.Object value)

public java.lang.Object getAttribute(java.lang.String name)

public void removeAttribute(java.lang.String name)

public java.lang.Object findAttribute(java.lang.String name)

当要查找某个属性时,findAttribute方法按照查找顺序"pagerequestsessionapplication"在这四个对象中去查找,只要找到了就返回属性值,如果四个对象都没有找到要查找的属性,则返回一个null

pageContext对象中封装了访问其它域的方法

public java.lang.Object getAttribute(java.lang.String name,int scope)

public void setAttribute(java.lang.String name, java.lang.Object value,int scope)

public void removeAttribute(java.lang.String name,int scope)

代表各个域的常量

 

—PageContext.APPLICATION_SCOPE

—PageContext.SESSION_SCOPE

—PageContext.REQUEST_SCOPE

—PageContext.PAGE_SCOPE 

PageContext引入和跳转到其他资源

PageContext类中定义了一个forward方法(用来跳转页面)和两个include方法(用来引入页面)来分别简化和替代RequestDispatcher.forward方法和include方法。

pagecontext.forward(uri)  pagecontext.include(uri)一般不用这种方法。

 

 

JSP的属性范围

 

JSP中提供了四种属性范围,四种属性范围分别指以下四种:

—当前页:一个属性只能在一个页面中取得,跳转到其他页面无法取得。

一次服务请求:一个页面中设置的属性,只要经过了服务器跳转,则跳转之后的页面可以继续取得。

一次会话:一个用户设置的内容,只要是与此用户相关的页面都可以访问(一个会话表示一个人,这个人设置的东西只要这个人不走,就依然有效)。

上下文中:在整个服务器上设置的属性,所有人都可以访问。

该四种属性范围都具有setAttributegetAttributeremoveAttribute方法。

 

page属性范围

 

当服务器发生了一次跳转后,当前页面的属性在跳转后的页面是不能够获得的。

a.jsp 

b.jsp 

浏览器结果

 

 

request属性范围

request属性范围,在服务器发生跳转的时候,该属性会传递下去。简单说就是你的浏览器的url没有变,则这个属性可以一直使用。

 

 % request.setAttribute("name","yu"); %>

 % pageContext.forward("b.jsp"); %>

 % String name = (String)request.getAttribute("name"); %>

 

这是一个错误的界面

    %=name %>

 

session属性范围

 

session属性范围不管是服务端跳转还是客户端跳转都可以继续操作该属性。

 

application属性范围

 

application是在服务器上设置的一个属性,所以一旦设置了,任何用户都可以浏览到此属性。

 

 

JSP标签

 

JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。

 

 标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。

语法:

page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。

flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。 

 

 

标签与include指令的区别

标签是动态引入, 标签涉及到的2JSP页面会被翻译成2servlet,这2servlet的内容在执行时进行合并。

  而include指令是静态引入,涉及到的2JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。

 

 

jspf扩展名文件在jsp:include和@include的区别。

 

 

注意:只有使用@include包含jspf文件的时候,文件内容才能被解析执行。而使用jspinclude动态包含的时候会在客户端输出文件的原内容。本身动态包含是将多个文件翻译为多个servlet,然后将执行的结果进行合并输出,但是jspf文件在使用动态包含的时候被当作纯文本文件处理了,即该jspf文件并没有被翻译为servlet执行,仅仅是当作文本进行输出了。

 

 

如何让服务器解析jspf文件呢

 

方法一:修改web应用的web.xml文件,添加映射  

 

 技术图片技术图片

 

 

方法二:修改服务器上的web.xml文件,添加类似上面的映射。

 

 

标签

该标签用于将请求转发给另一个资源。

语法:。服务器端跳转。

 

 

 

 

 

 

当使用标签引入或将请求转发给其它资源时,可以使用

语法一:

        

语法二:

        

 

 

 

 

 

 

 

 

 

 

 

jsp的实现和原理理解

标签:将不   范围   convert   需要   目录   一个人   run   base   初始化   

原文地址:https://www.cnblogs.com/laoyu-love-life/p/14699587.html


评论


亲,登录后才可以留言!