JavaWeb:JSP

JSP

  • JSP概念
  • JSP执行过程及原理理解
  • Servlet和JSP的区别
  • JSP的基础语法
  • 使用Servlet + JSP完成项目
  • JSP的指令元素
    • 1. page指示元素
    • 2. include指示元素
    • 3. taglib指示元素
  • JSP的九大内置对象
  • EL表达式
    • EL内置对象
  • JSTL标签库
    • 使用JSTL标签库的步骤:
    • JSTL标签的原理
    • jstl的核心标签库core中的常用标签

JSP概念

  1. JSP是Java程序(本质还是一个Servlet)。
  2. JSP是:JavaServer Pages的缩写(基于Java语言实现的服务器端的页面)。
  3. JSP也是JavaEE的13个子规范之一。
  4. JSP是一套规范,所有的web容器/web服务器都是遵循这套规范的,都是按照这套规范进行的“翻译”。
  5. 每一个web容器/web服务器都会内置一个JSP翻译引擎。

JSP执行过程及原理理解

JavaWeb:JSP_第1张图片
实际上访问index.jsp,index.jsp会被tomcat翻译生成index_jsp.java文件,然后tomcat服务器又会将index_jsp.java编译生成index_jsp.class文件。底层执行的是:index_jsp.class 这个java程序。
在这里插入图片描述
JSP实际上就是一个Servlet。

  • index.jsp访问的时候,会自动翻译生成index_jsp.java,会自动编译生成index_jsp.class,那么index_jsp 这就是一个类。
  • index_jsp 类继承 HttpJspBase,而HttpJspBase类继承的是HttpServlet。所以index_jsp类就是一个Servlet类。
  • jsp的生命周期和Servlet的生命周期完全相同。完全就是一个东西。没有任何区别。
  • jsp和servlet一样,都是单例的。(假单例)
  • jsp文件第一次访问的时候是比较慢的。
    • 第一次访问:
      • 要把jsp文件翻译生成java源文件
      • java源文件要编译生成class字节码文件
      • 然后通过class去创建servlet对象
      • 然后调用servlet对象的init方法
      • 最后调用servlet对象的service方法。
    • 第二次访问:
      • 直接调用单例servlet对象的service方法即可。

开发JSP的最高境界:眼前是JSP代码,但是脑袋中呈现的是java代码。 对JSP进行错误调试的时候,直接打开JSP文件对应的java文件,检查java代码。

Servlet和JSP的区别

职责不同:

  • Servlet的职责:收集数据。(Servlet的强项是逻辑处理,业务处理,然后链接数据库,获取/收集数据。)
  • JSP的职责:展示数据。(JSP的强项是做数据的展示)

JSP的基础语法

在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属性用来设置响应的内容类型。

使用Servlet + JSP完成项目

<%=request.getContextPath() %> 在JSP中动态的获取应用的根路径。

  • Servlet中连接数据库,查询并遍历结果集。

    • 遍历结果集的过程中,取出对应信息,封装成java对象。
    • 将java对象存放到List集合中。
    • 将List集合存储到request域当中。
    • 转发forward到jsp。
  • 在JSP中:

    • 从request域当中取出List集合。
    • 遍历List集合,取出每个对象,动态生成tr。

JSP的指令元素

1. page指示元素

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表达式。

2. include指示元素

包含指令,在JSP中完成静态包含,很少用了。

3. taglib指示元素

引入标签库的指令。

JSP的九大内置对象

JavaWeb:JSP_第2张图片

  1. jakarta.servlet.jsp.PageContext pageContext 页面作用域
  2. jakarta.servlet.http.HttpServletRequest request 请求作用域
  3. jakarta.servlet.http.HttpSession session 会话作用域
  4. jakarta.servlet.ServletContext application 应用作用域

pageContext < request < session < application
以上四个作用域都有:setAttribute、getAttribute、removeAttribute方法。
以上作用域的使用原则:尽可能使用小的域。

  1. java.lang.Throwable exception
  2. jakarta.servlet.ServletConfig config
  3. java.lang.Object page (其实是this,当前的servlet对象)
  4. jakarta.servlet.jsp.JspWriter out (负责输出)
  5. jakarta.servlet.http.HttpServletResponse response (负责响应)

EL表达式

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表达式优先从小范围中读取数据。

  • pageContext < request < session < application

EL表达式中有四个隐含的隐式的范围:

  • pageScope 对应的是 pageContext范围。
  • requestScope 对应的是 request范围。
  • sessionScope 对应的是 session范围。
  • applicationScope 对应的是 application范围。

从对应的域中取数据:${xxxScope.存入的名称}

EL表达式对null进行了预处理。如果是null,则向浏览器输出一个空字符串。

// 假设userObj里面为null
<%=request.getAttribute("userObj")%> 输出:null
${userObj} 输出:

EL表达式取数据的时候有两种形式:

  • 第一种:. (大部分使用这种方式)${userObj.username}
  • 第二种:[](如果存储到域的时候,这个name中含有特殊字符,可以使用这种方式)${userObj[“username”]}

EL表达式中其他的隐式对象:

  • pageContext
  • param
  • paramValues
  • initParam

EL表达式的运算符

  • 算术运算符:+、-、*、/、%
  • 关系运算符:== eq != > >= < <=
  • 逻辑运算符:! && || not and or
  • 条件运算符:? :
  • 取值运算符:[]和.
  • empty运算符:
    • empty运算符的结果是boolean类型
    • ${empty param.username}
    • ${not empty param.username}
    • ${!empty param.password}

EL内置对象

JavaWeb:JSP_第3张图片

JSTL标签库

Java Standard Tag Lib(Java标准的标签库)
JSTL标签库通常结合EL表达式一起使用。目的是让JSP中的java代码消失。
标签是写在JSP当中的,但实际上最终还是要执行对应的java程序。(java程序在jar包当中。)

使用JSTL标签库的步骤:

  • 第一步:引入JSTL标签库对应的jar包。

    • tomcat10之前引入的jar包是:
      • jstl.jar
      • standard.jar
    • tomcat10之后引入的jar包是:
      • jakarta.servlet.jsp.jstl-2.0.0.jar
      • jakarta.servlet.jsp.jstl-api-2.0.0.jar
  • tomcat服务器没有的jar包要放在WEB-INF/lib目录下

  • 第二步:在JSP中引入核心标签库。(使用taglib指令引入标签库。)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
这个就是核心标签库。
  • 第三步:在需要使用标签的位置使用即可。表面使用的是标签,底层实际上还是java程序。
<%--需求:将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>

JSTL标签的原理

<%@ 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>

jstl的核心标签库core中的常用标签

// 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>

你可能感兴趣的:(JavaWeb,java,web,java-ee)