JSP基础知识学习
一、JSP是什么
JSP(全称JavaServer Pages)是由[Sun](https://baike.baidu.com/item/Sun Microsystems)公司主导创建的一种动态网页技术标准。JSP技术以Java语言作为脚本语言,为用户的HTTP请求提供服务,并能与服务器上的其它Java程序共同处理复杂的业务需求。JSP文件在运行时会被其编译器转换成更原始的Servlet代码。
二、JSP原理
说到原理,我们就会思考JSP是怎么执行的!以IDEA为例,我们使用tomcat启动web服务时,会在电脑的 .IntelliJIdea
文件里生成一个tomcat文件,里面会有一个它的工作目录work,里面会生成一个org
包,会发现里面会有一个所访问的jsp对应的Java文件和class文件。如下图:
在我的电脑盘上目录为:
C:\Users\86183\.IntelliJIdea\system\tomcat\Tomcat_10_0_181_JavaWeb-jsp-maven\work\Catalina\localhost\JavaWeb_jsp_maven_war\org\apache\jsp
可见,JSP最终都会被转换为一个JAVA类,浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!
工作原理图如下:
- 客户端通过浏览器向服务器发出请求,请求访问的JSP文件。
- 服务器根据接收到的客户端的请求来加载相应的JSP文件。
- Web服务器中的JSP引擎会将被加载的JSP文件转化为Servlet文件(.java)。
- 将生成的Servlet文件编译成Class文件,Servlet容器(引擎)会像处理其他Servlet一样处理它。
- 服务器执行这个Class文件。即,执行jspService()方法处理客户端的请求。对于每一个请求,JSP容器都会创建个新的线程处理它。
- 最后服务器将执行结果发送给浏览器进行显示。
注意:JSP引擎本身也是一个servlet!
分析一下服务器最终响应的index_jsp.java
-
该Java类继承的是HttpJspBase(它继承的就是HttpServlet)
-
该java类里面就有servlet的三个生命周期方法
//初始化 public void _jspInit() { } //销毁 public void _jspDestroy() { } //service()处理客户端请求阶段 public void _jspService(final jakarta.servlet.http.HttpServletRequest request, final jakarta.servlet.http.HttpServletResponse response){
-
该java类的内置对象
final jakarta.servlet.jsp.PageContext pageContext; //页面上下文 jakarta.servlet.http.HttpSession session = null; //session final jakarta.servlet.ServletContext application; //application final jakarta.servlet.ServletConfig config; //配置 jakarta.servlet.jsp.JspWriter out = null; //out输出 final java.lang.Object page = this; //当前页面 servlet.http.HttpServletRequest request; //请求 servlet.http.HttpServletResponse response; //响应
-
输出页面前增加的代码
//设置响应的页面类型 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;
所以,JSP本质就是一个servlet!
三、JSP基础语法
四个基本语法
<%= %>表达式
<% %>脚本
<%! %>声明
<%----%>注释
JSP表达式
<%--1.JSP表达式
作用:将程序的结果输出到客户端
格式:<%= 变量或表达式%>
--%>
<%= new java.util.Date()%>
JSP脚本
<%--2.JSP脚本片段
格式:<% %>
作用范围:都是编译在那个tomcat项目index_jsp的 _jspService()方法里
--%>
<%--用法1--%>
<%
int sum =0;
for (int i = 0; i < 100; i++) {
sum+=i;
}
out.println("<h1>sum="+sum+"</h1>");
%>
<%--用法2--%>
<%
int x = 100;
out.println(x);
%>
<h1>这是HTML</h1>
<%
//一样可以输出上面定义的x变量
out.println(x);
%>
<%--用法3--%>
<%
for (int i = 0; i < 10; i++) {
%>
<h2>我是html <%= i%></h2>
<%
}
%>
JSP声明
<%--3.JSP声明
格式:<%! %>
作用范围:是编译在那个tomcat项目index_jsp的类上面 不在_jspService()方法里面的
--%>
<%!
static {
System.out.println("load Servlet!");
}
int globalVar = 99;
private void play(){
System.out.println("进入了play方法!");
}
%>
JSP注释
<%--4.JSP注释
格式:<%-- -->
不同:与html的注释相比,JSP的注释不会在客户端显示,html的会!
--%>
<!--我是html注释-->
<%--我是jsp注释--%>
四、JSP指令
指令是向容器提供指示和说明,告诉容器如何处理JSP处理的请求和响应。有三种类型指令标签:
<%@ page args... %> //定义页面相关属性,如脚本语言,错误页面和缓冲要求。
<%@ include args... %> //在编译阶段包括文件
<%@ taglib args... %> //声明页面中使用的包含自定义操作的标签库
page 指令
page指令用于向容器提供说明。这些说明涉及当前的JSP页面。可以在JSP页面的任何位置编写page指令。按照惯例,page指令被编码在JSP页面的顶部。
- 基本语法
<%@ page 属性="值" %>
对应的jsp动作语法为:
<jsp:page 属性 = "值" />
- 常用属性
属性 | 说明 |
---|---|
errorPage | 定义另一个报告Java未检查运行时异常的JSP的URL。 |
import | 指定JSP中使用的包或类的列表,就像Java的import语句一样。 |
contentType | 定义字符编码方案。 |
info | 定义可以使用servlet的getServletInfo()方法访问的字符串。 |
extends | 指定生成的servlet必须扩展的超类。 |
include 指令
include指令用于在编译阶段包括一个文件。这个指令告诉容器在编译阶段将其他外部文件的内容合并到当前JSP文件中。可在JSP页面的任何位置使用include指令进行编码 。
- 最常用的属性用法
<%@ include file = "relative url" >
对应的jsp动作语法为:
<jsp:include file = "relative url" >
<%--两者不同:指令是把文件合并为一个了,而jsp标签是拼接了文件--%>
taglib 指令
SP API允许自定义的JSP标签,如:HTML或XML标签,标签库是一组实现自定义行为的用户定义标签。taglib指令声明JSP页面使用一组自定义标签,标识库的位置,并提供了在JSP页面中标识自定义标签的方法。
- 唯一属性用法
<%@ taglib uri="uri" prefix = "prefixOfTag" >
对应的jsp动作语法为:
<jsp:taglib uri = "uri" prefix = "prefixOfTag" />
这里,uri属性值解析为容器理解的位置,并且prefix属性通知容器什么位置的标记是自定义操作。
五、JSP内置对象
了解内置对象
JSP提供了由容器实现和管理的内置对象,也可以称之为隐含对象。由于JSP使用Java作为脚本语言,所以JSP将具有强大的对象处理能力,并且可以动态创建Web页面内容。但Java语法在使用一个对象前,需要先实例化这个对象,非常的繁琐。JSP为了简化开发,提供了一些内置对象,用来实现很多JSP应用。在使用JSP内置对象时,不需要先定义这些对象,直接使用即可。
九大内置对象
- HttpServletRequet类的Request对象:代表请求对象,主要用于接受客户端通过HTTP协议连接传输服务器端的数据。
- HttpSevletResponse类的Response对象:代表响应对象,主要用于向客户端发送数据。
- JspWriter类的out对象:主要用于向客户端输出数据。
- HttpSession类的session对象:主要用来分别保存每个月的信息与请求关联的会话;会话状态的维持是web应用开发者必须面对的问题。
- ServletContext类的application对象:主要用于保存用户信息,代码片段的运行环境;它是一个共享的内置对象,即一个容器中的多个用户共享一个application,故其保存的信息被所有用户所共享。
- PageContext类的PageContext对象:管理网页属性,为jsp页面包装页面的上下文,管理对属于jsp的特殊可见部分中已经命名对象的访问,它的创建和初始化都是由容器来完成的。
- ServletConfig类的Config对象:代码片段配置对象,标识Servlet的配置。
- Object类的Page对象:处理jsp页面,是object类的一个实例,指的是jsp实现类的实例。
- Exception对象:处理jsp文件执行时发生的错误和异常,只有在错误页面里才使用,前提是在页面指令里要有isErrorPage=true。
四大作用域
- page范围:只在一个页面保留数据(javax.servlet.jsp.PageContext(抽象类)),它的有效范围仅限于用户请求的当前页面。
- request范围:只在一个请求中保存数据(javax.servlet.httpServletRequest),一个请求可以包含多个页面。它的有效范围是这个一个请求。请求转发注意:
- 转发是服务器行为,而重定向是客户端行为。
- 无论在服务器上如何转发,浏览器地址栏中显示的仍然是最初那个Servlet的地址。
- Session范围:在一次会话中保存数据,仅供单个用户使用(javax.servlet.http.HttpSession),它的有效范围是当前会话。所谓当前会话,就是指从用户打开浏览器开始,到用户关闭浏览器这中间的过程。
- Application范围:在整个服务器中保存数据,全部用户共享(javax.servlet.ServletContext),它的有效范围是整个应用。整个应用是指从应用启动,到应用结束。
特殊内置对象 PageContext
pageContetx对象是jsp页面中所有对象功能的最大集成着,使用他可以访问所有的jsp内置对象。pageContext对象的创建和初始化都是由容器来完成的,JSP页面中可以直接使用pageContext对象。
PageContext方法:
方法名 | 说明 |
---|---|
forward | 重定向到另一页面或Servlet组件 |
getAttribute | 重定向到另一页面或Servlet组件 |
findAttribute | 按范围搜索指定名字的属性 |
removeAttribute | 删除某范围中指定名字的属性 |
setAttribute | 设定某范围中指定名字的属性值 |
getException | 返回当前异常对象 |
getRequest | 返回当前请求对象 |
getResponse | 返回当前响应对象 |
getServletConfig | 返回当前页面的ServletConfig对象 |
getSession | 返回当前页面的会话对象 |
getServletContext | 返回所有页面共享的ServletContext对象 |
六、JSP动作、JSTL标签与EL表达式
-
jsp动作
与JSP指令元素不同的是,JSP动作元素在请求处理阶段起作用。JSP动作元素是用XML语法写成的,利用JSP动作可以动态地插入文件、重用JavaBean组件、把用户重定向到另外的页面、为Java插件生成HTML代码。
JSP动作元素只有一种语法,它符合XML标准:
<jsp:action_name(动作名称) attribute(属性)="value(值)" />
- JSP规范定义了一系列的标准动作,它用JSP作为前缀,可用的标准动作元素如下:
- 所有动作都有常见的两个属性:id属性和scope属性。
- **id属性:**id属性是动作元素的唯一标识,可以在JSP页面中引用。动作元素创建的id值可以通过PageContext来调用
- **scope属性:**该属性用于识别动作元素的生命周期。 id属性和scope属性有直接关系,scope属性定义了相关联id对象的寿命。 scope属性有四个可能的值: page, request, session, 和 application。对应着四大作用域。
具体的动作方法,属性这些可以上菜鸟编程学习:https://www.runoob.com/jsp/jsp-actions.html
-
jstl标签
什么是jstl标签呢?
JSTL(JSP标准标签库)是一个JSP标签集合,它封装了JSP应用的通用核心功能。支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。 除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。
根据JSTL标签所提供的功能,可以将其分为5个类别:
- core 核心标签 (重点)
- fmt 格式化标签**(了解)**
- SQL 标签
- XML 标签
- JSTL 函数
如何使用呢?
-
导包
在pom.xml文件引入这两个依赖
<!-- JSTL表达式 依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.1.2</version> </dependency> <!-- standard 标签库 --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
-
在使用标签的JSP页面中使用taglib指令导入标签库;
<%@ taglib prefix="引用的标志" uri="标签库相应的uri" %> <!-- prefix=" ":指定标签库的前缀,这个前缀可以随便给值,但大家都会在使用core标签库时指定前缀为c; uri=" ":指定标签库的uri,可以让JSP找到标签库的描述文件; -->
!注意:报tomcat异常–java.lang.ClassNotFoundException: org.apache.taglibs.standard.tlv.JstlCoreTLV。是由于tomcat服务器的原因,通过maven导入的jstl和standard包可能并没有被打包进入tomcat下web应用(即webapps)的WEB-INF\lib目录下,所以要手动复制过去!
core 核心标签库
core标签库是最常用的标签库,含有很多java常用关键字对应标签,引用语法如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
out、set与remove标签(存取删)
<c:out value=”${aaa}” default=”xxx”/> 当${aaa}不存在时,输出xxx字符串 <c:set var=”a” value=”hello” scope=”session”/> 在session中添加name为a,value为hello的数据。默认scope为page <c:remove var=“a” scope=”page”/> 删除pageContext中name为a的数据 。默认是删除所有 -
if标签、choose、when与otherwise标签(判断)
<!-- if标签等价于java里面的if,test属性为boolen类型,为true的话则执行下面的语句--> <c:set var="a" value="aaa"/> <c:if test="${ a }"> <c:out value="${ a }"/> </c:if> <!-- choose标签等价于java里面的switch,when和otherwise为choose的子标签,相对于case和default--> <c:set var="score" value="${param.score}"/> <c:choose> <c:when test="${score > 100 || score < 0}">错误的分数:${score }</c:when> <c:when test="${score >= 90 }">A级</c:when> <c:when test="${score >= 80 }">B级</c:when> <c:when test="${score >= 70 }">C级</c:when> <c:when test="${score >= 60 }">D级</c:when> <c:otherwise>不及格</c:otherwise> </c:choose>
-
forEach(迭代)
forEach就是循环标签,有两种使用方式:
- 使用循环变量,指定开始和结束值,类似for(int i = 1; i <= 10; i++) {};
<c:set var="sum" value="0" /> <c:forEach var="i" begin="1" end="10" step ="1"> <!--相当于for(int i = 1; i <= 10; i++)--> <c:set var="sum" value="${sum + i}" /> </c:forEach> <c:out value="sum = ${sum }"/>
- 循环遍历集合,类似for(Object o : 集合);
<% List<String> names = new ArrayList<String>(); names.add("张三"); names.add("李四"); names.add("王五"); pageContext.setAttribute("names", names); %> <c:forEach var="item" items="${ names }"> <c:out value="${item.key }: ${item.value }"/><br/> <!--相当于for(String item : names)--> </c:forEach>
-
param、redirect和url标签
<c:param name=“username” value=“abc”/> 用来给包含或重定向的页面传递参数 <c:redirect url=“url”/ > 重定向至一个新的URL. <c:url value=“url” var=“a” scope=“request”/> 使用可选的查询参数来创造一个URL,然后赋值给变量a.范围为request
fmt 格式化标签
JSTL格式化标签用来格式化并输出文本、日期、时间、数字。引用格式化标签库的语法如下:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-
格式化时间:
<% double d1 = 1.1; pageContext.setAttribute("d1", d1); %> <fmt:formatNumber value="${d1 }" pattern="0.00"/><br/>
pattern属性可以让您在对数字编码时包含指定的字符。下面列出了这些字符:
-
格式化数字:
<% Date date = new Date(); pageContext.setAttribute("d", date); %> <fmt:formatDate value="${d}" pattern="yyyy-MM-dd HH:mm:ss"/> <!--pattern与上面格式化数字类同,具体的一些日期字符描述自行上网学习-->
其他几个内容的格式化标签可自行上网学习:推荐菜鸟编程
-
el表达式
EL的介绍:
EL(Expression Language) 是表达式语言,为了使JSP写起来更加简单 ,是一种在JSP页面获取数据的简单方式(只能获取数据,不能设置数据),在JSP2.0时引入。
EL语法:
所有EL表达式的格式都是以“${}”表示,可获取JSP页面任何静态部分的表达式的值。
EL获取数据:
!只能从四大域中获取属性
-
属性值默认在page范围查找,然后依次在request、session、application范围查找。例如,${userinfo}代表获取变量userinfo的值。
-
用指定域作为前缀获取数据表示属于哪个范围的变量,提高查找速率。例如:${ pageScope. userinfo}表示访问page范围中的userinfo变量。
<% pageContext.setAttribute("yg","宇哥1"); request.setAttribute("yg","宇哥2"); session.setAttribute("yg","宇哥3"); application.setAttribute("yg","宇哥4"); %> <%--默认获取域为page--%> <h2>${yg}</h2> <%--指定域获取--%> <hr> <h2>${pageScope.yg}</h2> <h2>${requestScope.yg}</h2> <h2>${sessionScope.yg}</h2> <h2>${applicationScope.yg}</h2>
输出结果:
EL 中的运算符
-
常用运算符
- 算术运算符:+、-、*、/、%(不支持++、–)
- 关系运算符:==、!=、>、>=、<、<=
- 逻辑运算符:!、&&、||、not、and、or
- 条件运算符:?:
- 取值运算符:[]、点号
-
empty运算符
用法为${empty 变量},结果为布尔值。
- 对于没有定义的变量,结果为true。
- 对于null,结果为true。
- 对于字符串空串,结果为true。
- 对于没有元素的数组或集合,结果为true。
EL 总结
- EL表达式不能出现在Java代码块、表达式块等JSP动态代码部分
- EL只能从四大域属性空间中获取数据(pageContext、request、session、application)
- EL不会抛出空指针异常,只会不显示
- EL不会抛出数组越界异常,只会不显示
-
七、JSP JavaBean
什么是javabean?
是一种JAVA语言写成的可重用组件,在JSP的开发中可以使用JavaBean减少重复代码,使整个JSP代码的开发更简洁。它本质就是一个实体,遵循着特定的写法:
- 必须有一个无参构造函数
- 属性必须私有化
- 私有化的属性必须有public类的get/set方法
属性名称符合这种模式,其他Java 类可以通过自省机制(反射机制)发现和操作这些JavaBean 的属性。
javabean示例:
//people实体类
public class people {
//属性私有化
private int id;
private String name;
private int age;
//无参构造
public people() {
}
//有参构造
public people(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
//get/set方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//重写toString方法用于调写
@Override
public String toString() {
return "people{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
JSP 中JavaBean的使用
对应于JavaBean,有以下三个JSP标签使用:
- useBean标签:用于在JSP页面中查找或实例化一个JavaBean组件。
- setProperty标签:用于在JSP页面中设置一个JavaBean组件的属性。
- getProperty标签:用于在JSP页面中获取一个JavaBean组件的属性。
对应着Java里面的new一个类,然后使用类里面的set方法对设置属性的值,再使用类里面的get方法去获得属性的值。
示例用法:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--id 为bean的名字; class 为自己编写的JavaBean实体类; scope 为bean的作用域--%>
<jsp:useBean id="people" class="com.yg.pojo.people" scope="page" />
<%--name 为useBean的id; property 为JavaBean实体类的属性; value 为设置属性的值--%>
<jsp:setProperty name="people" property="id" value="1" />
<jsp:setProperty name="people" property="name" value="宇哥" />
<jsp:setProperty name="people" property="age" value="18" />
<%--name 为useBean的id; property 为JavaBean实体类的属性;--%>
<jsp:getProperty name="people" property="id" />
<jsp:getProperty name="people" property="name" />
<jsp:getProperty name="people" property="age" />
</body>
</html>
useBean标签的执行原理
对于这个对象是怎么实例化出来的呢?我们肯定很好奇,我们打开前面 JSP原理 所提到的项目启动后所生成的jsp转换为java的那个文件,即目录:“C:\Users\86183.IntelliJIdea\system\tomcat\Tomcat_10_0_181_JavaWeb-jsp-maven\work\Catalina\localhost\JavaWeb_jsp_maven_war\org\apache\jsp”。查看一下useBean的原理,在_jspService()方法中可以看到people对象的创建过程,如下所示:
com.yg.pojo.people people = null;
people = (com.yg.pojo.people) _jspx_page_context.getAttribute("people", jakarta.servlet.jsp.PageContext.PAGE_SCOPE);
if (people == null){
people = new com.yg.pojo.people();
_jspx_page_context.setAttribute("people", people, jakarta.servlet.jsp.PageContext.PAGE_SCOPE);
}
可以看到**<jsp:useBean id=“people” class=“com.yg.pojo.people” scope=“page” />**的执行原理就是:首先在指定的域范围内查找指定名称的JavaBean对象,如果存在则直接返回该JavaBean对象的引用,如果不存在则实例化一个新的JavaBean对象并将它以指定的名称存储到指定的域范围中。
总结:
以上就是对于JSP中JavaBean的基本内容,学会三大JSP标签的使用即可掌握!JavaBean一般和数据库做字段映射(ORM) ,往往都是在操作数据库中用于使用!
ORM:对象关系映射
- 表---->类
- 字段---->属性
- 行记录---->对象
本次JSP的基础学习就到这了。文章内容是我个人参考多篇文章及视频的理解,有个别错误地方欢迎大家指出纠正,谢谢!