JSP&Cookie&Session
学习目标
- 能够创建、发送、接收、删除cookie
- 能够说出cookie执行过程
- 能够操作session域中的数据
- 能够说出el表达式的作用
- 能够使用el表达式获取javabean的属性
- 能够使用jstl标签库的if标签
- 能够使用jstl标签库的foreach标签
一、JSP
1. JSP介绍
JSP全称java server pages(java服务器页面) , 本质是一个servlet.它是在传统的网页HTML文件中插入Java程序段和JSP标记,从而形成JSP文件,后缀名为(*.jsp).
JSP作用 : 将内容的生成和显示进行分离
用 JSP技术 , 开发人员可以使用HTML标签来设计和格式化最终页面,并使用JSP标签和脚本来生成页面上的动态内容
2. JSP执行流程(了解)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQfD28oa-1624496096917)(jsp&cookie&session.assets/1563119742375.png)]
1.浏览器输入网址,第一次访问hello.jsp
2.servlet/jsp容器接收请求,通过jspservlet匹配到hello.jsp
3.jspservle将其jsp文件(hello.jsp)转成java文件(hello_jsp.java)
4.jvm编译生成.class文件(就是一个servlet)
5.服务器将class文件加载到内存,运行该servlet,生成响应信息
6.服务器将响应信息返回给浏览器
3. JSP脚本(了解)
在jsp中编写java代码可以有三种方式 , 分别是 : 脚本片段、脚本声明、脚本表达式
脚本片段
格式 : <% int a = 1; System.out.println(a); %>
作用 : 内容会生成在_jspService()方法中,相当于servlet的service方法中
脚本声明
格式 : <%! int a = 1; %>
作用 : 声明的变量在类的成员位置上
脚本表达式
格式 : <%= "hello " + a %>
作用 : 内容也会生成在_jspService()方法中,且作为out.println()的参数将内容直接输出到页面中 , 注意表达式不能以分号结尾 . 相当于使用response.getWriter().println()往页面输出内容
这些脚本稍后我们都会使用EL和JSTL来替代 , 所以大家了解下即可
4. JSP注释
格式 : <%-- 注释内容 --%>
一般都使用快捷键生成
5. JSP指令
jsp指令一共有三个 , 分别是page、include和taglib指令 . 主要用来声明jsp页面的一些属性或有哪些行为的
格式 : <%@ 指令名称 属性名1="属性值1" 属性名2="属性值2"%>
注意 : 每个指令都可以出现多次
-
page指令
- 主要用来声明当前页面的属性的.
<%@ page import="java.util.List" %> 同java中的导包 <%@ page import="java.util.ArrayList" %> 同java中的导包 <%@ page contentType="text/html;charset=UTF-8"%> 声明当前页面的类型和编码
-
include指令
- 作用 : 在JSP页面中静态包含一个文件,同时由JSP解析包含的文件内容
- 例如 : 网站中每个页面的最上面和最下面部分是一样的,就可以将在两部分内容提取到两个单独的文件中 . 然后在每个页面通过include指令,将这两部分页面包含进来即可
top.jsp内容如下 <div> <a href="">登录</a> | <a href="">注册</a> </div>
main.jsp内容如下 <body> <%@ include file=“top.jsp”%> 欢迎使用CRM系统 </body>
就相当于 <body> <div> <a href="">登录</a> | <a href="">注册</a> </div> 欢迎使用CRM系统 </body>
-
taglib指令
-
作用 : 导入标签库
-
格式 :
<%@taglib prefix="" uri="" %>
- uri 标签文件的URI地址
- prefix 标签组的命名空间前缀
稍后课程中会使用JSTL在页面中执行判断、循环等操作 , 这时候就需要导入jstl的标签库了
-
二、会话
在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话 . Web应用中的会话过程类似于生活中的打电话过程,它指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应过程,例如,一个用户在某网站上的整个购物过程就是一个会话 .
在客户端与服务器端交互的过程中,会产生一些数据 . 例如,用户甲和乙分别登录了购物网站,甲购买了一个手机,乙购买了一个电脑,当这两个用户结账时,Web服务器需要对甲和乙的信息分别进行保存 . 在前面章节讲解的域对象中,HttpServletRequest对象和ServletContext对象都可以对数据进行保存,但是这两个对象都不可行,具体原因如下:
(1)客户端请求Web服务器时,针对每次HTTP请求,Web服务器都会创建一个HttpServletRequest对象,该对象只能保存本次请求所传递的数据 . 由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买请求中的数据将会丢失 .
(2)使用ServletContext对象保存数据时,由于同一个Web应用共享的是同一个ServletContext对象,因此,当用户在发送结账请求时,由于无法区分哪些商品是哪个用户所购买的,而会将该购物网站中所有用户购买的商品进行结算,这显然也是不可行的 .
(3)为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别是Cookie和Session .
Cookie是客户端会话技术 , 是将数据保存在浏览器端
Session是服务器端会话技术 , 是将数据保存在服务器端
三、cookie
1. 概念
浏览器端的会话技术,它通过在浏览器中记录一些服务器传递过来的数据,解决会话从什么时候开始,到什么时候结束 . 例如 : 平时上网的时候记住用户名操作
2. Cookie的基本使用
常用的方法介绍
- cookie方法
- 构造方法
- new Cookie(String name, String value)
- 其他方法
- 构造方法
方法名 | 作用 |
---|---|
String getName() | 获取cookie的名称 |
String getValue() | 获取cookie的值 |
void setPath(String uri) | 设置cookie的路径(浏览器根据这个路径判断那些cookie要发送给服务器) |
void setMaxAge(int expiry) | 设置cookie的最大生存时间(单位:秒),超过了该时间后Cookie会自动销毁 |
- response的方法
- void addCookie(Cookie cookie) 将cookie发送给浏览器
- request的方法
- Cookie[] getCookies() 获取浏览器发送的cookie
注意:
cookie主要是通过名称和路径来确定他的唯一性的 .
例如:以下表示的是两个cookie,虽然名字一样 , 但是路径不同 , 所以两个cookie可以同时存在 .
/day04/a/b/cookie1
/day04/a/cookie1
如果路径和名称都一样,后添加的cookie将覆盖前者
常用方法演示
- 在CookieServlet1创建cookie
- 在CookieServlet1设置cookie路径为当前项目根路径:“/day04”
- 在CookieServlet1使用response对象将cookie发送给浏览器
- 在CookieServlet2通过request对象获取浏览器发送的cookie
代码实现
- CookieServlet1:
//路径为 "/cookie1"
public class CookieServlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建cookie
Cookie cookie = new Cookie("username","tom");
//设置cookie的路径——浏览器根据这个路径判断那些cookie要发送给服务器
cookie.setPath("/day04");
//将cookie发送给浏览器
response.addCookie(cookie);
}
}
- CookieServlet2:
//路径为 "/cookie2"
public class CookieServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取浏览器发送的cookie
Cookie[] cookies = request.getCookies();
if(cookies != null){
for (Cookie coo : cookies) {
if("username".equals(coo.getName())){
//打印cookie的名称和值
System.out.println(coo.getName()+":"+coo.getValue());
}
}
}
}
}
执行过程分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z4KzIsXj-1624496096919)(jsp&cookie&session.assets/1563127712984.png)]
3. Cookie的分类
- 会话级别的Cookie:默认的.关闭了浏览器Cookie就销毁了.
- 持久级别的Cookie:可以设置指定cookie在浏览器的存活时间 , Cookie就不会随着浏览器关闭而销毁了.
通过setMaxAge(int 秒)方法设置Cookie在浏览器上的过期时间 , 当时间为0的时候 , 意思为立即删除此Cookie(前提:path和name必须一致) .
//路径为 "/maxage"
public class MaxAgeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
//创建cookie
Cookie cookie = new Cookie("name","tom");
//设置cookie的生存时间
cookie.setMaxAge(60*60*24*7);
//设置cookie的路径
cookie.setPath("/day04");
//发送cookie给浏览器
response.addCookie(cookie);
*/
//=====如果需要立刻删除cookie======
//创建空数据的cookie,名称保持一致
Cookie cookie = new Cookie("name","");
//设置cookie的生存时间为0立刻死亡
cookie.setMaxAge(0);
//设置cookie的路径,与原来的cookie路径保持一致
cookie.setPath("/day04");
//发送cookie给浏览器
response.addCookie(cookie);
}
}
4. 案例 : 模拟记录用户名?? 没有学js
案例需求:
用户在登录成功之后,将用户名保存到cookie中,下次再次打开此页面将用户名直接显示在此页面上
步骤分析:
- 编写登录页面login.jsp,复制javascript代码(用来获取cookie内容的)
- 创建RemeberUsernameServlet
- 获取用户提交过来的用户名和密码
- 比较用户名和密码是否与设定好的一致
- 若一致,需要将创建cookie,将用户名写入cookie中,永久保存,在当前页面上展示"xxx:欢迎回来"
- 若不一致,在登录页上提醒用户:“用户名或者密码错误”
代码实现
1.login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/day04/rem" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td></td>
<td>
<span><%=(request.getAttribute("msg") == null ? "" : request.getAttribute("msg")) %></span>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="登陆"></td>
</tr>
</table>
</form>
<script>
/*根据名字获取指定cookie的内容*/
function getCookie(cookieName) {
var cookies = document.cookie;
var arrCookie = cookies.split("; ");
for(var i = 0; i < arrCookie.length; i++){
var arr = arrCookie[i].split("=");
if(cookieName == arr[0]){
return arr[1];
}
}
return "";
}
/*在页面加载成功之后,判断是否有名字叫做rem_username的cookie,若有获取此cookie的值,赋值给用户名的输入框*/
var rem_username = getCookie("rem_username");
if(rem_username!=null){
document.getElementById("username").value=rem_username;
}
</script>
</body>
</html>
2.记住用户名的servlet
//访问路径为 "/rem"
public class RemeberUsernameServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//设置响应编码
response.setContentType("text/html;charset=utf-8");
//模拟登陆
if ("播仔".equals(username) && "123".equals(password)) {
//在页面上打印提示信息
response.getWriter().print("欢迎回来:"+username);
//登陆成功之后,创建cookie,将用户名写入cookie
Cookie ck = new Cookie("rem_username", username);
ck.setMaxAge(Integer.MAX_VALUE);
ck.setPath(request.getContextPath());
response.addCookie(ck);
}else {
//登录失败,在登录页上提醒用户
request.setAttribute("msg","用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
}
5. 注意事项
在cookie值中不能使用分号(;)、逗号(,)、空格等符号 . 如果存入的数据不合法,会出现一个错误:
java.lang.IllegalArgumentException:
An invalid character [32] was present in the Cookie value
cookie对于基本符号、数字、和字母是可以存储的,若真需要将这些特殊符号保存到cookie中,我们需要将非法数据转换成符号、数字、和字母形式存储,要使用的时候再转换成正常的数据(解码)即可 . 编码解码的操作可以通过URLEncoder和URLDecoder类中的静态方法来解决
URLEncoder类:
static String encode(String s, String enc)
将指定的字符串,按指定的编码表编码
URLDecoder类:
static String decode(String s, String enc)
将指定的字符串,按指定的编码表解码
四、session
1. 概念
当我们去银行存取钱时,需要办理银行卡,该卡上只有卡号,而没有其它信息 . 但我们每次去该银行时,只要出示银行卡,银行职员便可根据卡号查询到我们的账户信息 . Session技术就好比银行发放给我们的银行卡和银行为每个人生成账户的过程 . 当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性,其中,Session对象就相当于账户,ID就相当于银行卡号 . 当客户端后续访问服务器时,只要将标识号传递给服务器,服务器就能判断出该请求是哪个客户端发送的,从而选择与之对应的Session对象为其服务 .
需要注意的是,由于客户端需要接收、记录和回送Session对象的ID,因此,通常情况下,Session是借助Cookie技术来传递ID属性的 .
为了使读者更好的理解Session,接下来,以网站购物为例,通过一张图来描述Session保存用户信息的原理,具体如下图所示 .
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Mg0nSA1-1624496096920)(jsp&cookie&session.assets/1563211843498.png)]
Session保存用户信息的过程
在上图中,用户甲和乙都调用buyServlet将商品添加到购物车,调用payServlet进行商品结算 . 由于甲和乙购买商品的过程类似,在此,以用户甲为例进行详细说明 . 当用户甲访问购物网站时,服务器为甲创建了一个Session对象(相当于购物车) . 当甲将手机添加到购物车时,手机的信息便存放到了Session对象中 . 同时,服务器将Session对象的ID属性以Cookie (Set-Cookie: JSESSIONID=111)的形式返回给甲的浏览器 . 当甲完成购物进行结账时,需要向服务器发送结账请求,这时,浏览器自动在请求消息头中将Cookie (Cookie: JSESSIONID=111)信息回送给服务器,服务器根据ID属性找到为用户甲所创建的Session对象,并将Session对象中所存放的手机信息取出进行结算 .
2. session的与cookie的区别
cookie | session | |
---|---|---|
会话数据保存的位置 | 浏览器 | 服务器 |
数据的安全性 | 不安全 | 安全 |
存储数是否有限制 | 有 | 无 |
3. session的应用场景
- 保存购物车数据
- 保存用户登录信息数据
- 保存验证码
- …
4. session的基本使用
session也是一个域对象 , session就是用来保存会话中的数据的 , 所以他的主要方法就是添加数据 , 获取数据和移除数据 , 要操作session , 需要先通过request对象获取session . 接下来我们来看下它的方法
HttpServletRequest获取session的方法
HttpSession getSession() 获取session对象
所以关于session的方法我们查看api的时候需要查询HttpSession
HttpSession
方法名 | 方法作用 |
---|---|
void setAttribute(String name,Object object) | 将一个对象以指定的名称放入session中,若此名字已存在则会替换为此对象 |
Object getAttribute(String name) | 按照给定的名字从session中获取对应内容,若获取不到返回null |
void removeAttribute(String name) | 从session中移除对应名称的属性及其值 |
5. session的分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-InS5pOGu-1624496096921)(jsp&cookie&session.assets/1563168420491.png)]
5. 案例 : 一次性验证码 ??没有学js,没有做切换验证码
案例需求
用户在登录页面登录的时候要查看到验证码,如下图 . 当用户输入用户名、密码和验证码, 然后点击"登录"的时候 , 需要现在后台判断验证码是否一样 , 若验证码一样 ,再继续判断用户名和密码 ; 否则的话 , 直接在当前页面上提示"验证码输入错误"
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1QB9fjA6-1624496096922)(jsp&cookie&session.assets/1563210664838.png)]
步骤分析
- 配置生成验证码的servlet,路径为"/checkcode"
- 编写登录页面login_code.jsp , 在页面上的验证码图片通过请求"/checkcode"获取.
- 编写LoginServlet,在doPost方法中的逻辑如下:
- 获取用户输入的验证码和session中存放的验证码,获取完成之后将session中的验证码删除
- 比较两个验证码是否一致
- 若不一致,需要在登录页面提醒用户"验证码输入错误"
- 若一致,继续判断用户名和密码是否一致 .
- 若一致,跳转到myfile.jsp,提醒用户:“xxx:欢迎回来”
- 若不一致,需要在登录页面提醒用户"用户名或者密码错误"
代码实现
1.配置验证码servlet
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//访问路径为 "/checkcode"
public class CheckcodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建画布
int width = 120;
int height = 40;
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获得画笔
Graphics g = bufferedImage.getGraphics();
// 填充背景颜色
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
// 绘制边框
g.setColor(Color.red);
g.drawRect(0, 0, width - 1, height - 1);
// 生成随机字符
// 准备数据
String data = "ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789";
// 准备随机对象
Random r = new Random();
// 声明一个变量 保存验证码
String code = "";
// 书写4个随机字符
for (int i = 0; i < 4; i++) {
// 设置字体
g.setFont(new Font("宋体", Font.BOLD, 28));
// 设置随机颜色
g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
String str = data.charAt(r.nextInt(data.length())) + "";
g.drawString(str, 10 + i * 28, 30);
// 将新的字符 保存到验证码中
code = code + str;
}
// 绘制干扰线
for (int i = 0; i < 6; i++) {
// 设置随机颜色
g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
}
// 将验证码 打印到控制台
System.out.println(code);
// 将验证码放到session中
request.getSession().setAttribute("code_session", code);
// 将画布显示在浏览器中
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}
}
2.login_code.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>login</title>
</head>
<body>
<form action="/day04/login" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>验证码:</td>
<td><input type="text" name="code"></td>
</tr>
<!-- 通过向服务器发送请求,从服务器获取验证码数据 -->
<tr>
<td></td>
<td>
<img id="img" src="/day04/checkcode"/>
<span><%=(request.getAttribute("msg") == null ? "" : request.getAttribute("msg")) %></span>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="登陆"></td>
</tr>
</table>
</form>
</body>
</html>
3.登录servlet
//访问路径为:/login
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置请求的编码
request.setCharacterEncoding("utf-8");
//用户请求中的验证码获取
String code = request.getParameter("code");
//获取session中保存的验证码
String code_session = (String)request.getSession().getAttribute("code_session");
//为了保证验证码只能用一次,获取成功之后就可以将session中的页面销毁
request.getSession().removeAttribute("code_session");
//与session中保存的验证码进行校验
if(!code_session.equalsIgnoreCase(code)){
//验证码错误,告诉用户,页面提示
request.setAttribute("msg","验证码错误");
request.getRequestDispatcher("/login_code.jsp").forward(request,response);
return;
}
//获取用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//模拟登陆
if ("播仔".equals(username) && "123".equals(password)) {
//跳转到myfile.jsp,提醒用户:"xxx:欢迎回来"
request.getSession().setAttribute("username",username);
response.sendRedirect(request.getContextPath()+"/myfile.jsp");
}else {
//登录失败
request.setAttribute("msg","用户名或密码错误");
request.getRequestDispatcher("/login_code.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
4.myfile.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%=(session.getAttribute("username") == null ? "" : session.getAttribute("username")) %> : 欢迎回来
</body>
</html>
6. 三个域对象总结
ServletContext:
针对一个WEB应用 . 一个WEB应用只有一个ServletContext对象,使用该对象保存的数据在整个WEB应用中都有效 .
-
创建:服务器启动的时候.
-
销毁:服务器关闭的时候或者项目移除的时候.
HttpSession
针对一次会话 . 使用该对象保存数据,一次会话(多次请求)内数据有效 .
-
创建:可以暂且认为在服务器第一次调用getSession()的时候.服务器创建session的对象.因为session销毁后,再次调用getSession()的时候也会创建.
-
销毁:
- Session过期了,默认时间是30分钟.
- 手动调用session的invalidate的方法
- 服务器关闭
注意 : 服务器正常关闭的时候 , 会把session中的支持序列化的数据保存到磁盘上 .
HttpServletRequest
针对一次请求 . 使用该对象保存数据,一次请求(一个页面,如果是请求转发多个页面)内数据有效.
- 创建:客户端向服务器发送一次请求
- 销毁:服务器为这次请求作出响应之后,销毁request.
三个作用域对象操作的API
api都是一样的,完成存取和销毁的操作
- 存放数据:setAttribute(name,value)
- 获得数据:getAttribute(name)
- 删除数据:removeAttribute(name)
五、EL
1. EL介绍
在上个案例中,我们要在页面上获取request域中数据写法是:
<%=(request.getAttribute("msg")==null?"":request.getAttribute("msg")) %>
这种写法太繁琐 , 我们可以通过${msg}
就可以获取 , 这个就是EL.
EL是Expression Language的缩写,是jsp内置的表达式语言,从jsp2.0开始,就不让再使用java脚本,而是使用el表达式或动态标签来代替java脚本 . EL表达式的格式如下:
${表达式}
EL的主要作用:
- 在jsp中来获取域中的数据
- 在jsp中做一些运算
2. EL获取数据
- 获取request域中的数据 :
${requestScope.xxx}
(了解) - 获取session域中的数据 :
${sessionScope.xxx}
(了解) - 获取ServletContext域中的数据 :
${applicationScope.xxx}
(了解)
注意:
- 通过el获取时,如果没有查找到,会返回"".
- 还有一种写法
${requestScope[“xxx”]} , ${sessionScope[“xxx”]},${applicationScope.xxx}
,若放到域中的属性名中带有"."等特殊字符的时候 , 就可以使用这种方式了
上面写的这几种方式 , 都是从指定域中去获取内容的 , 在开发的时候我们一般使用${xxx}
这种方式去域中获取 , 他的内部实现是先去request域中查询,若找到就立即返回 , 若找不到就再去session域中查询 ;同理也是找到即返回,找不到继续去ServletContext域中查询 . 若都没有找到再返回"".
若放入到域中的为javabean对象、数组或者集合的时候 , 需要怎么获取呢 ?
- 获取javabean对象的某个属性
${对象名称.属性名称}
底层就是调用此属性的get方法 - 获取数组或者List中指定索引的值
${数组或者list对象名称[索引]}
- 获取map中指定key的内容
${map对象名称.key名称}
3. EL执行运算
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xirskUJk-1624496096923)(jsp&cookie&session.assets/1563194696130.png)]
注意事项:
- 我们在开发中使用empty检查对象是否为null或字符串是否为""或判断容器size是否为0
- EL表达式支持三元运算符
- EL表达式不可以嵌套
- KaTeX parse error: Expected '}', got 'EOF' at end of input: {a+{b}} 这种是不允许的
- EL表达式中加号两边必须是数字或者字符串形式的数字
4. 获取指定cookie的值
我们也可以使用el直接获取指定cookie的值 ,语法为: ${cookie.cookie的名字.value}
六、JSTL
1. JSTL介绍
JSTL(JSP Standard Tag Library,jsp标准标签库)是Apache对EL表达式的扩展,也就是说JSTL依赖EL表达式 . JSTL是标签语言,使用起来非常方便 . 但是它不是jsp内置的标签,所以用的时候需要我们自己导包,以及指定标签库 . 我们需要在这里使用jstl主要是在jsp页面上执行判断和循环操作 .
JSTL标签库提供5大功能(了解):
- core:jstl的核心标签库。(目前还在使用)
- fmt:格式化(国际化)的标签(几乎不用,对页面显示数据,格式化,现在都交给前端去做)
- functions:jstl中提供对字符串操作的函数库(不再使用)
- sql:jstl提供的在jsp页面上书写sql,操作数据库(不再使用)
- xml:jstl操作xml文件的 (不再使用)
所以我们重点使用的就是jstl的核心库
2. JSTL使用步骤
- 导入jar包(jstl.jar和standard.jar),放到web/WEB-INF/lib目录中,别忘记添加到类库
- 在页面中使用taglib指令导入标签库
- 例如 : 导入核心库
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- 例如 : 导入核心库
- 在页面中使用此标签即可
3. JSTL核心标签-c:if
作用 : 页面上的逻辑判断操作
格式:
<c:if test="el表达式">el的值为true时,展示的内容</c:if>
注意 : test属性是必须填写的.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WkzJZrqh-1624496096924)(jsp&cookie&session.assets/1563199286827.png)]
<c:if test="${3>4 }">
三大于四
</c:if>
<c:if test="${3<=4}">
三不大于四
</c:if>
4. JSTL核心标签-c:forEach
作用 : 在jsp页面上做循环操作
常用格式:
<c:forEach item='el表达式获取需要遍历的对象' var='接口遍历到每个元素'>
通过el对遍历到的元素进行操作
</c:forEach>
属性说明:
- begin: 设置循环变量从几开始
- end: 设置循环变量到几结束
- step: 设置循环变量的步长
- var: 定义一个变量,用于接收循环遍历的每一个元素
- varStatus: 用来记录循环状态的,它可以创建一个循环变量vs,该循环变量有如下属性:
- count:用来记录循环元素的个数;
- index:用来记录所循环元素的下标;
- first:判断当前循环的元素是否是第一个元素;
- last:判断当前循环的元素是否是最后一个元素;
- current:代表当前循环的元素。
- items: 指定要循环的变量,可以是一个数组也可以是一个集合,默认是支持EL表达式
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>基本使用</title>
</head>
<body>
<c:forEach begin="1" end="10" step="1" var="n" >
${n} <br/>
</c:forEach>
<hr/>
<%--varStatus使用--%>
<c:forEach begin="1" end="10" step="2" var="n" varStatus="vs">
当前元素:${n} - 计数:${vs.count} - 是否为第一个:${vs.first} - 是否为最后一个:${vs.last}<br/>
</c:forEach>
</body>
</html>
注意 : 在基本使用中 , 使用vs.index会有问题 . 在遍历集合或者数组的时候就没有此问题了
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>高级使用</title>
</head>
<body>
<%--循环数组--%>
<%
int[] arr = {1, 3, 5, 7};
request.setAttribute("arr", arr);
%>
<c:forEach items="${arr }" var="item" varStatus="vs">
${item } - ${vs.index} <br/>
</c:forEach>
<hr>
<%--循环list--%>
<%
List list = new ArrayList();
list.add("北京");
list.add("上海");
request.setAttribute("list", list);
%>
<c:forEach items="${list }" var="city">
${city }
</c:forEach>
<hr>
<%--循环map--%>
<%
Map map = new HashMap();
map.put("username", "tom");
map.put("passwrod", "123");
request.setAttribute("map", map);
%>
<c:forEach items="${map }" var="entry">
${entry.key } - ${entry.value }<br>
</c:forEach>
</body>
</html>