jsp
jsp 介绍
- jsp:java server pages,用于替代 html 页面的动态页面。
- jsp 页面本质上是一个 Servlet 程序,当第一次访问 jsp 页面时,Tomcat 服务器会自动将 jsp 页面转换成一个 java 源文件,并进一步编译成 .class 字节码文件。jsp 转换成的 java 类,间接继承了 HttpServlet 类,因此,每个 jsp 页面都是一个 Servlet 程序。
语法
jsp 的 page 指令可以修改 jsp 页面中的一些属性或行为
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
- language 属性:表示 jsp 页面被 tomcat 服务器转换为何种语言的文件,暂时只支持 java。
- contentType 属性:表示 jsp 返回给客户端的数据类型,即源码中 response.setContentType()的参数值。
- pageEncoding 属性:表示当前 jsp 页面本身的字符集。
- import 属性:用于导包、导类。
- autoFlush 属性:设置当 out 输出流缓冲区满了之后,是否自动刷新缓冲区,默认值为 true。
- buffer 属性:设置 out 缓冲区的大小,默认为 8kb。
- errorPage 属性:设置当 jsp 页面运行出错时,自动跳转到的错误页面的路径。
注意:errorPage 表示错误后自动跳转的路径,该路径一般以斜杠开始,表示请求地址为 http://ip:port/工程路径/ 映射到代码的 Web 目录 - isErrorPage 属性:设置当前 jsp 页面是否是错误信息页面,默认为 false,如果为 true 可以获取异常信息。
- session 属性:设置访问当前 jsp 页面,是否会创建 HttpSession 对象,默认为 true。
- extends 属性:设置 jsp 转换成的 java 类默认继承哪个父类。
jsp 脚本
声明脚本(极少使用)
声明脚本的格式为: <%! 声明 java 代码 %>
作用:可以给 jsp 转换的 java 类定义属性、方法、静态代码块、内部类等。
<%@ page import="java.util.Map"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jsp脚本</title>
</head>
<body>
<%-- 声明脚本:可以给jsp解析出来的java类定义属性、方法、静态代码块、内部类等。 --%>
<%-- 声明属性 --%>
<%!
private String name;
private int age;
private static Map<Integer, String> map;
%>
<%-- 声明方法 --%>
<%!
public int add(int a, int b){
return a+b;
}
%>
<%-- 声明静态代码块 --%>
<%!
static {
map.put(1, "val1");
map.put(2, "val2");
map.put(3, "val3");
}
%>
<%-- 声明内部类 --%>
<%!
public class A{
private int id;
private double salary;
}
%>
</body>
</html>
表达式脚本
表达式脚本的格式为:<%= 表达式 %>
表达式脚本的作用是:在 jsp 页面上输出数据。
表达式脚本的特点:
- 所有的表达式脚本都会被翻译到_jspService() 方法中。
- 表达式脚本都会被写入 out.print() 中输出到页面上。
- 由于表达式脚本翻译的内容都在_jspService() 方法中,所以_jspService()方法中的对象都可以直接使用。
- 表达式脚本中的表达式不能以分号结束。
<%@ page import="java.util.Map"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jsp脚本</title>
</head>
<body>
<%-- 表达式脚本:在jsp页面上输出数据 --%>
<%-- 输出常规数据 --%>
<%= 123 %>
<%= 3.14 %>
<%= "string" %>
<%-- 输出对象 --%>
<%= map %>
<%-- 获取请求参数 --%>
<%= request.getParameter("username") %>
</body>
</html>
代码脚本
代码脚本的格式为:
<%
java 语句;
%>
代码脚本的作用是:可以在 jsp 页面中,编写我们自己需要的功能(写的是 java 语句)。
代码脚本的特点:
- 代码脚本翻译之后都在_jspService 方法中。
- 代码脚本由于翻译到_jspService()方法中,所以在_jspService()方法中的现有对象都可以直接使用。
- 可以由多个代码脚本组合完成一个完整的 java 语句。
- 可以和表达式脚本一起组合使用,在 jsp 页面上输出数据。
<%@ page import="java.util.Map"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jsp脚本</title>
</head>
<body>
<%-- 代码脚本:可以在jsp页面中,编写java语句 --%>
<%
for(int i=1; i<3; i++){
System.out.println(i);
}
%>
<%
String username = request.getParameter("username");
System.out.println(username);
%>
</body>
</html>
脚本练习
练习1:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>table</title>
</head>
<body>
<!-- 根据用户输入的行数,输出对应行数的列表 -->
<table border="1">
<%-- 列表的函数动态生成,封装到jsp代码中 --%>
<%
String rowStr = request.getParameter("row");
for(int i=0; i<Integer.parseInt(rowStr); i++) {
%>
<tr>
<td>第<%= i %>行</td>
</tr>
<%
}
%>
</table>
</body>
</html>
练习2:打印九九乘法表
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
table {
width: 650px;
}
</style>
</head>
<body>
<%-- 输出乘法口诀表,行数由输入的参数决定 --%>
<%
String row = request.getParameter("row");
%>
<h2 align="center">乘法口诀表(<%= row+"x"+row %>)</h2>
<table align="center">
<%
for(int i=0; i<Integer.parseInt(row); i++){
%>
<tr>
<%
for(int j=0; j<i+1; j++){
int sum = (i+1)*(j+1);
%>
<td><%= (j+1)+"x"+(i+1)+"="+sum %></td>
<%
sum = 0;
}
%>
</tr>
<%
}
%>
</table>
</body>
</html>
jsp 注释
-
html 注释
<!-- 这是 html 注释 --> -
java 注释
<%
// 单行 java 注释
/* 多行 java 注释 */
%> -
jsp 注释
<%-- 这是 jsp 注释 --%>
jsp 注释可以注掉,jsp 页面中所有代码。
jsp 九大内置对象
对象 | 意义 |
---|---|
request | 请求对象 |
response | 响应对象 |
pageContext | jsp 上下文对象 |
session | 会话对象 |
application | ServletContext 对象 |
config | ServletConfig 对象 |
out | jsp 输出流对象 |
page | 当前 jsp 页面对象 |
exception | 异常对象 |
jsp 四大域对象
对象 | 所属类 | 有效范围 |
---|---|---|
pageContext | PageContextImpl 类 | 当前 jsp 页面内有效 |
request | HttpServletRequest 类 | 一次请求内有效 |
session | HttpSession 类 | 一个会话内有效(打开浏览器访问服务器,直到关闭浏览器) |
application | ServletContext 类 | 整个 web 工程内有效(只要 web 工程不停止,数据都共享) |
四个域对象从小到大的范围为:pageContext < request < session < application
存数据页面:
<body>
<%
//向四个域中保存数据
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
<%-- 取数据 --%>
pageContext 域是否有值:<%=pageContext.getAttribute("key")%> <br>
request 域是否有值:<%=request.getAttribute("key")%> <br>
session 域是否有值:<%=session.getAttribute("key")%> <br>
application 域是否有值:<%=application.getAttribute("key")%> <br>
<%
request.getRequestDispatcher("/scope2.jsp").forward(request,response);
%>
</body>
out 输出流
在 jsp 页面中,可以统一使用 out.print() 进行输出
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%--
两个输出流:
out
response.getWriter()/getOutputStream()
两个流在输出基本数据类型(如int)时:
(1)out.write(int i)与response.getWriter().write(int i)不能正常输出,会将i转换为对应的ASCII码
(2)out.print(int i)与response.getWriter().print(int i)可以正常输出
因此使用print()输出较好
特点:
out与response.getWriter()都有属于之自己的缓冲区,out写出的数据先存放在out缓冲区中,
当页面执行结束后,自动调用flush()方法,将out缓冲区中的数据追加到response缓冲区末尾,
因此,即使先写out输出语句,后写response输出语句,也是先输出response内容(手动flush除外)
--%>
<%
out.print(12);
out.write(13);
%>
</body>
</html>
jsp 标签
静态包含
<%@ include file="/地址" %>
file 属性表示被包含的页面所在的地址,一般以斜杠开始,表示工程的web目录
静态包含.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>这是标题</h1>
<div>这是内容</div>
<!-- 接下来的页尾由通用内容组成,多个页面共享该内容,当需要维护时,只需要修改资源页面代码即可 -->
<%-- / 斜杠表示路径为 http://localhost:8080/工程路径/ 对应工程的WebContent目录 --%>
<%@ include file="/jsp/staticInclude/staticIncludePage.jsp" %>
</body>
</html>
被包含的页面 staticIncludePage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div>静态包含页面</div>
</body>
</html>
动态包含
<jsp:include page="/地址"></jsp:include>
page 属性表示被包含的页面所在的地址,一般以斜杠开始,表示工程的web目录
动态包含可以通过 <jsp:param name="" value=""/> 传递数据给被包含的页面,被包含的页面可以通过 request.getParameter() 获取这些数据
动态包含.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>这是标题</h1>
<div>这是内容</div>
<!--
下面演示动态包含,动态包含可以传数据给被包含的页面,被包含的页面可以通过request.getParameter()获取这些数据
-->
<jsp:include page="/jsp/dynamicInclude/dynamicIncludePage.jsp">
<jsp:param name="username" value="admin"/>
</jsp:include>
</body>
</html>
被包含的页面 dynamicIncludePage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div>动态包含页面</div>
<%=request.getParameter("username") %>
</body>
</html>
请求转发
<jsp:forward page=""></jsp:forward>
page 属性表示被包含的页面所在的地址,一般以斜杠开始,表示工程的web目录
初始页面 initPage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%--
Servlet中的请求转发语句
request.getRequestDispatcher(String path).forward(Request req, Response resp);
在jsp中可以用下面的请求转发标签实现,且效果相同
--%>
<%
out.print("初始页面");
%>
<jsp:forward page="/requestTransmit/transmitPage.jsp"></jsp:forward>
</body>
</html>
要转发到的页面 transmitPage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
out.print("转发页面");
%>
</body>
</html>
Listener 监听器
介绍
- Listener 监听器是 JavaWeb 的三大组件之一,JavaWeb 的三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
- Listener 是 JavaEE 规范,即接口。
- 监听器的作用是:监听事件,然后通过回调函数,反馈给客户(程序)去做相应的处理。
ServletContextListener 监听器
- ServletContextListener 用于监听 ServletContext 对象的创建和销毁。
- 由于一个项目只有一个 ServletContext 对象,因此该监听器只有在项目开启和关闭时才会被触发。
public interface ServletContextListener extends EventListener {
/**
* 在 ServletContext 对象创建之后马上调用,做初始化
*/
public void contextInitialized(ServletContextEvent sce);
/**
* 在 ServletContext 对象销毁之后调用
*/
public void contextDestroyed(ServletContextEvent sce);
}
实现监听器
步骤如下:
- 编写一个类实现 ServletContextListener
- 实现两个回调方法
- 到 web.xml 中配置监听器
监听器类:
public class MyServletContextListenerImpl 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.atguigu.listener.MyServletContextListenerImpl</listener-class>
</listener>