1.会话技术
1.会话技术概述
会话:一次会话中包含多次请求和响应。
一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
功能:在一次会话的范围内的多次请求间,共享数据
分类
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
2.Cookie对象
概念:客户端会话技术,将数据保存到客户端
大白话:将需要共享的数据,响应时,发送给浏览器,当下一次请求时,浏览器又请求给服务器,实现数据共享
常用方法
- 创建Cookie对象:
new Cookie(String name, String value)
- 发送Cookie对象:
response.addCookie(Cookie cookie)
- 获取Cookie,拿到数据:
Cookie[] request.getCookies()
代码示例
Cookie01代码,往Cookie中存入信息
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie对象
Cookie c = new Cookie("msg","hello");
//2.发送Cookie
response.addCookie(c);
}
Cookie02代码,从Cookie中拿出信息
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//3.获取Cookie对象
Cookie[] cookies = request.getCookies();
//遍历Cookie
if (cookies!=null){
for (Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
System.out.println(name+"=="+value);
}
}
}
浏览器收到set-cookie响应头,就明白了,这个数据要存储到cookie中去,当我们下一次请求浏览器时,就将数据通过请求头cookie发送到服务器中去实现。
cookie细节
一次可不可以发送多个cookie?
- 可以
- 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可
cookie在浏览器中保存多长时间?
默认情况下,当浏览器关闭后,Cookie数据被销毁
持久化存储
持久化存储用setMaxAge(int seconds)
- 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
- 负数:默认值
- 零:删除cookie信息
代码示例
向cookie中保存信息,并设置浏览器保存60s
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie对象
Cookie c = new Cookie("msg","setMaxAge");
//2.设置cookie保存时间
//将cookie持久化到硬盘,60秒后会浏览器自动删除cookie文件,那么服务器就接收不到该数据
c.setMaxAge(60);
//3.发送Cookie
response.addCookie(c);
}
获取指定信息
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//3.获取Cookie对象
Cookie[] cookies = request.getCookies();
//遍历Cookie
if (cookies!=null){
for (Cookie c : cookies) {
if ("msg".equals(c.getName())){
String name = c.getName();
String value = c.getValue();
System.out.println(name+"=="+value);
}
}
}
}
关闭浏览器60s之内,我们再次访问该路径,服务器控制台任然能够得到msg数据
cookie能不能存中文?
- 在tomcat 8 之前 cookie中不能直接存储中文数据。(需要将中文数据转码—一般采用URL编码(%E3))
- 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
cookie共享问题?
假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
- 默认情况下cookie不能共享
- setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
- 如果要共享,则可以将path设置为"/"
不同的tomcat服务器间cookie共享问题?
- setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
- setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享
Cookie特征
特征
- cookie存储数据在客户端浏览器
- 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
作用
- 在不登录的情况下,完成服务器对客户端的身份识别
- cookie一般用于存出少量的不太敏感的数据
3.Session对象
概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中
常用方法
request.getSession()
:获取HttpSession对象
Object getAttribute(String name)
:得到保存数据
void setAttribute(String name, Object value)
:保存数据
void removeAttribute(String name)
:移除数据
代码示例
Session01
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取session对象
HttpSession session = req.getSession();
//2.往session中存入数据
session.setAttribute("msg","hello,session");
}
Session02
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取session对象
HttpSession session = req.getSession();
//2.获取session对象的数据
Object msg = session.getAttribute("msg");
System.out.println(msg);
}
session实现原理
其实就是利用cookie对象,来传递一个Session的ID,当下次请求时,通过ID来找到储存在服务器中的Session对象
Session细节
当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
- 默认情况下。不是。
- 如果需要相同,则需要手动创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存那么cookie所携带的session的ID也将在下一次请求发送给服务器。
代码示例
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取session对象
HttpSession session = req.getSession();
//2.往session中存入数据
session.setAttribute("msg","hello,session");
//3.手动设置Cookie
Cookie cookie = new Cookie("JSESSIONID",session.getId());
//4.设置Cookie存活时间(一个小时)
cookie.setMaxAge(60*60);
//5.发送cookie
resp.addCookie(cookie);
}
客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
- 不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
session的钝化:
- 在服务器正常关闭之前,将session对象系列化到硬盘上
session的活化
- 在服务器启动后,将session文件转化为内存中的session对象即可。
Tocat服务器已经帮我们自动实现session的钝化和session的活化
session什么时候被销毁?
- 服务器关闭时被销毁
- session对象调用invalidate()后,被销毁
- session默认失效时间 30分钟
选择性配置修改(在web.xml中配置)
<session-config>
<session-timeout>30</session-timeout>
</session-config>
session特点
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型,任意大小的数据
- session与Cookie的区别
- session存储数据在服务器端,Cookie在客户端
- session没有数据大小限制,Cookie有
- session数据安全,Cookie相对于不安全
2.JSP基础
什么是JSP:Java Server Pages: java服务器端页面
- 可以理解为:一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码
- 用于简化书写!!!
原理
- JSP本质上就是一个Servlet
1.JSP的脚本
- <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
- <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置。
- <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<% System.out.println("hello,jsp"); int i=200; %> <%-- 等于在service方法中--%>
<%! int i=100; %> <%-- 定义成员变量--%>
<%= "hello,jsp" %> <%-- 把值输出到页面上--%>
<%= i %> <%-- 把值输出到页面上--%>
</body>
</html>
注意:如果定义的变量名相同(<%! 代码 %>和 <% 代码 %>都定义了相同的i),<%= 代码 %>在输出时,<% 代码 %>优先
2.指令
作用:用于配置JSP页面,导入资源文件
格式:<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 … %>
例如:<%@ page contentType="text/html;charset=UTF-8" language="java" %>
分类
- page: 配置JSP页面的
- include : 页面包含的。导入页面的资源文件
- taglib : 导入资源
1.page指令
- contentType:等同于response.setContentType()
- 设置响应体的mime类型以及字符集
- 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
- import:导包
- errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
- isErrorPage:标识当前也是是否是错误页面
- true:是,可以使用内置对象exception
- false:否。默认值。不可以使用内置对象exception
2.include指令
include : 页面包含的。导入其他页面
例如: <%@include file="top.jsp"%>
A页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>A页面</h1>
B页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导入A页面--%>
<%@ include file="A.jsp" %>
<html>
<head>
<title>B</title>
</head>
<body>
BBBBB
</body>
</html>
页面显示
3.taglib指令
taglib : 导入标签库
prefix:前缀,自定义的
例如: <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
代码示例
<%--导入java包--%>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%--contentType:设置响应体的mime类型以及字符集,设置当前jsp页面的编码--%>
<%--errorPage:当前页面发生异常后,会自动跳转到500.jsp页面--%>
<%@ page contentType="text/html;charset=gbk" errorPage="500.jsp" pageEncoding="GBK" language="java" buffer="16kb" %>
<%--设置标签库 prefix:给使用的标签库取名字 uri:要导入的标签库--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
</body>
</html>
使用
向使用xml标签一样
3.内置对象
在jsp页面中不需要创建,直接使用的对象,一共有9个
变量名 | 真实类型 | 作用 |
pageContext | PageContext | 当前页面共享数据,还可以获取其他八个内置对象 |
request | HttpServletRequest | 一次请求访问的多个资源(转发) |
session | HttpSession | 一次会话的多个请求间 |
application | ServletContext | 所有用户间共享数据 |
response | HttpServletResponse | 响应对象 |
page | Object | 当前页面(Servlet)的对象 this |
out | JspWriter | 输出对象,数据输出到页面上 |
config | ServletConfig | Servlet的配置对象 |
exception | Throwable | 异常对象 |
3.EL表达式
概念:Expression Language 表达式语言
作用:替换和简化jsp页面中java代码的编写
语法:${表达式}
例如 ${3>4}
网页显示
注意
- jsp默认支持el表达式的。如果要忽略el表达式
- 设置jsp中page指令中:**isELIgnored=“true”** 忽略当前jsp页面中所有的el表达式
- ${表达式} :忽略当前这个el表达式
1.运算符
算数运算符
算数运算符: + - * /(div) %(mod)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<hr>
<h3>算数运算符</h3>
${3 + 4}<br> <%--结果为7--%>
${3 / 4}<br> <%--结果为0.75--%>
${3 div 4}<br> <%--结果为0.75--%>
${3 % 4}<br> <%--结果为3--%>
${3 mod 4}<br> <%--结果为3--%>
</body>
</html>
比较运算符
比较运算符: > < >= <= == !=
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<hr>
<h3>比较运算符</h3>
${3 == 4}<br> <%--结果为 false--%>
</body>
</html>
逻辑运算符
逻辑运算符: &&(and) ||(or) !(not)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<hr>
<h3>逻辑运算符</h3>
${3 > 4 && 3 < 4}<br> <%--结果为 false--%>
${3 > 4 and 3 < 4}<br> <%--结果为 false--%>
</body>
</html>
空运算符
空运算符: empty
- 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
- ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
- ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0
代码示例
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>empty运算符</h3>
<%
String str = "";
request.setAttribute("str",str);
List list = new ArrayList();
request.setAttribute("list",list);
%>
${not empty str}<br> <%--结果为false --%>
${not empty list}<br> <%--结果为false --%>
</body>
</html>
显示结果
2.获取值
el表达式只能从域对象中获取值
语法
获取方式一
1. ${域名称.键名}:从指定域中获取指定键的值
* 域名称:
1. pageScope --> pageContext
2. requestScope --> request
3. sessionScope --> session
4. applicationScope --> application(ServletContext)
* 举例:在request域中存储了name=张三
* 获取:${requestScope.name}
获取方式二
2. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
代码示例(获取值)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--存入数据--%>
<%
request.setAttribute("name","张三");
session.setAttribute("age",18);
%>
<%--获取数据--%>
${requestScope.name}
${sessionScope.age}
<%--如果没有,则在页面上什么都不显示(空字符串)--%>
${sessionScope.ss}
</body>
</html>
显示结果
上面的案例是从域对象中获取值
获取对象
对象:${域名称.键名.属性名}
- 本质上会去调用对象的getter方法
代码示例
User实体对象
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
jsp页面
<%@ page import="domain.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--存入数据--%>
<%
User user = new User();
user.setName("李四");
user.setAge(21);
request.setAttribute("u",user);
%>
<%--获取数据--%>
${requestScope.u}<br>
${requestScope.u.age}<br>
${requestScope.u.name}<br>
</body>
</html>
这里调用了User类中的getXxxx方法
网页显示
获取List集合
语法:${域名称.键名[索引]}
代码示例
<%@ page import="domain.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--存入数据--%>
<%
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(200);
list.add(300);
request.setAttribute("list",list);
%>
<%--获取数据--%>
${requestScope.list}<br>
${requestScope.list[0]}<br>
${requestScope.list[1]}<br>
${requestScope.list[2]}<br>
</body>
</html>
显示结果
获取Map集合
语法
- ${域名称.键名.key名称}
- ${域名称.键名[“key名称”]}
代码示例
<%@ page import="domain.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--存入数据--%>
<%
HashMap<String, String> map = new HashMap<>();
map.put("小明","哈哈哈");
map.put("小红","呵呵呵");
map.put("小王","嘻嘻嘻");
request.setAttribute("people",map);
%>
<%--获取数据--%>
${requestScope.people}<br>
${requestScope.people.小红}<br>
${requestScope.people["小王"]}<br>
</body>
</html>
显示结果
注意:如果map集合的K是Integer类,无法实现上面的功能
4.JSTL基础
概念:JavaServer Pages Tag Library JSP标准标签库,是由Apache组织提供的开源的免费的jsp标签
作用:用于简化和替换jsp页面上的java代码
1.使用步骤
- 导入jstl相关jar包
- 引入标签库:taglib指令: <%@ taglib %>
- 使用标签
2.常用的JSTL标签
if标签
1. if:相当于java代码的if语句
1. 属性:
* test 必须属性,接受boolean表达式
* 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
* 一般情况下,test属性值会结合el表达式一起使用
2. 注意:
* c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签
代码示例
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>if标签</title>
</head>
<body>
<c:if test="true">
<h1>我是真...</h1>
</c:if>
<br>
<c:if test="${not empty list}">
遍历集合...
</c:if>
<br>
<c:if test="${number % 2 != 0}">
${number}为奇数
</c:if>
<c:if test="${number % 2 == 0}">
${number}为偶数
</c:if>
</body>
</html>
choose标签
2. choose:相当于java代码的switch语句
1. 使用choose标签声明 相当于switch声明
2. 使用when标签做判断 相当于case
3. 使用otherwise标签做其他情况的声明 相当于default
代码示例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>choose标签</title>
</head>
<body>
<%--
完成数字编号对应星期几案例
1.域中存储一数字
2.使用choose标签取出数字 相当于switch声明
3.使用when标签做数字判断 相当于case
4.otherwise标签做其他情况的声明 相当于default
--%>
<%
request.setAttribute("number",51);
%>
<c:choose>
<c:when test="${number == 1}">星期一</c:when>
<c:when test="${number == 2}">星期二</c:when>
<c:when test="${number == 3}">星期三</c:when>
<c:when test="${number == 4}">星期四</c:when>
<c:when test="${number == 5}">星期五</c:when>
<c:when test="${number == 6}">星期六</c:when>
<c:when test="${number == 7}">星期天</c:when>
<c:otherwise>数字输入有误</c:otherwise>
</c:choose>
</body>
</html>
foreach标签
3. foreach:相当于java代码的for语句
代码示例
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>foreach标签</title>
</head>
<body>
<%--
foreach:相当于java代码的for语句
1. 完成重复的操作
for(int i = 0; i < 10; i ++){
}
* 属性:
begin:开始值
end:结束值
var:临时变量
step:步长
varStatus:循环状态对象
index:容器中元素的索引,从0开始
count:循环次数,从1开始
2. 遍历容器
List<User> list;
for(User user : list){
}
* 属性:
items:容器对象
var:容器中元素的临时变量
varStatus:循环状态对象
index:容器中元素的索引,从0开始
count:循环次数,从1开始
--%>
<c:forEach begin="1" end="10" var="i" step="2" varStatus="s">
${i} <h3>${s.index}<h3> <h4> ${s.count} </h4><br>
</c:forEach>
<hr>
<%
List list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
request.setAttribute("list",list);
%>
<c:forEach items="${list}" var="str" varStatus="s">
${s.index} ${s.count} ${str}<br>
</c:forEach>
</body>
</html>