JSP、EL表达式、JSTL标签库干货(建议收藏)
yuyutoo 2024-10-12 01:06 5 浏览 0 评论
作者 | 活到老_码到老
来源 | urlify.cn/QremIj
JSP语法
除了HTML语法,扩展的其他内容如下
嵌套Java代码的格式
- 声明标签:<%! 变量声明或方法声明 %>
- 表达式标签:<%= 表达式 %> 表达式的值将输出到JSP页面的相应位置
- 代码标签: <% Java代码 %> 页面上动态显示的内容
JSP指令
用于声明 JSP 页面的属性,如编码方式、文档类型等等。一共有三种指令:page、include、taglib。
指令使用格式
<%@ directive attribute1="value1" attribute2="value2" ... %>
- directive: 指 page、include、taglib其中之一
- attribute:属性名
- value:属性值
- ...:这个不是语法哦,指其他未写出的 attribute="value"
page指令
属性名 | 属性值 | 描述 |
language | java | 解释JSP文件时采用的语言。默认为java |
extends | 类的全名 | 由该JSP文件生成的类继承哪个类,JSP为Servlet,因此当指明继承普通类时需要实现Servlet的init、destroy等方法 |
import | 包名/类名 | import是唯一可以声明多次的page指令属性。一次可以导入多个类,中间用英文逗号隔开 |
session | true/false | 是否内置session对象。默认为true |
autoFlush | true/false | true代表使用out.println()等方法输出的字符串暂时存到缓存里,当缓存满了或者程序行完毕或者执行out.?ush()操作时才输出到客户端。默认为true |
buffer | none/nKB | 指定缓存大小,例如 4KB |
isThreadSafe | true/false | 是否线程安全。值为true时允许多线程执行该JSP,否则必须排队执行。默认为false |
isErrorPage | true/false | 该 JSP页面是否为错误显示页面。为true时该JSP拥有内置exception对象,否则没有。默认为false |
errorPage | 某个JSP页面的相对路径 | 指明一个错误页面,如果该JSP程序抛出一个未捕捉的异常,则将该异常传递给errorPage指定JSP页面并跳转至errorPage指定JSP页面 |
contentType | 文档类型 | 客户端浏览器根据该属性判断文档类型。例如,HTML:text/html、纯文本:text/plain、JPG图像:image/jpeg、GIF图像:image/gif、WORD文档:application/msword |
pageEncoding | 字符集 | 指定该JSP页面的字符集,如UTF-8、ISO-8859-1等 |
include指令
将其他 JSP文件、HTML文件、文本包含到该 JSP中一并编译。这是一种静态包含,相当于直接复制粘贴进来,所以在编译该JSP文件的时候将会一并编译被包含的文件
- 属性名:file
- 属性值:URL相对路径
- 例:<%@ include file="文件相对 url 地址" %>
taglib指令
JSP支持标签技术,后面会讲到标签的用法,JSTL标签库的使用等。
作用:用来指明JSP页面内使用的JSP标签库,taglib指令有两个属性,uri为类库的地址,prefix为标签的前缀
- 例:<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
JSP的9个内置对象
使用内置对象进行便捷的开发,大部分都是HttpServlet中使用的对象(除了pageContext和out),关于HttpServlet请看上一篇博文
对象 | 类型 | 简述 |
request | HttpServletRequest | 该对象是客户端的HTTP请求,作用域为一次请求,包含头信息、系统信息、请求方式等 |
response | HttpServletResponse | HTTP响应对象,作用域为该 JSP页面 |
session | HttpSession | 作用域为一次会话 |
application | ServletContext | 作用域为Servlet容器,直到服务器关闭前都有效 |
config | ServletConfig | 服务器的配置信息。config在上一篇博文的Servlet级始化参数中使用过。 |
page | HttpServlet | 指该 JSP编译为Java代码中的Servlet类的对象(Servlet是单实例的,所以这个指向是明确的),相当于this |
exception | Exception | 只有当前页面是错误页面(<%@ page isErrorPage="true" %>)才能使用,若不是错误页面使用exception会导致编译报错。 |
out | JspWriter | 用于向页面输出(包括js代码),上面提到的page指令的autoFlush属性就是控制这个对象 |
pageContext | PageContext | 表示页面的上下文,可以获取request、response、session、application、config等 |
EL表达式
EL(Expression Language)表达式可以更方便的展示变量和对象,避免在HTML中嵌入Java代码(显的很混乱)
基本使用格式
${EL表达式} 变量名不用加引号
获取4个域(pageContext、request、session、application)中值
EL表达式只能获取域中的值,不能获取Java代码中的值!需要使用的变量一定要先存在域中。
例如:<% session.setAttribute("score",99) %> ,此时可以读取score这个值${score}
另外一点,如果找不到值会返回空字符串"",而不是null
完全限定获取方式
- 获取pageContext域的变量:${pageScope.key}
- 获取request域的变量:${requestScope.key}
- 获取session域的变量:${sessionScope.key}
- 获取application域的变量:${applicationScope.key}
隐式获取
${key} : 将会以pageContextrequestsessionapplication顺序读取,域的范围是从小到大
- 关于集合的展示
<%
List list = new ArrayList();
list.add("one");
list.add("two");
list.add("three");
pageContext.setAttribute("aList",list);
Map map = new HashMap();
map.put("color","red");
map.put("shape","square");
pageContext.setAttribute("aMap",map);
%>
${aList}<br/> <!--直接输出数组-->
${aList[0]}<br/> <!--按下标读取数组-->
${aList[2]}<br/> <!--按下标读取数组-->
${aMap}<br/> <!--直接输出映射-->
${aMap.shape}<br/> <!--按键读取映射-->
- 下面是在网页中输出的结果
[one, two, three]
one
three
{color=red, shape=square}
square
对象的展示
- 测试
<%
class Student{
private final String name = "Tom";
private final String sex = "boy";
@Override
public String toString() {
return name+" is a "+sex;
}
}
Student student = new Student();
pageContext.setAttribute("aStudent",student);
%>
${aStudent}<br/>
下面是在网页中输出的结果
Tom is a boy
可以看出来EL对于对象的展示其实就是调用了toString()方法,包括集合也一样。如果这个对象没有重写toString()方法,那么机会调用父类toString()方法。比如父类是Object,那么就会输出hashcode。
对象的字段(属性)的获取
- 获取方式: ${object.field} 即可获取对象的字段(属性)
- 测试代码
com.java.webtest.Student
package com.java.webtest;
public class Student {
private String name = "Jack";
public String getName() {
return name;
}
}
myTest.jsp
<%@ page import="com.java.webtest.Student" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>myTest</title>
</head>
<body>
<%
Student s1 = new Student();
pageContext.setAttribute("s1",s1);
%>
name = ${s1.name}<br/>
</body>
</html>
- 运行结果
name = Jack
?? EL表达式获取对象字段(属性)是通过反射机制。${s1.name} 底层逻辑是将首字母"n"大写再在前面拼接一个"get",然后反射获取"getName"方法。所以对象必须提供字段的get方法,才能使用EL表达式 ${object.field} ,如果不写就会报错,或者你让get方法返回一个和相应字段无关的东西来证明确实是调用了get方法得到值的。
EL的运算
运算类型 | 描述 |
算术型 | 加+ 减- 乘* 除/、 div 取余% 、mod |
逻辑型 | and、&&、or、||、!、not |
关系型 | ==、eq、!=、ne、<、lt、>、gt、<=、le、>=、ge |
empty | 判断一个值是否为null或者为empty,如${empty ""} 返回值为true |
三目运算 | expression ? valueA : valueB 若expression为true返回valueA否则返回valueB |
- 做一个测试
<%
class Person{
private int id;
private String sex;
public Person(int id,String sex){ this.id = id; this.sex = sex; }
@Override
public boolean equals(Object o) { return id == ((Person) o).id; }
}
Person p1 = new Person(777,"boy");
Person p2 = new Person(777,"girl");
Person p3 = new Person(666,"boy");
pageContext.setAttribute("p1",p1);
pageContext.setAttribute("p2",p2);
pageContext.setAttribute("p3",p3);
%>
1 + 2 = ${1 + 2}<br/>
1 - 2 = ${1 - 2}<br/>
3 * 3 = ${3 * 3}<br/>
10 / 3 = ${10 / 3}<br/>
10 div 3 = ${10 div 3}<br/>
10 % 3 = ${10 % 3}<br/>
10 mod 3 = ${10 mod 3}<br/>
true and false -> ${true and false}<br/>
true && false ->${true && false}<br/>
true or false -> ${true or false}<br/>
true || false -> ${true || false}<br/>
not true -> ${not true}<br/>
!true -> ${!true}<br/>
666 == 666 -> ${666 == 666}<br/>
p1 == p2 -> ${p1 == p2}<br/>
p1 == p3 -> ${p1 == p3}<br/>
"ABCDEFG" == "abcdefg" -> ${"ABCDEFG" == "abcdefg"}<br/>
"ABCDEFG" == "ABCDEFG" -> ${"ABCDEFG" == "ABCDEFG"}<br/>
"ABCDEFG" eq "abcdefg" -> ${"ABCDEFG" eq "abcdefg"}<br/>
"ABCDEFG" eq "ABCDEFG" -> ${"ABCDEFG" eq "ABCDEFG"}<br/>
"ABCDEFG" != "abcdefg" -> ${"ABCDEFG" != "abcdefg"}<br/>
"ABCDEFG" != "ABCDEFG" -> ${"ABCDEFG" != "ABCDEFG"}<br/>
"ABCDEFG" ne "abcdefg" -> ${"ABCDEFG" ne "abcdefg"}<br/>
"ABCDEFG" ne "ABCDEFG" -> ${"ABCDEFG" ne "ABCDEFG"}<br/>
10 < 3 -> ${10 < 3}<br/>
10 lt 3 -> ${10 lt 3}<br/>
10 > 3 -> ${10 > 3}<br/>
10 gt 3 -> ${10 gt 3}<br/>
10 <= 3 -> ${10 <= 3}<br/>
10 le 3 -> ${10 le 3}<br/>
10 >= 3 -> ${10 >= 3}<br/>
10 ge 3 -> ${10 ge 3}<br/>
empty "" -> ${empty ""}<br/>
empty null -> ${empty null}<br/>
empty 666 -> ${empty 666}<br/>
55 > 60 ? "you pass!" : "you fail..." -> ${55 > 60 ? "you pass!" : "you fail..."}<br/>
- 页面的输出结果
1 + 2 = 3
1 - 2 = -1
3 * 3 = 9
10 / 3 = 3.3333333333333335
10 div 3 = 3.3333333333333335
10 % 3 = 1
10 mod 3 = 1
true and false -> false
true && false ->false
true or false -> true
true || false -> true
not true -> false
!true -> false
666 == 666 -> true
p1 == p2 -> true
p1 == p3 -> false
"ABCDEFG" == "abcdefg" -> false
"ABCDEFG" == "ABCDEFG" -> true
"ABCDEFG" eq "abcdefg" -> false
"ABCDEFG" eq "ABCDEFG" -> true
"ABCDEFG" != "abcdefg" -> true
"ABCDEFG" != "ABCDEFG" -> false
"ABCDEFG" ne "abcdefg" -> true
"ABCDEFG" ne "ABCDEFG" -> false
10 < 3 -> false
10 lt 3 -> false
10 > 3 -> true
10 gt 3 -> true
10 <= 3 -> false
10 le 3 -> false
10 >= 3 -> true
10 ge 3 -> true
empty "" -> true
empty null -> true
empty 666 -> false
55 > 60 ? "you pass!" : "you fail..." -> you fail...
- 我认为应该特别注意两点
- 两个整数相除的结果并不是整数
- p1 == p2 -> true 和 "ABCDEFG" == "ABCDEFG" -> true。显然不同于Java,EL表达式重载了 == ,对象之间使用 == 比较的时候,并不是比较对象的引用变量(也就是对象地址或指针),而是使用了 equals(Object o) 方法。!= 比较对象也是同理,可以自己测试一下。
JSTL标签库
JSTL(Java server pages standarded tag library)是一个JSP标准标签库,它封装了JSP应用的通用核心功能。JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。下文将阐述部分常用的JSTL标签。EL和JSTL核心标签库通常搭配使用效果最佳
使用前的准备
- 导入相应的jar包:standard.jar 和 jstl.jar
- JSP页面引入标签库<%@ taglib pre?x="前缀" uri="功能范围路径" %>功能范围prefixuricorechttp://java.sun.com/jsp/jstl/corei18nfmthttp://java.sun.com/jsp/jstl/fmt_rtsqlsqlhttp://java.sun.com/jsp/jstl/sqlxmlxhttp://java.sun.com/jsp/jstl/xmlfunctionsfnhttp://java.sun.com/jsp/jstl/function?? 如果在后面使用中出现 500错误页面,其中包含类似这样的信息:atrribute [value] does not accpet any expressions,有可能是uri的问题,可能需要换一个uri。uri不同版本功能有差别所以会导致一些错误。
标签使用语法
<prefix:tag attribute="value" ... >
...
</prefix:tag>
重要标签
免责声明:以下标签属性总结并不全面,只讲比较常用的属性;并且由于uri不同属性不同。具体内容请查看你导入的standard.jar
<c:tag>标签
使用标签前不要忘记导入标签,不过IDEA也会自动导入。核心标签按照功能可以分为
表达式操作: out、set、remove、catch
流程控制: if、choose、when、otherwise
迭代操作: forEach、forTokens
URL操作: import、param、url、redirect
<c:set>标签
属性 | 缺省 | 说明 |
value | - | 向域中存入的变量值 |
var | - | 向域中存入的变量名 |
scope | page | 指定存储在4个域中的哪一个 |
target | - | Java对象 |
property | - | Java对象的字段(属性)。因为使用的是反射技术,与前面EL表达式获取字段值同理:该字段必须有set方法 |
<c:out>标签
属性 | 缺省 | 说明 |
value | - | 需要显示出来的值 |
default | - | 如果value的值为null,则显示default的值 |
escapeXml | true | 是否转义xml字符。有些字符如<在xml中被认为是<,若要它的字面意思,就需要使用转移 |
案例
com.java.testclass.Person
package com.java.testclass;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name+" is "+age+" years old.";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
JSTL-test.jsp
<%@ page import="com.java.testclass.Person" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>
<html>
<head>
<title>JSTL-test</title>
</head>
<body>
<%
pageContext.setAttribute("person1",new Person("Tom",18));
pageContext.setAttribute("person2",null);
%>
<h6>********** set & out Test **********</h6>
<%--向域中存值--%>
<c:set var="fruit" value="apple"></c:set>
<c:set var="fruit" value="banana" scope="session"></c:set>
<%--设置Java对象的字段--%>
<c:set value="David" target="${person1}" property="name"></c:set>
<c:set target="${person1}" property="age">18</c:set><br>
<%--输出--%>
<c:out value="${fruit} is fruit." default="fruit is null!"></c:out><br>
person1 : ${person1}<br>
person2 : <c:out value="${person2}" default="person2 is null!"></c:out><br>
<c:out value="<==when escapeXml is true==>"></c:out><br>
<c:out value="<==when escapeXml is false==>" escapeXml="false"></c:out><br>
</body>
</html>
结果
********** set & out Test **********
apple is fruit.
person1 : David is 18 years old.
person2 : person2 is null!
<==when escapeXml is true==>
<==when escapeXml is false==>
<c:if>标签
属性 | 缺省 | 说明 |
test | - | if 的条件表达式 |
var | - | 定义一个变量存储if 条件表达式的结果 |
scope | page | var变量的JSP范围 |
<c:choose>标签
属性 | 缺省 | 说明 |
test | 无 | 如果表达式的结果为true,则执行体内容,false则相反 |
<c:choose>
<c:when test="boolean表达式">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>
<c:forEach>标签
用于遍历集合元素
属性 | 缺省 | 说明 |
var | - | 遍历用的循环变量 |
items | - | 被遍历的集合对象 |
varStatus | - | 存放本轮循环变量的相关参数 |
begin | 0 | 遍历起点下标 |
end | 最后元素下标 | 遍历终点下标 |
step | 1 | 每次迭代的间隔数 |
直接看例子
<%
int[] arr = {100,200,300,400,500,600,700,800,900,1000};
pageContext.setAttribute("arr",arr);
%>
<h6>********** process control Test **********</h6>
foreach arr
<c:forEach items="${arr}" var="it" begin="1" end="7" step="2" varStatus="status">
<c:if test="${status.count==1}">
from ${status.begin} to ${status.end} by step = ${status.step}<br>
</c:if>
arr[${status.index}] = ${it} , count = ${status.count}<br>
</c:forEach>
结果
********** process control Test **********
foreach arr from 1 to 7 by step = 2
arr[1] = 200 , count = 1
arr[3] = 400 , count = 2
arr[5] = 600 , count = 3
arr[7] = 800 , count = 4
从结果count属性并不是与index属性关联的值,index是数组的下标,count仅作为循环的计数器。
<fmt:tag>标签
<fmt:formatDate>标签
该标签用于格式化输出Date类型变量,比较常用
属性 | 缺省 | 说明 |
value | - | 用于指定被格式化对象 |
pattern | - | 格式化的模式,与SimpleDateFormat的参数设置一样 |
var | - | 指定产生的格式化字符串所存放的变量,若不指定则直接输出在页面中 |
scope | page | 指定var变量的存储域 |
type | date | 说明value对象包含时间或包含日期还是两者兼具。取值为date/time/both |
<fmt:parseDate>标签
<fmt:formatDate>的逆向过程,用于将指定字符串转化为日期类型
属性 | 说明 |
value | 用于指定被转化的字符串 |
pattern | 指定解析字符串的格式 |
var | 指定生成的时间对象所存放的变量 |
请看测试代码
<%
pageContext.setAttribute("now",new Date());
%>
<h6>******************** fmt Test ********************</h6>
before formatting : ${now}. <br>
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd" var="parse_date"></fmt:formatDate>
after formatting : ${parse_date}. <br>
<fmt:parseDate value="${parse_date}" var="gotten_date" pattern="yyyy-MM-dd"></fmt:parseDate>
date get from string : ${gotten_date}. <br>
结果
******************** fmt Test ********************
before formatting : Sat Mar 13 23:03:16 CST 2021.
after formatting : 2021-03-13.
date get from string : Sat Mar 13 00:00:00 CST 2021
? 注意第一个日期与第三个日期的差别,这是由于第一次转换的时候丢失了时间信息
<fmt:formatNumber>标签
主要用于控制数字的展示格式。还记得前面EL运算10/3的结果展示为3.3333333333333335,通常我们不想展示这么多小数位。
属性 | 说明 |
maxIntegerDigits | 整数部分最多的位数 |
minIntegerDigits | 整数部分最少的位数 |
maxFrctionDigits | 小数部分最多的位数 |
minFrctionDigits | 小数部分最少的位数 |
var | 指定存储格式化结果的变量 |
scope | 指定var属性的作用域 |
相关推荐
- 国内外注塑机及电脑密码大全(常见注塑机通用密码)
-
一、国外注塑机(日本、德国等)东洋注塑机万能码:9422345日精注塑机密码:222|7777DAMEG注塑机密码:000000000新泻注塑机密码:241650|261450住友注塑机密码:...
- 并发编程实战来咯(并发编程的艺术和并发编程实战)
-
提到并发编程,就不得不提C++ConcurrencyinAction(SecondEdition)(《C++并发编程实战第2版》)啦!《C++并发编程实战第2版》英文原版&中文译版看到这个...
- 无锁队列Disruptor原理解析(无锁队列应用场景)
-
队列比较队列...
- 无锁CAS(附无锁队列的实现)(cas是一种无锁算法)
-
本文所有代码对应的Github链接为:https://github.com/dongyusheng/csdn-code/tree/master/cas_queue...
- Linux高性能服务器设计(linux 服务器性能)
-
C10K和C10M计算机领域的很多技术都是需求推动的,上世纪90年代,由于互联网的飞速发展,网络服务器无法支撑快速增长的用户规模。1999年,DanKegel提出了著名的C10问题:一台服务器上同时...
- 浅谈Go语言的并发控制(go语言 并发)
-
前言本文原创,著作权归...
- Datenlord |Etcd 客户端缓存实践(etcd 数据存储)
-
简介和背景...
- 无锁编程——从CPU缓存一致性讲到内存模型
-
缓存是一个非常常用的工程优化手段,其核心在于提升数据访问的效率。缓存思想基于局部性原理,这个原理包括时间局部性和空间局部性两部分:...
- 如何利用CAS技术实现无锁队列(cas会锁总线吗)
-
linux服务器开发相关视频解析:...
- Kotlin协程之一文看懂Channel管道
-
概述Channel类似于Java的BlockingQueue阻塞队列,不同之处在于Channel提供了挂起的send()和receive()方法。另外,通道Channel可以...
- 详解C++高性能无锁队列的原理与实现
-
1.无锁队列原理1.1.队列操作模型...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
推荐7个模板代码和其他游戏源码下载的网址
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)