目录
生命周期
我们虽然写的是jsp,代码中包含了html、css、js,以及Java代码,但是真正执行的是一个servlet。当我们把jsp写好之后,经过一些操作之后,会将该jsp转换为一个servlet(将html、css、js当做字符串输出),形成一个java文件,然后进行编译,产生class文件。最终请求该jsp,执行的就是对应servlet的class文件。
jsp的生命周期有一下几个阶段:
编译阶段
当浏览器请求JSP页面时,JSP引擎会首先去检查是否需要编译这个文件。如果这个文件没有被编译过,或者在上次编译后被更改过,则编译这个JSP文件。如果这个文件已经编译过,说上次编译过之后,jsp文件未修改过,则不用再次编译。编译的时候,会先解析jsp文件,将其转换为servlet,然后编译该servlet。
我们可以随意编写一个jsp,假设命名为demo.jsp,那么转换后的servlet文件名为demo_jsp.java,而编译后生成的是demo_jsp.class。
初始化阶段
初始化阶段之前,jsp文件已经被转换为servlet了,此时的初始化操作,就是调用转化后servlet中的jspInit()方法。
执行阶段
执行阶段就是调用转换后的servlet中的_jspService,和普通servlet中的service一样接收request和response。
销毁阶段
和servlet的destroy一样,调用jspDestroy进行一些清理操作。
9大对象
可以写一个demo.jsp,查看生成的demo_jsp.java中的代码,你会发现,我们写的jsp代码,其实就是在写对应jsp_servlet中的_jspService方法。
并且,我们会发现,在生成的demo_jsp.java中,有很多的代码都是自动生成的,生成的代码中包含了9个对象,我们可以在jsp中使用他们。这9个对象分别是:
类型 对象 | 解释 | 作用范围 |
javax.servlet.http.HttpServletRequest request |
和servlet中的reqeust对象一样 包含请求信息 |
一次请求 |
javax.servlet.http.HttpServletResponse response |
和servlet中的response对象一样 响应处理结果 |
一次请求 |
javax.servlet.jsp.PageContext pageContext |
页面上下文对象(包含jsp所有运行信息) 封装了其他8个内置对象 每一个jsp文件有一个自己的pageContext 每次请求的pageContext都不同。 |
当前页面 |
javax.servlet.http.HttpSession session | 和servlet中的session一样使用 | 一次会话 |
javax.servlet.ServletContext application |
就是ServletContext对象,一个项目只有一个, 用于存储用户共享的数据 |
整个项目 |
javax.servlet.ServletConfig config |
就是servlet中的servletConfig对象 可以获取web.xml中的配置数据(为本servlet配置的数据) |
|
javax.servlet.jsp.JspWriter out |
jsp内部使用的输出对象(带有缓冲) 相当于servlet中的response.getWriter() |
本页面 |
java.lang.Object page | 代表当前jsp对象,相当于转换后的servlet的this | 当前页面 |
javax.lang.Throwable exception |
异常对象,存储当前运行的异常信息 需要使用page执行,设置isErrorPage="true"来开启 |
当前页面 |
常用指令
指令可以用来设置jsp页面的属性。指令的形式如下:
<%@ 指令名 key="value" %>
常用的有三个指令,分别是page、include、taglib:
page指令
用于定义网页依赖属性,比如脚本语言、error页面、缓存需求等等;
比如我们设置当前页面的语言、编码格式、字符集、导入哪些类、是否使用session、设置错误页面、
<%@ page
language="java"
contentType="text/html; charset=utf-8"
errorPage="error.html"
import="java.util.Date"
session="true"
pageEncoding="utf-8"
%>
include指令
用来包含其他文件,类似于php的include()函数
<%@ include file="demo.jsp" %>
taglib指令
用来引入标签库的定义,比如要使用jstl标签库,都要使用tablib导入
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
基本语法
java代码使用<% %>括起来即可,比如下面定义了一个方法,在方法中使用上面介绍的9个内置对象,然后调用方法:
<%
out.println("hello world");
out.println(request.getRequestURL());
%>
如果我们想注释掉jsp中的某些java代码,我们不希望他出现在转换后的servlet中,也不会出现在客户端获取到的响应html中,那么我们可以使用下面这种格式:
<%--
out.println("this is comment");
这部分内容不会出现在servlet中,也不会出现在html代码中
--%>
前面已经介绍了,使用指令,可以用下面的格式:
<%@ 指令名 key="value" %>
输出数据,虽然我们可以使用out.print()来输出,但是,稍显复杂,可以使用下面的方式:
<% int a = 10;%> <% out.println(a); %>
等价于
<%= a%>
表达式语言(EL)
其实就是对${ } 的使用。
<%
request.setAttribute("name", "aaaaaaaa");
%> <a>${name}</a>
${ } 可以对其中的内容进行处理或者计算,可以像对象一样在里面使用.表示访问属性:
${person.name}
还可以进行数学运算
<h1>${100*2}</h1>
${ } 可以访问哪些数据?包含以下四个作用域的数据都可以访问,作用域范围从小到大依次是:
pageScope | page 作用域 |
requestScope | request 作用域 |
sessionScope | session 作用域 |
applicationScope | application 作用域 |
在不加作用域的时候,默认是pageScope作用域。如果要指定访问哪一个作用域的参数,可以使用下面的格式:
${name} 等价于 ${pageScope.name} ${sessionScope.name} 访问sessionScope下的name
下面说明了每一个作用域的使用方法:
<%
String data = "aaaaaaa";
%>
<%= data%> <c:set var="data" value="xxx"></c:set>
${pageScope.data } <%
request.setAttribute("data1", "requestData");
// 或者是在servlet中通过request.setAttribute()来设置的参数
%>
${requestScope.data1} <%
session.setAttribute("data2", "sessionData");
//或者是在servlet中通过request.getSession().setAttribute()设置的参数
%>
${sessionScope.data2} <%
application.setAttribute("data3", "applicationData");
// 或者是在servlet中通过this.getServletContext().setAttribute()设置的参数
%>
${applicationScope.data3}
还有几个用法:
EL | 在servlet中相当于 |
获取请求参数(注意,作用域是page) |
|
${param.key} ${param["key"]} |
request.getParameter("key") |
${paramValues.key} ${paramValues["key"]} |
request.getParameterValues("key") |
获取header信息 |
|
${header.key} ${header["key"]} |
request.getHeader("key") |
${headerValues.key} ${headerValues["key"]} |
request.getHeaders("key") |
对于整个application,在web.xml中设置的配置项 |
|
${pageContext.key} ${pageContext["key"] |
在servlet中使用 this.getServletContext().getInitParameter("key") |
jstl介绍
jstl可以用来简化我们平时开发中的很多复杂操作,比如条件判断、循环、输出。
需要使用taglib指令来引入标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set>
在jsp页面中设置变量,可以指定作用域,默认是pageScope。
<c:set var="变量名" scope="作用域" value="值"/>
<c:out>
输出内容,相当于<%= value %>,不过可以指定默认值。
<c:out value="${sessionScope.name}" default="xyz"></c:out>
<c:out value="${pageScope.name }"></c:out>
<c:remove>
删除某个作用域中的参数值
<c:remove var="age" scope="request"/>
<c:if>
<c:if test="${param.age > 18}">
<c:out value="bigger than 18"></c:out>
</c:if>
<c:choose>
相当于switch~case、if~else
<c:choose>
<c:when test="${param.age > 9}">
bigger than 9
</c:when>
<c:when test="${param.age == 9 }">
equal with 9
</c:when>
<c:otherwise>
smaller than 9
</c:otherwise>
</c:choose>
<c:forEach>
for (int index = 0; index < data.length; index++) {
System.out.println(data[index]);
}
使用jstl实现的方式如下:
<c:forEach var="index" begin="0" end="${data.length}" step="1">
<c:out value="${data[index]}"></c:out>
</c:forEach> List<Person> list = new ArrayList<>();
for (Person person : list) {
System.out.println(person.name);
System.out.println(person.age);
}
使用jstl实现的方式如下:
<c:forEach items="${list}" var="person">
<c:out value="${person.name}"></c:out>
<c:out value="${person.age}"></c:out>
</c:forEach>