实际上访问index.jsp,index.jsp会被tomcat翻译生成index_jsp.java文件,然后tomcat服务器又会将index_jsp.java编译生成index_jsp.class文件。底层执行的是:index_jsp.class 这个java程序。
JSP实际上就是一个Servlet。
开发JSP的最高境界:眼前是JSP代码,但是脑袋中呈现的是java代码。 对JSP进行错误调试的时候,直接打开JSP文件对应的java文件,检查java代码。
职责不同:
在jsp文件中编写的HTML CSS JS代码,都会自动被翻译到servlet类的service方法的out.write(“jsp内容”),直接翻译到双引号里,被Java程序当做普通字符串打印输出到浏览器。
JSP结构:
<%@page contentType="text/html;charset=UTF-8"%>
以上代码表示响应的内容类型是text/html,采用的字符集UTF-8
<%@page import="包名"%> 导包
<html>
<head>
<title>$Title$</title>
</head>
<body>
$END$
</body>
</html>
在JSP中编写Java程序:
<% java表达式; %>
在这个符号当中编写的java表达式被视为java程序,会被被翻译到Servlet类的service方法内部。
<%= java表达式; %>
在这个符号当中编写的java表达式,会被翻译到out.print();
输出的内容中含有java的变量,输出的内容是一个动态的内容,不是一个死的字符串,在<%= %>里编写。如果输出的是一个固定的字符串,直接在JSP文件中编写即可。
<%! java表达式; %>
在这个符号当中编写的java表达式,会被翻译到service方法之外。
JSP的注释:
<%--JSP的专业注释,不会被翻译到java源代码当中。--%>
<!--这种注释属于HTML的注释,这个注释信息仍然会被翻译到java源代码当中,不建议。-->
<%// 这种注释与java注释相同,在翻译文件中有相应的注释内容 %>
<%/* 这种注释与java注释相同 */%>
总结:
JSP中直接编写普通字符串
翻译到service方法的out.write("这里")
<% %>
翻译到service方法体内部,里面是一条一条的java语句。
<%! %>
翻译到service方法之外。
<%= %>
翻译到service方法体内部,翻译为:out.print();
<%@page contentType="text/html;charset=UTF-8"%>
page指令,通过contentType属性用来设置响应的内容类型。
<%=request.getContextPath() %> 在JSP中动态的获取应用的根路径。
Servlet中连接数据库,查询并遍历结果集。
在JSP中:
page指示元素包含了与整个JSP页面相关的一些属性。一共有13种属性,常用的有以下几种:
//1. import属性
<%@ page import="java.util.Vector,java.io.*" %>
<%@ page import="java.util.*" %>
该属性用于指定在脚本环境中可以使用的Java类。
属性的值和Java程序中的import声明类似,该属性的值是以逗号分隔的导入列表。
page指令中只有import属性可以重复设置。
import 默认导入的列表是:`java.lang.*`,`javax.servlet.*`,`javax.servlet.jsp.*`和`javax.servlet.http.*`。
//2. isErrorPage属性
<%@ page isErrorPage="true|false" %>
该属性用于指定当前的JSP页面是否是另一个JSP页面的错误处理页面。默认值是false。
//3. errorPage属性
<%@ page errorPage="/error.jsp" %>
该属性用于指定当JSP页面发生异常时,将转向哪一个错误处理页面。
//4. contentType属性
<%@ page contentType="text/html; charset=gb2312" %>
contentType属性用来设置响应的内容类型。
但同时也可以设置字符集。
//5. pageEncoding属性
<%@ page pageEncoding="UTF-8" %>
该属性指定JSP页面使用的字符编码。如果设置了这个属性,则JSP页面的字符编码使用该属性指定的字符集,如果没有设置这个属性,则JSP页面使用contentType属性指定的字符集,如果这两个属性都没有指定,则使用字符集“ISO-8859-1”。
注:与contentType作用一致
// 6. Session属性
<%@ page session="true|false" %>
true表示启用JSP的内置对象session,表示一定启动session对象。没有session对象会创建。
如果没有设置,默认值就是session="true"
session="false" 表示不启动内置对象session。当前JSP页面中无法使用内置对象session。
page指令当中,有一个属性,可以忽略EL表达式
<%@page contentType="text/html;charset=UTF-8" isELIgnored="true" %>
isELIgnored="true" 表示忽略EL表达式
isELIgnored="false" 表示不忽略EL表达式。(这是默认值)
isELIgnored="true" 这个是全局的控制。
可以使用反斜杠进行局部控制:\${username} 这样也可以忽略EL表达式。
包含指令,在JSP中完成静态包含,很少用了。
引入标签库的指令。
pageContext < request < session < application
以上四个作用域都有:setAttribute、getAttribute、removeAttribute方法。
以上作用域的使用原则:尽可能使用小的域。
Expression Language(表达式语言)
EL表达式可以代替JSP中的java代码,让JSP文件中的程序看起来更加整洁,美观。JSP中夹杂着各种java代码,例如<% java代码 %>、<%=%>等,导致JSP文件很混乱,不好看,不好维护。所以才有了后期的EL表达式。
EL表达式可以算是JSP语法的一部分。EL表达式归属于JSP。
EL基本的语法格式:${表达式}
EL表达式的使用:
<%
// 创建User对象
User user = new User();
user.setUsername("admin");
user.setPassword("123");
user.setAge(18);
// 将User对象存储到某个域当中。一定要存,因为EL表达式只能从某个范围中取数据。
// 数据是必须存储到四大范围之一的。
request.setAttribute("userObj", user);
%>
使用EL表达式前:<%=request.getAttribute("userObj")%>
使用EL表达式后:${userObj}
<%=userObj.getusername()%>
${userObj.username} //前提有getxxx()方法,没有的话,会报500异常
${userObj} 底层是从域中取数据,取出user对象,然后调用user对象的toString方法,转换成字符串,输出到浏览器。
从map集合中取数据:${map.key}
从数组和list集合中取数据:${数组[0]},${list[0]}
<%=pageContext.getRequest()%>与<%=request%>一样
不通过EL表达式获取应用的根:<%=request.getContextPath()%>
通过EL表达式获取应用的根:${pageContext.request.contextPath}
// 在EL表达式中没有request这个影视对象
// requestScope 这个只代表"请求范围",不等同以request对象。
// 在EL表达式中有一个隐式对象pageContext和JSP中的九大内置对象pageContext是同一对象。
${abc} 和 ${"abc"}的区别是什么?
${abc}表示从某个域中取出数据,并且被取的这个数据的name是"abc",之前一定有这样的代码: 域.setAttribute("abc", 对象);
${"abc"} 表示直接将"abc"当做普通字符串输出到浏览器。不会从某个域中取数据了。
EL语言中的作用域包括页面作用域pageContext 、请求作用域request、会话作用域session和应用作用域application。
EL表达式优先从小范围
中读取数据。
EL表达式中有四个隐含的隐式的范围:
从对应的域中取数据:${xxxScope.存入的名称}
EL表达式对null进行了预处理。如果是null,则向浏览器输出一个空字符串。
// 假设userObj里面为null
<%=request.getAttribute("userObj")%> 输出:null
${userObj} 输出:
EL表达式取数据的时候有两种形式:
.
(大部分使用这种方式)${userObj.username}[]
(如果存储到域的时候,这个name中含有特殊字符,可以使用这种方式)${userObj[“username”]}EL表达式中其他的隐式对象:
EL表达式的运算符
Java Standard Tag Lib(Java标准的标签库)
JSTL标签库通常结合EL表达式一起使用。目的是让JSP中的java代码消失。
标签是写在JSP当中的,但实际上最终还是要执行对应的java程序。(java程序在jar包当中。)
第一步:引入JSTL标签库对应的jar包。
tomcat服务器没有的jar包要放在WEB-INF/lib目录下。
第二步:在JSP中引入核心标签库。(使用taglib指令引入标签库。)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
这个就是核心标签库。
<%--需求:将List集合中的元素遍历。--%>
<%--使用java代码--%>
<%
// 从域中获取List集合
List<Student> stus = (List<Student>)request.getAttribute("stuList");
// 编写for循环遍历list集合
for(Student stu : stus){
%>
id:<%=stu.getId()%>,name:<%=stu.getName()%><br>
<%
}
%>
<hr>
<%--使用core标签库中forEach标签。对List集合进行遍历--%>
<%--EL表达式只能从域中取数据。--%>
<%--var后面的名字是随意的。var属性代表的是集合中的每一个元素。--%>
<%--varStatus="这个属性表示var的状态对象,这里是一个java对象,这个java对象代表了var的状态,名字随意"--%>
<%--varStatus这个状态对象有count属性。可以直接使用。--%>
<c:forEach items="${stuList}" var="s" varStatus="stuStatus">
<%--varStatus的count值从1开始,以1递增,主要是用于编号/序号。--%>
编号:${stuStatus.count},id:${s.id},name:${s.name} <br>
</c:forEach>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
以上uri后面的路径实际上指向了一个xxx.tld文件。
tld文件是一个xml配置文件,在tld文件中描述了“标签”和“java类”之间的关系。
以上核心标签库对应的tld文件是:c.tld文件。
tomcat10之前:c.tld文件在standard.jar里面META-INF目录下。
tomcat10之后:c.tld文件在jakarta.servlet.jsp.jstl-2.0.0.jar里面META-INF目录下。
tomcat10之后的配置文件tld源码解析:
<tag>
<description>对该标签的描述</description>
<name>catch</name> 标签的名字
<tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class> 标签对应的java类。
<body-content>JSP</body-content> 标签体当中可以出现的内容,如果是JSP,就表示标签体中可以出现符合JSP所有语法的代码。例如EL表达式。
<attribute>
<description>
对这个属性的描述
</description>
<name>var</name> 属性名
<required>false</required> false表示该属性不是必须的。true表示该属性是必须的。
<rtexprvalue>false</rtexprvalue> 这个描述说明了该属性是否支持EL表达式。false表示不支持。true表示支持EL表达式。
</attribute>
</tag>
<c:catch var="">
JSP....
</c:catch>
// c:if
<c:if test="boolean类型,支持EL表达式"></c: if>
// c:forEach
<c:forEach items="集合,支持EL表达式" var="集合中的元素" varStatus="元素状态对象"> ${元素状态对象.count} </c: forEach>
<c:forEach var="i" begin="1" end="10" step="2"> ${i} </c: forEach>
// c:choose c:when c:otherwise
<c:choose>
<c:when test="${条件}"> // 条件只能是boolean类型
</c:when>
...
<c:when test="${条件}">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>