EL&JSTL详解

EL&JSTL

1. EL表达式

1.1. 传统JSP代码的痛点

<table>
    <tr>
        <th>ID</th>
        <th>姓名</th>
        <th>称号</th>
        <th>头像</th>
    </tr>
    <%
        Object obj = request.getAttribute("list");
        List<UserInfo> list = (List<UserInfo>) obj;
        for (UserInfo u : list) {
    %>
    <tr>
        <td><%=u.getId()%></td>
        <td><%=u.getName()%></td>
        <td><%=u.getTitle()%></td>
        <td><img src="<%=u.getImg()%>" alt=""></td>
    </tr>
    <% } %>
</table>

以上jsp页面中既有html代码,也有Java代码,并且Java代码还必须包含在<%%>之间,可读性行非常差,并且代码编写起来相对复杂:

  • 可读性差
  • 编写复杂

1.2. EL表达式概述

EL(Expression Language)表达式语言,是JSP2.0规范中引入一种新特性,灵感来自于ECMAScript中XPath(快速节点检索技术)语法;允许使用${}操作jsp各个作用域中的数据,另外EL表达式还引入了一些内置对象,也支持一些基本的运算操作

1.3. EL基础语法

EL表达式基本语法为:

${表达式内容}

例如:

<!-- 基本运算 -->
${4 + 5}
<!-- 从session返回获取数据 -->
${sessionScope.msg}   等同于 <%=session.getAttribute("msg")%>
<!-- 获取cookie数据 -->
${cookie.name}

注意事项:

由于目前最新版本中为了防止表达式的冲突,jsp默认关闭了对EL表达式的识别,因此如果需要在jsp页面中使用EL表达式,则必须开启EL表达式的支持:

<%@ page language="java" pageEncoding="UTF-8" isELIgnored="false" %>

以上将isElIgnored设置为false代表不忽略EL表达式

1.4. 运算符

EL表达式对于基本算数运算和关系运算都有提供相应支持,常见的运算符主要包含如下

分类运算符案例
算术运算符+、-、*、/或div、%或mod 2 + 3 < b r > {2+3}<br> 2+3<br>{3-2}
3 ∗ 4 < b r > {3*4}<br> 34<br>{6/3}或 6 d i v 3 < b r > {6 div3 }<br> 6div3<br>{10 % 3}或${10 mod 3}
关系运算符==或eq、!=或ne、<或lt、>或gt、<=或le、>=或ge 5 = = 5 或 { 5 == 5}或 5==5{5 eq 5}
2 ! = 3 或 {2 != 3}或 2!=3{2 ne 3}
5 < 6 或 {5 < 6}或 5<6{5 lt 6}
7 > 6 或 { 7 > 6}或 7>6{7 gt 6}
8 < = 9 或 {8 <= 9}或 8<=9{8 le 9}
8 > = 7 或 {8 >= 7}或 8>=7{8 ge 7}
布尔逻辑运算符&&或and、||或or、!或notKaTeX parse error: Expected '}', got '&' at position 7: {true &̲& true}或{true and true}
t r u e ∥ ∥ f a l s e 或 {true \|\| false}或 truefalse{true or false}
! t r u e 或 {!true}或 !true{not true}
其他Empty运算符、三目运算符、()运算符 e m p t y [ ′ a ′ , ′ b ′ , ′ c ′ ] < b r > {empty ['a','b','c']}<br> empty[a,b,c]<br>{a > b ? a : b}
${10 > 6 ? 10 : 10 > 11 ? 10 : 11}

1.5. 内置对象(隐含对象)

EL表达式中对于一些JSP/Servlet对象的访问,提供了内置的对象(无需声明直接使用的对象),主要包含如下:

  • 作用域对象
  • 请求参数对象
  • 请求头对象
  • 全局初始化参数
  • cookie对象
1.5.1. 作用域对象

作用域对象即用于从jsp的四个内置对象中获取数据的对象,分为:

  • pageScope
  • requestScope
  • sessionScope
  • applicationScope

用法如下:

<p>${pageScope.page}</p>
<p>${requestScope.request}</p>
<p>${sessionScope.session}</p>
<p>${applicationScope.app}</p>

以上代码等同于:

<p><%=pageContext.getAttribute("page")%></p>
<p><%=request.getAttribute("request")%></p>
<p><%=session.getAttribute("session")%></p>
<p><%=application.getAttribute("app")%></p>

实际使用过程中四个隐含对象可以无需编写,例如:

${msg}

以上${msg}表示从page范围获取数据,若获取不到则依次向更大的范围搜索:

pageContext < requestScope < sessionScope < applicationScope

1.5.2. 请求参数对象

在servlet/jsp中需要获取客户端提交的数据时一般会使用request.getParamater("XX")来获取表单或者url参数数据,在EL表达式中对于请求参数的获取也提供了两个隐含对象:

  • param(等同于request.getParamater("XX"))
  • paramValues(等同于request.getParamaterValues(“XXX”)

使用方式:

  • 请求地址:http://localhost/doLogin.jsp?username=softeem&password=123&lang=java&lang=c&lang=python

  • 数据获取

    Username:${param.username}<br>
    Password:${param.password}<br>
    langs:${paramValues.lang}
    

    以上代码等同于:

    String username = request.getParameter("username");
    String password = request.getParameter("password");
    String[] langs = request.getParameterValues("lang");
    
1.5.3. 其他对象
  • 请求头对象

    • header:获取请求头对象
    • headerValues:获取请求头对象,其中所有的值为一个数组对象
    请求头:${header}<br>
    请求头中指定的属性:${header['host']}--${header.get("host")}<br>
    ${header['user-agent']}<br>
    ${headerValues}
    
  • cookie:获取cookie对象

    cookie:${cookie.JSESSIONID.value}<br>
    获取cookie中的用户名:${cookie.name.value}
    

    注意事项,使用cookie的name获取的是一个Cookie对象(而非值),如果需要获取cookie的值,则需要在调用value属性才行

  • initParam:全局初始化参数对象

    全局的初始化的对象主要用于获取web.xml文件中context-param参数值:

    <!-- 全局初始化参数-->
    <context-param>
        <param-name>applicationContextConfig</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    

    jsp页面中获取方式包含如下:

    全局初始化参数获取:${initParam.applicationContextConfig}
    <hr>
    <%=application.getInitParameter("applicationContextConfig")%>
    <hr>
    <%=request.getServletContext().getInitParameter("applicationContextConfig")%>
    

    以上每一个表达式获取的结果都是一致的:classpath:applicationContext.xml

  • pageContext

    可以通过该对象配置页面的根地址

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <base href="${pageContext.request.contextPath}/">
        <title>Title</title>
    </head>
    <body>
    
    </body>
    </html>
    

    ${pageContext.request.contextPath}:获取当前项目所在的根地址

1.6. Web项目中WEB-INF目录问题

实际开发中通常会将jsp页面都存储在WEB-INF目录中,WEB-INF下的资源外界通过重定向的方式访问,只能由服务器请求转发传输到客户端浏览器显示,对jsp的安全访问提供了保障

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aOn2nQaD-1634725310826)(assets/image-20211004114556921.png)]

以上为一个正常的jsp页面在web项目中的存储方式,外界如果发起以下请求:

http://localhost/WEB-INF/pages/page1.jsp

页面会如下显示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8zaldhkx-1634725310828)(assets/image-20211004114658706.png)]

所以,对于WEB-INF下的资源使用重定向的方式是无法访问的,必须由服务端请求转发,因此可以使用如下的Servlet:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ktsmfw1b-1634725310829)(assets/image-20211004115145362.png)]

此时请求地址栏只需要按照如下方式请求即可:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-euDHVDS9-1634725310831)(assets/image-20211004115220345.png)]

2. JSTL(标准标签库)

2.1. JSTL概述

EL表达式可以使用简洁的语法实现数据的获取,但是对于一些负责的逻辑判断,或者循环操作,EL可能无法满足需求,因此需要配合一些其他技术共同实现需求,这一项技术称之为JSTL.

JSTL(JSP Standard TagLib):jsp标准标签库,标签库即使用一些预定义(自定义)好的标签,替代原本jsp中的<% %>之类的原始java代码,使得jsp页面中的代码编写风格更为统一。

2.1.1. 传统JSP代码
<table>
    <tr>
        <th>工号</th>
        <th>姓名</th>
        <th>职位</th>
        <th>生日</th>
        <th>月薪</th>
        <th>部门</th>
        <th>操作</th>
    </tr>
    <%
        Object obj = request.getAttribute("list");
        if(obj != null){
        List<Emp> list = (List<Emp>) obj;
        for(Emp e:list){
    %>
    <tr>
        <td><%=e.getEno()%></td>
        <td><%=e.getEname()%></td>
        <td><%=e.getJob().equals("2") ? "部门经理" : "普通员工" %></td>
        <td>
            <%
            DateFormat fmt = DateFormat.getDateInstance(); //yyyy-mm-dd
            String birth = fmt.format(e.getBirth());
            out.write(birth);
            %>
        </td>
        <td>
            <%
            NumberFormat numberFormat = NumberFormat.getNumberInstance();
            String sal = numberFormat.format(e.getSal());
            out.write(sal);
            %>
        </td>
        <td><%=e.getDept().getDname()%></td>
        <td>
            <a href="">详情</a>&nbsp;&nbsp;
            <a href="">操作</a>
        </td>
    </tr>
    <%
    }
    }else{
        out.write("<tr><th colspan='7' style='color:#f00'>暂无数据!</th></tr>");
    }
    %>
</table>

从以上的源代码语法来看,编写方式极其复杂,可读性差。使用JSTL之后以上代码可以统一一种风格:

2.1.2. 使用JSTL的JSP页面
<table>
    <tr>
        <th>工号</th>
        <th>姓名</th>
        <th>职位</th>
        <th>生日</th>
        <th>月薪</th>
        <th>部门</th>
        <th>操作</th>
    </tr>
    <c:if test="${empty list || list.size() < 1}">
        <tr><th style="color: #ff0000;">暂无数据!</th></tr>
    </c:if>
    <c:if test="${not empty list}">
        <c:forEach items="${list}" var="e">
            <tr>
                <td>${e.eno}</td>
                <td>${e.ename}</td>
                <td>${e.job eq "2" ? "部门经理":"普通员工"}</td>
                <td><fmt:formatDate value="${e.birth}" pattern="yyyy-MM-dd"/></td>
                <td><fmt:formatNumber value="${e.sal}" pattern="###.##"/></td>
                <td>${e.dept.dname}</td>
                <td>
                    <a href="">详情</a>&nbsp;&nbsp;
                    <a href="">操作</a>
                </td>
            </tr>
        </c:forEach>
    </c:if>
</table>

2.2. JSTL使用方式

2.2.1. JSTL基本使用
  • 在jsp中使用JSTL通常需要引入两个依赖:jstl.jarstandard.jar

    <!--    引入jstl标准标签库-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    
  • 在需要使用JSTL的页面中导入标签库:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h1>page1页面</h1>
    
    </body>
    </html>
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5kXRlr77-1634725310833)(assets/image-20211004142745585.png)]

  • 使用标签库

     <c:out value="${msg}"></c:out>
    

    以上表示一个输出标签,直接在页面中输出${msg}所获取的数据

2.3. JSTL常用标签

JSTL标签库主要包含以下标签分类:

  • 核心标签库(c标签
  • 格式化标签库(fmt标签
  • 函数标签库(functions标签
  • 数据库标签(sql标签
  • xml标签
标签库标签库的URI前缀
Corehttp://java.sun.com/jsp/jstl/corec
Formathttp://java.sun.com/jsp/jstl/fmtfmt
XMLhttp://java.sun.com/jsp/jstl/xmlxml
SQLhttp://java.sun.com/jsp/jstl/sqlsql
Functionshttp://java.sun.com/jsp/jstl/functionsfn
2.3.1. c标签

c标签也称之为核心标签库(core),主要用于页面进行数据的展示,包括一些逻辑判断和循环处理,常用c标签主要包含以下:

  • c:out:输出标签

    • value:用于输出的内容(配合el表达式使用,获取四个作用域的数据)
    • default:如果value无法获取数据时,可以显示该默认值
    • escapeXml:是否忽略xml代码(包括html),默认值:true
    <c:out value="${code}" default="无数据" escapeXml="false"></c:out>
    
  • c:import:包含标签,将一个页面包含到当前的页面中(动态包含)

  • c:set:设置参数的标签,用于向指定的范围或者bean中设置属性

    • var:存储的变量名
    • value:存储的变量值
    • scope:存储范围(page,request,session,application)
  • c:urlc:redirect

    • c:url:用于创建url的标签

      • var:该url的属性名
      • value:url的地址值
      • scope:url的存储范围(page,request,session,application)
      <c:url var="page3" value="/user/page3" scope="request">
          <c:param name="username" value="softeem"/>
          <c:param name="password" value="123456"/>
      </c:url>
      

      以上代码等同于request.setAttribute("page3","/user/page3?username=softeem&password=123456")

    • c:redirect:重定向到指定的目标

      • url:目标地址,可以使用el表达式获取指定范围的数据
      <c:redirect url="${page3}"/>
      

      以上代码等同于

      response.sendRedirect("/user/page3?username=softeem&password=123456");
      
2.3.1.1. c:if标签

<c:if>标签用于执行一些简单的逻辑判断,包含一个核心属性test,该属性中可以使用EL编写一个返回布尔结果的表达式:

<c:if test="${age lt 18}">
    未成年
</c:if>
<c:if test="${age ge 18 and age le 50}">
    中年
</c:if>
<c:if test="${age gt 50}">
    老年
</c:if>

c:if标签并未像java一样对应有一个c:else

2.3.1.2. c:choose&c:when&c:overwise标签

由于c:if标签只提供一个分支,进行逻辑判断;如果对于存在多个分支的需求可以使用c:choosec:when解决,语法如下:

<c:choose>
    <c:when test="${age < 18}">未成年</c:when>
    <c:when test="${age >= 18 and age < 36}">青年</c:when>
    <c:when test="${age >= 36 and age < 55}">中年</c:when>
    <c:when test="${age >= 55 and age < 65}">中老年</c:when>
    <c:otherwise>
        老年
    </c:otherwise>
</c:choose>
2.3.1.3. c:forEach&c:forTokens标签
  • c:forEach

    在对集合数据遍历时,jsp中除了可以直接使用java代码之外,另外也可以使用jstl中c:forEach(推荐),例如:

    <div class="layui-container">
        <table class="layui-table" lay-even lay-skin="line" lay-size="lg">
            <tr>
                <th><input type="checkbox"></th>
                <th>ID</th>
                <th>姓名</th>
                <th>性别</th>
                <th>年龄</th>
                <th>电话</th>
                <th>操作</th>
            </tr>
            <c:forEach var="u" items="${requestScope.list}">
                <tr>
                    <td><input type="checkbox"></td>
                    <td>${u.id}</td>
                    <td>${u.name}</td>
                    <td>${u.sex}</td>
                    <td>${u.age}</td>
                    <td>${u.tel}</td>
                    <td>
                        <button class="layui-btn layui-btn-normal">详情</button>
                        <button class="layui-btn layui-btn-warm">编辑</button>
                        <button class="layui-btn layui-btn-danger">删除</button>
                    </td>
                </tr>
            </c:forEach>
        </table>
    </div>
    

    c:forEach标签中常用的属性

    • var:迭代到的每一个元素的变量名(自定义)

    • items:需要被迭代(遍历)的集合或者数组

    • varStatus:表示当前迭代的数据状态,内部包含一些常用子属性

      • index:获取当前数据行的索引,从0开始
      • count:获取当前行的总行数,即:第几行
      • last:是否是集合中的最后一行数据
      • first:是否是集合中的第一行数据
      <table class="layui-table">
          <tr>
              <th>索引</th>
              <th>序号</th>
              <th>名称</th>
              <th>是否第一个</th>
              <th>是否最后一个</th>
          </tr>
          <c:forEach var="name" items="admin,jack,rose,tom,jerry" varStatus="stat">
              <tr>
                  <td>${stat.index}</td>
                  <td>${stat.count}</td>
                  <td>${name}</td>
                  <td>${stat.first}</td>
                  <td>${stat.last}</td>
              </tr>
          </c:forEach>
      </table>
      
    • begin:起始的显示索引

    • end:结束的显示索引

    • step:步进值,即每次跳过的行数

    <form class="layui-form" style="padding: 20px">
        <div class="layui-col-md2">
            <select>
                <c:forEach var="year" begin="2000" end="2021" step="4">
                    <option>${year}</option>
                </c:forEach>
            </select>
        </div>
    </form>
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xt0754eH-1634725310834)(assets/image-20211004162809436.png)]

  • c:forTokens

    <c:forTokens>是按照指定的分隔符对字符串文本内容截取之后获得为集合,并且可以实现对该集合遍历,

    使用方式:

    <% pageContext.setAttribute("tags","乡村/摇滚/R&B/美式");%>
    <c:forTokens items="${tags}" delims="/" var="tag">
        <span class="layui-badge layui-bg-danger">${tag}</span>
    </c:forTokens>
    

    常用属性:

    • items:需要进行截取的字符串
    • delims:分隔符
    • var:分割之后的每一个元素的名称
2.3.2. fmt标签

c标签作为核心标签库是经常需要被使用到的,但是有些时候c标签无法满足所有需求。例如需要对显示的时间日期,或者数值进行格式化的时候,c标签不能很好的解决,因此需要其他标签辅助解决问题,其中用于进行格式化处理的需求,JSTL提供了fmt标签

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Y6t3UQR-1634725310836)(assets/image-20211004170812704.png)]

fmt作用于对日期,数值等数据进行格式化或者解析操作

  • 使用fmt标签必须先导入标签库

    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    
  • 具体使用

    <td>
        <fmt:formatDate value="${u.regTime}" pattern="yyyy-MM-dd HH:mm:ss"/>
    </td>
    <td>
        <fmt:formatNumber value="${u.money}" pattern="¥###.#"/>
    </td>
    
2.3.3. 综合案例

使用JSTL显示如下一个表格效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jEimfpVY-1634725310837)(assets/image-20211004171432856.png)]

  • Servlet代码

    @WebServlet("/jstl/*")
    public class JSTLServlet extends BaseServlet{
    
        public String getData(HttpServletRequest request, HttpServletResponse response){
    
            List<User> list = new ArrayList<User>(){
                {
                    add(new User(1,"softeem","0",18,"123456","游戏,小说,帅哥",new Date(),4567.89));
                    add(new User(2,"admin","0",28,"123456","唱,跳,rap,篮球",new Date(120,8,15),4567.89));
                    add(new User(3,"刘德华","1",45,"123456","编程,帅哥",new Date(),46.89));
                    add(new User(4,"张三丰","1",64,null,"游戏,小说,帅哥",new Date(121,6,30),46.19));
                    add(new User(5,"张无忌","1",88,"123456","游戏,小说,帅哥",new Date(),4567.89));
                    add(new User(6,"周杰伦","0",27,"123456","看帅哥,听音乐",new Date(119,5,13),1456.42));
                    add(new User(7,"刘亦菲","1",19,null,"游戏,帅哥",new Date(),561.91));
                    add(new User(8,"马德华","0",15,"123456","游戏,小说",new Date(),467.18));
                }
            };
    
            request.setAttribute("list",list);
    
            return "/WEB-INF/pages/page1.jsp";
        }
    
    }
    
    
  • jsp页面代码

    <div class="layui-fluid">
        <table class="layui-table" lay-even lay-skin="line" lay-size="lg">
            <tr>
                <th><input type="checkbox"></th>
                <th>ID</th>
                <th>姓名</th>
                <th>性别</th>
                <th>年龄</th>
                <th>年龄状态</th>
                <th>电话</th>
                <th>兴趣爱好</th>
                <th>注册时间</th>
                <td>余额</td>
                <th>操作</th>
            </tr>
            <c:forEach var="u" items="${requestScope.list}">
                <tr>
                    <td><input type="checkbox"></td>
                    <td>${u.id}</td>
                    <td>${u.name}</td>
                    <td>${u.sex eq '0' ? '女' : '男'}</td>
                    <td>${u.age}</td>
                    <td>
                        <c:choose>
                            <c:when test="${u.age < 18}">未成年</c:when>
                            <c:when test="${u.age >= 18 and u.age < 36}">青年</c:when>
                            <c:when test="${u.age >= 36 and u.age < 55}">中年</c:when>
                            <c:when test="${u.age >= 55 and u.age < 65}">中老年</c:when>
                            <c:otherwise>老年</c:otherwise>
                        </c:choose>
                    </td>
                    <td>
                        <c:if test="${u.tel eq null}">未知</c:if>
                        <c:if test="${u.tel ne null}">${u.tel}</c:if>
                    </td>
                    <td>
                        <c:forTokens var="h" items="${u.hobbies}" delims=",">
                            <a href=""><span class="layui-badge layui-bg-blue">${h}</span></a>
                        </c:forTokens>
                    </td>
                    <td>
                        <fmt:formatDate value="${u.regTime}" pattern="yyyy-MM-dd HH:mm:ss"/>
                    </td>
                    <td>
                        <fmt:formatNumber value="${u.money}" pattern="¥###.#"/>
                    </td>
                    <td>
                        <button class="layui-btn layui-btn-normal">详情</button>
                        <button class="layui-btn layui-btn-warm">编辑</button>
                        <button class="layui-btn layui-btn-danger">删除</button>
                    </td>
                </tr>
            </c:forEach>
        </table>
    </div>
    
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西伯利亚大熊猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值