[Java Web]JSP基础部分 | JSP:一项较老但仍具学习意义的技术
创始人
2025-05-31 10:14:24
0

⭐作者介绍:大二本科网络工程专业在读,持续学习Java,努力输出优质文章
⭐作者主页:@逐梦苍穹
⭐所属专栏:Java Web

目录

  • 1、JSP概述
    • 1.1、简单介绍
    • 1.2、优点
    • 1.3、缺点
    • 1.4、逐渐淘汰
    • 1.5、学习的意义
  • 2、JSP的简单样例
    • 2.1、注意事项
  • 3、一个常见bug
  • 4、JSP原理
  • 5、JSP脚本
  • 6、实践样例
    • 6.1、注意事项

1、JSP概述

1.1、简单介绍

  JSP(JavaServer Pages)是Java Web技术体系中的一种动态网页开发技术,它允许开发人员在HTML网页中嵌入Java代码以及Java EE标签库,从而实现动态生成网页内容的功能。
  与静态网页不同,JSP页面可以包含Java代码片段、Java EE标签库以及HTML标签。在客户端请求访问该JSP页面时,Java代码片段将会被服务器端解释执行并生成动态内容,然后将生成的结果作为HTML网页返回给客户端。
  在JSP中,可以使用Java语言的所有功能和API。它还提供了许多内置的对象,例如request、response、session、application等,这些对象可以用来处理用户请求和响应的数据。
  除了使用Java代码,JSP页面还可以使用标签库(Tag Library)来简化开发。标签库是一组可重用的代码块,类似于HTML的标签,它们可以在JSP页面中使用,以简化常见的Web开发任务。
  总之,JSP是Java Web技术体系中重要的组成部分之一,它使得开发人员可以使用Java语言和API来开发动态Web页面,同时也提供了许多内置的对象和标签库,以简化开发过程。

1.2、优点

  1. 简单易学:JSP技术基于HTML,开发人员可以使用标准的HTML标记语言进行开发,同时可以嵌入Java代码来实现动态内容生成。
  2. 可重用性:通过使用JSP标签库(Tag Library),可以将代码块打包成可重用的组件,这些组件可以在不同的JSP页面中共享,提高了代码的可重用性。
  3. 高性能:JSP页面在首次访问时需要编译成Java Servlet,之后每次访问时就不需要再次编译,因此可以提高Web应用程序的性能。
  4. 容易维护:JSP页面的代码可以分离出来,从而实现模块化和易于维护。

  JSP的使用,相比于单纯使用Servlet开发,效率和开发质量大大提升。
  在之前直接使用Servlet对浏览器写前端网页的内容,如果内容较多的情况下,会显得非常繁琐,并且代码是写死在程序里面的,不好维护,可读性也较差。因为之前是需要通过Servlet的response对象来向浏览器响应数据的,因此调用的是response.getWriter().write()方法来写,写出来的效果就像这样:
JSP&Servlet

  可以看到一个非常简单的前端表单页面,直接拿Servlet响应请求给浏览器显得多么复杂。JSP在当时,就很好的解决了这个问题。

1.3、缺点

缺点:

  1. 容易混淆:JSP页面中包含了Java代码和HTML标记,代码量较大时容易混淆。
  2. 容易滥用:JSP页面可以包含大量的Java代码,导致页面变得臃肿,降低可读性和可维护性。
  3. 不够灵活:JSP技术可能会受到容器限制,例如无法使用自定义的Java类加载器。
  4. 不够安全:由于JSP页面允许包含Java代码,如果编写不当,可能会导致安全漏洞。因此,需要使用安全的编程实践来确保应用程序的安全性。

1.4、逐渐淘汰

在现代Web开发中,越来越多的开发人员转向了使用前端框架来构建动态Web应用,如React、Vue.js等。
同时,Java EE平台在2019年被Oracle放弃维护,取而代之的是Jakarta EE平台,也就是Eclipse基金会维护的Java EE的开源版本。

JSP为什么会逐渐被淘汰?主要有以下原因:
  1. 前后端分离:随着前端框架的发展和普及,越来越多的开发人员开始采用前后端分离的开发模式。在这种模式下,后端提供API接口,前端通过AJAX等方式获取数据并动态渲染页面,这种方式更加灵活,更容易实现复杂的Web应用。
  2. 低效的开发:JSP中的Java代码片段可能会导致页面变得混乱,降低了可读性和可维护性。同时,使用JSP时,开发人员需要手动处理各种请求和响应,这可能会导致开发效率低下。
  3. 安全问题:由于JSP允许在页面中嵌入Java代码,如果编写不当,可能会导致安全漏洞,如SQL注入、XSS等。
  4. Java EE平台的变化:Java EE平台在2019年被Oracle放弃维护,取而代之的是Jakarta EE平台,这也导致开发人员不得不转向使用新的技术栈来开发Web应用。
  因此,尽管JSP作为一种经典的Web开发技术在一定程度上仍然被广泛应用,但随着前端技术和后端技术的发展,越来越多的开发人员转向使用前后端分离的方式来构建动态Web应用。

1.5、学习的意义

学习JavaWeb的过程,就像在学习Web开发领域的发展史,以史为鉴,从历史中总结学习经验,取其精华去其糟粕。因此,时至今日学习JSP仍然具有一定的意义,尤其对于初学者和想要了解Web开发历史和演变过程的人来说。
以下列举几个学习JSP技术的意义所在:
  1. 掌握Java Web开发的基本原理:JSP是Java Web开发的重要组成部分,学习JSP可以帮助初学者掌握Java Web开发的基本原理,包括Servlet、HTTP协议、JSP的工作原理等。
  2. 理解现代Web开发的演变过程:JSP曾经是Java Web开发的主流技术之一,但现在已经被前后端分离、模板引擎等技术所替代。学习JSP可以帮助人们了解现代Web开发的演变过程,以及现在的Web开发趋势。
  3. 学习JSP的一些基本概念对于维护和升级已有的JSP应用程序仍然有用。在很多公司中,可能还有一些老的JSP应用程序需要维护和升级,因此对于熟悉JSP的开发人员来说,仍然具有一定的价值。
  总的来说,虽然JSP已经不再是主流的Web开发技术,但学习JSP仍然有其独特的价值,能够帮助开发人员理解Java Web开发的基本原理和现代Web开发的演变过程。

2、JSP的简单样例

①创建一个Maven的Web项目,编写xml文件(重点是导入jsp的依赖)


4.0.0org.exampleJSP_demo1.0-SNAPSHOTwar1717javax.servlet.jspjsp-api2.2providedjavax.servletjavax.servlet-api4.0.1org.apache.tomcat.maventomcat7-maven-plugin2.2

②创建JSP文件,这里创建的是helloJSP.jsp。

③访问JSP

2.1、注意事项

  JSP是不能像之前的前端三剑客那样,写出来的代码文件可以直接在浏览器运行的,如果直接选择浏览器运行则会报错。
  
  报错信息写的是:没有找到已配置/正在运行的web服务器。
  这说明什么问题?说明这个JSP可能本质上就是个Servlet服务端。事实上真是如此,下面会详细讲述。

3、一个常见bug

在访问JSP的时候出现了如下错误:
  
  显示的是无法编译JSP。
  出现这个原因是因为使用了低版本的tomcat和高版本的JDK导致的, 解析出错,无法识别System类。可以尝试更换版本解决。
高版本tomcat配高版本JDK,低版本tomcat配低版本JDK。
  这里我使用的是JDK11+tomcat7/tomcat8。两个tomcat版本都是可以适用的。

4、JSP原理

JSP本质上就是一个Servlet。
浏览器访问JSP的执行流程如下:

  1. 浏览器第一次访问 helloJSP.jsp 页面
  2. tomcat 会将 helloJSP.jsp 转换为名为 helloJSP_jsp.java 的一个 Servlet
  3. tomcat 再将转换的 servlet 编译成字节码文件 hello_jsp.class
  4. tomcat 会执行该字节码文件,向外提供服务
  为了验证上面的执行流程,可以到磁盘中进行查看。进入该项目的target\tomcat\work\Tomcat\localhost\jsp_demo\org\apache\jsp 目录,而这个目录下就能看到转换后的 servlet。我自己目录如下:
  
  
下面贴上一份编译后的helloJSP_jsp.class文件:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.jsp;import java.io.IOException;
import java.util.Map;
import javax.el.ExpressionFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspFactory;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import org.apache.jasper.runtime.HttpJspBase;
import org.apache.jasper.runtime.InstanceManagerFactory;
import org.apache.jasper.runtime.JspSourceDependent;
import org.apache.tomcat.InstanceManager;public final class helloJSP_jsp extends HttpJspBase implements JspSourceDependent {private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();private static Map _jspx_dependants;private ExpressionFactory _el_expressionfactory;private InstanceManager _jsp_instancemanager;public helloJSP_jsp() {}public Map getDependants() {return _jspx_dependants;}public void _jspInit() {this._el_expressionfactory = _jspxFactory.getJspApplicationContext(this.getServletConfig().getServletContext()).getExpressionFactory();this._jsp_instancemanager = InstanceManagerFactory.getInstanceManager(this.getServletConfig());}public void _jspDestroy() {}public void _jspService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {JspWriter out = null;JspWriter _jspx_out = null;PageContext _jspx_page_context = null;try {response.setContentType("text/html;charset=UTF-8");PageContext pageContext = _jspxFactory.getPageContext(this, request, response, (String)null, true, 8192, true);_jspx_page_context = pageContext;pageContext.getServletContext();pageContext.getServletConfig();pageContext.getSession();out = pageContext.getOut();out.write("\r\n");out.write("\r\n");out.write("\r\n");out.write("\r\n");out.write("    Title\r\n");out.write("\r\n");out.write("\r\n");out.write("    

hello jsp

\r\n");out.write("\r\n");out.write(" ");System.out.println("hello jsp->java code");out.write("\r\n");out.write("\r\n");out.write("\r\n");} catch (Throwable var13) {if (!(var13 instanceof SkipPageException)) {out = (JspWriter)_jspx_out;if (_jspx_out != null && ((JspWriter)_jspx_out).getBufferSize() != 0) {try {out.clearBuffer();} catch (IOException var12) {}}if (_jspx_page_context == null) {throw new ServletException(var13);}_jspx_page_context.handlePageException(var13);}} finally {_jspxFactory.releasePageContext(_jspx_page_context);}} }

可以发现编译后的class文件中,继承了HttpJspBase,查看HttpJspBase源码:
  

可以看到HttpJspBase是继承了HttpServlet,所以helloJSP.jsp间接继承了HttpServlet,什么JSP本质上就是Servlet。
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 java.io.IOException;import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;import org.apache.jasper.Constants;
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() {}@Overridepublic final void init(ServletConfig config)throws ServletException{super.init(config);jspInit();_jspInit();}@Overridepublic String getServletInfo() {return Localizer.getMessage("jsp.engine.info", Constants.SPEC_VERSION);}@Overridepublic final void destroy() {jspDestroy();_jspDestroy();}/*** Entry point into service.*/@Overridepublic final void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{_jspService(request, response);}@Overridepublic void jspInit() {}public void _jspInit() {}@Overridepublic void jspDestroy() {}protected void _jspDestroy() {}@Overridepublic abstract void _jspService(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException;
}

_jspService方法每次访问的时候都会自动执行,和Servlet中的service方法类似。在_jspService方法中则存放着往浏览器写标签的代码。所以实际上就是以前这部分代码是自己写,现在由tomcat来帮助完成。

5、JSP脚本

JSP脚本是一种在JSP页面中嵌入Java代码的方式,可以在JSP页面中执行Java代码,从而动态生成HTML页面。JSP脚本可以出现在JSP页面的任何位置,包括JSP页面的文本、HTML标记和XML标记之间。JSP脚本可以使用以下语法:
  1. <% … %>:内容会直接放到_jspService()方法之中。这是最常用的JSP脚本标记,可以用来嵌入任意的Java代码,包括声明变量、定义方法、调用Java API等。
  2. <%= … %>:内容会放到out.print()中,作为out.print()的参数。这个标记可以用来在HTML页面中输出Java表达式的值,类似于Java中的System.out.println()语句。例如:<%= name %>可以输出变量name的值。
  3. <%-- --%>:这个标记可以用来注释JSP页面中的代码。
  4. <%! … %>:内容会放到_jspService()方法之外,被类直接包含。这个标记用来定义全局变量和方法,这些变量和方法可以在整个JSP页面中使用。
JSP脚本的执行顺序是从上到下,从左到右,与在Java中的执行顺序相同。

下面依次对这几个脚本进行测试:
  

①<% … %>:上面提到,该脚本会把内容直接放到_jspService()方法之中。
  

②<%= …%>:内容会放到_jspService()方法中out.print()中,作为out.print()的参数。
  

③<%! …%>:内容会直接放在类中。

6、实践样例

  在第二部分简单样例的基础上,编写本次的实践样例。
  这次的实践样例中,采用了JDBC操作数据库的方式,获取到数据库中的数据,在前端页面上进行展示。(JDBC的相关代码直接在JSP中完成)
  准备工作:打开本地的MySQL服务;在pom.xml中配置MySQL驱动依赖

下面对JSP的编写进行解析:
  ①HTML部分:
    写好表头标签:
     

    编写表格内容的标签:
     
  HTML的这部分中,由于后面是要写Java代码来获取数据填充在HTML页面的表格中,所以这里的表格内容要动态获取,不能写死。
  ②java代码:
    编写jdbc实现代码的步骤:注册驱动、获取连接、定义SQL语句、获取执行SQL对象、执行SQL、处理返回的结果、释放资源。

    动态获取数据:
    

    下面是JSP的完整代码:

<%--Created by IntelliJ IDEA.User: 逐梦苍穹Date: 2023/3/19Time: 21:59To change this template use File | Settings | File Templates.
--%>
<%@ page import="java.sql.*" %><%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title


<%Connection conn = null;Statement stmt = null;ResultSet rs = null;try {// 加载MySQL JDBC驱动程序Class.forName("com.mysql.jdbc.Driver");// 建立与数据库的连接conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jsp", "root", "你的密码");// 创建一个 Statement 对象stmt = conn.createStatement();// 执行查询语句rs = stmt.executeQuery("SELECT * FROM jspDemo");// 处理查询结果while (rs.next()) {%><%}} catch (SQLException ex) {ex.printStackTrace();} catch (ClassNotFoundException ex) {ex.printStackTrace();} finally {// 关闭数据库连接try {if (rs != null) rs.close();if (stmt != null) stmt.close();if (conn != null) conn.close();} catch (SQLException ex) {ex.printStackTrace();}}%>
序号名称介绍商品数量状态
<%=rs.getString("id")%><%=rs.getString("name")%><%=rs.getString("information")%><%=rs.getString("number")%><%=(rs.getString("status")).equals("1") ? "启用":"禁用"%>修改 删除

6.1、注意事项

在写java代码的时候,如果想在其中穿插执行前端代码,可以使用<% %>进行截断。

相关内容

热门资讯

Application 初始化... Application 的 onCreate 和 attachBaseContextApplicat...
Unity 热更新技术 | (... 🎬 博客主页:https://xiaoy.blog.csdn.net ...
01分布式电源接入对配电网影响... 说明书 MATLAB代码:分布式电源接入对配电网影响分析 关键词:分布式...
“付诸一炬”的意思 “付诸一炬”的意思 成语拼音: [fù zhū yī jù] ...
四字开头的成语 四字开头的成语四字开头的成语1  四通五达  四通八达  四停八当  四体不勤  四体不勤  四体百...
“过目成诵”的意思 “过目成诵”的意思 成语拼音: [guò mù chéng sòng] ...
“年复一年”的意思 “年复一年”的意思 成语拼音: [nián fù yī nián] ...
2023-第十四届蓝桥杯冲刺计... 💬前言 💡本文以目录形式列举大纲,可根据题目点击跳转 dz...
JavaScript查找数组内... 需求:查找数组内元素6是否存在 let arr = [1, 3, 6, 5, ...
Redis缓存穿透、击穿、雪崩... 系列文章目录 Spring Cache的使用–快速上手篇 分页查询–Java项目实战篇 全局异常处理...
新婚四字成语祝福语 新婚四字成语祝福语  在朋友或者同学的新婚上,为了表达真挚的`祝福,有哪些四字成语祝福语?下面是小编...
带有邻字的成语及解释 带有邻字的成语及解释  以“邻”字开头的成语及解释如下:  [邻女詈人] 比喻各为其主。詈,指“骂”...
“寻风捉影”的意思 “寻风捉影”的意思 成语拼音: [xún fēng zhuō yǐng] ...
Java开发 | 内部类 | ... 目录 1.内部类 1.1内部类的简单创建  1.2内部类的分类 1.2.1普通内部类 1.2.2静态...
“穷途之哭”的意思 “穷途之哭”的意思 成语拼音: [qióng tú zhī kū] ...
python 3.10安装Bo... 文章目录前言环境背景问题一:如何在指定版本python下安装第三方库问题二࿱...
使用Node.js+Koa 从... 此项目始终贯彻在做实际项目中,学习新的知识,适合看不进去视频࿰...
贬义词成语是哪些 贬义词成语是哪些  成语是中国汉字语言词汇中一部分定型的词组或短句。以下是小编收集的贬义词成语,欢迎...
“白首一节”的意思 “白首一节”的意思 成语拼音: [bái shǒu yī jié] ...
形容山水的成语 形容山水的成语大全  山的雄伟,水的柔和,想找一些关于描写山水的成语吗?下面是YJBYS小编为大家搜...