jsp简介
JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,是一种动态网页技术标准。它是在传统的网页HTML文件中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件,后缀名为(*.jsp)。 用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能在其他操作系统上运行。
它实现了Html语法中的java扩展(以 <%, %>形式)。JSP与Servlet一样,是在服务器端执行的。通常返回给客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览。
jsp优缺点与servlet的关系
jsp优缺点
优点:在原有html的基础上添加java脚本,构成jsp页面。
缺点:html标签中包含大量的java代码,不利于后期的维护。
jsp与servlet关系
jsp的本质就是一个servlet,所有servlet 可以做的事情,jsp 都可以做。但是两者各有优缺点。
jsp擅长的是页面的展示,包括发起界面(form表单),结束界面(显示数据table),可以直接使用html标签,而不需要使用大量的需要大量的response.getWriter().print(““)。
Serlvet:用来处理数据
jsp:显示数据
jsp当中的所有的内容,实际上都是会被转换成 out.writer()…
jsp页面的组成部分
jsp页面的组成主要包含以下部分:
- html标签
- 注释(html和jsp注释)
- jsp动作标签
- 指令
- 小脚本<% %>
- 表达式<%= %>
- 申明<%! %>
html标签
支持所有的html标签。也可以直接使用(css/js)。就像写html页面一样写jsp页面
注释
jsp页面中可以使用两种注释。
- html注释:<!—html注释 —>:在页面源码中是可以看见的
- jsp注释:<%—jsp注释—%>:在页面源码中是隐藏的,只能看源代码查看。
jsp内置动作标签
jsp内置的标签库,不同的标签拥有不同的功能
jsp常用的动作标签有:参考http://www.runoob.com/jsp/jsp-actions.html
jsp指令
jsp指令用来设置整个JSP页面相关的属性,指令可以有很多个属性,它们以键值对的形式存在,并用逗号隔开。
jsp中的三种指令标签:
指令 | 描述 |
---|---|
<%@ page … %> | 指定页码的属性,例如设置编码格式 |
<%@ include … %> | 静态包含,可以用来包含其他文件 |
<%@ taglib … %> | 引入标签库的定义,可以引入第三方标签库(jstl) |
page指令
page指令用来指定页面的属性,例如:如下设置jsp使用的脚本语言及文档类型
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
下表列出与Page指令相关的属性:
属性 | 描述 |
---|---|
buffer | 指定out对象使用缓冲区的大小 |
autoFlush | 控制out对象的 缓存区 |
contentType | 指定当前JSP页面的MIME类型和字符编码 |
errorPage | 指定当JSP页面发生异常时需要转向的错误处理页面 |
isErrorPage | 指定当前页面是否可以作为另一个JSP页面的错误处理页面 |
extends | 指定servlet从哪一个类继承 |
import | 导入要使用的Java类 |
info | 定义JSP页面的描述信息 |
isThreadSafe | 指定对JSP页面的访问是否为线程安全 |
language | 定义JSP页面所用的脚本语言,默认是Java |
session | 指定JSP页面是否使用session |
isELIgnored | 指定是否执行EL表达式 |
isScriptingEnabled | 确定脚本元素能否被使用 |
jsp脚本
JSP脚本就是Java代码片段,它分为三种:
- <%…%>:小脚本,Java语句;
- <%=…%>:Java表达式;
- <%!…%>:申明,Java定义类成员;
小脚本
<body>
<%
String text = "hello 你好";
System.out.println(text);
%>
</body>
表达式
<body>
<%
String text = "hello 你好";
System.out.println(text);
%>
<%=text %>
</body>
申明
<body>
<!--定义一个方法-->
<%!public String sayHello() {
return "hello";
}%>
<%=sayHello()%>
</body>
jsp案例
- 用户登录,注册。
- 当用户登录成功之后跳转到主界面显示所有的员工信息。
用户登录实现思路
- a.创建jsp页面,登录。
- b.创建LoginServlet接收登录的请求,处理验证。
- c.创建jdbc连接数据库。
- d.如果验证成功,跳转到主页面。
jsp内置对象
在JSP中无需创建就可以使用的9个对象,它们是:
- out(JspWriter):等同与response.getWriter(),用来向客户端发送文本数据;
- config(ServletConfig):对应“真身”中的ServletConfig;
- page(当前JSP的真身类型):当前JSP页面的“this”,即当前对象;
- pageContext(PageContext):页面上下文对象,它是最后一个没讲的域对象;
- exception(Throwable):只有在错误页面中可以使用这个对象;
- request(HttpServletRequest):即HttpServletRequest类的对象;
- response(HttpServletResponse):即HttpServletResponse类的对象;
- application(ServletContext):即ServletContext类的对象;
- session(HttpSession):即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个页面不能使用session。
EL表达式语言
EL的作用
JSP2.0要把html和css分离、要把html和javascript分离、要把Java脚本替换成标签。标签的好处是非Java人员都可以使用。
JSP2.0 –纯标签页面,即:不包含<% … %>、<%! … %>,以及<%= … %>
EL(Expression Language)是一门表达式语言,它对应<%=…%>。我们知道在JSP中,表达式会被输出,所以EL表达式也会被输出。
主要作用用来替换jsp当中<%= %>语句
EL的格式
格式:${…}
例如:${price}*${number} ==${price*number}
表达式:1+2;
语句:int a= 1+2;
关闭EL
如果希望整个JSP忽略EL表达式,需要在page指令中指定isELIgnored=”true”。 默认是true。
如果希望忽略某个EL表达式,可以在EL表达式之前添加“\”,例如:${1 + 2}。
EL运算符
运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
+ | 加 | ${17+5} | 22 |
- | 减 | ${17-5} | 12 |
* | 乘 | ${17*5} | 85 |
/或div | 除 | ${17/5}或${17 div 5} | 3 |
%或mod | 取余 | ${17%5}或${17 mod 5} | 2 |
==或eq | 等于 | ${5==5}或${5 eq 5} | true |
!=或ne | 不等于 | ${5!=5}或${5 ne 5} | false |
<或lt | 小于 | ${3<5}或${3 lt 5} | true |
>或gt | 大于 | ${3>5}或${3 gt 5} | false |
<=或le | 小于等于 | ${3<=5}或${3 le 5} | true |
>=或ge | 大于等于 | ${3>=5}或${3 ge 5} | false |
&&或and | 并且 | ${true&&false}或${true and false} | false |
!或not | 非 | ${!true}或${not true} | false |
||或or | 或者 | ${true||false}或${true or false} | true |
empty | 是否 为空 | ${empty “”},可以判断字符串、数据、集合的长度是否为0,为0返回true。empty还可以与not或!一起使用。${not empty “”} | true |
EL不显示null
当EL表达式的值为null时,会在页面上显示空白,即什么都不显示。
JSTL标签库
- JSTL(JavaServer Pages Standard Tag Library,JSP标准标签库)
- JSTL是apache对EL表达式的扩展(也就是说JSTL依赖EL),JSTL是标签语言!JSTL标签使用以来非常方便,它与JSP动作标签一样,只不过它不是JSP内置的标签,需要我们自己导包,以及指定标签库而已!
- 如果你使用MyEclipse开发JavaWeb,那么在把项目发布到Tomcat时,你会发现,MyEclipse会在lib目录下存放jstl的Jar包!如果你没有使用MyEclipse开发那么需要自己来导入这个JSTL的Jar包:jstl-1.2.jar。
JSTL标签库
JSTL一共包含四大标签库:
- core:核心标签库,我们学习的重点,也称为C标签;
- fmt:格式化标签库,只需要学习两个标签即可;
- sql:数据库标签库,不需要学习了,它过时了;
- xml:xml标签库,不需要学习了,它过时了。
使用taglib指令导入标签库
除了JSP动作标签外,使用其他第三方的标签库都需要:
导包
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
在使用标签的JSP页面中使用taglib指令导入标签库;
下面是导入JSTL的core标签库:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- prefix=”c”:指定标签库的前缀,这个前缀可以随便给值,但大家都会在使用core标签库时指定前缀为c;
- uri=”http://java.sun.com/jstl/core“:指定标签库的uri,它不一定是真实存在的网址,但它可以让JSP找到标签库的描述文件;
core标签库常用标签
out
输出aaa字符串常量 | |
---|---|
与${aaa}相同 | |
当${aaa}不存在时,输出xxx字符串 |
if
if标签的test属性必须是一个boolean类型的值,如果test的值为true,那么执行if标签的内容,否则不执行。
<c:set var="a" value="hello"/>
<c:if test="${not empty a }">
<c:out value="${a }"/>
</c:if>
choose
choose标签对应Java中的if/else if/else结构。when标签的test为true时,会执行这个when的内容。当所有when标签的test都为false时,才会执行otherwise标签的内容。
<!--选择标签 if else if else -->
<c:choose>
<c:when test="${map.age<18}">
<c:out value="未成年"></c:out>
</c:when>
<c:when test="${map.age>=18 && map.age < 30}">
<c:out value="青年人"></c:out>
</c:when>
<c:when test="${map.age>=30 && map.age < 60}">
<c:out value="中年人"></c:out>
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>
forEach
forEach当然就是循环标签了,forEach标签有两种使用方式:
- 使用循环变量,指定开始和结束值,类似for(int i = 1; i <= 10; i++) {};
- 循环遍历集合,类似for(Object o : 集合);
遍历集合或数组方式:
<c:forEach var="score" items="${socreArray}">
<c:out value="${score}"></c:out>
</c:forEach> <br/>
遍历List
<c:forEach var="data" items="${list}">
<c:out value="${data.name}"></c:out> <br/>
</c:forEach> <br/>
遍历Map
<c:forEach var="map" items="${data}">
<c:out value="key = ${map.key} value = ${map.value} "></c:out> <br/
</c:forEach>
varStatus
forEach标签还有一个属性:varStatus,这个属性用来指定接收“循环状态”的变量名,例如:<forEach varStatus=”vs” …/>,这时就可以使用vs这个变量来获取循环的状态了
- count:int类型,当前以遍历元素的个数;
- index:int类型,当前元素的下标;从0开始
- first:boolean类型,是否为第一个元素;
- last:boolean类型,是否为最后一个元素;
current:Object类型,表示当前项目。 ```xml
<c:if test="${vs.first}">
<c:out value="${map.name} 是第一条记录"></c:out>
</c:if> <br/>
<c:if test="${vs.last}">
<c:out value="${map.name} 是最后一条记录"></c:out>
</c:if> <br/>
<c:if test="${vs.index == 2}">
<c:out value="${map.name} 是第三条"></c:out>
</c:if>
</c:forEach>
<a name="ER9nk"></a>
### fmt标签库常用标签
fmt标签库是用来格式化输出的,通常需要格式化的有时间和数字。
**格式化时间:**
```xml
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
......
<%
Date date = new Date();
pageContext.setAttribute("d", date);
%>
<fmt:formatDate value="${d }" pattern="yyyy-MM-dd HH:mm:ss"/>
格式化数字:
<%
double d1 = 3.5;
double d2 = 4.4;
pageContext.setAttribute("d1", d1);
pageContext.setAttribute("d2", d2);
%>
<fmt:formatNumber value="${d1 }" pattern="0.00"/><br/>
<fmt:formatNumber value="${d2 }" pattern="#.##"/>
会话跟踪技术
什么是会话跟踪技术
http协议 是一个无状态协议:每次请求都是独立的,第一次请求和第二次请求没有关系的
我们需要先了解一下什么是会话(多次请求)!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应。例如你给10086打个电话,你就是客户端,而10086服务人员就是服务器了。从双方接通电话那一刻起,会话就开始了,到某一方挂断电话表示会话结束。在通话过程中,你会向10086发出多个请求,那么这多个请求都在一个会话中。
在JavaWeb中,客户向某一服务器发出第一个请求开始,会话就开始了,直到客户关闭了浏览器会话结束。
在一个会话的多个请求中共享数据,这就是会话跟踪技术。例如在一个会话中的请求如下:
- 请求银行主页;
- 请求登录(请求参数是用户名和密码);
- 请求转账(请求参数与转账相关的数据);
- 请求信用卡还款(请求参数与还款相关的数据)。
在这上会话中当前用户信息必须在这个会话中共享的,因为登录的是张三,那么在转账和还款时一定是相对张三的转账和还款!这就说明我们必须在一个会话过程中有共享数据的能力。
什么是会话呢?我 们可以通俗一点理解。只要你的browers(浏览器)不关闭我们就称这一系列的request与response为一个会话。一断你close就称这个会话已结束。 虽然会话结束但并不代表你的session就被destroy.因为session是存活在server上的。它的生命完全由server来主宰 (tomcat服务器web.xml中的设定)
虽然你的session还存活在server上但你已无法再取得它。因为j2ee的api只给我们一种方法来取得与当前会话相关的session的引用:request.getsession() or reqeust.getsession(boolean)
会话跟踪技术
会话跟踪技术使用Cookie或session完成
我们知道HTTP协议是无状态协议,也就是说每个请求都是独立的!无法记录前一次请求的状态。但HTTP协议中可以使用Cookie来完成会话跟踪!
在JavaWeb中,使用session来完成会话跟踪,session底层依赖Cookie技术。
常见的cookie场景
- 记住用户名和密码(不安全)
- 商品浏览记录
- 猜你喜欢
- 购物车
Cookie
什么叫Cookie
浏览器与WEB服务器之间是使用HTTP协议进行通信的,当某个用户发出页面请求时,WEB服务器只是简单的进行响应,然后就关闭与该用户的连接。因此当一个请求发送到WEB服务器时,无论其是否是第一次来访,服务器都会把它当作第一次来对待,这样的不好之处可想而知。为了弥补这个缺陷,Netscape开发出了cookie这个有效的工具来保存某个用户的识别信息,因此人们昵称为“小甜饼”。
Cookie是由服务器创建,然后通过响应发送给客户端的一个键值对。客户端会保存Cookie,并会标注出Cookie的来源(哪个服务器的Cookie)。当客户端向服务器发出请求时会把所有这个服务器Cookie包含在请求中发送给服务器,这样服务器就可以识别客户端了!
Cookie规范
- Cookie大小上限为4KB;
- 一个服务器最多在客户端浏览器上保存20个Cookie;
- 一个浏览器最多保存300个Cookie;
上面的数据只是HTTP的Cookie规范,但在浏览器大战的今天,一些浏览器为了打败对手,为了展现自己的能力起见,可能对Cookie规范“扩展”了一些,例如每个Cookie的大小为8KB,最多可保存500个Cookie等!但也不会出现把你硬盘占满的可能!
cookie属于客户端
注意,不同浏览器之间是不共享Cookie的。也就是说在你使用IE访问服务器时,服务器会把Cookie发给IE,然后由IE保存起来,当你在使用FireFox访问服务器时,不可能把IE保存的Cookie发送给服务器。
Cookie第一例
我们这个案例是,客户端访问AServlet,AServlet在响应中添加Cookie,浏览器会自动保存Cookie。然后客户端访问BServlet,这时浏览器会自动在请求中带上Cookie,BServlet获取请求中的Cookie打印出来。
AServlet.java
/**
* 给客户端发送Cookie
* @author Administrator
*
*/
public class AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String id = UUID.randomUUID().toString();//生成一个随机字符串
Cookie cookie = new Cookie("id", id);//创建Cookie对象,指定名字和值
response.addCookie(cookie);//在响应中添加Cookie对象
response.getWriter().print("已经给你发送了ID");
}
}
BServlet.java
/**
* 获取客户端请求中的Cookie
* @author Administrator
*
*/
public class BServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
Cookie[] cs = request.getCookies();//获取请求中的Cookie
if(cs != null) {//如果请求中存在Cookie
for(Cookie c : cs) {//遍历所有Cookie
if(c.getName().equals("id")) {//获取Cookie名字,如果Cookie名字是id
response.getWriter().print("您的ID是:" + c.getValue());//打印Cookie值
}
}
}
}
}
Cookie的生命
什么是Cookie的生命
Cookie不只是有name和value,Cookie还是生命。所谓生命就是Cookie在客户端的有效时间,可以通过setMaxAge(int)来设置Cookie的有效时间。
cookie.setMaxAge(-1):cookie的maxAge属性的默认值就是-1,表示只在浏览器内存中存活。一旦关闭浏览器窗口,那么cookie就会消失。
cookie.setMaxAge(60*60):表示cookie对象可存活1小时。当生命大于0时,浏览器会把Cookie保存到硬盘上,就算关闭浏览器,就算重启客户端电脑,cookie也会存活1小时;
cookie.setMaxAge(0):cookie生命等于0是一个特殊的值,它表示cookie被作废!也就是说,如果原来浏览器已经保存了这个Cookie,那么可以通过Cookie的setMaxAge(0)来删除这个Cookie。无论是在浏览器内存中,还是在客户端盘上都会删除这个Cookie。
浏览器查看cookie
在google浏览器中输入:
chrome://settings/siteData
浏览器—>设置—>高级—->内容设置—->Cookie—->查看所有 Cookie 和网站数据
案例:显示上次访问时间
创建Cookie,名为lasttime,值为当前时间,添加到response中;
在AServlet中获取请求中名为lasttime的Cookie;
如果不存在输出“您是第一次访问本站”,如果存在输出“您上一次访问本站的时间是xxx”;
Cookie中保存中文
Cookie的name和value都不能使用中文,如果希望在Cookie中使用中文,那么需要先对中文进行URL编码,然后把编码后的字符串放到Cookie中。
向客户端响应中添加Cookie
String name = URLEncoder.encode("姓名", "UTF-8");
String value = URLEncoder.encode("张三", "UTF-8");
Cookie c = new Cookie(name, value);
c.setMaxAge(3600);
response.addCookie(c);
从客户端请求中获取Cookie
response.setContentType("text/html;charset=utf-8");
Cookie[] cs = request.getCookies();
if(cs != null) {
for(Cookie c : cs) {
String name = URLDecoder.decode(c.getName(), "UTF-8");
String value = URLDecoder.decode(c.getValue(), "UTF-8");
String s = name + ": " + value + "<br/>";
response.getWriter().print(s);
}
}
弊端:
- 保存在客户端,安全性差;
- 无法实现多浏览器,多电脑之间的数据共享
优点
- 不需要占用服务器资源。
HttpSession概述
什么是HttpSesssion
javax.servlet.http.HttpSession接口表示一个会话,我们可以把一个会话内需要共享的数据保存到 HttpSession对象中。
会话:就是一系列的请求。session是实现会话跟踪技术的一种,另一种可以使用cookie实现。
http是属于一种无状态的协议(一次请求完之后,所有的都消失了)。
session的底层依赖与cookie。
获取HttpSession对象
- HttpSession request.getSesssion():如果当前会话已经有了session对象那么直接返回,如果当前会话还不存在会话,那么创建session并返回;
- HttpSession request.getSession(boolean):当参数为true时,与requeset.getSession()相同。如果参数为false,那么如果当前会话中存在session则返回,不存在返回null;
HttpSession是域对象
我们已经学习过HttpServletRequest、ServletContext,它们都是域对象,现在我们又学习了一个HttpSession,它也是域对象。它们三个是Servlet中可以使用的域对象,而JSP中可以多使用一个域对象
- HttpServletRequest:一个请求创建一个request对象,所以在同一个请求中可以共享request,例如一个请求从AServlet转发到BServlet,那么AServlet和BServlet可以共享request域中的数据;
- ServletContext:一个应用只创建一个ServletContext对象,所以在ServletContext中的数据可以在整个应用中共享,只要不启动服务器,那么ServletContext中的数据就可以共享;
- HttpSession:一个会话创建一个HttpSession对象,同一会话中的多个请求中可以共享session中的数据;
session的域方法:
- void setAttribute(String name, Object value):用来存储一个对象,也可以称之为存储一个域属性,例如:session.setAttribute(“xxx”, “XXX”),在session中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同;
- Object getAttribute(String name):用来获取session中的数据,当前在获取之前需要先去存储才行,例如:String value = (String) session.getAttribute(“xxx”);,获取名为xxx的域属性;
- void removeAttribute(String name):用来移除HttpSession中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做;
- Enumeration getAttributeNames():获取所有域属性的名称;
session其他常用API
//获取sessionId
String getId();
//获取session可以的最大不活动时间(秒),默认为30分钟。
//当session在30分钟 内没有使用,那么Tomcat会在session池中移除这个session;
int getMaxInactiveInterval();
//设置session允许的最大不活动时间(秒),
//如果设置为1秒,那 么只要session在1秒内不被使用,那么session就会被移除;
void setMaxInactiveInterval(int interval);
//返回session的创建时间,返回值为当前时间的毫秒值
long getCreationTime();
//返回session的最后活动时间,返回值为当前时间的毫秒值
long getLastAccessedTime();
//(退出登录)让session失效!调用这个方法会被session失效,当session失效后,
//客户端再次请求,服务 器会给客户端创建一个新的session,并在响应中给客户端新session的sessionId;
void invalidate();
//查看session是否为新。当客户端第一次请求时,服务器为客户端创建session,
//但这时服务器还 没有响应客户端,也就是还没有把sessionId响应给客户端时,这时session的状态为新。
boolean isNew();
淘宝……吃饭(30分钟)….买买(登录失效,重新登录)
session的实现原理
session底层是依赖Cookie的!我们来理解一下session的原理吧!
当我首次去银行时,因为还没有账号,所以需要开一个账号,我获得的是银行卡,而银行这边的数据库中留下了我的账号,我的钱是保存在银行的账号中,而我带走的是我的卡号。
当我再次去银行时,只需要带上我的卡,而无需再次开一个账号了。只要带上我的卡,那么我在银行操作的一定是我的账号!
当首次使用session时,服务器端要创建session,session是保存在服务器端,而给客户端的session的id(一个cookie中保存了sessionId)。客户端带走的是sessionId,而数据是保存在session中。
当客户端再次访问服务器时,在请求中会带上sessionId,而服务器会通过sessionId找到对应的session,而无需再创建新的session。
服务器是如何实现一个session为一个用户浏览器服务的?
服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session id过来了,就会使用内存中与之对应的session为之服务。可以用如下的代码证明:
第一次访问
第二次访问
session与浏览器
session保存在服务器,而sessionId通过Cookie发送给客户端,但这个Cookie的生命是-1,即只在浏览器内存中存在,也就是说如果用户关闭了浏览器,那么这个Cookie就丢失了。
当用户再次打开浏览器访问服务器时,就不会有sessionId发送给服务器,那么服务器会认为你没有session,所以服务器会创建一个session,并在响应中把sessionId中到Cookie中发送给客户端。
你可能会说,那原来的session对象会怎样?当一个session长时间没人使用的话,服务器会把session删除了!这个时长在Tomcat中配置是30分钟,可以在${CATALANA}/conf/web.xml找到这个配置,当然你也可以在自己的web.xml中覆盖这个配置!
web.xml
<session-config>
<session-timeout>30</session-timeout>
</session-config>
session失效时间也说明一个问题!如果你打开网站的一个页面开始长时间不动,超出了30分钟后,再去点击链接或提交表单时你会发现,你的session已经丢失了!
Session和Cookie主要区别
- Cookie是把用户的数据写给用户的浏览器。好处不占用服务器资源,安全性低
- Session技术把用户的数据写到用户独占的session中。
- Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。