JSP 和 JSTL

次要内容

JSP

JSP的根底语法

简介

JSP:Java Server Page SUN 公司提供的动静网页编程技术,是 Java Web 服务器端的动静资源。

它相比 html 而言,html 只能为用户提供静态数据,而 Jsp 技术容许在页面中嵌套 java 代码,为用户提供动态数据。

相比 servlet 而言,servlet 很难对数据进行排版,而 jsp 除了能够用 java 代码产生动态数据的同时,也很容易对数据进行排版。

不论是 JSP 还是 Servlet,尽管都能够用于开发动静 web 资源。但因为这 2 门技术各自的特点,在长期的软件实际中,人们逐步把 servlet 作为 web 利用中的控制器组件来应用, 而把 JSP 技术作为数据显示模板来应用。

其实 Jsp 就是一个 Servlet,当咱们第一次拜访 Jsp 的时候,Jsp 引擎都会将这个 Jsp 翻译 成一个 Servlet,这个文件寄存在tomcat(源码目录) 中的 work 目录中

筹备工作
配置IDEA

这一步不是必须的,当然因为 编辑器中有些默认的配置项咱们感觉不是很完满,比方"编码格局"、页面模板等。咱们能够在新建 JSP 页面之前就先批改为咱们须要的。

1.抉择"File" —> "Settings..."

2.设置编码格局。搜寻"encode",抉择"File Encoding"

[外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-aWGzNmLu-1607481120171)(/jsp_idea配置jsp_3.png)]

3.设置页面模板。搜寻"template",抉择"File and Code Templates",抉择右侧的"Other",抉择下方的"Jsp File"

新建JSP页面
正文

在 JSP 中反对两种正文的语法操作:

一种是显示正文,这种正文是容许客户端看见的; 另一种是隐式正文,此种正文是客户端无奈看见的

① 显示正文语法:从 HTML 格调继承而来

② 隐式正文语法:从 JAVA 格调继承;JSP 本人的正文

JSP 的三种正文形式:

1) // 正文,单行正文  /* 多行正文*/ 2)<!--  HTML格调的正文 -->3)<%--   JSP正文  --%>
Scriptlet

在 JSP 中最重要的局部就是 Scriptlet(脚本小程序),所有嵌入在 HTML 代码中的 Java 程序

在 JSP 中一共有三种 Scriptlet 代码:都必须应用 Scriptlet 标记进去

第一种:<%    %>: java 脚本段,能够定义局部变量、编写语句第二种:<%!   %>:申明,能够定义全局(成员)变量、办法、类第三种:<%=  %>:表达式,数据一个变量或具体内容

通过观察解析为 java 文件的 jsp 代码了解三种小脚本

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE ><html>    <head>           <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">        <title>Scriptlet</title>    </head>    <body>        <%            String str = "Hello JSP";            System.out.println(str);            response.getWriter().write(str);        %>        <%!            String memberStr = "a member String";        %>        <%=memberStr%>        <h1>This is a JSP page!!</h1>    </body></html>

JSP的指令标签

应用蕴含操作,能够将一些反复的代码蕴含进来持续应用,从失常的页面组成来看,有时可能分为几个区域。而其中的一些区域可能是始终不须要扭转的,扭转的就其中的一个具体内容区域。当初有两种办法能够实现上述性能。

办法一:在每个 JSP 页面(HTML)都蕴含工具栏、头部信息、尾部信息、具体内容

办法二:将工具栏、头部信息、尾部信息都分成各个独立的文件,应用的时候间接导入

很显著,第二种办法比第一种更好,第一种会存在很多反复的代码,并且批改很不不便,在 JSP 中如果要想实现蕴含的操作,有两种做法:动态蕴含动静蕴含,动态蕴含应用 include 指令即可,动静蕴含则须要应用 include 动作标签。

include 动态蕴含
<%@ include file="要蕴含的文件门路" %>  <!-- 相对路径 -->

例如:

<%@include file="include.jsp" %>或<%@include file="include.html" %>

动态蕴含就是将内容进行了间接的替换,就好比程序中定义的变量一样,是在 servlet 引擎转译时,就把此文件内容蕴含了进去(两个文件的源代码整合到一起, 全副放到_jspService 办法中),所以只生成了一个 servlet,所以两个页面不能有同名的变量。 运行效率高一点点。耦合性较高,不够灵便。

include 动静蕴含

动静蕴含在代码的编译阶段,蕴含和被蕴含局部是两个独立的局部,只有当运行时,才会动静蕴含进来,好比办法的调用。

<jsp:include page="include.jsp"></jsp:include>

留神:动静蕴含,中间不要加任何内容,包含空格,除非确认要应用参数,否则报错!

<jsp:include page="include.html"></jsp:include><%    String a = "hello.jsp";%><jsp:include page="<%=a %>"></jsp:include>

应用动静蕴含还能够通过在页面之间传参。

接管参数通过 request.getParameter(name);

<jsp:include page="hello.jsp" flush="true">    <jsp:param name="uname" value="zhangsan"/></jsp:include>

hello.jsp

<!-- 接管参数 --><%=request.getParameter("uname")%>

JSP的四大域对象

四种属性范畴

在JSP中提供了四种属性的保留范畴,所谓的属性保留范畴,指的就是一个设置的对象,能够再多少个页面中保留并能够持续应用

  1. page范畴

    pageContext : 只在一个页面中保留属性,跳转之后有效

  2. request范畴

    request : 只在一次申请中保留,服务器跳转后仍然无效

  3. session范畴

    session : 在一次会话范畴中,无论何种跳转都能够应用

  4. application范畴

    application : 在整个服务器上保留

办法类型形容
public void setAttribute(String name, Object o)一般设置属性的名称及内容
public Object getAttribute(String name)一般依据属性名称取属性
public void removeAttribute(String name)一般删除指定的属性
验证属性范畴的特点
  1. page

本页面获得,服务器端跳转(<jsp :forward>)后有效

  1. request

    服务器跳转无效,客户端跳转有效

    如果是客户端跳转,则相当于收回了两次申请,那么第一次的申请将不存在了;如果心愿不论是客户端还是服务器跳转,都能保留的话,就须要持续扩大范围。

  2. session

    无论客户端还是服务器端都能够获得,然而当初从新开启一个新的浏览器,则无奈获得之前设置的session了,因为每一个session只保留在以后的浏览器当中,并在相干的页面获得。

    对于服务器而言,每一个连贯到它的客户端都是一个session

    如果想要让属性设置一次之后,不论是否是新的浏览器关上都能获得则能够应用application

  3. application

    所有的application属性间接保留在服务器上,所有的用户(每一个session)都能够间接拜访获得

    只有是通过application设置的属性,则所有的session都能够获得,示意公共的内容,然而如果此时服务器重启了,则无奈获得了,因为敞开服务器后,所有的属性都隐没了,所以须要从新设置。

问:应用哪个范畴呢?

答:<font color="red">在正当范畴尽可能小</font>

EL表达式的应用

EL表达式的语法

EL(Expression Language) 是为了使 JSP 写起来更加简略。表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的办法,让 Jsp 的代码更加简化。

语法结构非常简单: ${expression}

EL 表达式个别操作的都是<font color="red">域对象中的数据</font>,操作不了局部变量。

域对象的概念在 JSP 中一共有四个:pageContext, request, session, application;范畴顺次是,本页面一次申请一次会话整个应用程序

当须要指定从某个特定的域对象中查找数据时能够应用四个域对象对应的空间对象,别离是:pageScope, requestScope, sessionScope, applicationScope。

而 EL 默认的查找形式为从小到大查找,找到即可。当域对象全找完了还未找到则返回空字符串""。

EL表达式的应用
获取数据

设置域对象中的数据

<%    pageContext.setAttribute("uname","zhangsan"); // page作用域    request.setAttribute("uname","lisi"); // request作用域    session.setAttribute("uname","wangwu"); // session作用域    application.setAttribute("uname","zaholiu"); // application%>

获取域对象的值

<%-- 获取域对象中的数据:默认查找形式为从小到大,找到即止。若四个范畴都未找到,则返回空字符串。--%>${uname} <!-- 输入后果为:zhangsan -->

获取指定域对象的值

${pageScope.uname}             <!-- page作用域 -->${requestScope.uname}         <!-- request作用域 -->${sessionScope.uname}         <!-- session作用域 -->${applicationScope.uname}     <!-- application作用域 -->

获取List

<%    List<String> list = new ArrayList<String>();    list.add("aaa");    list.add("bbb");    list.add("ccc");    request.setAttribute("list", list);%>
<%--    获取List中指定下标的数据        ${list[下标] }    获取汇合的长度        ${list.size()}    注:       list代表的是存在域对象中的变量名(限域变量名)--%>${list[1] }  

获取Map

<%    Map map = new HashMap();    map.put("aaa", "111");    map.put("bbb", 2222);    map.put("ccc-a", 333);    request.setAttribute("map", map);%>
<%--    获取Map中指定值       ${map["key"] } 或 ${map.key }    注:        map代表的是存在域对象中的变量名(限域变量名)--%>${map.aaa }${map["bbb"]}

获取JavaBean对象

User.java

public class User {    private Integer userId;    private String uname;    private String upwd;    public Integer getUserId() {        return userId;    }    public void setUserId(Integer userId) {        this.userId = userId;    }    public String getUname() {        return uname;    }    public void setUname(String uname) {        this.uname = uname;    }    public String getUpwd() {        return upwd;    }    public void setUpwd(String upwd) {        this.upwd = upwd;    }}
<%    User user = new User();    user.setUserId(1);    user.setUname("zhangsan");    user.setUpwd("123456");    request.setAttribute("user",user);%>
<%-- JavBean中的属性字段须要提供get办法 --%>${user} <%-- 获取对象 --%>${user.uname} <%--获取对象中的属性--%>
empty
<%--    empty        判断域对象是否为空。为空,返回true;不为空返回false;            ${empty 限域变量名 }        判断对象是否不为空。            ${!empty 限域变量名 }--%>${empty uname}${empty list}${empty map}${empty user}
EL运算
<%    request.setAttribute("a", 10);    request.setAttribute("b", 2);    request.setAttribute("c", "aa");    request.setAttribute("d", "bb");%>

等值判断

<%--    比拟两个值是否相等,返回true或false        ==  或  eq--%>${a == b }${c == d }${c eq d }${a == 5 }${c == 'aa' }

算术运算

<%--    加法: +    减法: -    乘法: *    除法:    / 或 div--%>${a + b }${a / b } 或 ${a div b }

大小比拟

<%--    大于:>    小于:<    大于等于:>=    小于等于:<=--%>${a > b}${a + 1 > 10 }${a + b >= 10 }${a > b && b > 5 }${a + b > 10 || a - b > 5 }

JSTL

标签的应用

Java Server Pages Standard Tag Libray(JSTL):JSP 规范标签库,是一个定制标签类库的汇合,用于解决一些常见的问题,例如迭代一个映射或者汇合、条件测试、XML 解决,甚至数据库和拜访数据库操作等。

咱们当初只探讨 JSTL 中最重要的标签,迭代汇合以及格式化数字和日期几个标签。

外围标签库

http://java.sun.com/jsp/jstl/...

蕴含 Web 利用的常见工作,比方:循环、表达式赋值、根本输入输出等。

格式化标签库

http://java.sun.com/jsp/jstl/fmt

用来格式化显示数据的工作,比方:对不同区域的日期格式化等。

为了在 JSP 页面应用 JSTL 类库,必须以下列格局应用 taglib 指令:

<%@taglib uri="" prefix="" %>

例如:

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

前缀能够是任意内容,遵循标准能够使团队中由不同人员编写的代码更加类似;所以,倡议应用当时设计好的前缀。

此时须要导入两个jar 包

[外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-O1CY3wpj-1607481120180)(/jstl_1.png)]

从Apache的规范标签库中下载的二进包(jakarta-taglibs-standard-current.zip)。

官网下载地址:http://archive.apache.org/dis...

下载 jakarta-taglibs-standard-1.1.2.zip 包并解压,将 jakarta-taglibs-standard-1.1.2/lib/ 下的两个 jar 文件:standard.jarjstl.jar 文件拷贝到我的项目的指定目录下。

条件动作标签

条件动作指令用于解决页面的输入后果依赖于某些输出值的状况,在 Java 中是利用 if、 if…else 和 switch 语句来进行解决的。在 JSTL 中也有 4 个标签能够执行条件式动作指令:if、 choose、when 和 otherwise。

if 标签

if 标签先对某个条件进行测试,如果该条件运算后果为 true, 则解决它的主体内容,测试后果保留在一个 Boolean 对象中,并创立一个限域变量来援用 Boolean 对象。能够利用 var 属性设置限域变量名,利用 scope 属性来指定其作用范畴。

语法格局
<c:if test="<boolean>" var="<string>" scope="<string>">   ...</c:if>
属性

if 标签有如下属性:

属性形容是否必要默认值
test条件
var用于存储条件后果的变量(限域变量名)
scopevar属性的作用域
可取值:page\
request\session\applicationpage
示例
<%    request.setAttribute("flag",true);    request.setAttribute("num",1);%><c:if test="${flag}">   <p>后果为true<p></c:if><c:if test="${num > 0}">   <p>num的值比0大<p></c:if>

注:<font color="red"> JSTL中没有else标签</font>,为了模仿 else 的情景,须要应用两个 if 标签,并且这两个标签为相同的条件。

choose、when 和 otherwise 标签

choose 和 when 标签的作用与 Java 中的 switch 和 case 关键字类似,用于在泛滥选项中做出抉择。也就是说:他们为互相排挤的条件式执行提供相干内容。

switch语句中有case,而choose标签中对应有when,switch语句中有default,而choose标签中有otherwise。

语法格局
<c:choose>    <c:when test="<boolean>">        ...    </c:when>    <c:when test="<boolean>">        ...    </c:when>    ...    ...    <c:otherwise>        ...    </c:otherwise></c:choose>
属性
  • choose标签没有属性。
  • when标签只有一个test属性。
  • otherwise标签没有属性。
示例
<%    request.setAttribute("score", 90);%><c:choose>    <c:when test="${score < 60 }">        <h3>你个小渣渣!</h3>    </c:when>    <c:when test="${score >= 60 && score < 80 }">        <h3>反动尚未胜利,同志仍需致力!</h3>    </c:when>    <c:otherwise>        <h3>你很棒棒哦!</h3>    </c:otherwise></c:choose> 
留神点
  • choose标签和otherwise标签没有属性,而when标签必须设置test属性
  • choose标签中必须有至多一个when标签,能够没有otherwise标签
  • otherwise标签必须放在最初一个when标签之后
  • choose标签中只能有when标签和otherwise标签,when标签和otherwise标签能够嵌套其余标签
  • otherwise标签在所有的when标签不执行的状况下才会执行

迭代标签

forEach 是将一个主体内容迭代屡次,或者迭代一个对象汇合。能够迭代的对象包含所有的 java.util.Collection 和 java.util.Map 接口的实现,以及对象或者根本类型的数组。他还可 以迭代 java.util.Iterator 和 java.util.Enumeration,但不能在多个动作指令中应用 Iterator 或者 Enumeration,因为 Iterator 或者 Enumeration 都不能重置(reset)。 各属性含意如下:

forEach标签
语法格局
<c:forEach    items="<object>"    begin="<int>"    end="<int>"    step="<int>"    var="<string>"    varStatus="<string>"></c:forEach>    
属性
属性形容是否必要默认值
items要被循环的数据
begin开始的元素(0=第一个元素,1=第二个元素)0
end最初一个元素(0=第一个元素,1=第二个元素)Last element
step每一次迭代的步长1
var代表以后条目标变量名称
varStatus代表循环状态的变量名称

forEach varStatus 属性

  • index: 以后这次迭代从 0 开始的迭代索引
  • count: 以后这次迭代从 1 开始的迭代计数
  • first: 用来表明以后这轮迭代是否为第一次迭代的标记
  • last: 用来表明以后这轮迭代是否为最初一次迭代的标记
示例

1.遍历主体内容屡次

<c:forEach begin="开始数" end="完结数" step="迭代数" var="限域变量名"></c:forEach>相当于java的for循环:for(int i = 0; i < 10; i++) {}

如下:

<!-- 遍历主体内容屡次  --><c:forEach begin="0" end="10" var="i" >    题目${i }<br></c:forEach>

2.循环

<c:forEach items="被循环的汇合" var="限域变量名" varStatus="以后成员对象的相干信息">                    </c:forEach>相当于java的foreach循环:for(String str : list) {}

如下:

 <%    List<String> list = new ArrayList<String>();    for (int i = 1; i <= 10; i++) {        list.add("A:" + i);    }    pageContext.setAttribute("li", list);%>     <!-- 循环汇合 --><c:forEach items="${li }" var="item">    ${item }</c:forEach><hr><table align="center" width="800" border="1" style="border-collapse: collapse;">    <tr>        <th>名称</th>        <th>以后成员下标</th>        <th>以后成员循环数</th>        <th>是否第一次被循环</th>        <th>是否最初一次被循环</th>    </tr>    <c:forEach items="${li }" var="item" varStatus="itemp">        <tr>            <td>${item }</td>            <td>${itemp.index }</td>            <td>${itemp.count }</td>            <td>${itemp.first }</td>            <td>${itemp.last }</td>        </tr>    </c:forEach></table><!-- 循环对象汇合 --><%    List<User> userList = new ArrayList<User>();    User user = new User(1,"zhangsan","123456");    User user2 = new User(2,"lisi","123321");    User user3 = new User(3,"wangwu","654321");    userList.add(user);    userList.add(user2);    userList.add(user3);    // 将数据设置到作用域中    request.setAttribute("userList", userList);%><c:if test="${!empty userList }">    <table align="center" width="800" border="1" style="border-collapse: collapse;">        <tr>            <th>用户编号</th>            <th>用户名称</th>            <th>用户明码</th>            <th>用户操作</th>        </tr>        <c:forEach items="${userList }" var="user">            <tr align="center">                <td>${user.userId }</td>                <td>${user.uname }</td>                <td>${user.upwd }</td>                <td>                    <button>批改</button>                     <button>删除</button>                </td>            </tr>        </c:forEach>    </table></c:if><!-- 遍历Map --><%    Map<String,Object> map = new HashMap<String,Object>();    map.put("map1", "aaa");    map.put("map2", "bbb");    map.put("map3", "ccc");    pageContext.setAttribute("map", map);%><c:forEach items="${map }" var="mymap">    键:${mymap.key }-值:${mymap.value } <br></c:forEach>

格式化动作标签

JSTL 提供了格式化和解析数字和日期的标签,咱们探讨外面有:formatNumber、formatDate、parseNumber及parseDate。

formatNumber标签

formatNumber标签用于格式化数字,百分比,货币。该标签用指定的格局或精度来格式化数字。(将数值型数据转换成指定格局的字符串类型。)

语法格局
<fmt:formatNumber  value="<string>"  type="<string>"  var="<string>"  scope="<string>"/>
属性
属性形容是否必要默认值
value要显示的数字
typeNUMBER,CURRENCY,或 PERCENT类型Number
var存储格式化数字的变量Print to page
scopevar属性的作用域page

留神:

  1. 如果设置了var属性,则格式化后的后果不会输入,须要通过el表达式获取var对应的限域变量名
  2. 默认的类型(type)的取值为number。可取值:number数值型、percent百分比类型、currency货币型
示例
<fmt:formatNumber value="10" type="number" var="num" /> ${num } <br><fmt:formatNumber value="10" type="percent"  />  <br><fmt:formatNumber value="10" type="currency"  />  <br><!-- 设置时区  --><fmt:setLocale value="en_US"/><fmt:formatNumber value="10" type="currency"  />  <br>
formatDate标签

formatDate标签用于应用不同的形式格式化日期。(将Date型数据转换成指定格局的字符串类型。)

语法格局
<fmt:formatDate  value="<string>"  type="<string>"  dateStyle="<string>"  timeStyle="<string>"  pattern="<string>"  timeZone="<string>"  var="<string>"  scope="<string>"/>
属性
属性形容是否必要默认值
value要显示的日期
typeDATE, TIME, 或 BOTHdate
dateStyleFULL, LONG, MEDIUM, SHORT, 或 DEFAULTdefault
timeStyleFULL, LONG, MEDIUM, SHORT, 或 DEFAULTdefault
pattern自定义格局模式
timeZone显示日期的时区默认时区
var存储格式化日期的变量名显示在页面
scope存储格式化日志变量的范畴页面

标签格局模式

代码形容实例
y不蕴含纪元的年份。如果不蕴含纪元的年份小于 10,则显示不具备前导零的年份。2002
M月份数字。一位数的月份没有前导零。April & 04
d月中的某一天。一位数的日期没有前导零。20
h12 小时制的小时。一位数的小时数没有前导零。12
H24 小时制的小时。一位数的小时数没有前导零。0
m分钟。一位数的分钟数没有前导零。45
s秒。一位数的秒数没有前导零。52
示例
<%    request.setAttribute("myDate", new Date());%>     ${myDate } <br/><fmt:formatDate value="${myDate }" /><br/><fmt:formatDate value="${myDate }" type="date"/><br/><fmt:formatDate value="${myDate }" type="time"/><br/><fmt:formatDate value="${myDate }" type="both"/><br/><fmt:formatDate value="${myDate }" type="both" dateStyle="full"/><br/><fmt:formatDate value="${myDate }" type="both" dateStyle="long"/><br/><fmt:formatDate value="${myDate }" type="both" dateStyle="short"/><br/><fmt:formatDate value="${myDate }" type="both" timeStyle="full"/><br/><fmt:formatDate value="${myDate }" type="both" timeStyle="long"/><br/>     <fmt:formatDate value="${myDate }" pattern="HH:mm yyyy/MM/dd"/><br/>
parseNumber标签

parseNumber标签用来解析数字,百分数,货币。(parseNumber 标签能够将数字、货币或百分比类型的字符串转换成数值型。)

语法格局
<fmt:parseNumber  value="<string>"  type="<string>"  var="<string>"  scope="<string>"/>
属性
属性形容是否必要默认值
value要解析的数字Body
typeNUMBER,,CURRENCY,或 PERCENTnumber
var存储待解析数字的变量Print to page
scopevar属性的作用域page
示例
<fmt:parseNumber value="100"  /> <br><fmt:parseNumber value="100"  type="number" /> <br><fmt:parseNumber value="100%"  type="percent" /> <br><fmt:parseNumber value="¥10.00"  type="currency" /> <br>
parseDate标签

parseDate标签用于解析日期。(将指定格局的字符串转换成Date类型。)

语法格局
<fmt:parseDate   value="<string>"   type="<string>"   dateStyle="<string>"   timeStyle="<string>"   pattern="<string>"   var="<string>"   scope="<string>"/>
属性
属性形容是否必要默认值
value要显示的日期
typeDATE, TIME, 或 BOTHdate
dateStyleFULL, LONG, MEDIUM, SHORT, 或 DEFAULTdefault
timeStyleFULL, LONG, MEDIUM, SHORT, 或 DEFAULTdefault
pattern自定义格局模式
var存储格式化日期的变量名显示在页面
scope存储格式化日志变量的范畴页面
示例
<fmt:parseDate value="2020-01-06" type="date" /> <br><fmt:parseDate value="2020/01/06" pattern="yyyy/MM/dd" /> <br>

e
value="<string>"
type="<string>"
dateStyle="<string>"
timeStyle="<string>"
pattern="<string>"
var="<string>"
scope="<string>"/>

##### 属性| 属性      | 形容                                  | 是否必要 | 默认值     || --------- | ------------------------------------- | -------- | ---------- || value     | 要显示的日期                          | 是       | 无         || type      | DATE, TIME, 或 BOTH                   | 否       | date       || dateStyle | FULL, LONG, MEDIUM, SHORT, 或 DEFAULT | 否       | default    || timeStyle | FULL, LONG, MEDIUM, SHORT, 或 DEFAULT | 否       | default    || pattern   | 自定义格局模式                        | 否       | 无         || var       | 存储格式化日期的变量名                | 否       | 显示在页面 || scope     | 存储格式化日志变量的范畴              | 否       | 页面       |##### 示例

<fmt:parseDate value="2020-01-06" type="date" />

<fmt:parseDate value="2020/01/06" pattern="yyyy/MM/dd" />