最初出现的目的是为了取代 JSP 页面中的 "脚本表达式<%= %>",格式:${...}
。但随着 EL 的发展,其功能已不限于此。
${"root" }
${12345 }
${true }
findAttriubte()
,在 4 大作用域中以给定的名字找对应的属性值,然后进行输出<%
String[] names = {"A","B","C","D"};
pageContext.setAttribute("names", names);
%>
${names[0] }
<%
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
pageContext.setAttribute("list", list);
%>
${list[2] }
map["key"]
和 map.key
在使用上的不同:当 key 是数字或者包含特殊字符 -/.
,只能用 map["key"]
${obj.xxx}
这句话的底层其实是 EL 调用了 obj 的 getXxx()
${pageContext.request.contextPath}
+
| -
| *
| /
${1+‘1‘} → 2
${1+‘a‘} → 抛异常
< lt
> gt
<= le
>= ge
!= ne
== eq
--------
${1 eq 1}、${3 ge 2}
&& and
|| or
! not
--------
${not (3>2) and 1<2 or 10>3} => false
${7>6 ? "yes" : "no"}
EL 中内置了 11 个对象,这些对象不需要提前定义就可以直接使用
《web.xml》
<context-param>
<param-name>name1</param-name>
<param-value>value1</param-value>
</context-param>
不是任意方法都可以被调用,需要满足如下 3 个条件:
举例:对给定的 URL 进行 URL 编码
ELFunc.java
public class ELFunc {
public static String encode(String str, String encode) {
try {
return URLEncoder.encode(str, encode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
MyELFunc.tld(放在 WEB-INF 目录下)
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<tlib-version>1.0</tlib-version>
<short-name>MyELFunc</short-name>
<uri>http://www.nuist.edu.cn/MyELFunc</uri>
<function>
<name>urlEncode</name>
<function-class>cn.edu.nuist.util.ELFunc</function-class>
<function-signature>
java.lang.String encode(java.lang.String, java.lang.String)
</function-signature>
</function>
</taglib>
el3.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.nuist.edu.cn/MyELFunc" prefix="MyELFunc" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>使用EL表达式调用方法</title>
</head>
<body>
调用自定义函数:${MyELFunc:urlEncode("徐州","utf-8") }
调用JSTL函数库中的函数:${fn:toLowerCase("JAFIOjifeoFIAWfjiof") }
</body>
</html>
JSTL 中提供了一套 EL 自定义函数,这些函数包含了 JSP 页面制作者经常要用到的字符串操作。例如, fn:toLowerCase
将字符串中的字符变为小写,fn:indexOf
返回一个指定字符串在另一个字符串中第一次出现的索引位置。JSTL 中提供的 EL 自定义函数必须在 EL 表达式中使用。
全称:JavaServer Pages Standard Tag Library。提供给 Java Web 开发人员一个标准通用的标签函数库和 EL 配合来取代传统直接在页面上嵌入 Java 程序(Scripting)的做法,以提高程序可读性、维护性和方便性。
导入 [核心标签库c]:<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:out>
:标签用于输出一段文本内容到 pageContext 对象当前保存的 out 对象中<c:out value="<hhhh>"></c:out>
<c:out value="${name }"></c:out>
<c:out value="${addr }" default="XZ"></c:out>
<c:out value="<a href=‘#‘>xxx</a>"></c:out>
<c:set>
<c:set scope="request" var="name" value="金敏喜"></c:set>
<%
Map<String, String> map = new HashMap<String, String>();
pageContext.setAttribute("map", map);
%>
<h4>target属性的值是Map对象,property属性表示该Map对象的某个key</h4>
<c:set target="${map }" property="cellphone" value="10086"></c:set>
${map.cellphone }
<%
Person p = new Person();
pageContext.setAttribute("p", p);
%>
<h4>target属性的值是JavaBean对象,property属性表示JavaBean对象的属性</h4>
<c:set target="${p }" property="name" value="玉珠"></c:set>
${p.name }
<c:remove>
<c:remove var="varName" [scope="{page|request|session|application}"] />
<c:catch>
<c:catch var="myex" >
<%
10/0;
%>
</c:catch>
异常:<c:out value="${myex}" /> ${myex}<br />
异常 myex.getMessage:<c:out value="${myex.message}" /><br />
异常 myex.getCause:<c:out value="${myex.cause}" /><br />
异常 myex.getStackTrace:<c:out value="${myex.stackTrace}" />
<c:if>
<c:if test="${6<7 }">you will.</c:if>
<c:choose>
<c:choose>
标签用于指定多个条件选择的组合边界,它必须与 <c:when>
和 <c:otherwise>
标签一起使用。使用 <c:choose>
,<c:when>
和 <c:otherwise>
三个标签,可以构造类似 “if-else if-else” 的复杂条件判断结构。<%
int day = 1;
pageContext.setAttribute("day", day);
%>
<c:choose>
<c:when test="${day == 1 }">周一</c:when>
<c:when test="${day == 2 }">周二</c:when>
<c:when test="${day == 3 }">周三</c:when>
<c:when test="${day == 4 }">周四</c:when>
<c:when test="${day == 5 }">周五</c:when>
<c:otherwise>周末</c:otherwise>
</c:choose>
<c:forEach>
<h1>遍历数组中的数据</h1>
<%
String[] cities = {"北京", "上海", "广州", "深圳"};
pageContext.setAttribute("cities", cities);
%>
<c:forEach items="${cities }" var="c">
${c }
</c:forEach>
<hr/>
<h1>遍历集合中的数据</h1>
<%
List<String> list = new ArrayList<String>();
list.add("英国");
list.add("法国");
list.add("德国");
list.add("荷兰");
pageContext.setAttribute("list", list);
%>
<c:forEach items="${list }" var="country">
${country }
</c:forEach>
<hr/>
<h1>遍历Map中的数据</h1>
<%
Map<String,String> map = new HashMap<String, String>();
map.put("aaa", "111");
map.put("bbb", "222");
map.put("ccc", "333");
map.put("ddd", "444");
pageContext.setAttribute("map", map);
%>
<c:forEach items="${map }" var="entry">
${entry.key } —— ${entry.value }
</c:forEach>
<hr/>
<h1>循环执行指定的内容若干次</h1>
<c:forEach begin="0" end="10" step="2" var="i">
${i }
</c:forEach>
<hr/>
<h1>varStatus 属性:遍历10~100的偶数, 如果"数字所在的位置"是3的倍数, 显示成红色</h1>
<c:forEach begin="10" end="100" step="2" var="i" varStatus="stat">
<c:if test="${stat.count % 3 == 0 }">
<font color="red">${i }</font>
</c:if>
<c:if test="${stat.count % 3 != 0 }">
<font color="blue">${i }</font>
</c:if>
</c:forEach>
<c:forTokens>
<c:forTokens items="www.nuist.edu.cn" delims="." var="str">
${str } <br/>
</c:forTokens>
<c:import>
:请求包含<c:redirect>
:请求重定向<c:url>
<c:url value="/index.jsp" context="${pageContext.request.contextPath }"
var="url" scope="page"></c:url>
<a href="${url }"></a>
<c:param>
:配合上述三个标签使用;示例:<c:param name="name" value="value" />
第一次被使用时创建出来, 后续一直驻留在内存中, 为后续请求服务
以显示客户机 IP 为例
javax.servlet.jsp.tagext.Tag<I>
public class ShowIPTag implements Tag{
private PageContext pc;
public void setPageContext(PageContext pc) {
// 1.
this.pc = pc;
}
public void setParent(Tag t) {
// 2. 传入的是当前标签的"父标签", 没有则传null
}
public Tag getParent() {
return null;
}
public int doStartTag() throws JspException {
// 3.
try {
pc.getOut().write(pc.getRequest().getRemoteAddr());
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return 0;
}
public int doEndTag() throws JspException {
// 4.
return 0;
}
public void release() {}
}
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<tlib-version>1.0</tlib-version>
<short-name>MyTag</short-name>
<uri>http://www.nuist.edu.cn/MyTag</uri>
<tag>
<name>showip</name>
<tag-class>cn.edu.nuist.tag.ShowIPTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
<%@ taglib uri="http://www.nuist.edu.cn/MyTag" prefix="MyTag" %>
<MyTag:showip/>
SimpleTag<I>
/ 继承它的默认实现类 SimpleTagSupport
当 JSP 在执行的过程中,每当遇到一个简单标签时,都会创建一个处理类对象(如下步骤是实现接口方式的;若是继承默认实现类方式,则父类会把前几步替你做了,你就只需要提供属性声明、属性对应 setXxx()
和 doTag()
即可)
setJspContext(JspContext pc)
setParent(JspTag parent)
将父标签传入;如果没有父标签,则这个方法不会被调用setXxx()
将属性的值传入setJspBody(JspFragment jspBody)
将封装了标签体信息的 JspFragment 传入;如果没有标签体,则这个方法不会被调用doTag()
,在这个方法里我们可以书写处理【标签事件】的 Java 代码setXxx()
<attribute>
<name>标签的属性名必须与对应的标签类的成员变量名一致</name>
<required>是否是必须的属性</required>
<rtexprvalue>是否支持EL表达式</rtexprvalue>
<type>属性的数据类型</type>
</attribute>
public class SimpleShowIPTag implements SimpleTag {
private JspContext pc;
public void doTag() throws JspException, IOException {
PageContext pcx = (PageContext) pc;
pcx.getOut().write(pcx.getRequest().getRemoteAddr());
}
public void setParent(JspTag parent) {}
public JspTag getParent() {
return null;
}
public void setJspContext(JspContext pc) {
this.pc = pc;
}
public void setJspBody(JspFragment jspBody) {}
}
public class DemoSimpleTag extends SimpleTagSupport {
// 成员属性对应自定义标签的属性
private int times;
// 对外必须提供 setXxx()
public void setTimes(int times) {
this.times = times;
}
@Override
public void doTag() throws JspException, IOException {
// 功能1: 控制标签体是否执行
// 不执行 —— 什么都不做,标签体就不会执行
// 执行 —— 调用封装着标签体的 JspFragment 对象的 invoke()
// 参数可以传 null, 如果传 null 底层还是会打给 out 缓冲区
// getJspBody().invoke(getJspContext().getOut());
// 功能2: 控制标签之后的内容是否执行
// 执行 —— 什么都不做
// 不执行 —— 抛出SkipPageException
// throw new SkipPageException();
// 功能3: 控制标签体重复执行
for(int i = 0; i < times; i++)
getJspBody().invoke(null);
// 功能4: 修改标签体后进行输出
/*
StringWriter writer = new StringWriter(); // 目的地为String 的一个字符输出流
JspFragment jspBody = getJspBody();
jspBody.invoke(writer);
String str = writer.toString();
str = str.toUpperCase();
getJspContext().getOut().write(str);
*/
}
}
<tag>
<name>simpleshowip</name>
<tag-class>cn.edu.nuist.simpletag.SimpleShowIPTag</tag-class>
<body-content>empty</body-content>
</tag>
<tag>
<name>demosimpletag</name>
<tag-class>cn.edu.nuist.simpletag.DemoSimpleTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>times</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>int</type>
</attribute>
</tag>
public class IfTag extends SimpleTagSupport {
private boolean test;
public void setTest(boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
if(test) getJspBody().invoke(null);
}
}
<tag>
<name>if</name>
<tag-class>cn.edu.nuist.simpletag.IfTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>boolean</type>
</attribute>
</tag>
public class RefTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
PageContext pC = (PageContext) getJspContext();
HttpServletRequest request = (HttpServletRequest) pC.getRequest();
HttpServletResponse response = (HttpServletResponse) pC.getResponse();
String ref= request.getHeader("referer");
if(ref == null || "".equals(ref) || !ref.startsWith("http://localhost")) {
response.sendRedirect(request.getContextPath() + "/index.jsp");
return;
}
}
}
<tag>
<name>ref</name>
<tag-class>cn.edu.nuist.simpletag.RefTag</tag-class>
<body-content>empty</body-content>
</tag>
public class TranHTMLTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
StringWriter writer = new StringWriter();
getJspBody().invoke(writer);
String str = writer.toString();
// 转义
str = filter(str);
getJspContext().getOut().write(str);
}
private String filter(String message) {
if (message == null) return (null);
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case ‘<‘:
result.append("<");
break;
case ‘>‘:
result.append(">");
break;
case ‘&‘:
result.append("&");
break;
case ‘"‘:
result.append(""");
break;
default:
result.append(content[i]);
}
}
return (result.toString());
}
}
<tag>
<name>tran</name>
<tag-class>cn.edu.nuist.simpletag.TranHTMLTag</tag-class>
<body-content>scriptless</body-content>
</tag>
private int thisPage;
private int rowPerPage;
private int countRow;
private int countPage;
private int firstPage;
private int lastPage;
private int prePage;
private int nextPage;
private List<Cust> list;
userList.subList(10,20);
limit
关键字
SELECT * FROM user LIMIT 10,10;
public List<Cust> getCustByScope(int from, int count) {
String sql = "select * from customer limit ?,?";
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
try {
return runner.query(sql, new BeanListHandler<Cust>(Cust.class),from,count);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public Page pageCust(int thisPage, int rowPerPage) {
Page page = new Page();
page.setThisPage(thisPage);
page.setRowPerPage(rowPerPage);
int countRow = dao.getCountRow();
page.setCountRow(countRow);
int countPage = countRow%rowPerPage==0 ? countRow/rowPerPage : countRow/rowPerPage+1;
page.setCountPage(countPage);
page.setFirstPage(1);
page.setLastPage(countPage);
page.setPrePage(thisPage==1 ? 1 : thisPage-1);
page.setNextPage(thisPage==countPage ? countPage : thisPage+1);
int index = (thisPage-1) * rowPerPage;
page.setList(dao.getCustByScope(index, rowPerPage));
return page;
}
public class PageCustServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
CustService service = BasicFactory.getFactory().getInstance(CustService.class);
// 获取当前要显示的页
int thisPage = Integer.parseInt(request.getParameter("thisPage"));
// 每页记录数就设成10
int rowPerPage = 10;
// 调用 service 中分页查询客户的方法
Page page = service.pageCust(thisPage,rowPerPage);
// 存入 request 域中,带到 pageCust.jsp 做显示
request.setAttribute("page", page);
request.getRequestDispatcher("/pageCust.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>分页查询</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<script type="text/javascript">
function changePage(obj) {
if(isNaN(obj.value)) {
alert("页码必须是数字!");
obj.value = "${page.thisPage}";
return;
} else if(obj.value <= 0 || obj.value > ${page.countPage}) {
alert("页码必须在有效范围内!");
obj.value="${page.thisPage}";
return;
} else {
window.location.href = "${pageContext.request.contextPath}/servlet/PageCustServlet?thisPage=" + obj.value;
}
}
</script>
</head>
<body>
<div align="center">
<h1>分页查询</h1>
<table border="1">
<tr>
<th>客户姓名</th>
<th>客户性别</th>
<th>出生日期</th>
<th>手机号码</th>
<th>电子邮箱</th>
<th>客户爱好</th>
<th>客户类型</th>
<th>描述信息</th>
</tr>
<c:forEach items="${requestScope.page.list }" var="cust">
<tr>
<td><c:out value="${cust.name }"/></td>
<td><c:out value="${cust.gender }"/></td>
<td><c:out value="${cust.birthday }"/></td>
<td><c:out value="${cust.cellphone }"/></td>
<td><c:out value="${cust.email }"/></td>
<td><c:out value="${cust.preference }"/></td>
<td><c:out value="${cust.type }"/></td>
<td><c:out value="${cust.description }"/></td>
</tr>
</c:forEach>
</table>
共${page.countRow }条记录
共${page.countPage }页
<a href="${pageContext.request.contextPath }/servlet/PageCustServlet?thisPage=${page.firstPage}">首页</a>
<a href="${pageContext.request.contextPath }/servlet/PageCustServlet?thisPage=${page.prePage}">上一页</a>
<!-- 分页逻辑开始 -->
<c:if test="${page.countPage <= 5 }">
<c:set var="begin" value="1" scope="page"/>
<c:set var="end" value="${page.countPage }" scope="page"/>
</c:if>
<c:if test="${page.countPage > 5 }">
<c:choose>
<c:when test="${page.thisPage <= 3 }">
<c:set var="begin" value="1" scope="page"/>
<c:set var="end" value="5" scope="page"/>
</c:when>
<c:when test="${page.thisPage >= page.countPage - 2 }">
<c:set var="begin" value="${page.countPage - 4 }" scope="page"/>
<c:set var="end" value="${page.countPage }" scope="page"/>
</c:when>
<c:otherwise>
<c:set var="begin" value="${page.thisPage - 2 }" scope="page"/>
<c:set var="end" value="${page.thisPage + 2 }" scope="page"/>
</c:otherwise>
</c:choose>
</c:if>
<c:forEach begin="${begin }" end="${end }" var="i">
<c:if test="${page.thisPage != i }">
<a href="${pageContext.request.contextPath }/servlet/PageCustServlet?thisPage=${i}">${i }</a>
</c:if>
<c:if test="${page.thisPage == i }">${i }</c:if>
</c:forEach>
<!-- 分页逻辑结束 -->
<a href="${pageContext.request.contextPath }/servlet/PageCustServlet?thisPage=${page.nextPage}">下一页</a>
<a href="${pageContext.request.contextPath }/servlet/PageCustServlet?thisPage=${page.lastPage}">尾页</a>
跳到 <input type="text" value="${page.thisPage }" style="width: 50px;" onchange="changePage(this)"> 页
</div>
</body>
</html>
原文:https://www.cnblogs.com/liujiaqi1101/p/13388631.html