【Java Web编程 三】JSP基本概念和语法

简介: 【Java Web编程 三】JSP基本概念和语法

上文中提到,Tomcat会处理JSP和Servlet两种类型的文件,那么我们先来看看这两种类型文件是什么,有什么作用,然后再从Tomcat的架构角度去看请求是怎么被处理的,本篇文章重点探讨JSP的整体运行机制。

JSP概念简介

前文我们说过有静态和动态两种网站模式,其实我们大多数的网站都是动态网站,所以不能依赖单纯的Html去构建。这个时候我们有两种方式去解决这个问题:

  1. 把html代码和样式嵌入到Java代码中,然后将Java文件解析运行,这种方式下我们需要分析的是html代码,将html代码打印出来
  2. 把Java代码嵌入到html代码和样式中,然后将该文件动态解析为Java文件运行,这种方式下我们需要分析的是Java代码,将Java代码运行。

依据实际情况来看,因为html样式代码数量远大于Java代码,我们的修改动作也较为频繁,而我们希望更方便的调整html样式而不需要面对大量的print打印语句。

所以我们选择第二种方式,由此也引出了JSP的概念:Java Server Page 简称 JSP,是由 Sun 公司倡导建立的一种动态网页技术标准,用于开发动态网页,JSP就是将传统Java代码嵌入到Html页面代码中,由Web服务器进行编译执行,生成最终的静态Html返回客户端

JSP执行流程

浏览器无法直接运行JSP文件,只有将包含JSP文件的Web项目部署到Web服务器上,才能看到JSP的显示效果,当客户端浏览器向服务器发出请求访问一个JSP页面后,服务器根据该请求加载相应的JSP 页面,并对该页面进行转换、编译和执行。

具体的执行过程如下:

  1. 浏览器发送一个 HTTP 请求给服务器。
  2. Web 服务器识别出这是一个对 JSP 网页的请求,并且将该请求传递给 JSP 引擎。通过使用 URL或者 .jsp 文件来完成。
  3. JSP 引擎从磁盘中载入 JSP 文件,然后将它们转化为 Servlet。这种转化只是简单地将所有模板文本改用 println() 语句,并且将所有的 JSP 元素转化成 Java 代码。
  4. JSP 引擎将 Servlet 编译成可执行类,并且将原始请求传递给 Servlet 引擎。
  5. Web 服务器的某组件将会调用 Servlet 引擎,然后载入并执行 Servlet 类。在执行过程中,Servlet 产生 HTML 格式的输出并将其内嵌于 HTTP response 中上交给 Web 服务器。
  6. Web 服务器以静态 HTML 网页的形式将 HTTP response 返回到浏览器中。
  7. 最终,Web 浏览器处理 HTTP response 中动态产生的HTML网页,就好像在处理静态网页一样

总体而言,引擎会帮我们将JSP编译为Servlet,然后执行

JSP组成元素

JSP文件中包括两类代码:JSP元素和Template(模版):

  • JSP元素:指的就是<%...... %>内的代码,这部分代码是JSP引擎直接处理的部分,这部分必须符合Java语法
  • Template(模版):指的就是<%...... %>外的代码,例如代码中HTML的内容,这些数据JSP引擎不作处理,直接返回给客户端的浏览器

所以解析处理的时候其实只需要处理JSP元素。

JSP生命周期

JSP生命周期就是从创建到销毁的整个过程,类似于servlet生命周期,区别在于JSP生命周期还包括将JSP文件编译成servlet:

  1. 编译阶段:servlet容器编译servlet源文件,生成servlet类。当浏览器请求JSP页面时,JSP引擎会首先去检查是否需要编译这个文件。如果这个文件没有被编译过,或者在上次编译后被更改过,则编译这个JSP文件。分为三个步骤:解析JSP文件;将JSP文件转为servlet;编译servlet
  2. 初始化阶段:加载与JSP对应的servlet类,创建其实例,并调用它的初始化方法jspInit
  3. 执行阶段:调用与JSP对应的servlet实例的服务方法_jspService
  4. 销毁阶段:调用与JSP对应的servlet实例的销毁方法jspDestroy,然后销毁servlet实例

整个流程图如下:

JSP语法标识

JSP的语法分为三类:指令标识、脚本标识注释标识动作标识。这里我们以一个JSP页面进行举例,贯穿接下来的练习代码

index.jsp文件

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*" %>
<%@ include file="top.jsp" %>
<!DOCTYPE html>
<html>
<head>
    <title>JSP - Hello World</title>
    <%!
        int number = 0;// 声明全局变量
        int count() {
            number++;//number 自增
            return number;
        }%>
</head>
<h1><%= "Hello World!" %>
</h1>
<br/>
<body>
<%
    String print = "我是脚本语句内容";
    List<String> strList = new ArrayList<>();
    strList.add("脚本语句1");
    strList.add("脚本语句2");
    strList.add("脚本语句3");
//  strList.add("脚本语句4");  //这是一个Java注释,用来注释Java代码,查看源码时不可见
%>
<a href="hello-servlet">我的第一个JavaWeb项目</a> <!-- 这是一个html注释,可见<%= new Date().getTime() %> -->
<br/>
<%--这是一个JSP注释,查看源码时不可见--%>
声明语句示例:这是第 <%=count()%> 次访问该页面
<br/>
表达式语句示例: <%="我是一个表达式语句"%>
<br/>
脚本语句示例: <%=print%>, 打印列表 <%=strList%>
<jsp:forward page="result.jsp"></jsp:forward>
跳转语句之后,代码不会被执行:<%="我是一个跳转后的表达式语句"%>
</body>
</html>

top.jsp文件

<%--
  Created by IntelliJ IDEA.
  User: tianmaolin
  Date: 2021/7/13
  Time: 8:15 下午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*" %>
<html>
<head>
    <title>我是include的top.jsp页面</title>
</head>
<body>
<%
  String printTop="top打印";
%>
<a href="hello-servlet">我是top的打印,<%=printTop%></a>
</body>
</html>

result.jsp文件

<%--
  Created by IntelliJ IDEA.
  User: tianmaolin
  Date: 2021/7/14
  Time: 11:32 上午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>跳转的结果页面</title>
</head>
<body>
<a>我是跳转后的结果页面</a>
</body>
</html>

test.jsp文件

按照语法基础,我们实践三种语法流程:判断逻辑,循环逻辑:

<%--
  Created by IntelliJ IDEA.
  User: tianmaolin
  Date: 2021/7/14
  Time: 12:30 下午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*,java.io.*" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%! int day = 3; %>
if语句输出练习:
<br/>
<% if (day == 1 || day == 7) { %>
<p>今天是周末</p>
<% } else { %>
<p>今天不是周末</p>
<% } %>
<br/>
for语句输出练习;
<br/>
<%for ( int fontSize = 1; fontSize <= 3; fontSize++){ %>
<span style="color: green; ">
    循环第 <%=fontSize%> 遍<br/>
</span><br/>
<%}%>
</body>
</html>

指令标识

指令标识主要用于设定在整个 JSP 页面范围内都有效的相关设置信息,它是被服务器解释并执行的,不会产生任何内容输出到网页中,格式如下:

<%@ 指令名 属性 1=“属性值 1” 属性 2=“属性值 2”...%>
  • 指令名:用于指定指令名称,在 JSP 中包含 page、include 和 taglib 3 个指令。
  • 属性:用于指定属性名称,不同的指令包含不同的属性。在一个指令中,可以设置多个属性,属性之间用逗号或空格隔开。
  • 属性值:用户指定属性值

上述文件中<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> 就是一个page指令。

指令标识包含:page指令、include指令以及taglib指令。

page指令

Page指令为容器提供当前页面的使用说明。一个JSP页面可以包含多个page指令,page的标准语法如下:

<%@ page attribute="value" %>

page指令的常用属性如下:

例如我们想要访问list相关的方法,就需要引入java的util类:

<%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%>

include指令

JSP可以通过include指令来包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是该JSP文件的一部分,会被同时编译执行。Include指令的语法格式如下:

<%@ include file="文件相对 url 地址" %>

include 指令中的文件名实际上是一个相对的 URL 地址,例如:

注意:在应用 include 指令包含文件时,为使整个页面的层次结果不发生冲突,应将被包含页面中的 元素和 元素删除,因为包含该页面的文件中已经指定了这些标记

Taglib指令

在 JSP 文件中,可以通过 taglib 指令声明该页面中所使用的标签库,同时引用标签库,并指定标签前缀,在页面中引用标签库后,就可以通过前缀引用标签库中的标签

<%@taglib prefix=“core” uri=“http://java.sun.com/jsp/jstl/core” %>

标签库的使用后续会提到。

脚本标识

脚本标识是JSP中最主要的元素,相当于JSP中需要编译的那一部分内容,也是JSP语法中的核心内容,包含声明、表达式以及脚本段

声明

声明标识用于在 JSP 页面中定义全局的变量或方法,通常使用该标识定义整个 JSP 页面需要引用的变量或方法,在JSP文件中,必须先声明这些变量和方法然后才能使用它们,相当于Java里的成员变量和成员方法定义。语法规则如下:

<%! 声明变量或方法代码 %>

一个全局的统计访问次数的例子如下:

<%!
        int number = 0;// 声明全局变量
        int count() {  //声明全局方法
            number++;//number 自增
            return number;
        }%>
  这是第 <%=count()%> 次访问该页面

可以打印出来第几次访问页面

脚本段

Scriptlet(代码片段)脚本程序,是在 JSP 页面中嵌入的 Java 代码或脚本代码,代码片段将在页面请求的处理期间被执行,通过 Java 代码可以定义变量或流程控制语句等,相当于Java里main方法的代码逻辑,语法规则如下:

<% 表达式或者变量名 %>

脚本段语句示例:

<%
    String print = "我是脚本语句内容";
    List<String> strList = new ArrayList<>();
    strList.add("脚本语句1");
    strList.add("脚本语句2");
    strList.add("脚本语句3");
%>
脚本语句示例: <%=print%>, 打印列表 <%=strList%>

可以直接打印脚本段内的内容。

表达式

JSP 表达式用于向页面中输出信息,类似于System.out.println()括号中的内容,相当于Java里main方法里的System.out.println()语句,只不过是输出回客户端,而非服务端本地打印,语法规则如下:

<%= 表达式或者变量名 %>

以上我们无论是声明还是脚本段的输出其实都用到了表达式:

<br/>
声明语句示例:这是第 <%=count()%> 次访问该页面
<br/>
表达式语句示例: <%="我是一个表达式语句"%>
<br/>
脚本语句示例: <%=print%>, 打印列表 <%=strList%>

注释标识

注释用于对某些代码做功能性的说明,从而增加程序的可读性。JSP 程序中可以包含 3 种不同类型的注释:

JSP注释

JSP注释主要有两个作用:为代码作注释以及将某段代码注释掉。主要是给JSP页面提供注释,JSP注释在客户端浏览器无法查看到,注释内容不会被发送至浏览器甚至不会被编译,其语法规则如下:

<%-- JSP标准注释 --%>

例如我们可以这么编写:

<%--表达式展示的JSP注释--%>
声明语句示例:这是第 <%=count()%> 次访问该页面
<br/>
表达式语句示例: <%="我是一个表达式语句"%>
<br/>
脚本语句示例: <%=print%>, 打印列表 <%=strList%>
</body>

Java注释

Java注释指的是java代码,和Java代码的注释格式是一致的,同样的Java注释在客户端浏览器无法查看到,注释内容不会被发送至浏览器甚至不会被编译,语法规则如下:

<%
       //Java单行注释
       /*
           Java多行注释
       */
%>

例如我们可以这么编写:

<%
    String print = "我是脚本语句内容";
    List<String> strList = new ArrayList<>();
    strList.add("脚本语句1");
    strList.add("脚本语句2");
    strList.add("脚本语句3");
//  strList.add("脚本语句4");  //这是一个Java注释,用来注释Java代码
%>

HTML注释

HTML注释主要给JSP页面的Template元素提供注释,HTML网页注释在客户端浏览器可以看到,语法规则如下:

<!-- HTML网页注释 -->

这类在查看源码时可见,其中的脚本语句也是可执行的,示例如下:

<!-- 这是一个html注释,可见<%= new Date().getTime() %> -->

点击查看源码我们可以看到注释:

动作标识

JSP行为标签使用XML语法结构来控制servlet引擎。它能够动态插入一个文件,重用JavaBean组件,引导用户去另一个页面,为Java插件产生相关的HTML等等。行为标签只有一种语法格式,它严格遵守XML标准。其语法格式如下:

<jsp:action_name attribute="value" />

包含很多种可以作用的动作标识:

举例说明如下,执行到跳转动作后会跳转到结果页面:

<jsp:forward page="result.jsp"></jsp:forward>
跳转语句之后,代码不会被执行:<%="我是一个跳转后的表达式语句"%>

总结一下

这篇Blog我们大致了解了JSP的基本概念,为什么要用JSP,以及JSP的生命周期、执行流程和组成元素,但是最最重要的还是JSP的基本语法:指令、注释、脚本、动作,这几个各有用处,指令管理页面的配置和属性,脚本管理JSP元素的代码和逻辑,动作可以简化指令和脚本,用标签的形式去体现,让整个页面Java代码更少看起来更加的配置化,注释则用于对文件进行解释。其中脚本可谓核心,我们希望脚本的内容越少越好,这样JSP的视图而非逻辑作用发挥的就越好,所以后续我们还会学习一些高级语法:JSTL标签和EL表达式,这两配合起来可以大量简化写法

相关文章
|
8天前
|
SQL Java 数据库
2025 年 Java 从零基础小白到编程高手的详细学习路线攻略
2025年Java学习路线涵盖基础语法、面向对象、数据库、JavaWeb、Spring全家桶、分布式、云原生与高并发技术,结合实战项目与源码分析,助力零基础学员系统掌握Java开发技能,从入门到精通,全面提升竞争力,顺利进阶编程高手。
159 1
|
9天前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
264 100
|
13天前
|
存储 SQL NoSQL
Redis-常用语法以及java互联实践案例
本文详细介绍了Redis的数据结构、常用命令及其Java客户端的使用,涵盖String、Hash、List、Set、SortedSet等数据类型及操作,同时提供了Jedis和Spring Boot Data Redis的实战示例,帮助开发者快速掌握Redis在实际项目中的应用。
162 1
Redis-常用语法以及java互联实践案例
|
19天前
|
NoSQL Java 关系型数据库
超全 Java 学习路线,帮你系统掌握编程的超详细 Java 学习路线
本文为超全Java学习路线,涵盖基础语法、面向对象编程、数据结构与算法、多线程、JVM原理、主流框架(如Spring Boot)、数据库(MySQL、Redis)及项目实战等内容,助力从零基础到企业级开发高手的进阶之路。
113 1
|
5月前
|
Web App开发 前端开发 JavaScript
鸿蒙5开发宝藏案例分享---Web适配一多开发实践
这是一份实用的鸿蒙Web多设备适配开发指南,针对开发者在不同屏幕尺寸下的布局难题提供了解决方案。文章通过三大法宝(相对单位、媒体查询和窗口监听)详细介绍如何实现智能适配,并提供了多个实战案例,如宫格布局、对话框变形和自适应轮播图等。此外,还分享了调试技巧及工具推荐,帮助开发者快速上手并优化性能。最后鼓励读者实践探索,并提示更多官方资源等待发现。
|
12月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
622 3
|
7月前
|
关系型数据库 MySQL 数据库
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
TIS 是一款基于Web-UI的开源大数据集成工具,通过与人大金仓Kingbase的深度整合,提供高效、灵活的实时数据集成方案。它支持增量数据监听和实时写入,兼容MySQL、PostgreSQL和Oracle模式,无需编写复杂脚本,操作简单直观,特别适合非专业开发人员使用。TIS率先实现了Kingbase CDC连接器的整合,成为业界首个开箱即用的Kingbase CDC数据同步解决方案,助力企业数字化转型。
1206 5
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
|
7月前
|
机器学习/深度学习 开发框架 API
Python 高级编程与实战:深入理解 Web 开发与 API 设计
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧以及数据科学和机器学习。本文将深入探讨 Python 在 Web 开发和 API 设计中的应用,并通过实战项目帮助你掌握这些技术。
|
11月前
|
开发框架 搜索推荐 数据可视化
Django框架适合开发哪种类型的Web应用程序?
Django 框架凭借其强大的功能、稳定性和可扩展性,几乎可以适应各种类型的 Web 应用程序开发需求。无论是简单的网站还是复杂的企业级系统,Django 都能提供可靠的支持,帮助开发者快速构建高质量的应用。同时,其活跃的社区和丰富的资源也为开发者在项目实施过程中提供了有力的保障。
424 67
|
11月前
|
存储 前端开发 JavaScript
如何在项目中高效地进行 Web 组件化开发
高效地进行 Web 组件化开发需要从多个方面入手,通过明确目标、合理规划、规范开发、加强测试等一系列措施,实现组件的高效管理和利用,从而提高项目的整体开发效率和质量,为用户提供更好的体验。
324 63