1. jsp基础
1.1 jsp概念
- JSP(java server Pages),java的服务器页面,里面包含html和java代码。其中html负责静态内容,Java代码负责动态内容。
- 特点:
- 跨平台
- 业务代码相分离
- 组件重组
- 预编译
- jsp解决的问题:
- 简化html书写,动态生成页面
1.2 jsp的执行原理
图解:
- jsp的底层是一个Servlet。
- jsp在服务器中先翻译成一个java文件(一个类),该类继承HttpJspBase,而HttpJspBase又是继承httpServlet。故jsp代码中可以直接调用Servlet的request和response对象。
- 编写在jsp的代码在翻译时会封装到该Servlet的service方法中。
- 服务器会完成jsp的翻译,编译成.class文件,以及加载的操作,最后将操作之后的html页面发送给浏览器
1.3 jsp的基本语法
1.3.1 jsp注释
- 格式:
<%-- jsp注释 --%>
- 特点:
-
jsp的注释能注释静态内容和java代码,且不会显示在源码上,更加安全;
-
html注释通过查看网页源代码仍可看到;
html注释只能注释静态内容(html、css、js),而里面如0有java代码仍能运行
-
推荐使用jsp的注释。
-
1.3.2 jsp编写java代码方式
1.3.2.1 脚本片段格式
- 格式:
<% Java代码片段 %>
- 特点和作用:在脚本片段中书写的Java代码,会翻译到java文件中的_jspService方法中
- 注意事项:脚本片段可以分开书写,但最后会组合在一起
1.3.2.2 脚本声明
-
格式:
<%! 全局成员 %>
-
特点和作用:在脚本声明中书写的Java代码,会翻译在类的成员位置上,用来声明成员变量或具有返回值的成员方法
-
注意事项:声明方法的时候,不要声明与jsp翻译的java文件中默认的一些方法或者变量同名的方法或者变量
1.3.2.3 脚本表达式
-
格式:
<%= 输出页面的内容 %>
-
特点:脚本表达式书写的java代码,会翻译到java文件中的_jspService方法内,被out.print()输出到页面
这里的out对象是一个字符输出流
-
作用:代替response向页面输出内容
-
注意事项:
- 脚本表达式和response不能同时使用,否则会出现页面输出顺序和代码顺序错乱的情况;
- 脚本表达式不能包含分号
;
1.3.2.4 jsp编写java示例代码:
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp基本语法</title>
</head>
<body>
<h4>1.脚本片段</h4>
<%
//在jsp内可以编写java代码
//使用集合存储列表
List<String> userList = new ArrayList<>();
userList.add("明明");
userList.add("大黄");
userList.add("狗蛋");
userList.add("jojo");
%>
<table width="50%" border="1px" style="border-collapse: collapse;text-align:center" align="center">
<tr>
<th>序号</th>
<th>姓名</th>
</tr>
<%--如果按照原来的做法,在html需要一个个的添加td。而使用jsp可以直接插入Java代码--%>
<%for (int i = 0; i < userList.size(); i++) {%>
<tr>
<td><%out.write(i + 1);%></td>
<td><%out.write(userList.get(i));%></td>
</tr>
<%}%>
</table>
<h4>2.脚本表达式</h4>
<%--脚本表达式可以将out.write()或者out.print()进行简化--%>
<table width="50%" border="1px" style="border-collapse: collapse;text-align:center" align="center">
<tr>
<th>序号</th>
<th>姓名</th>
</tr>
<%for (int i = 0; i < userList.size(); i++) {%>
<tr>
<td><%=i + 1%>
</td>
<td><%=userList.get(i)%>
</td>
</tr>
<%}%>
</table>
<h4>3.脚本声明</h4>
<%--在成员位置声明变量或者方法--%>
<%!
/*定义方法*/
public int sum(int i, int j) {
return i + j;
}
%>
<%--调用方法--%>
<p>1+2的和:<%=sum(1, 2)%></p>
</body>
</html>
1.4 jsp和Servlet技术的选用
- servlet:主要负责产生动态资源数据。接收浏览器请求,从数据库中获取数据,并存储在域对象中,然后跳转到jsp页面
- jsp:主要负责显示布局动态资源数据。获取域对象的数据,并使用html布局动态页面响应浏览器。
图解
1.5 简化jsp
- 页面上的脚本表达式<%=java代码%>☞使用EL技术代替
- 页面上的脚本代码片段<%java代码;%>的循环、条件判断等☞使用JSTL技术代替
2. EL表达式
EL(Expression Language):代替jsp中脚本表达式的功能,简化对java代码的操作。
2.1 EL表达式的格式和作用
- 格式:
${域里面的key或者表达式}
- 作用:从域对象中查找指定的数据
- 前提:数据都必须存入域对象el才能获取到!!
2.2 EL表达式的使用
2.2.1 EL获得容器(域对象)的数据
- el通过域对象中的name,来获取对应的value。如果name不一样,可以直接用name来获取value;
- 默认情况下,el会依次从request==>session==>servletContext的顺序获取name对应value,一旦获取成功将不会继续往下获取。如果多个域对象的name一样,只会按照顺序获取第一个;
- el如果没有获取到name对应的value,则不会显示,而不是返回null;
- 如果要获取指定的域对象数据,使用下表的
el对象.域对象name
获取(重要)。如果不指定则按默认处理。
域对象 | 对应的el对象 |
---|---|
request | requestScope |
session | sessionScope |
servletContext | applicationScope |
<h3>使用el获取域对象数据</h3>
<%
//往各个域里面存储数据
request.setAttribute("requestName","requestAdmin");
session.setAttribute("sessionName","sessionAdmin");
request.getServletContext().setAttribute("servletContextName","servletContextAdmin");
%>
<%--使用el表达式获取域里面的数据--%>
<p>从request里面获取数据:${requestName}</p>
<p>从session里面获取数据:${sessionName}</p>
<p>从servletContext里面获取数据:${servletContextName}</p>
<%
//往各个域里面存储数据
request.setAttribute("name","requestAdmin");
session.setAttribute("name","sessio nAdmin");
request.getServletContext().setAttribute("name","servletContextAdmin");
%>
<p>从域里面获取数据:${name}</p><%--输出requestAdmin,el获取域里面的数据会依次从request/session/servletContext获取数据,查找到为止--%>
<p>从session域里面name数据:${sessionScope.name}</p>
<p>从servletContext域里面name数据:${applicationScope.name}</p>
<p>从request域里面name数据:${requestScope.name}</p>
2.2.2 EL获取和解析复杂数据
2.2.2.1 获取数组的元素
-
获取数组:
${数组名}
-
格式:
${数组名[index]}
,其中index为元素的索引 -
如果元素是一个实体类对象,如果要获取对象的变量,格式为:
${数组名[index].变量名}
2.2.2.2 获取集合的元素
-
获取集合:
${List集合名}
、${Map集合名}
-
List集合获取元素与数组相同,
${List集合名[index]}
-
Map集合根据key获取value:
${Map集合名[key]}
或者${Map集合名.key}
-
注意事项:设置map集合数据的key,尽量不要出现”.“,如果出现,只能用[]获取
2.2.2.3 获取JavaBean数据
- 如果要获取JavaBean对象的属性值,可以直接用属性名调取,el自动调用对应的getXxx方法
- 格式:
${JavaBean对象.属性名}
或${JavaBean对象[属性名]}
2.2.2.4 el获取数据的示例代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el获取复杂数据</title>
</head>
<body>
<h4>1.使用el获得数组的数据</h4>
<%
/*添加数据到数组中*/
User[] users = new User[2];
users[0] = new User("狗蛋",18);
users[1] = new User("明明",20);
//记得el必须要将数据添加到域对象中
request.setAttribute("users",users );
%>
<p>获取数组里面第一个元素的name属性值:${users[0].name}</p>
<p>获取数组里面第一个元素的age属性值: ${users[0].age}</p>
<p>获取数组里面第二个元素的name属性值:${users[1].name}</p>
<p>获取数组里面第二个元素的age属性值:${users[1].age}</p>
<h4>2.使用el获得list集合的数据</h4>
<%
/*添加数据到数组中*/
List<User> list = new ArrayList<>();
list.add(new User("王全",20));
list.add(new User("dio",98));
//记得el必须要将数据添加到域对象中
request.setAttribute("list",list );
%>
<p>获取List里面第一个元素的name属性值:${list[0].name}</p>
<p>获取List里面第一个元素的age属性值: ${list[0].age}</p>
<p>获取List里面第二个元素的name属性值:${list[1].name}</p>
<p>获取List里面第二个元素的age属性值:${list[1].age}</p>
<h4>3.使用el获得map集合的数据</h4>
<%
/*添加数据到数组中*/
Map<String,User> map = new HashMap<>();
map.put("zs",new User("张三",20));
map.put("ls",new User("李四",30));
//记得el必须要将数据添加到域对象中
request.setAttribute("map",map );
%>
<p>获取Map里面第一个元素的name属性值:${map.zs.name}</p>
<p>获取Map里面第一个元素的age属性值: ${map.zs.age}</p>
<p>获取Map里面第二个元素的name属性值:${map[lisi].name}</p>
<p>获取Map里面第二个元素的age属性值:${map[lisi].age}</p>
<h4>4.使用el获得JavaBean的数据</h4>
<%
//往域里面写javaBean
request.setAttribute("user",new User("JoJO",18));
//el获取javaBean数据时,".属性名"就会自动调用属性的get封装方法。
%>
<p>获取user对象里面name属性值:${user.name}</p>
<p>获取user对象里面age属性值:${user.age}</p>
</body>
</html>
2.2.3 EL执行运算
2.2.3.1 算术运算符
- 在el表达式中可使用算术运算符
注意事项
- 在EL中,只要是数字就能执行运算,EL在执行计算的时候,会将数字除尽,最多保留16位小数(而java中整数相除取整数);
- 在EL中,如果在一个算式中有数据不存在,那么这个数据不参与运算,不报错继续执行。
- 在EL中,算术运算符只能做数学运算,不具备java代码中的拼字符串的功能,即3+"5"的结果是8而不是35。
- 使用时都必须先将判断的条件提交到域对象中!
2.2.3.2 逻辑运算符
注意事项
- el运算符不支持异或^运算
2.2.3.3 比较运算
注意事项
- 使用比较运算符要保证数据是存在的并且是可比较的
2.2.3.4 Empty运算符和三目运算符
-
Empty运算符:
${empty 域里面的数据}
常用的Empty运算 运行结果 ${empty ""}
如果数据为空字符串,则返回true ${empty null}
如果数据为null,返回true ${empty list}
如果list元素个数为0,返回true ${empty str}
如果字符串为空,返回true Empty运算符对应的取反方法
${not empty 域里面的数据}
-
三目运算符,用法与Java一致:
${三目运算符}
3. JSTL的核心标签库使用
3.1 JSTL概述
- JSTL(jsp的标准标签库:Jsp Standard Tag Library)。保存许多服务器端标签(封装了具有特定的功能的java代码,以标签形式编写,代替特定功能的java代码)。
3.2 jstl标签的安装
3.2.1 导包
-
javax.servlet.jsp.jstl.jar
-
jstl-impl.jar
3.2.2 使用taglib指令在jsp页面导入要使用的jstl标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
其中:taglib是导入标签库,uri选择核心标签库core,prefix用于指定将要使用的标签起前缀名,一般是标签库的第一个字母
3.3 常用的jstl标签
3.3.1 if标签
- 起判断的作用,相当于java代码的
if(){}
3.3.1.1 if标签属性介绍
属性名 | 是否支持el | 属性类型 | 属性描述 |
---|---|---|---|
test | √ | boolean | 编写el条件表达式(表达式结果为true执行,为false不执行) |
var | × | String | 设置保存test属性的结果保存的域对象的名称 |
scope | × | String | 指定保存test属性的结果的域对象。 |
3.3.2 choose标签
-
<c:choose>
标签用于指定多个条件选择的组合边界,它必须与<c:when>
和<c:otherwise>
标签一起使用。三个标签组合发挥java代码if(){}else if(){} else{}
语句的作用 -
其中:
<c:otherwise>
,相当于else{}。<c:when>
,相当于if(){}
和else if(){}
。<c:when>
标签含有test属性,作用与if相同 -
注意事项:三个标签必须组合使用,一组标签中不能出现两个
<c:otherwise>
3.3.3 foreach标签
- 相当于Java的for循环
属性名 | 是否支持el | 属性类型 | 属性描述 |
---|---|---|---|
var | × | String | 在不循环对象的时候,保存的是控制循环的变量;在循环对象的时候,保存的是被循环对象中的元素 |
items | √ | 任何类型 | 指定要循环的对象 |
varStatus | × | String | 存储循环过程变量信息(循环索引、循环序号) |
begin | √ | int | 循环开始变量值 |
end | √ | int | 循环结束变量值 |
step | √ | int | 循环变量递增值,没有设置默认是1 |
注意事项
- varStatus,存储循环过程变量信息。在forEach循环过程中产生很多循环信息,比如循环索引,循环序号。
- forEach标签会将这些信息存储到varStatus对象里面:
index,循环索引,从0开始
count,循环序号,从1开始
3.3.3.1 有限次数的循环
-
格式:
<c:forEach begin="开始变量值" end="结束变量值" step="变量递增值"> <%--循环体代码--%> </c:forEach>
3.3.3.2 循环对象(数组、list、map)
-
格式: