1.EL表达式
1.1 简介
EL表达式替代jsp表达式。因为开发jsp页面的时候遵守原则:在jsp页面中尽量少些甚至不写java代码。
EL表达式作用:向浏览器输出域对象中的变量或表达式计算的结果
基本语法: ${变量或表达式} 代替<%=变量或表达式%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>EL基础语法</title> </head> <body> <% String name = "eric"; //把变量放入域对象中 //pageContext.setAttribute("name", name); pageContext.setAttribute("name", name, PageContext.REQUEST_SCOPE); %> <%=name%> <br /> EL表达式:${name} <%-- 1)EL从四个域中自动搜素 ${name} 等价于: <%=pageContext.findAttribute("name")%> --%> <%-- 2)EL从指定域中获取 pageScope: page域 requestScope: request域 sessionScope: session域 applicationScope: application域 --%> 指定域获取的EL: ${pageScope.name } </body> </html>
1.2 EL获取不同类型的数据
普通字符串
普通的对象
数组或List集合
Map集合
<%@ page language="java" import="java.util.*,cn.jxufe.entity.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>EL获取不同类型的数据</title> </head> <body> <%-- 1)普通的字符串 --%> <% String email = "zhangsan@qq.com"; //一定要把数据放入域中 pageContext.setAttribute("email", email); %> 普通字符串: ${email } <hr /> 2)普通的对象 EL表达式的属性表示调用对象的getXX方法.例如 student.name 调用了Stduent对象的getName()方法 --%> <% Student student = new Student("eric", "123456"); pageContext.setAttribute("student", student); %> <br /> 普通的对象: ${student} <br /> 对象的属性: ${student.name1 } - ${student.password } <hr /> <%-- 3)数组或List集合 --%> <% //数组 Student[] stus = new Student[3]; stus[0] = new Student("jacky", "123456"); stus[1] = new Student("rose", "123456"); stus[2] = new Student("lucy", "123456"); pageContext.setAttribute("stus", stus); //List List<Student> list = new ArrayList<Student>(); list.add(new Student("eric", "123456")); list.add(new Student("lily", "123456")); list.add(new Student("maxwell", "123456")); pageContext.setAttribute("list", list); %> <br /> 数组: <br /> ${stus[0].name1 } - ${stus[0].password } <br /> ${stus[1].name1 } - ${stus[1].password } <br /> ${stus[2].name1 } - ${stus[2].password } <br /> <br /> List集合 <br /> ${list[0].name1 } - ${list[0].password } <br /> ${list[1].name1 } - ${list[1].password } <br /> ${list[2].name1 } - ${list[2].password } <hr /> 4) Map集合 --%> <% Map<String, Student> map = new HashMap<String, Student>(); map.put("001", new Student("eric", "123456")); map.put("002", new Student("jacky", "123456")); map.put("003", new Student("rose", "123456")); pageContext.setAttribute("map", map); %> Map集合: <br /> ${map['001'].name1 } - ${map['001'].password } <br /> ${map['002'].name1 } - ${map['002'].password } <br /> ${map['003'].name1 } - ${map['003'].password } <br /> </body> </html>
1.3 EL执行表达式
算术表达式
比较表达式
逻辑表达式
判空表达式
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>EL执行表达式</title> </head> <body> <%-- 1)算术表达式: + - * / --%> <% int a = 10; int b = 5; pageContext.setAttribute("a", a); pageContext.setAttribute("b", b); %> ${a+b } <br /> ${a-b } <br /> ${a*b } <br /> ${a/b } <hr /> <%-- 2)比较表达式: > < >= <= == --%> ${a>b } <br /> ${a==b } <br /> <hr /> <%-- 3)逻辑表达式: && (与) || (或) !(非) --%> ${true&&true } <br /> ${true||false } <br /> ${!true } <br /> ${!(a>b) } <hr /> <%-- 4)判空表达式 empty null: ==null 空字符串: =="" --%> <% //String name1 = null; String name1 = ""; pageContext.setAttribute("name1", name1); %> null: ${name1==null } <br /> 空字符串: ${name1=="" } <br /> null或空字符串: ${name1==null || name1=="" } <br /> null或空字符串:${empty name1} </body> </html>
1.4 EL的11个内置对象
pageContext
pageScope
requestScope
sessionScope
applicatinoScope
param
paramValues
header
headerValues
cookie
initParam
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>EL的11个内置对象</title> </head> <body> <%-- 1)pageContext 等价于 jsp的pageContext内置对象 --%> <%--获取上下文路径 --%> ${pageContext.request.contextPath } <hr /> <%-- pageScope requestScope sessionScope applicatinoScope 从指定的域中获取数据 --%> <%-- 2)param: 获取参数 注意: param返回所有参数Map集合 --%> <%=request.getParameter("name")%><br /> <br /> ${param['name']} <%=request.getParameterValues("name")[1]%> <br /> ${paramValues['name'][0] }-${paramValues['name'][1] } <hr /> <%-- 3) header :获取请求头 headerValues --%> <%=request.getHeader("host")%><br /> <%=request.getHeaders("host").nextElement()%><br /> ${header['host'] } <br /> ${headerValues['host'][0] } <%-- 4)cookie: 获取cookie --%> <hr /> <%=request.getCookies()[0].getValue()%><br /> ${cookie['JSESSIONID'].name } - ${cookie['JSESSIONID'].value } <hr /> <%-- 5) initParam: 获取全局参数 --%> <%=application.getInitParameter("AAA")%><br /> ${initParam['AAA'] } </body> </html>
2.Jsp标签
2.1 简介
EL表达式可以替换jsp表达式,但是EL表达式局限:
不能条件判断,不能赋值,不能迭代。
jsp标签替代jsp脚本,完成条件判断,赋值,迭代等等功能。
2.2 Jsp标签分类
1)jsp内置标签(动作标签): 使用的时候不需要导入标签库
2)jstl标签(标准标签): 使用的时候都需要导入标签库
3)自定义标签:使用的时候都需要导入标签库
2.3 动作标签
<jsp:forward/> 转发标签
<jsp:param/> 参数标签
<jsp:include/> 包含标签
注意:
包含标签的原理是包含与被包含的页面单独翻译成不同的java文件,然后再运行时合并在一起。 (先翻译再合并,动态包含)
静态包含 vs 动态包含
静态包含: 先合并再翻译。不能携带参数
动态包含: 先翻译再合并。携带参数
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>动作标签</title> </head> <body> <%-- 1)<jsp:foward/> 转发 --%> <% //request.getRequestDispatcher("/01el3.jsp").forward(request, response); %> <%-- <jsp:forward page="/01el3.jsp"></jsp:forward> --%> <%--注意: 一定要使用jsp注释来注释标签 <jsp:forward page="/02action2.jsp"> <jsp:param value="eric" name="name" /> <jsp:param value="jacky" name="name" /> </jsp:forward> --%> <%-- 3 ) <jsp:include/> 动态包含。可以携带参数给被包含的页面,但是静态包含不能携带参数给被包含的页面 --%> <jsp:include page="/common/header.jsp"> <jsp:param value="eric" name="name" /> </jsp:include> 主页内容 </body> </html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'header.jsp' starting page</title> </head> <body> 通用的头部页面<br/> 接收参数: ${param['name'] } <hr /> </body> </html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>动作标签</title> </head> <body> 接收参数 : ${paramValues['name'][0] } -${paramValues['name'][1] } </body> </html>
2.4 JSTL标签
jstl标签,java standard tag libarary java标准标签库。
特点: 在使用jstl标签时需要导入标签库
jstl标签库分类:
核心标签库(重要)
国际化标签库(fmt)
EL函数库(fn)
SQL标签库(sql)
XML标签库(x)
2.5 使用JSTL标签
1)导入jstl的支持jar包,在java5.0之后jstl已经是属于5.0的支持包里面。
2)使用jsp页面,需要在jsp的顶部使用taglib指令导入需要的标签库
3)使用标签:
<c:set/>
2.6 核心标签库的标签
保存数据:
<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>
<%@ page language="java" import="java.util.*,cn.jxufe.entity.*" pageEncoding="UTF-8"%> <%--导入核心标签库 --%> <%-- uri: 表示需要导入的标签库的uri名称。每个标签库都会有一个tld后缀名的标签声明文件,在tld文件中都有唯一的uri的名称。这个uri的名称就是当前标签库的名称。 prefix: 使用标签库的前缀,通用和tld文件的short-name名称相同 --%> <%@ 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> </head> <body> <%-- 1) <c:set/> 给域对象赋值 --%> <% //String name = "eric"; //pageContext.setAttribute("name",name); %> <%-- var: 数据的名称 value: 保存的数据值 scope: 保存到哪个域。 page-》page域 requset->request域 session->session域 application->application域 --%> <c:set var="name" value="jacky" scope="request" /> ${name} <hr /> <%-- 2) <c:out/> 获取域对象的数据 --%> <%-- value: 代表获取域中的某个名称内容。如果数据在域中,必须使用EL语法去获取 default: 默认值。当前需要获取的内容为null,那么使用默认值代替 escapeXml: 默认情况下为true,out标签会把输入的内容进行转义。如果不需要转义,则为false既可! --%> <c:out value="${name}" default="<h3>标题3</h3>" escapeXml="false"></c:out> <hr /> <%-- 3) <c:if/> 单条件判断 --%> <%-- test: 条件表达式。返回true的时候,就会执行if标签体内容,否则,不执行。 --%> <c:if test="${10>8}"> <input type="submit" value="提交" /> </c:if> <hr /> <%-- 4) <c:choose/>+<c:when/>+<c:otherwise/> 多条件判断 登录之后,一定会把数据存放到session域,user名称 session.setAttribute("user",user); --%> <%--模拟登录 --%> <c:set var="user" value="eric" scope="session"></c:set> <c:choose> <c:when test="${!empty sessionScope.user}"> 欢迎回来,你的用户名是 :eric,<a href="">【退出登录】</a> </c:when> <c:otherwise> 请先<a href="">注册</a>或<a href="">登录</a> </c:otherwise> </c:choose> <hr /> <%-- 5) <c:forEach/> 用于迭代或循环 --%> <% //List List<Student> list = new ArrayList<Student>(); list.add(new Student("eric", "123456")); list.add(new Student("lily", "123456")); list.add(new Student("maxwell", "123456")); pageContext.setAttribute("list", list); %> <hr /> <%-- begin: 从哪个元素开始遍历,从0开始 end: 到哪个元素位置 step: 增加步长。默认step为 1 items: 需要遍历的数据。(数组|List集合|Map集合) 如果是获取域数据,那么使用EL表达式获取 var: 每个元素名称 varStatus: 当前状态对象。该对象封装当前元素状态信息。 例如 count属性: 表示当前遍历的是哪个元素,从1开始 --%> List集合: <br /> <c:forEach items="${list}" var="student" varStatus="varSta"> 序号:${varSta.count } 姓名:${student.name1 } - 密码: ${student.password }<br /> </c:forEach> <c:forEach begin="0" end="3" step="2" items="${list}" var="student" varStatus="varSta"> 序号:${varSta.count } 姓名:${student.name1 } 密码:${student.password }<br /> </c:forEach> <hr /> <% Map<String, Student> map = new HashMap<String, Student>(); map.put("001", new Student("eric", "123456")); map.put("002", new Student("jacky", "123456")); map.put("003", new Student("rose", "123456")); pageContext.setAttribute("map", map); %> Map集合: <br /> <%-- 注意: forEach标签遍历Map集合时,把每个Map的对象使用Entry封装, Entry封装键对象和值对象,通过getKey()获取键对象,通过getValue()获取值对象 --%> <c:forEach items="${map}" var="entry"> 编号: ${entry.key } - 姓名:${entry.value.name1 } - 密码: ${entry.value.password }<br /> </c:forEach> <hr /> <%-- 6) <c:forToekens/> 遍历特殊字符串 --%> <c:set var="str" value="java-net-php-平面设计"></c:set> <% String str = (String) pageContext.getAttribute("str"); String[] strs = str.split("-"); for (int i = 0; i < strs.length; i++) { out.write(strs[i] + ","); } %> <br /> <%-- items: 需要遍历的字符串 delims: 指定分割符号 var: 每个内容的名称 --%> <c:forTokens items="${str}" delims="-" var="s"> ${s }, </c:forTokens> <hr /> <%-- 7) <c:rediect/> 重定向标签 --%> <% //response.sendRedirect(request.getContextPath()+"/03.el3.jsp"); %> <%-- <c:redirect url="/01el3.jsp"></c:redirect> --%> </body> </html>
2.7 自定义标签
当现有的标签无法满足需求的时候,就需要开发者自行开发标签。
需求: 获取客户端的IP地址
开发步骤:
1)开发标签处理程序,是一个普通的java类,继承SimpleTagSupport类,覆盖doTag方法
package cn.jxufe.a_tag; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.SimpleTagSupport; /* * 自定义标签的标签处理程序 */ public class ShowIpTag extends SimpleTagSupport { /* private JspContext jspContext; // 用于设置PageContext对象 // JspContext是PageContext的父类,实际传入的是PageContext对象 @Override public void setJspContext(JspContext pc) { this.jspContext = pc; } */ @Override public void doTag() throws JspException, IOException { // TODO Auto-generated method stub // 1)获取客户端ip PageContext pageContext = (PageContext) this.getJspContext(); // 2)通过PageContext获取到其他8个内置对象 HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); String ip = request.getRemoteHost(); // 3)把ip输入给浏览器 JspWriter out = pageContext.getOut(); out.write("当前客户端的IP为:" + ip); } }
2)在项目的WEB-INF目录下建立一个tld文件,例如jxufe.tld,内容可以参考核心标签库的c.tld内容
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <!-- 标签的版本号 --> <tlib-version>1.1</tlib-version> <!-- 简单名称,用于使用标签库的前缀 --> <short-name>jxufe</short-name> <!-- 是标签库的唯一名称 --> <uri>http://jxufe.cn</uri> <!-- 定义一个标签 --> <tag> <!-- 标签名称 --> <name>showIp</name> <!-- 标签处理程序的全名: 包名+类名 --> <tag-class>cn.jxufe.a_tag.ShowIpTag</tag-class> <!-- 标签体内容输出格式 --> <body-content>scriptless</body-content> </tag> <tag> <!-- 标签名称 --> <name>parent</name> <!-- 标签处理程序的全名: 包名+类名 --> <tag-class>cn.jxufe.a_tag.ShowIpTag</tag-class> <!-- 标签体内容输出格式 --> <body-content>scriptless</body-content> </tag> </taglib>
3)在jsp页面顶部导入自定义标签库
4)使用标签库中的标签
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%--导入自定义标签库 --%> <%@ taglib uri="http://jxufe.cn" prefix="jxufe"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>自定义标签</title> </head> <body> <%-- 向浏览器输出当前访问客户的IP地址 --%> <% //1)获取客户端IP地址 //String ip = request.getRemoteHost(); //2)向浏览器输入内容 //out.write("当前客户的IP为:" + ip); %> <%--使用自定义标签代替以上脚本 --%> <%-- showIp标签: 作用可以显示客户端的IP地址 --%> <jxufe:showIp></jxufe:showIp> </body> </html>
2.8 自定义标签的执行过程
访问:http://localhost:8080/day12/04tag.jsp
前提: tomcat启动的时候,会读取day12JSP项目下的WEB-INF的文件。包括web.xml和tld文件。
1)翻译成java文件-》 编译成class文件-> 构造方法- 》 调用_jspService()方法
2)在内存tld文件中,查询是否存在一个uri名称为http://gz.itcast.cn的tld文件
3)得到对应的tld文件内容。
4)读到<itcst:showIp>内容时,截取showIp名称(就是标签),到tld文件中查询是否存在name为showIp的tag标签。
5)取出<tag>标签的内容<tag-class>字符串: gz.itcast.a_tag.ShowIpTag
2.9 自定义标签的生命周期
由tocmat服务器调用的
1)构造方法: 构造标签器对象
2)void setJspContext(JspContext pc) 传入PageContext对象。JspContext是PageContext的父类。可以使用getJspContext()方法获取PageContext对象。
3)void setParent(JspTag parent) 传入父标签对象。如果没有父标签,则不调用次方法。使用getParent()方法获取父标签
4)void setJspBody(JspFragment jspBody) 传入标签体内容。如果没有标签体,则不调用次方法。使用getJspBody()获取标签体内容。标签体内容封装到JspFragment中
5)void doTag() 调用标签时执行方法。我们的业务逻辑就写在这个方法中。可以调用getJspContext(),getParent(),getJspBody();
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)