一、 Jsp基础
1、Jsp引入
① Servlet的作用: 用java语言开发动态资源的技术!!!
② Jsp的作用:用java语言(+html语言)开发动态资源的技术!!!
Jsp就是servlet!
2、Jsp的特点
① jsp的运行必须交给tomcat服务器!
tomcat的work目录: tomcat服务器存放jsp运行时的临时文件
① jsp页面既可以写html代码,也可以写java代码
(html页面不能写java代码,而jsp页面可以写java代码)
3、体验jsp页面作用
需求:显示当前时间到浏览器上
可以把jsp页面当做html页面在tomcat中访问!!!
<%@ page language="java" import="java.util.*,java.text.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>第一个jsp页面</title>
</head>
<body>
<%
//写java代码
//获取当前时间
SimpleDateFormat sdf = new SimpleDateFormat();
String curDate = sdf.format(new Date());
//输出内容到浏览器
//response.getWriter().write("");
out.write("当前时间为2:"+curDate);
%>
</body>
</html>
4、Jsp的执行过程
问题: 访问http://localhost:8080/day12/hello.jsp 如何显示效果?
① 访问到01.hello.jsp页面,tomcat扫描到jsp文件,在%tomcat%/work把jsp文件翻译成java源文件:(hello.jsp > _hello_jsp.java) (翻译)
② tomcat服务器把java源文件编译成class字节码文件 :(_hello_jsp.java > _hello_jsp.class)(编译)
③ tomcat服务器构造_hello_jsp类对象
④ tomcat服务器调用_hello_jsp类里面方法,返回内容显示到浏览器
第一次访问jsp:走①②③④
第n次访问jsp:走④
注意:jsp文件修改了或jsp的临时文件被删除了,就要重新走翻译①和编译②过程
5、问题: 为什么Jsp就是servlet!!!
jsp翻译的java文件:
public final class _hello_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent {}
HttpJspBase类:
public abstract class org.apache.jasper.runtime.HttpJspBase extends javax.servlet.http.HttpServlet implements javax.servlet.jsp.HttpJspPage {}
结论: Jsp就是一个servlet程序!!!
servlet的技术可以用在jsp程序中,jsp的技术并不是全部适用于servlet程序!
Servlet的生命周期:
1)构造方法(第1次访问)
2)init方法(第1次访问)
3)service方法
4)destroy方法
Jsp的生命周期
1)翻译: jsp->java文件
2)编译: java文件->class文件(servlet程序)
3)构造方法(第1次访问)
4)init方法(第1次访问):_jspInit()
5)service方法:_jspService()
6)destroy方法:_jspDestroy()
6、Jsp语法
① Jsp模板:jsp页面中的html代码就是jsp的模板
② Jsp表达式
◆ 语法:<%=变量或表达式%>
◆ 作用: 向浏览器输出变量的值或表达式计算的结果
◆ 注意:
◇ 表达式的原理就是翻译成out.print(“变量”);
通过该方法向浏览器写出内容
◇ 表达式后面不需要带分号结束
③ Jsp的脚本
◆ 语法:<%java代码 %>
◆ 作用: 执行java代码
原理:就是把脚本中java代码原封不动拷贝到_jspService方法中执行
<!-- 练习: 使用脚本和html代码显示99乘法表 -->
<%
for(int i=1;i<=9;i++){//行
for(int j=1;j<=i;j++){//公式
%>
<%=i %> x <%=j %>=<%=(i*j) %>
<%
}
%>
<br/>
<%
}
%>
④ Jsp的声明
◆ 语法:<%! 变量或方法 %>
◆ 作用: 声明jsp的变量或方法
注意:变量翻译成成员变量,方法翻译成成员方法
⑤ Jsp的注释
◆ 语法: <%!--jsp注释--%>
注意:html的注释<!--html注释-->
会被翻译和执行,而jsp的注释不能被翻译和执行
7、Jsp的三大指令
① include指令
◆ 作用: 在当前页面用于包含其他页面
◆ 语法: <%@include file="common/header.jsp"%>
◆ 注意:
◇ 原理是把被包含的页面(header.jsp)的内容翻译到包含页面(index.jsp)中,合并成翻译成1个java源文件,再编译运行,这种包含叫静态包含(源码包含)
◇ 如果使用静态包含,被包含页面中不需要出现全局的html标签了!(如html、head、body)
② page指令
◆ 作用: 告诉tomcat服务器如何翻译jsp文件
注意:在开发工具中,以后只需要设置pageEncoding即可解决中文乱码问题
<%@ page
language="java" -- 告诉服务器使用什么动态语言来翻译jsp文件
import="java.util.*" -- 告诉服务器java文件使用什么包;多个包的导入之间用逗号分割
pageEncoding="utf-8" -- 告诉服务器使用什么编码翻译成jsp文件
contentType="text/html; charset=utf-8" -- 服务器发送浏览器的数据类型和内容编码,这个属性可以省略,如果不写就参考pageEncoding
errorPage="error.jsp" -- 指定当前jsp页面的错误处理页面
isErrorPage="false" -- 指定当前页面是否为错误处理页面。false,不是错误处理页面,则不能使用exception内置对象;true,是错误处理页面,可以使用exception内置对象
buffer="8kb" -- jsp页面的缓存区大小
session="true" --是否开启session功能。false,不能用session内置对象;true,可以使用session内置对象
isELIgnored="false" -- 是否忽略EL表达式
%>
配置全局的错误处理页面
<!-- 全局错误处理页面配置 -->
<error-page>
<error-code>500</error-code>
<location>/common/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/common/404.html</location>
</error-page>
③ taglib指令
<%@taglib uri="tld文件的uri名称" prefix="标签库的简写" %>
二、Jsp的内置对象(重点)
1、什么是内置对象?
在jsp开发中,会频繁使用到一些对象,例如HttpSession、ServletContext、ServletContext、HttpServletRequet。如果我们每次要使用这些对象都去创建这些对象就显示非常麻烦。所以Sun公司设计Jsp时,在jsp页面加载完毕之后就会自动帮开发者创建好这些对象,而开发者只需要直接使用这些对象调用方法即可,这些创建好的对象就叫内置对象。
举例使用HttpSession对象:
① servlet:
HttpSession session = request.getSession(true);
(需要开发者做)
② jsp:
tomcat服务器:HttpSession session = request.getSession(true);
(不需要开发者做)
开发者做的: session.getId();
2、九大内置对象
内置对象名 | 类型 | 注释 |
---|---|---|
request | HttpServletRequest | 获取一些请求信息 |
response | HttpServletResponse | 设置响应信息 |
config | ServletConfig | 加载配置信息 |
application | ServletContext | web资源 |
session | HttpSession | 会话对象 |
exception | Throwable | 异常 |
page | Object(this) | 翻译过来的java的类对象 |
out | JspWriter | 带缓存 |
pageContext | PageContext | 上下文对象 |
3、Out对象
① out对象类型是JspWriter类,相当于带缓存的PrintWriter
② PrintWriter: wrier(内容): 直接向浏览器写出内容
③ JspWriter:writer(内容):向jsp缓冲区写出内容
④ 当满足以下条件之一,缓冲区内容写出:
◆ 缓冲区满了
◆ 刷新缓存区out.flush()
◆ 关闭缓存区buffer="0kb"
◆ 执行完毕jsp页面
4、pageContext对象
① pageContext对象的类型是PageContext,叫jsp的上下文对象
② 可以获取其他八个内置对象
使用场景: 在自定义标签的时候,PageContext对象频繁使用到!
//伪代码
public class _hello_jsp {
public void _jspService(request,response){
//创建内置对象
HttpSession session =....;
ServletConfig config = ....;
//把8个经常使用的内置对象封装到PageContext对象中
PageContext pageContext = 封装;
//调用method1方法
method1(pageContext);
}
public void method1(PageContext pageContext){
//希望使用内置对象
//从PageContext对象中获取其他8个内置对象
JspWriter out =pageContext.getOut();
HttpServletRequest rquest = pageContext.getRequest();
........
}
}
② 本身是一个域对象
ServletContext:context域 -- Servlet学习的
HttpServletRequet:request域 -- Servlet学习的
HttpSession:session域 -- Servlet学习的
PageContext:page域 -- jsp学习的
◆ 作用: 保存数据和获取数据,用于不同资源之间的共享数据
◆ 保存数据
◇ 默认情况下,保存到page域pageContext.setAttribute("name","value");
◇ 可以向四个域对象保存数据pageContext.setAttribute("name","value",域范围常量)
◆ 获取数据
◇ 默认情况下,从page域获取pageContext.getAttribute("name")
◇ 可以从四个域中获取数据pageContext.getAttribute("name",域范围常量)
◆ 域范围常量
PageContext.PAGE_SCOPE
PageContext.REQUEST_SCOPE
PageContext..SESSION_SCOPE
PageContext.APPLICATION_SCOPE
③ findAttribute()
自动在四个域中搜索数据
pageContext.findAttribute("name");
自动搜索的顺序: page域 > request域 > session域 > context域(application域)
三、Jsp中的四个域对象
pageContext:page域
request:request域
session:session域
application:context域
1、域对象作用:保存数据 和 获取数据 ,用于数据共享
2、域对象方法:
setAttribute("name",Object):保存数据
getAttribute("name"):获取数据
removeAttribute("name"):清除数据
3、域对象作用范围:
page域: 只能在当前jsp页面中使用(当前页面)【不同页面的转发也不能使用】
request域: 只能在同一个请求中使用【转发可以使用,重定向不行】
session域: 只能在同一个会话(session对象)中使用(私有的)
context域: 只能在同一个web应用中使用(全局的)
范围从上到下越来越大
四、Jsp的最佳实践
1、Servlet技术: 开发动态资源,是一个java类,最擅长写java代码
2、jsp技术: 开发动态资源,通过java代码最擅长输出html代码
3、各取所长:
在web项目中涉及到逻辑:
◆ 接收参数 -- servlet做
◆ 处理业务逻辑,返回结果 -- servlet做
◆ 显示数据到浏览器 -- jsp做
◆ 跳转到其他页面 -- servlet做
4、以后做项目:servlet+jsp模式
① servlet:
◆ 接收参数◆ 处理业务逻辑◆ 把结果保存到域对象中◆ 跳转到jsp页面
②Jsp:
◆ 从域对象取出数据◆ 把数据显示到浏览器
五、EL表达式
1、EL作用: 向浏览器输出域对象中的变量值或表达式计算的结果!
jsp的核心语法: jsp表达式 <%= %>
和 jsp脚本<% %>
以后开发jsp的原则: 尽量在jsp页面中少写甚至不写java代码
所以,使用EL表达式替换掉jsp表达式
2、EL语法: ${变量或表达式}
① 输出基本数据类型变量
◆ 从四个域中获取${name}
◆ 指定域获取${pageScope.name}
◆ 域范围: pageScoep、requestScope 、sessionScope 、applicationScope
② 输出对象的属性值Student
③ 输出集合对象 List 和 Map
<%
//保存数据
Student student = new Student("eric",20);
//放入域中
pageContext.setAttribute("student",student);
//List
List<Student> list = new ArrayList<Student>();
list.add(new Student("rose",18));
list.add(new Student("jack",28));
list.add(new Student("lucy",38));
//放入域中
pageContext.setAttribute("list",list);
//Map
Map<String,Student> map = new HashMap<String,Student>();
map.put("100",new Student("mark",20));
map.put("101",new Student("maxwell",30));
map.put("102",new Student("narci",40));
//放入域中
pageContext.setAttribute("map",map);
%>
<%--使用EL获取对象 --%>
${student.name} - ${student.age }
<%--${student.name} 等价于(点相对于调用getXX()方法)
<%=((Student)pageContext.findAttribute("student")).getName()%>
--%>
<hr/>
<%--使用EL获取List对象 --%>
${list[0].name } - ${list[0].age }<br/>
${list[1].name } - ${list[1].age }<br/>
${list[2].name } - ${list[2].age }
<%--
list[0]等价于(中括号相对于调用get(参数)方法)
((List)pageContext.findAttribute("list")).get(0)
--%>
<hr/>
<%--使用EL获取Map对象 --%>
${map['100'].name } - ${map['100'].age }<br/>
${map['101'].name } - ${map['101'].age }<br/>
${map['102'].name } - ${map['102'].age }<br/>
④ EL表达式计算
<%--1)算术表达式 + - * / --%>
${10+5 }<br/>
${10*5 }
<hr/>
<%--2)比较运算 > < >= <= == != --%>
${10>5 }<br/>
${10<5 }<br/>
${10!=10 }
<hr/>
<%-- 3)逻辑运算 && || ! --%>
${true && false }<br/>
${true || false }<br/>
${!false }<br/>
<hr/>
<%-- 4)判空 null或空字符串 empty --%>
<%
//String name = null;
String name = "";
pageContext.setAttribute("name",name);
%>
判断null: ${name==null }<br/>
判断空字符: ${name=="" }<br/>
判空: ${name==null || name=="" }
另一种判空写法: ${empty name }
五、Jsp标签
1、jsp标签的作用:替换jsp脚本
① 流程判断(if、for循环)
② 跳转页面(转发、重定向)
③ 。。。。。
2、Jsp标签分类
① 内置标签(动作标签):不需要在jsp页面导入标签
② jstl标签:需要在jsp页面中导入标签
③ 自定义标签:开发者自行定义,需要在jsp页面导入标签
3、动作标签
① 转发标签:<jsp:forward />
② 参数标签:<jsp:pararm />
③ 包含标签:<jsp:include />
<%--转发 --%>
<%
//request.getRequestDispatcher("/09.action2.jsp?name=eric").forward(request,response);
%>
<%-- 参数 --%>
<%--
<jsp:forward page="/09.action2.jsp">
<jsp:param value="jacky" name="name"/>
<jsp:param value="123456" name="password"/>
</jsp:forward>
--%>
<%-- 包含 --%>
<%--
<jsp:include page="/common/header.jsp">
<jsp:param value="lucy" name="name"/>
</jsp:include>
--%>
原理: 包含与被包含的页面先各自翻译成java源文件,然后再运行时合并在一起
(先翻译再合并),叫做动态包含
4、静态包含(指令)和动态包含(标签)的区别
① 语法不同
◆ 静态包含语法:<%@inclue file="被包含的页面"%>
◆ 动态包含语法:<jsp:include page="被包含的页面">
② 参数传递不同
◆ 静态包含不能向被包含页面传递参数
◆ 动态包含可以向被包含页面传递参数
③ 原理不同
◆ 静态包含: 先合并再翻译
◆ 动态包含: 先翻译再合并
5、JSTL标签
① JSTL (全名:java standard tag libarary: java标准标签库 )
◆ 核心标签库 (c标签库) 天天用
◆ 国际化标签(fmt标签库)
◆ EL函数库(fn函数库)
◆ xml标签库(x标签库) 不重要
◆ sql标签库(sql标签库) 不重要
② 使用JSTL标签步骤
◆ 导入jstl支持的jar包(标签背后隐藏的java代码)
注意:如果是javaee5.0的项目会自动导入jstl支持jar包
◆ 使用taglib指令导入标签库
<%@taglib uri="tld文件的uri名称" prefix="标签库的简写" %>
<uri>http://java.sun.com/jsp/jstl/core</uri>
和<short-name>c</short-name>
◆ 在jsp中使用标签
③ 核心标签库的重点标签
保存数据:
<c:set></c:set>
获取数据:
<c:out value=""></c:out>
单条件判断:
<c:if test=""></c:if>
多条件判断:
<c:choose></c:choose>
<c:when test=""></c:when>
<c:otherwise></c:otherwise>
循环数据:
<c:forEach></c:forEach>
<c:forTokens items="" delims=""></c:forTokens>
重定向:
<c:redirect></c:redirect>
<%--使用标签 --%>
<%--set标签 :保存数据(保存到域中)默认保存到page域 --%>
<c:set var="name" value="rose" scope="request"></c:set>
<%
String msg = null;
pageContext.setAttribute("msg",msg);
%>
${msg}
<br/>
<%--out标签: 获取数据(从域中)
default: 当value值为null时,使用默认值
escapeXml: 是否对value值进行转义,false,不转义,true,转义(默认)
--%>
<c:out value="${msg}" default="<h3>标题3</h3>" escapeXml="true"></c:out>
<hr/>
<%--if标签 :单条件判断--%>
<c:if test="${!empty msg}"> //test返回true或者false
条件成立
</c:if>
<hr/>
<%--choose标签+when标签+otherwirse标签: 多条件判断 --%>
<c:set var="score" value="100"></c:set>
<c:choose>
<c:when test="${score>=90 && score<=100}">
优秀
</c:when>
<c:when test="${score>=80 && score<90}">
良好
</c:when>
<c:when test="${score>=70 && score<80}">
一般
</c:when>
<c:when test="${score>=60 && score<70}">
及格
</c:when>
<c:otherwise>
不及格
</c:otherwise>
</c:choose>
<%-- forEach标签:循环 --%>
<%
//List
List<Student> list = new ArrayList<Student>();
list.add(new Student("rose",18));
list.add(new Student("jack",28));
list.add(new Student("lucy",38));
//放入域中
pageContext.setAttribute("list",list);
//Map
Map<String,Student> map = new HashMap<String,Student>();
map.put("100",new Student("mark",20));
map.put("101",new Student("maxwell",30));
map.put("102",new Student("narci",40));
//放入域中
pageContext.setAttribute("map",map);
%>
<%--
begin="":从哪个元素开始遍历,从0开始.默认从0开始
end="":到哪个元素结束,默认到最后一个元素
step="":步长(每次加几),默认1
items="":需要遍历的数据(集合)
var="":每个元素的名称
varStatus="":当前正在遍历元素的状态对象(count属性:当前位置,从1开始)
--%>
<c:forEach items="${list}" var="student" varStatus="varSta">
序号:${varSta.count} - 姓名:${student.name } - 年龄:${student.age}<br/>
</c:forEach>
<hr/>
<c:forEach items="${map}" var="entry">
${entry.key } - 姓名: ${entry.value.name } - 年龄:${entry.value.age }<br/>
</c:forEach>
<hr/>
<%-- forToken标签: 循环特殊字符串 --%>
<%
String str = "java-php-net-平面";
pageContext.setAttribute("str",str);
%>
<c:forTokens items="${str}" delims="-" var="s">
${s }<br/>
</c:forTokens>
<hr/>
<%--redrict:重定向 --%>
<c:redirect url="http://www.baidu.com"></c:redirect>