JSP(全称 Java Server Pages,Java 的服务器页面)是由 Sun 公司专门为了解决动态生成 HTML 文档的技术。
jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据。
如果我们要往客户端输出一个页面,我们可以使用 Servlet 程序来实现,但是十分不方便和繁琐。 并且有些复杂的页面上千上万行,那就更加的困难,开发成本和维护成本都极高。 所以 sun 公司推出一种叫做 jsp 的动态页面技术帮助我们实现对页面的输出繁锁工作。
选中 Web目录,右键创建一个 jsp 文件
输入 jsp 页面的文件名
在 body 标签中添加你想要显示的文本内容
然后启动Tomcat,在浏览器中输入 jsp 页面的访问地址
jsp 页面的访问地址和 html 页面的访问路径一样 http://ip地址:端口号/工程名/文件名
注意:jsp 页面的访问千万不能像 HTML 页面一样,直接手拖到浏览器中或是直接用地址名访问。只能通过启动 Tomcat 服务器再用浏览器访问 jsp 页面
jsp 页面本质上是一个 Servlet 程序。
当我们第一次访问 jsp 页面的时候,Tomcat 服务器会帮我们把 jsp 页面翻译成为一个 java 源文件。并且把它进行编译成为.class 字节码程序。我们可以通过启动Tomcat时IDEA的输出,找到Using CATALINA_BASE这一项,复制后面的地址到我的电脑的地址栏,再逐步点进work/Catalina/localhost/项目名org/apache/jsp
,就可以找到我们的jsp页面翻译后的java源文件。我们打开 java 源文件不难发现其里面的内容是:
我们跟踪原代码发现,这个jsp翻译出来的类继承了HttpJspBase 类,查看HttpJspBase的源码发现,它直接地继承了 HttpServlet 类。也就是说:jsp 翻译出来的 java 类,它间接了继承了 HttpServlet 类。也就是说,jsp页面翻译出来的是一个 Servlet 程序。
总结:jsp 就是 Servlet 程序。
当我们访问 一个 xxx.jsp
文件后,翻译成 java 文件的全名是 xxx_jsp.java
文件
大家也可以去观察翻译出来的 Servlet 程序的源代码,不难发现,其底层实现,也是通过输出流,把 html 页面数据回传给客户端:
jsp 的 page 指令可以修改 jsp 页面中一些重要的属性,或者行为。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
page指令中有如下属性:
/
斜杠打头,它表示请求地址为 http://ip:port/工程路径/
,映射到代码的 Web 目录格式:
<%!
java 代码
%>
作用:可以给 jsp 翻译出来的 java 类定义全局变量、方法、静态代码块和内部类等。 (几乎可以写在类的内部写的代码,都可以通过声明脚本来实现)
格式: <%=表达式 %>
作用:表达式脚本用于向页面输出内容。
案例:
<%=12 %> <br>
<%=12.12 %> <br>
<%="我是字符串" %> <br>
<%=map%> <br>
<%=request.getParameter("username")%>
12345
格式:
<%
java 代码
%>
作用:代码脚本里可以书写任意的 java 语句。
练习2:jsp 输出一个表格,里面有 10 个学生信息
Student类:
public class Student {
//用Integer而不是int,当没有数据时,此属性默认值为null而不是0,毕竟0也是个确定的数值
private Integer id;
private String name;
private Integer age;
private String phone;
public Student() {
}
public Student(Integer id, String name, Integer age, String phone) {
this.id = id;
this.name = name;
this.age = age;
this.phone = phone;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", phone='" + phone + '\'' +
'}';
}
}
Servlet:
import com.fox.bean.Student;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class SearchStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 使用for循环生成查询到的数据做模拟
List<Student> studentList = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
int t = i + 1;
studentList.add(new Student(t,"name"+t, 18+t,"phone"+t));
}
// 保存查询到的结果(学生信息)到request域中
req.setAttribute("stuList", studentList);
// 请求转发到showStudent.jsp页面
req.getRequestDispatcher("/showStudent.jsp").forward(req,resp);
}
}
web.xml:
<servlet>
<servlet-name>SearchStudentServletservlet-name>
<servlet-class>com.fox.servlet.SearchStudentServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>SearchStudentServletservlet-name>
<url-pattern>/searchStudentServleturl-pattern>
servlet-mapping>
html 注释会被翻译到 java 源代码中,在_jspService() 方法里,以 out.writer 输出到客户端。
用于给脚本中的java代码注释
<%
// 单行 java 注释
/*
多行 java 注释
*/
%>
java 注释会被翻译到 java 源代码中。
<%-- 这是 jsp 注释 --%>
jsp 注释可以注释掉jsp 页面中所有代码
我们打开翻译后的 java 文件,查看_jspService() 方法:
jsp 中九大内置对象分别是:
九大内置对象,都是我们可以在【代码脚本】或【表达式脚本】中直接使用的对象
四大域对象经常用来保存数据信息。
四个域对象分别是:
域对象就是可以像 Map 一样存取数据的对象。四个域对象功能一样,不同的是它们对数据的存取范围。 虽然四个域对象都可以存取数据。在使用上它们是有优先顺序的。 四个域在使用的时候,优先顺序是他们有效范围从小到大的顺序:
pageContext ——>request——> session ——> application
案例:测试四个域对象的作用域(有效范围)
context1.jsp:
a.jsp:
浏览器访问a.jsp:
图解 out 流和 writer 流的两个缓冲区如何工作:
当jsp页面所有代码执行完成后会做以下两个操作:
由于 jsp 翻译之后,底层源代码都是使用 out 来进行输出,所以一般情况下,我们在 jsp 页面中统一使用 out 输出流来进行输出,避免打乱页面输出内容的顺序。
out.write()
输出字符串没有问题,但是输出别的类型会得不到想要的结果out.print()
输出任意数据类型都没有问题(都会转换成为字符串后调用out.write()
输出)结论:在 jsp 页面中,可以统一使用 out.print()来进行输出
开发中,我们可能会写很多网页,但是假设每个网页的页脚信息都是一样的,而我们需要修改页脚信息就要把每个网页都修改一遍很麻烦,于是想到将页脚信息提取出来成为单独一份jsp,再将它包含到每个网页即可。(静态包含或动态包含)
静态包含是把包含的页面内容原封不动地输出到包含的位置。
格式:
<%@ include file="/被包含的 jsp 页面的路径" %>
file 属性指定你要包含的jsp页面的路径
地址中第一个斜杠 /
表示为http://ip:port/工程路径/
映射到代码的web目录
我们可以在main.jsp翻译出来的java源代码中看到被包含的jsp的内容:
静态包含的特点:
动态包含会把包含的 jsp 页面单独翻译成 servlet 文件,然后在执行到的时候再调用翻译的 servlet 程序,并把计算的结果返回。 动态包含是在执行的时候,才会加载,所以叫动态包含。
格式:
<jsp:include page="/被包含的 jsp 页面的路径">jsp:include>
案例:
JspRuntimeLibrary.include(request, response, "/footer.jsp", out, false);
静态包含 | 动态包含 | |
---|---|---|
是否生成 java 文件 | 不生成 | 生成 |
_JspService() 方法中的区别 | 把被包含的内容原封拷贝到 _JspService() 中 | _JspService() 方法中调用JspRuntimeLibrary.include 方法 |
是否可以传递参数 | 不能 | 可以 |
编译次数 | 1 | 被包含的文件数 + 1 |
适用范围 | 适用包含纯静态内容(CSS,HTML,JS),或没有非常耗时操作、或大量 java 代码的 jsp | 包含需要传递参数,或含有大量 java代码的jsp |
在这里需要补充说明一点:我们在工作中,几乎都是使用静态包含。理由很简单,因为 jsp 页面虽然可以写 java 代码,做其他的功能操作,但是由于 jsp 在开发过程中被定位为专门用来展示页面的技术。也就是说,jsp 页面中,基本上只有 html,css,js,还有一些简单的 EL,表达式脚本等输出语句,所以我们都使用静态包含。
格式:
<jsp:forward page="/转发的路径">jsp:forward>
相当于 request.getRequestDispatcher("/xxxx.jsp").forward(request, response);
的功能。
public interface ServletContextListener extends EventListener {
// 在 ServletContext 对象创建之后马上调用,做初始化
public void contextInitialized(ServletContextEvent sce);
// 在 ServletContext 对象销毁之后调用
public void contextDestroyed(ServletContextEvent sce);
}
如何使用 ServletContextListener 监听器监听 ServletContext 对象?
使用步骤如下:
案例:
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext对象被创建了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext对象被销毁了");
}
}
web.xml:
<listener>
<listener-class>com.fox.servlet.MyServletContextListenerlistener-class>
listener>
启动web工程:
停止web工程: