JSP

发布时间 2023-09-15 20:16:26作者: yanggdgg

一、JSP

1. 简介

JSP(全称Java Server Pages)是由 Sun Microsystems 公司倡导和许多公司参与共同创建的一种使软件开发者可以响应客户端请求,而动态生成 HTML、XML 或其他格式文档的Web网页的技术标准。

JSP 技术是以 Java 语言作为脚本语言的,JSP 网页为整个服务器端的 Java 库单元提供了一个接口来服务于HTTP的应用程序。

JSP文件后缀名为 *.jsp 。

JSP开发的WEB应用可以跨平台使用,既可以运行在 Linux 上也能运行在 Windows 上。

2. 执行原理

jsp是一种后端技术,它的原理是:

  第一次发送请求访问jsp资源时,Tomcat服务器中的JSP加载引擎会将该jsp资源转换成 .java文件。这个java文件其实就是一个Servlet,其中html的代码通过响应流writer.print()的方式响应回浏览器。

3. 执行过程

JSP的执行过程大致可以分为三个时期:转换、编译、执行。

 转换/翻译(trranslation)

  Tomcat中的JSP引擎将JSP网页转换成一个 .java文件,即一个servlet

编译(compile)

  通过javac命令将转换得到的 .java文件编译成 .class文件

运行

  运行 .class字节码文件,处理请求。

具体流程:

  ①浏览器发起请求访问jsp

  ②Tomcat服务器收到请求,调用对应的Servlet处理请求,调用的是JSPServlet

  ③JspServlet将请求的jsp文件 翻译成 .java文件并完成编译得到字节码文件

  ④将编译后的class文件加载到内存并执行,即运行了一个servlet

  ⑤servlet执行service()方法将结果响应回浏览器。

注意:当JSP页面在执行时,JSP 引擎会做检查工作,

  如果没有更新,就直接执行之前转换好的Servlet;

  如果发现JSP页面中有更新修改时,JSP引擎会再次转换JSP为Servlet。

4. JSP性能问题

  有人认为JSP的执行性能和Servlet相差很多。其实执行性能上的差别只在第一次的执行上。因为在第一次执行jsp时,jsp要经过转换、编译、执行三个过程。而之后再次访问jsp页面时,就直接执行第一次所产生的Servlet即可,不需要每次都转换、编译。

  JSP和HTML相比的话肯定是要慢些的,他们的机制就不一样,JSP本质上是Servlet,在请求jsp时,要经过执行,其内部是通过大量的IO流形式将内容发送给页面的,IO流就是一种比较耗费资源的操作。而HTML本身资源是已经存在的,不需要服务器执行什么操作。

但JSP是动态资源,可以动态的展示数据。这点是HTML比不了的!

5. JSP加载引擎

在Tomcat的 conf/web.xml文件中配置了JSP的加载引擎 JspServlet

<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>
    <url-pattern>*.jspx</url-pattern>
</servlet-mapping>

可以发现所有 xxx.jsp的请求都会调用jsp加载引擎JspServlet。

JspServlet作用:

  转换JSP页面

    将Jsp页面转换成一个Servlet

  编译Jsp对应的java文件

    JSP引擎调用Java编译器对这个Servlet进行编译,得到.class文件

  请求处理

    JSP引擎调用java虚拟机来执行class文件,即执行servlet,将结果响应回浏览器

6. JSP继承结构

  JSP文件转换成JAVA代码之后,它默认继承了HttpJspBase,实现了JspSourceDependent,和JspSourceImports两个接口,

其中HttpJspBase又继承了HttpServlet ,也就是说,JSP本质上就是一个Servlet。

  • HttpJSPBase重写了init,service和destory方法。

  • 并且自定义了 jspInit, jspService, jspDestory。

  • 然后在重写的init方法中调用了 JSPInit,在重写的service方法中调用了 jspService,在重写的destory方法中调用了 jspDestory。

  • 我们JSP的文件编译成JAVA代码后,继承HttpJspBase重写的方法是 jspInit, jspService, jspService。

public abstract class HttpJSPBase extends HttpServlet implements HttpJSPPage {
    private static final long serialVersionUID = 1L;
    protected HttpJSPBase() {
    }
    @Override
    public final void init(ServletConfig config)
            throws ServletException {
        super.init(config);
        JSPInit();
        _JSPInit();
    }
    @Override
    public String getServletInfo() {
        return Localizer.getMessage("JSP.engine.info", Constants.SPEC_VERSION);
    }
    @Override
    public final void destroy() {
        JSPDestroy();
        _JSPDestroy();
    }
    @Override
    public final void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        _JSPService(request, response);
    }
    @Override
    public void JSPInit() {
    }
    public void _JSPInit() {
    }
    @Override
    public void JSPDestroy() {
    }
    protected void _JSPDestroy() {
    }
    @Override
    public abstract void _JSPService(HttpServletRequest req,HttpServletResponse resp)
            throws ServletException, IOException;
}
HttpJSPBase源码

二、JSP的使用

1. 在JSP中写Java代码

在jsp中可以通过 <%%> 、 <%!%>和<%= %> 三种方式来书写代码

这两种方式中写的Java代码在转换后生成的代码在Servlet中位置是不一样的,

 <%%> 在_jspService方法中(局部变量);

<%!%>在Servlet中作为类的成员。JSP本质上是Servlet,在Servlet中我们是不推荐定义一些成员变量的。

<%= %>也是在_jspService方法中,但会直接将其中的内容响应给浏览器

2. 注释

JSP中可以写HTML、Java、CSS、JS代码,那么也就可以写这些语言的注释,并且JSP也有自己的注释方式。

JSP的注释格式是:<%--注释内容--%>

注释类型进入转译文件响应给浏览器
JSP注释 no no
JAVA注释 yes no
HTML,css,js注释 yes yes

所以在jsp中的注释推荐使用JSP的注释格式

三、JSP常用指令标签

1. 指令标签简介

指令标签是JSP页面上的一种特殊标签,JSP指令可以用来设置整个JSP页面相关的属性,如网页的编码方式、网页使用的脚本语言、导包等。

指令标签的语法:

<%@ directive attribute="value" %>
指令描述
<%@ page %> 定义网页依赖属性,如脚本语言、error页面、缓存需求等等
<%@ include %> 包含其他文件
<%@ taglib %> 引入标签库的定义

2. page指令标签

属性描述
buffer 指定out对象使用缓冲区的大小
autoFlush 控制out对象的 缓存区
contentType 指定当前JSP页面的MIME类型和字符编码
errorPage 指定当JSP页面发生异常时需要转向的错误处理页面
isErrorPage 指定当前页面是否可以作为另一个JSP页面的错误处理页
extends 指定servlet从哪一个类继承
import 导入要使用的Java类
info 定义JSP页面的描述信息
isThreadSafe 指定对JSP页面的访问是否为线程安全
language 定义JSP页面所用的脚本语言,默认是Java
session 指定JSP页面是否使用session,默认是使用
isELIgnored 指定是否执行EL表达式
isScriptingEnabled 确定脚本元素能否被使用

errorPage配置错误页面

<error-page>
    <error-code>500</error-code>
    <location>/error500.jsp</location>
</error-page>
<error-page>
    <error-code>404</error-code>
    <location>/error404.jsp</location>
</error-page>

出现错误后,服务器会根据对应的响应码来匹配对应的错误页面

3. include指令标签

  • JSP可以通过include指令来包含其他文件。被包含的文件可以是jsp文件、HTML文件或文本文件。

  • 包含的文件就像是jsp文件的一部分,会被同时编译执行。

  • 除了使用include指令标签可以实现引入外,使用jsp:include动作也可以实现引入。

    <%--
        静态引入,被引入的jsp页面不会单独生成java代码文件,当前页和被引入页会生成一个java文件
    --%>
    <%@ include file="hello2.jsp"%>

    <%--
        动态引入:被引入的页面会生成独立的java代码,在当前页生成的java代码中使用
        org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "hello3.jsp", out, false);
        引入其他页面
    --%>
    <jsp:include page="hello3.jsp"></jsp:include>

4. taglib指令标签

taglib就是标签库的意思,我们可以在jsp页面中引入其他的标签库,帮我们去快速简单的做一些事情。

语法

<%@ taglib uri="uri" prefix="prefixOfTag" %>

四、JSP内置对象

1. 内置对象简介

因为JSP的本质是Servlet,在JSP文件经过转译之后,生成JAVA代码,在运行时,JSP给我们准备好了九个可以直接使用而不用我们自己去new的对象,这九个对象我们称之为内置对象。

内置对象完全由JSP自行去维护, 我们直接使用即可。

内置对象类型描述
config javax.servlet.ServletConfig 由于JSP本身也是一个Servlet,所以容器也会给我们准备一个ServletConfig。
page javax.servlet.jsp.JspPage 就是JSP转换的Servlet的对象,也就是当前JSP对象本身 。
exception javax.servlet.jsp.JspException 异常对象,在错误提示页上使用,当isErrorpage=true 才具有该对象。
request javax.servlet.http.HttpServletRequest reqeust域。一次请求有效。
response javax.servlet.http.HttpServletResponse 响应对象。
session javax.servlet.http.HttpSession session域。一次会话中多次请求有效。
application javax.servlet.ServletContext application域。整个项目运行期间 多次请求、多次会话都有效。
out javax.servlet.JspWriter 打印流对象。
pageContext javax.servlet.jsp.PageContext page 域。当前页面内可用。

注意事项:

response对象

  当服务器创建request对象时会同时创建用于响应客户端的response对象。

out对象

  是 JspWriter 类的实例,不是PrinterWriter的实例;用来在response对象中写入内容。JspWriter类包含了大部分java.io.PrintWriter类中的方法。不过,JspWriter增了一些专为处理缓存而设计的方法。另外JspWriter类会抛出IOExceptions异常。 最初的JspWriter类对象根据页面是否有缓存来进行不同的实例化操作。可以在page指令中使用。buffered='false'属性来轻松关闭缓存。

pageContext对象

   PageContext类的实例,用来代表整个JSP页面;提供对JSP页面所有对象以及命名空间的访问。

2. Servlet与JSP的联系与区别

联系:

  1. JSP和Servlet都是Sun公司推出的动态网页技术。

  2. 基于Servlet开发页面的繁琐性,推出JSP来简化页面开发。

  3. JSP本质上是一个Servlet,会翻译成一个Servlet。

区别

  1. JSP使人们把显示和逻辑分隔成为可能,这意味着两者的开发可并行进行;而Servlet并没有把两者分开。

  2. JSP是在HTML代码里写JAVA代码,框架是HTML;而Servlet是在JAVA代码中写HTML代码,本身是个JAVA类。

  3. Servlet需要在web.xml中配置,而JSP无需配置。

  4. 目前JSP主要用在视图层负责显示,而Servlet主要用在控制层负责调度