JSP
1).初识JSP、脚本元素、执行/编译原理、指令元素、内置对象
(1)概念: J(Java) S(Server) P(Page)
可以运行在服务器端的动态显示页面技术.
本质: JSP运行时候,本质就是servlet程序。
作用: 负责动态数据展示。 替代servlet中view的servlet程序。
文件命名: `*.jsp`
代码书写形式: 在HTML标签中,个别嵌套java代码。
JSP部署位置: 相当于HTML
访问: 相当于HTML
(2)JSP脚本元素
可以书写Java代码标签。
①表达式脚本:
作用:运行java代码,并产生结果;将结果显示给浏览器
语法格式: <%= java的表达式 %>
注意事项:不能在java表达式结尾写”;”号
②声明脚本:
作用:声明变量(相当于service的servlet的属性),定义函数(service方法外的方法)
语法格式:<%! 声明函数或者定义变量的代码%>
③普通脚本:
作用:书写并运行流程控制普通java代码
语法格式:<% 普通java代码 %>
注意问题:JSP中java脚本标签不能嵌套的。
(3)JSP执行、编译原理
执行原理:
浏览器-->A.jsp--(tomcat将jsp翻译成servlet)---->A_jsp.java—(编译)-->A_jsp.class-->调用service方法。
JSP编译原理(翻译规则):
①HTML标签: 翻译成响应流输出的参数中。 例如:req.getWriter.print(“<hr />”)
②表达式脚本: 表达式翻译到out.print(表达式脚本)。 out也是输出流
③声明脚本: 翻译成servlet中的service方法外内容。
④普通脚本: 翻译成servlet的service方法内的代码。
(4)JSP指令元素
`<%@指令名 属性名='值'%>`
①页面指令 page
语法:`<%@page 属性名='值'%>`
常用页面指令属性:
pageEncoding: tomcat读取jsp文件翻译成servlet,读取jsp使用字符流的编码。
import: `import='java.util.*'`
isErrorPage: 是否是错误页面。(true:当前页面是一个错误页面 内置java对象 **exception**)
errorPage: 指定错误页面。`errorPage="错误页面的url-pattern"`
contentType: 设置浏览器解析内容响应类型,编码: 指定浏览器解析页面的编码格式。
session: 值为boolean类型:
session="true" 饿汉式 相当于JSP: req.getSession();
session="false" 懒汉式 相当于JSP中没有 req.getSession();
isELIgnored: 是否忽略el表达式,默认为false
②包含指令
语法:`<%@include file="被包含文件的url-pattern"%>`
作用: 复用部分jsp的代码。
原理:源代码包含[静态包含]
缺点:`可能存在java变量声明冲突的问题`
③动作指令
语法:<jsp:动作名称 属性名="属性值"/>
`<jsp:include page="被包含的jsp的url-pattern"/>`
作用: 复用jsp的效果。
特点:不会产生java变量的声明冲突。
(5)JSP内置对象
概念:
①可以直接在java脚本中使用的对象。(无需创建无需声明)
②原理: servlet中的service方法的局部变量。
注意: 内置对象只能在表达式脚本和普通脚本中使用。
<%= %> 、<% %>
常见内置对象(9个):
①exception: 只能在isErrorPage='true'
②request: 代表请求对象,service方法的形参。
③session: 代表HttpSession
④application: 代表ServletContext对象。`ServletContext application = ...;`
⑤response: 代表service方法响应对象。HttpServletResponse
⑥page: this 当前jsp翻译后的servlet的对象.
⑦out: JspWriter(相当于PrintWriter), 面向浏览器输出流对象。
⑧config: ServletConfig:
<servlet>
<init-param>
<param-name>名</param-name>
<param-value>值</param-value>
</init-param>
</servlet>
⑨pageContext [全能jsp对象] [最重要]
a可做作用域: 当前JSP页面内的生命周期。
存: pageContext.setAttribute("name",值);
取: pageContext.getAttribute("name");
b可管理4个作用域:
存值: pageContext.setAttribute(String 名字, Object 值, int)
第三个参数int:
PageContext.PAGE_SCOPE; 将命名属性存入pageContext作用域
pageContext.REQUEST_SCOPE: 将命名属性存入request作用域
PageContext.SESSION_SCOPE: 将命名属性存入session作用域
PageContext.APPLICATION_SCOPE:将命名属性存入application(ServletContext)作用域
取值: pageContext.getAttribute(String 名字,int 作用域常量值);
第二个参数:
PageContext.PAGE_SCOPE; 蒋命名属性存入pageContext作用域
pageContext.REQUEST_SCOPE: 蒋命名属性存入request作用域
PageContext.SESSION_SCOPE: 将命名属性存入session作用域
PageContext.APPLICATION_SCOPE: 将命名属性存入application(ServletContext)作用域
c管理其他8个内置对象
动态获得项目名:
req.getContextPath();//"/项目名"
借助于pageContext动态获得/项目名
pageContext.getRequest().getContextPath();
2).EL表达式
EL表达式: expression language 表达式语言
作用: 执行表达式,并且将表达式的结果,响应输出浏览器。
语法: ${el表达式} 结果: ${..}结果显示给浏览器。
(1)数学运算表达式
运算符号: + - * / %
注意: el表达式弱类型,不区分数据类型运算。 比如: ${10/3} ----> 3.3333333
(2)逻辑运算表达式
< <= >= == != && || ! eq(类似于==)
注意: 逻辑判断忽略数据类型。 比如: ${1=="1"} ==== true
细节补充: 表示字符串 '字符串内容' "字符串内容"
(3)三元运算符(三目运算符)
语法: ${boolean表达式?值1:值2}
(4)获得作用域中的值
EL内置对象:
获得PageContext作用域: ${pageScope} ${pageScope.命名属性的name}
获得request作用域: ${requestScope.命名属性的name}
获得session作用域的值: ${sessionScope.命名属性的name}
获得application作用域: ${applicationScope.命名属性的name}
(5)访问对象的属性
语法: ${对象.属性名}
${对象.属性名.属性的属性名}
原理(重要): ${对象.get属性的方法名取get首字母小写}
内置对象: pageContext
问题: 动态获得项目名?
方法: pageContext.getRequest().getContextPath();
${pageContext.request.contextPath}
(6)获得请求参数
请求参数: 浏览器(超链接, form提交,地址栏)发送servlet的请求数据
servlet: 接受请求参数: req.getParameter("name");
JSP: ${param.请求参数名字}
(7)访问list和map集合
EL访问List集合:
访问list集合中i下标的元素: ${list集合[i]} //list.get(i)
EL访问Map集合:
根据map的key获得对应的值:
语法要求: key必须是数字或者字符串类型。
语法: ${map.key} key不能是数字
${map["key"]} 通用。
(8)访问cookie中值
访问cookie中的值:
java脚本:
Cookie[] cs = request.getCookies();
if(cs != null){
for(Cookie c:cs){
if(c.getName().equals("JSESSIONID")){
out.print(c.getValue());
}
}
}
EL表达式: ${cookie.cookie的name.value} // 得到的对应name的cookie对象
补充:
${命名属性的name}
el表达式依次从小到大的作用域,寻找该名字的命名属性的值。找到即返回显示。
3).JSTL标签库
jsp页面头部:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
(1)JSTL标签库:第三方提供的标签库
语法: <c:if 属性名='值'></前缀:标签名>
使用:
a 导入标签库的jar:javax.servet.jsp.jstl.jar、jstl-impl.jar
b 在jsp引入标签库。(标签库指令):<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix='c'%>
c 使用标签:<c: 标签名 属性名='值'></c:标签名>
(2)常见的jstl标签
①单条件判断:
<c:if test="条件(el表达式)"> … </c:if>
②多条件分支:
<c:choose>
<c:when test="条件1(el表达式)">条件1成立运行的代码</c:when>
<c:when test="条件2(el表达式)">条件2成立运行的代码</c:when>
<c:otherwise> 所有条件都不成立,执行的代码</c:otherwise>
</c:choose>
③循环遍历list:
<c:forEach var="p" items="被遍历的list集合(el表达式)">
当前被遍历的对象默认放入pageContext作用域中,pageContext.setAttribute("p",当前对象)
${pageScope.p} 或 ${p} //访问p对象
</c:forEach>
例如:
<c:forEach var="d" items="${requestScope.departments}"> //从request作用域取
<tr style="text-align: center;">
<td>${d.id}</td>
<td>${d.name}</td>
</tr>
<c:forEach>
循环标签内常用属性:
items: 被遍历的集合
var: 当前被遍历对象的名字
begin: 起始下标
end: 截止下标。
step: 步长 (类似于for循环的i++, i+=x)
varStatus: 描述下标和序号
varStatus="vs" // 自动在vs对象中绑定两个属性: count(从1开始序号) index(从0开始的下标)
${vs.count} --- 序号
${vs.index} ---- 下标
④forEach遍历map
<c:forEach items="被遍历的map" var='e'>
//${e}----> Map.Entry 包含key-value
e.key 或 e.value 获取值
</c:forEach>
⑤c:set标签
作用: 可以向作用域中存入数据(命名属性: name value)
本质: pageContext.setAttribute("name",value,int哪个作用域)
第一种:<c:set var="name" value=”值” scope="哪个作用域(可选值: page request session application)"></c:set>
第二种:<c:set var="命名属性的name" scope="作用域"> 值 </c:set>
⑥c:remove 从作用域中删除某个值
<c:remove var="命名属性的name" scope="哪个作用域">
scope可选值:
page ---- pageContext作用域
request ----request作用域
session ----session作用域
application ----servletContext 作用域
<c:remove>
⑦c:url标签
作用: a自动追加项目名
b 在cookie被禁用的情况下,自动url重写
语法: <c:url value="url-pattern路径"></c:url>
⑧日期格式化显示标签
注意: 先导入jstl格式化显示的标签路径。
语法: <fmt:formatDate value="日期" pattern="yyyy年MM月dd日 HH:mm:ss"/>
value: 要格式化显示的日期
pattern: 格式(年yyyy 月MM 日dd 时HH 分mm 秒ss)
例子:显示生日
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> //引入
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> //引入
<fmt:formatDate value="${p.birth }" pattern="yyyy年MM月dd日"/>