• (八)JSP 技术知识点总结(来自那些年的笔记)



    目录


    可能是JSP知识总结的最全的博客之一了,你想要寻找的知识,这里都有 ;

    作者:淮左白衣
    
    来源:笔者当时学web的笔记
    
    时间:-2018年5月4日21:25:09
    

    什么是 jsp

    JSP全称是 java servlet pages,它和 servlet 技术一样,都是Sun公司定义的一种用于开发动态web页面的技术

    • 为什么jsp也是一种动态web资源的开发技术呢?

      jsp,虽然就像是在写HTML,但是jsp允许在页面中编写java代码,并且允许开发人员在页面中获取requestresponseweb开发常用对象,实现与浏览器的交互,所以jsp也是一种动态web资源的开发技术;

      例子:输出当前时间

    Date date = new Date();
    //这个out对象是可以直接使用的,它是JspWriter的实例
    out.write(date.toLocaleString());

    Jsp 调用和运行原理(简略版)

    浏览器访问 jsp 页面时,Web 服务器是如何调用并执行一个jsp页面的?

    首先知道,我们访问服务器的资源时,无论访问的是什么?比如访问的是HTML、jsp,其实我们访问的都是一个servlet,而不是真正的jsp、html ,因此,我们访问 jsp 其实就是去访问 servlet

    Jsp在被访问的时候,服务器会将它 翻译为 servlet,转换后的servlet,被保存在服务器目录下的work/项目名/apache/…

    提问:

    • web 服务器在执行jsp页面时,是如何把jsp页面中的HTML排版标签输出给浏览器的?

      这里其实是 jsp 对应的 servlet 的功劳,我们知道服务器会将jsp转为一个servlet 对象,我们去访问jsp的时候,实际访问到的也是这个servlet对象;

      在这个servlet对象对应的类中。它是通过out.writer()语句将 jsp 中的 HTML 语句,原封不动的打给浏览器;遇到<%java代码%>,就直接执行;

    • jsp页面中的java代码,服务器是如何执行的?

      是原封不动的,代码最后都在在servlet类中执行了;

    • Web服务器在调用jsp时,会给jsp提供一些什么java对象

      会提供许多对象;request、response、out、application、session等这些对象,在jsp中是直接可以使用的,因为在jsp对应的servlet类中已经提供好了
      如果想要获得jsp对应的servlet类的对象的自身,使用page,也是它内置提供的;

    上面的几个问题,其实都可以翻看对应的 servlet 类的源码,,找到答案;


    Jsp语法

    • Jsp模板元素

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

      Jsp的模板元素定义了网页的基本骨架,即定义了页面的结构和外观;

    下面的几个概念,分清楚了,别混淆;

    • Jsp脚本表达式

      语法:<%= xxxx %>

      jsp脚本表达用于将程序数据输出到客户端,只能写在一行

      Jsp引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应的位置用out.print(...),将数据输出给客户端

      Jsp脚本表达式的变量或者表达式后面不能有分号 ,其实原因很简单,脚本表达式是要被放到 out.print(...) 里面的,在结尾加上一个 ; 会被输出,而我们并不想输出这个分号;

    • Jsp脚本片段

      jsp脚本片段用于在jsp页面中编写 多行 java代码;

      语法:

        <%
                多行java代码
        %>

    注意jsp脚本片段中只能出现java代码,不能出现其他模板元素因为,jsp引擎在翻译jsp页面时,会将jsp脚本片段中的 java代码原封不动的放到 servlet_jspService 方法中。

    jsp脚本片段中的java代码,必须严格遵守java语法!废话,最后被转到servlet中,java代码原封不动的;

    在一个jsp页面中可以有多个脚本片段,在脚本片段之间是可以写上模板元素的;并且多个脚本片段之间的数据是共享的;(了解下底层原理,就知道为啥共享了

    单个脚本片段中的java代码可以是不完整的,但是多个脚本片段中,java代码必须完整了 ;

    • Jsp声明

      在jsp中,脚本片段中java代码,都被翻译到servlet的jspService方法中了;

      那么假如,我们想要将java代码,写到jspService方法外面的话,就需要使用jsp声明了;

    <%!
        java代码
    %>

    我们就可以为servlet类添加方法字段等属性了,但是一般没啥人使用这个技术;

    • Jsp注释

      格式:

    <%--
        注释信息
    --%>

    JSP引擎在将 jsp 页面翻译成 servlet 程序时,会 忽略jsp页面中被注释的内容 ;注意是被jsp引擎翻译时,就抛弃了,也就是在servlet类中将没有这个注释的内容;但是你要是使用HTML的注释,就不行了;

    • Jsp指令

      jsp指令 是为 jsp引擎 而设计的。它们并不直接产生任何可见输出而只是告诉引擎如何处理jsp页面中的其余部分
      jsp2.0规范中共定义3个指令:

      今天2018年4月23日,jsp规范,早就不是2.0点了。需要注意下,但是不影响你学习JSP
      

      page指令
      Include指令
      taglib指令


    Jsp指令简介

    • jsp指令的基本语法格式:
    <%@ 指令 属性名=“值” %>

    举例:

    <%@ page contentType="text/html; ISO-8859-1" %>

    如果一个指令有多个属性,这多个属性可以写在一个指令中,用 空格 分隔多个属性,也可以分开写 ;

    下面讲解3大指令;


    Page指令

    page指令用于定义jsp页面的各种属性,无论page指令出现在jsp页面中的什么地方,它作用的都是整个jsp页面;

    为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个jsp页面的初始位置。

    Jsp2.0规范中定义的 page指令 的完整语法:

    属性名 = “ 作 用
    pageEncoding = "xxx" 指明翻译 jsp 的时候,使用 xxx 码表
    contentType = "text/html;charset=UTF-8" 指明jsp翻译成的 servlet 文件,里面的 response 使用的码表
    language = "java" 指明 jsp 页面中的语言是 java
    extends = "xxx.class" 表名生成jsp翻译的servlet类继承自xxx,不过一般,继承自默认类,即可。不需要改动
    import = "xxx" 表示,我们的java语句,需要导入的包,一般自动导包就好了,不用我们手动去指定这个属性
    session = "false / true " false 表示,翻译过去的servlet中不要自动创建session 对象,目的是为了,在不需要 session 的情况下,避免生成 session,减轻服务器的压力。或者我们需要session对象,但是,我们想手动让服务器创建session对象的
    buffer = "8kb / none / xx kb" out.print()的数据,不是直接写到浏览器中(效率太慢),还是先写到缓冲区中,再写到浏览器,buffer指定缓冲区的大小,默认是8kb
    autoFlush = "false / true" 是否自动刷新缓冲区,默认为true
    isThreadSafe = "true" 翻译过去的servlet是否是线程安全的,这个最TM奇怪了,默认为true。但是表示默认线程不安全
    isErrorPage = "true" 表示该jsp是页面 错误处理 页面,属性值置为true时,jsp 翻译为 servlet时,会传进去一个异常对象,表示错误的异常;

    作用 当服务器出错了,跳到错误页面(404页面),然后返回给浏览器,但这404是个正确的页面,服务器就会返回200状态码,我们 为了告知浏览器我们出错了,就在页面中加上这个属性值,服务器将返回500
    isELIgnored = "true" 是否忽略 EL表达式
    errorPage = "url" 用来指定当前页面出错时,跳转的界面。属性值必须使用相对路径,以 / 开头则相对当前 web 应用;没有 / 打头,则相对于当前页面;

    当然,我们也可以在服务器的 web.xml 文件 使用<error-page>元素为整个web应用指定错误处理页面,其中的两个子标签,一个用于指明异常的类型(写全名),这个子标签还可以写成状态码,一个用于指明出现该异常。跳准的界面地址;

    如果我们在 jsp 中写明了 errorPage 属性,那么web.xml文件中的错误处理配置,对此jsp不生效

    Include指令

    include 指令用于引入 jsp 页面,如果使用 include 引入其他 jsp 页面,那么 jsp 引擎将把这两个jsp翻译为一个servlet,所以,include指令引入通常也称为 静态导入

    属性名 = “ 作 用
    file = "url" 其中的file属性用于指定被引入文件的路径。路径以“/”开头,来表示当前web应用;

    细节

    • 被引入的文件必须遵循jsp语法
    • 被引入的文件可以使用任意的扩展名,即使是HTML扩展名,jsp引擎还是会按照处理jsp页面的方式处理页面的内容;为了,见名思意,jsp规范建议使用 .jspf 作为静态导入文件的扩展名;
    • 由于使用.jspf指令会涉及到两个jsp页面,并会把2个jsp翻译为一个servlet,所有这两个jsp页面的指令不能冲突
    • 被导入的页面,不要包含HTML语句了,否则页面将不是一个完成的页面,会出现两个 <head> 这样的标签;

    动态包含

    语法: request.getRequestDispatcher("url").include(request,response);

    这是在运行时包含,会将 每一个 jsp 都对应生成一个servlet也就是最终生成不止一个 servlet

    我们一般选择静态导入,性能高 ;


    taglib指令

    在讲标签库的时候,再讲;


    Jsp乱码问题

    乱码产生的根由无外乎两种

    • jsp文件 保存的编码和服务器翻译 servlet 的时候的编码不一致
    • 浏览器的编码和翻译的servletresponse 的编码编码不一致;

    解决方法<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8" %>

    我们发现只要这两个地方使用相同的编码,乱码就不会产生;

    pageEncoding=”xxx” 告诉服务器翻译时使用什么码表;

    contentType="text/html;charset=UTF-8" 再告诉浏览器用什么码表打开 ;

    其实可以不告诉浏览器用什么码表,因为 只要告诉服务器翻译的码表,服务器会自动将servlet的response的码表设为一致的;但是,我们还是写上吧


    jsp运行原理(详细版)

    每个jsp页面在 第一次 被访问时,web容器 都会把请求交给 jsp引擎(即一个java程序)去处理。Jsp引擎 先将 jsp 翻译成一个_jspServlet(实际上就是一个servlet),然后按照 servlet 的调用方式进行调用 ;

    由于JSP第一次访问时,会被翻译成servlet,所有第一次访问通常会比较慢但是第二次访问,JSP引擎 如果发现 JSP 没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响


    JSP中的九大隐式对象

    JSP引擎 在调用 JSP 对应的 _JspServlet 时,会 传递或创建 9个与WEB开发相关的对象供_JspServlet使用

    JSP技术的设计者为了方便web开发人员在编写JSP页面时,获得这些对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这9个变量就可以快速的获得这9大对象的引用

    这九大隐式对象就是:responserequestsessionapplication(ServletContext)page (jsp对象自身)、config(servlertConfig)exceptionout(JspWriter)PageContext

    前面7个,在学JSP之前,都已经学过了,这里重点讲最后两个;

    • Out隐式对象

      作用Out隐式对象 用于向客户端发送文本数据;

      Out对象 是通过调用 PageContext 对象的 getOut() 方法返回的,其作用和用法与servletResponse.getWriter方法返回的 PrintWriter 对象非常相似。

      JSP页面中的out隐式对象的类型为JspWriterJspWriter相当于一种带缓存功能PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存(buffer属性的值为none);

      只有向out对象中写入了内容,且 满足如下任何一个条件时(相当于刷新缓冲区)out对象才会去调用servletResponse.getWriter方法,并且通过该方法返回PrinterWriter对象将out对象缓冲区中的内容 真正的写入 servlet引擎提供的缓冲区中(response缓冲区):

      条件
      √ 设置page指令的buffer属性关闭了out对象的缓存功能
      out对象的缓冲区已满 ;
      √ 整个JSP页面结束;

      备注
      Out对象输出的数据 可能滞后于 response.getWriter 对象输出的数据,原因就在于out对象自己的缓冲区;out对象的缓存区满了,才将数据刷新到response的缓冲区;服务器发现response缓冲区有数据,才会将数据发送到客户端


    PageContext对象

    jsp技术中最重要的一个对象,它代表jsp页面的运行环境

    生命周期是一个jsp页面;

    这个对象自身就封装可其他8大隐式对象的引用;(这个最厉害了)

    它自身还是一个域对象,可以用来保存数据;

    这个对象中,还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其他资源、检索其他域对象中的属性;


    通过PageContext对象获得其他对象

    通过 getXXX()方法;

    PageContext对象中包含其他8大隐式对象的引用;

    首先知道一个事实:JSP页面中是不应该出现java代码,良好的jsp中,是不应该出现一行java代码的;

    但是有些时候,我们为了获取servlet传过来的数据,不得已要使用java代码,这时候,我们就需要一个技术:自定义标签;(以后会讲这个技术)

    我们把java代码替换成一个自定义标签,这个标签对应着一个java类,我们需要把web中的这些对象传给java类,一个一个传,很麻烦的,因此,我们就直接传一个pageContext对象过去;


    Javaweb的四个域

    范围(从小到大
    Page域: pageContext,最小的域,只能在页面中使用
    Request域: 请求域
    Session域: 会话级别的域
    ServletContext域: 最大的域,在整个应用程序中可用

    PageContext域的方法

    获取数据

    pageContext.getAttribute(String) ;

    设置数据

    pageContext.setAttribute(String,String);

    移除数据

    pageContext.removeAttribute(String);

    PageContext跨域访问的方法

    获取id对应的域的数据

    pageContext.getAttribute(String,id) ;

    设置id对应的域数据

    pageContext.setAttribute(String,String,id);

    移除id对应的域数据

    pageContext.removeAttribute(String,id);

    PageContext查找属性的方法

    pageContext.findAttribute(String)

    用于查找某个属性的属性值,它会依次从pagerequestsessionapplication四个域,从小到大的查找,在某个域中查到数据,即刻返回这个数据,不会再继续查下去。如果四个域都没查到,则返回null

    这个方法,便利于我们可以在jsp中直接使用这个方法来查找数据,而不要去关注数据在哪一个域中;


    引入和跳转到其他资源

    PageContext类中定义了一个forward方法和两个include方法来分别简化和替代RequestDispatcher(...).forward方法和RequestDispatcher(...).include方法。

    原始的操作

    // forward
    request.getRequestDispatcher("/xxx").forward(request, response);
    // include
    request.getRequestDispatcher("/xxx").include(request, response);

    使用pageContext简化:

    // forward
    pageContext.forward("/xxx");
    // include
    pageContext.include("/xxxx");

    方法接受的资源如果以 / 开头,/ 代表当前web应用;


    JSP标签

    JSP Action (JSP动作)它用于jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护

    常用的三种标签:

    
    // 动态包含
    <jsp:include page=""> </jsp:include>  
    
     //跳转页面
    <jsp:forward page="">    
    
    // 负责带数据到另一个JSP页面中,value的值,可以是脚本表达式
    // 一般和包含include便签一起使用
     <jsp:param name="" value=""></jsp:param>
    
    // 将数据带到xxx.jsp 中
    <jsp:include page="xxxx.jsp">  
        <jsp:param name="xxx" value="xxx"/>  
    </jsp:include> 
    

    其中 </jsp:forward> Jsp跳转 应用场景:

    在配置欢迎首页的时候,是不让配置servlet的,只能配置成jsp 因此,在jsp中进行跳转页面;


    映射JSP

    <servlet>
        <servlet-name>myform</servlet-name>
        <!--Jsp的路径需要 / 来指认 -->
        <jsp-file>/form.jsp</jsp-file>
    </servlet>
    <servlet-mapping>
        <servlet-name>myform</servlet-name>
        <url-pattern>/myform.html</url-pattern>
    </servlet-mapping>

    JSP抽风时好时坏的原因

    如果访问JSP的时候,出现服务器报错,紧接着再次访问,服务器又不报错的情况,像神经病一样一时好一时坏;

    出现这样的问题的原因在于:JSP文件被我们写错了;并其写错之前,这个JSP曾经被我们正确写对过,并且在服务器中有翻译过的servlet,这样,当我们把JSP修改出错以后,再次访问,服务器发现JSP被修改过,就会重新翻译一次,生成新的servlet,覆盖之前的servlet。但是由于,JSP语法有错,无法被正确的翻译为servlet这样旧的servlet就不会被覆盖掉。还存在在服务器中

    这样,当我们第一次访问的时候,服务器翻译JSP失败,就会爆错,但是我们紧接着,再次访问,服务器发现,这人怎么回事啊,我刚翻译完这个servlet啊,它就不会再次翻译servlet,而是把之前旧的servlet当成上一次翻译的servlet这个过程,跟JSP变没变,没有任何关系,应该是JSP设计者,为了减轻服务器的压力设计的),给我们;这就是我们第一次报错,紧接着再次访问,就正确的原因;

    当我们,过一会再次访问,服务器就会发现,我曹这个JSP,我并没有翻译啊,就会再次翻译,然后,就会再次报错,周而复始,给我们的感觉就是JSP在抽风,时好时坏;


    仿佛一下子回到了90年代的夏天,你光着上身,穿着大裤衩,一双简单的人字拖,摇着一把破旧的芭蕉扇,VCD里转动着盗版的碟片,满满都是广东香港泛滥到内地的流行歌曲和港片,手里的冰激凌在融化,碟片偶尔会卡,你拿起遥控摁了一下快进键,一下子就这么快进了十几年。
    写的真好!

    《over》


  • 相关阅读:
    ubuntu中apt-get安装与默认路径
    css计数器
    jq实现多级菜单
    video文件格式说明(笔记)
    css文字闪烁效果
    video设置视频的播放位置(本例中实现效果是视频第一次播放完成后,接下来中从视频的中间部位开始循环播放)
    css3鼠标经过出现转圈菜单(仿)
    jq弹框 (1)内容自适应宽度 2(内容框显示,几秒后自动消失)
    jq实现 元素显示后 点击页面的任何位置除元素本身外 隐藏元素
    nginx https配置记录
  • 原文地址:https://www.cnblogs.com/young-youth/p/11665719.html
Copyright © 2020-2023  润新知