当前位置:

首页 > 编程开发 > JSP动态网页开发技术概述

JSP动态网页开发技术概述

本文目录

    JSP是基于Servlet规范的动态网页技术,文件扩展名为.jsp。其特点包括预编译、业务代码分离、组件重用和跨平台。运行采用请求/响应模式,首次访问时JSP容器将文件转换为Servlet并编译为字节码,后续请求直接执行缓存,修改后重新编译。

    在动态web项目开发中,经常需要动态生成HTML内容,比如统计当前在线人数这种场景。如果单纯用Servlet去拼HTML,那代码里会塞满out.println,不仅写起来痛苦,维护起来更是一场噩梦。静态内容和动态内容搅在一起,程序会变得异常臃肿。为了解决这些问题,Oracle(Sun)公司推出了JSP技术。

    1. JSP概述

    JSP(Ja va Server Pages)是建立在Servlet规范之上的动态网页开发技术,本质上就是一个简化版的Servlet。在JSP文件中,HTML和Ja va代码可以共存:HTML负责静态内容的展示,Ja va代码负责动态内容的生成。为了和传统HTML区分,JSP文件的扩展名是.jsp。

    基于Ja va的JSP技术,有几个非常鲜明的特点:

    (1)预编译
    第一次访问时,服务器会把JSP文件编译成Servlet,而且只编译一次。编译好的结果会被缓存起来,下次再有人访问,直接执行缓存的字节码就行。这样一来,CPU资源省了,客户端的响应速度也上去了。

    (2)业务代码相分离
    用JSP开发Web应用,可以把界面设计和业务逻辑开发拆开,各司其职,互不干扰。

    (3)组件重用
    JSP可以使用Ja vaBean来封装业务逻辑或作为数据存储模型。一个写好的Ja vaBean,不仅能在当前JSP页面里反复使用,还能在整个项目中复用,甚至拿到其他Ja va应用里继续用。

    (4)跨平台
    JSP基于Ja va,自然继承了Ja va的跨平台能力,无论是在Windows还是Linux上,都能跑得顺顺畅畅。

    JSP 运行原理

    JSP的工作模式是典型的请求/响应模式:客户端发来HTTP请求,JSP程序收到后进行处理,然后返回结果。当一个JSP文件第一次被请求时,JSP引擎(容器)会把它转换成一个Servlet——这个引擎本身也是一个Servlet。

    具体运行过程是这样的:

    (1)客户端发出请求,请求访问某个JSP文件。

    (2)JSP容器先把JSP文件转换成Ja va源文件(也就是Servlet源程序)。如果转换过程中发现语法错误,容器会直接中断,并向服务器和客户端返回错误信息。

    (3)转换成功后,JSP容器会把生成的Ja va源文件编译成对应的字节码文件(.class)。这个.class文件就是一个Servlet,Servlet容器会像处理其他Servlet一样处理它。

    (4)Servlet容器加载这个转换后的Servlet类,创建实例,并执行jspInit()方法。注意,这个方法在整个Servlet生命周期里只会执行一次。

    (5)执行jspService()方法来处理客户端的请求。每个请求进来,JSP容器都会创建一个新的线程来处理——如果多个客户端同时请求同一个JSP文件,容器就会创建多个线程,每个线程对应一个客户端请求。

    (6)如果JSP文件被修改了,服务器会根据配置决定是否重新编译。如果需要重新编译,就用新编译的结果替换掉内存中的旧Servlet,继续处理后续请求。不过要注意,虽然JSP效率很高,但第一次调用时因为要转换和编译,会有一点轻微的延迟。

    (7)如果系统资源不足,JSP容器可能会以某种不确定的方式把Servlet从内存中移除。这时候会先调用jspDestroy()方法,然后Servlet实例就会被当作垃圾回收掉。

    (8)请求处理完成后,响应对象由JSP容器接收,最后把HTML格式的响应信息送回客户端。

    JSP动态网页开发技术概述

    所以,浏览器向服务器发送请求,不管访问的是什么资源,本质上都是在访问一个Servlet。访问JSP页面时,其实也是在访问一个Servlet——服务器会先把JSP翻译成一个Servlet,然后才去执行。举个例子:

    C1.jsp

    <%@ page language="ja va" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    
    
    
    
    Insert title here
    
    
        This is my first JSP 
        <%  out.print("你好啊C1");  %>
    
    

    当我们通过浏览器访问http://localhost:8080/day11_01_jsp(项目名称)/C1.jsp时,服务器首先会把C1.jsp翻译成一个C1_jsp.class。在Tomcat服务器的work\Catalina\localhost\项目名\org\apache\jsp目录下,可以看到C1_jsp.class的源代码。(1.jsp会被翻译成_1_jsp.class)

    JSP动态网页开发技术概述

    C1_jsp.ja va的代码:

    /*
     * Generated by the Jasper component of Apache Tomcat
     * Version: Apache Tomcat/7.0.52
     * Generated at: 2018-10-05 08:32:50 UTC
     * Note: The last modified time of this file was set to
     *  the last modified time of the source file after
     *  generation to assist with modification tracking.
     */
    package org.apache.jsp;
    
    import ja vax.servlet.*;
    import ja vax.servlet.http.*;
    import ja vax.servlet.jsp.*;
    
    public final class C1_jsp extends org.apache.jasper.runtime.HttpJspBase
        implements org.apache.jasper.runtime.JspSourceDependent {
    
        private static final ja vax.servlet.jsp.JspFactory _jspxFactory =
            ja vax.servlet.jsp.JspFactory.getDefaultFactory();
    
        private static ja va.util.Map _jspx_dependants;
    
        private ja vax.el.ExpressionFactory _el_expressionfactory;
        private org.apache.tomcat.InstanceManager _jsp_instancemanager;
    
        public ja va.util.Map getDependants() {
            return _jspx_dependants;
        }
    
        public void _jspInit() {
            _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
            _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
    
        public void _jspDestroy() {
        }
    
        public void _jspService(final ja vax.servlet.http.HttpServletRequest request,
                                final ja vax.servlet.http.HttpServletResponse response)
            throws ja va.io.IOException, ja vax.servlet.ServletException {
    
            final ja vax.servlet.jsp.PageContext pageContext;
            ja vax.servlet.http.HttpSession session = null;
            final ja vax.servlet.ServletContext application;
            final ja vax.servlet.ServletConfig config;
            ja vax.servlet.jsp.JspWriter out = null;
            final ja va.lang.Object page = this;
            ja vax.servlet.jsp.JspWriter _jspx_out = null;
            ja vax.servlet.jsp.PageContext _jspx_page_context = null;
    
            try {
                response.setContentType("text/html; charset=UTF-8");
                pageContext = _jspxFactory.getPageContext(this, request, response,
                        null, true, 8192, true);
                _jspx_page_context = pageContext;
                application = pageContext.getServletContext();
                config = pageContext.getServletConfig();
                session = pageContext.getSession();
                out = pageContext.getOut();
                _jspx_out = out;
    
                out.write("\r\n");
                out.write("\r\n");
                out.write("\r\n");
                out.write("\r\n");
                out.write("\r\n");
                out.write("Insert title here\r\n");
                out.write("\r\n");
                out.write("\r\n");
                out.write("\tThis is my first JSP \r\n");
                out.write("\t");
                out.print("你好啊C1");
                out.write("\r\n");
                out.write("\r\n");
                out.write("");
            } catch (ja va.lang.Throwable t) {
                if (!(t instanceof ja vax.servlet.jsp.SkipPageException)){
                    out = _jspx_out;
                    if (out != null && out.getBufferSize() != 0)
                        try { out.clearBuffer(); } catch (ja va.io.IOException e) {}
                    if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
                    else throw new ServletException(t);
                }
            } finally {
                _jspxFactory.releasePageContext(_jspx_page_context);
            }
        }
    }

    可以看到,C1_jsp这个类继承自org.apache.jasper.runtime.HttpJspBase。通过查看Tomcat的源码,在apache-tomcat-6.0.20-src\ja va\org\apache\jasper\runtime目录下能找到HttpJspBase这个类的源码文件,如下图所示:

    JSP动态网页开发技术概述

    HttpJspBase类的源码:

    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more
     * contributor license agreements.  See the NOTICE file distributed with
     * this work for additional information regarding copyright ownership.
     * The ASF licenses this file to You under the Apache License, Version 2.0
     * (the "License"); you may not use this file except in compliance with
     * the License.  You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package org.apache.jasper.runtime;
    
    import ja va.io.IOException;
    
    import ja vax.servlet.ServletConfig;
    import ja vax.servlet.ServletException;
    import ja vax.servlet.http.HttpServlet;
    import ja vax.servlet.http.HttpServletRequest;
    import ja vax.servlet.http.HttpServletResponse;
    import ja vax.servlet.jsp.HttpJspPage;
    
    import org.apache.jasper.compiler.Localizer;
    
    /**
     * This is the super class of all JSP-generated servlets.
     *
     * @author Anil K. Vijendran
     */
    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");
        }
    
        @Override
        public final void destroy() {
            jspDestroy();
            _jspDestroy();
        }
    
        /**
         * Entry point into service.
         */
        @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 request,
                                         HttpServletResponse response)
            throws ServletException, IOException;
    }

    HttpJspBase继承自HttpServlet,所以它本身就是一个Servlet。而C1_jsp又继承自HttpJspBase,因此C1_jsp也是一个Servlet。浏览器访问C1.jsp时,实际上就是在访问C1_jsp这个Servlet,由它的_jspService方法来处理请求。

    2. JSP的基本语法

    2.1 JSP模板元素

    就是网页的静态内容,比如HTML标签和纯文本。

    2.2 JSP脚本元素

    (1)JSP Scriptlets(脚本片断)
    用于在JSP页面中编写多行Ja va代码。语法:

    <% ja va代码(变量、方法、表达式等) %>
    <%
        int sum=0;
        //声明变量
        /*编写语句*/
        for (int i=1;i<=100;i++){
            sum+=i;
        }
        out.println("

    Sum="+sum+"

    "); %>

    JSP动态网页开发技术概述

    JSP脚本片断中只能出现Ja va代码,不能出现其他模板元素。JSP引擎在翻译时,会把脚本片断中的Ja va代码原封不动地放到Servlet的_jspService方法里。这些代码必须严格遵循Ja va语法,比如每句后面都要有分号(;)。一个JSP页面里可以有多个脚本片断,它们之间可以嵌入文本、HTML标记和其他JSP元素。多个脚本片断中的代码可以相互访问,就像所有代码都放在一对<%%>里一样。比如:

    <% for (int i=1; i<5; i++)  { %>
        

    http://localhost:8080/Ja vaWeb_Jsp_Study_20140603/

    <% } %>

    单个脚本片断中的Ja va语句可以是不完整的,但多个脚本片断组合后的结果必须是完整的Ja va语句。

    (2)JSP声明
    JSP页面中编写的所有代码,默认会被翻译到Servlet的service方法里。而JSP声明中的Ja va代码则会被翻译到_jspService方法外面。语法:

    <%! ja va代码:定义变量或者方法 %>

    多个静态代码块、变量和方法可以定义在一个JSP文件中,也可以分别单独定义在多个JSP声明中。

    需要注意的是,JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象。

    JSP声明案例:

    <%!
        static {
            System.out.println("loading Servlet!");
        }
        private int globalVar = 0;
        public void jspInit(){
            System.out.println("initializing jsp!");
        }
    %>
    <%!
        public void jspDestroy(){
            System.out.println("destroying jsp!");
        }
    %>

    (3)JSP 表达式
    JSP脚本表达式(expression)用于把程序数据输出到客户端。将要输出的变量或表达式直接封装在<%= %>标记中,语法:

    <%=expression%>

    举例:输出当前系统时间

    <%= new ja va.util.Date() %>

    JSP引擎在翻译脚本表达式时,会把程序数据转成字符串,然后在相应位置用out.print(...)输出给客户端。注意,表达式的变量或表达式后面不能有分号(;)。

    JSP动态网页开发技术概述JSP动态网页开发技术概述

    3. JSP注释

    (1)显式注释
    直接使用HTML风格的注释:。特点是不安全、费流量——HTML注释在浏览器中查看源文件时是可见的。

    (2)隐式注释
    包括Ja va的注释://、/*……*/,以及JSP自己的注释:<%-- 注释内容 --%>。特点是安全、省流量——Ja va注释和JSP注释在浏览器中查看源文件时都看不到。

    
    <%
        //JA VA中的单行注释
        /*
            JA VA中的多行注释
        */
    %>
    <%--JSP自己的注释--%>
    本文内容来源于网友投稿,如有侵权请联系删除。
    作者最新文章
    编程开发
    相关文章 更多
    解决PHP递归报错:max_nesting_level限制与内存溢出处理
    解决PHP递归报错:max_nesting_level限制与内存溢出处理

    遇到PHP递归报错时,不要盲目调大max_nesting_level。本文教你区分Xdebug限制、内存耗尽和正则递归错误,提供代码级的终止条件优化与迭代替代方案,彻底解决栈溢出问题。

    PHP递归中static变量与引用传递的常见陷阱及调试
    PHP递归中static变量与引用传递的常见陷阱及调试

    本文分析PHP递归中static变量导致的状态污染及引用传递引发的共享数据修改问题。提供具体的代码复现、缓存键设计建议及调试打印技巧,帮助开发者避免隐蔽的逻辑错误。

    PHP递归性能优化技巧与迭代替代方案
    PHP递归性能优化技巧与迭代替代方案

    解析PHP递归函数在树形数据处理中的性能瓶颈,提供预加载数据消除I/O、使用显式栈替代深层递归的实战方案,帮助开发者在代码可读性与执行效率间做出合理取舍。

    Java测试中怎么使用Mockito模拟依赖对象
    Java测试中怎么使用Mockito模拟依赖对象

    详细讲解在Java单元测试中如何使用Mockito模拟依赖对象,包括引入依赖、创建Mock、打桩返回值、行为验证以及Mock与Spy的核心差异和常见陷阱排查。

    链表删除节点的时间复杂度是多少及其详细分析
    链表删除节点的时间复杂度是多少及其详细分析

    详细分析链表删除节点的时间复杂度,深入探讨单链表与双向链表在不同已知前提下的查找与删除开销,并结合完整代码与清晰图解进行对比总结。

    codex如何配置模型参数及文件设置教程
    codex如何配置模型参数及文件设置教程

    想知道如何让AI写出的代码更贴合你的习惯?本文手把手教你在VS Code中调整Codex相关模型参数,通过修改配置文件优化温度值和令牌限制,解决代码建议不准确或响应慢的问题。

    Claude Code AI编程工具实力揭秘与编程助手实测
    Claude Code AI编程工具实力揭秘与编程助手实测

    通过实测展示Claude Code在终端中如何理解自然语言指令、自动修改代码文件并处理复杂编程任务,帮助开发者评估其实际辅助能力。

    winforms教程自学入门与基础开发步骤详解
    winforms教程自学入门与基础开发步骤详解

    本教程详细讲解如何使用Visual Studio创建WinForms项目,通过添加按钮和标签控件并编写点击事件代码,实现一个基础的计数器功能,适合C#初学者快速上手Windows窗体应用开发。

    Cursor自动补全设置教程教你快速开启代码补全功能
    Cursor自动补全设置教程教你快速开启代码补全功能

    详解Cursor编辑器中自动补全功能的开启与优化设置,涵盖Tab触发机制、上下文窗口调整及模型切换,帮助开发者解决补全延迟、干扰大等问题,提升编码流畅度。

    pandas的数据格式怎么转换和设置方法教程
    pandas的数据格式怎么转换和设置方法教程

    详解Pandas中数据格式转换的核心方法,包括astype强制转换、to_numeric容错处理及日期解析技巧,解决常见类型错误并提升数据处理效率。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    macOS软件
    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    Mac软件 更多
    photoshop
    photoshop
    Windows、macOS 、 iPad

    Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

    灵活计算器
    灵活计算器
    macOS/iOS/Android

    灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

    WINDOWS 更多
    3dmax(3ds max)
    3dmax(3ds max)
    Windows

    Autodesk 3ds Max 是一款专业的三维建模、动画与渲染软件,广泛应用于建筑可视化、游戏开发、影视动画、广告设计和产品展示等领域。

    photoshop
    photoshop
    Windows、macOS 、 iPad

    Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。