Session介绍
Session是什么
一个终端用户与交互系统进行通信的时间间隔。
Session的作用
在 Web服务器上保持用户的状态信息供在任何时间从任何设备上的页面进行访问。
工作原理:
client———>1.request————————->server
2. session_start();
|<————-3.reponse(SESSION_ID)<——–|
|————->4.request(SESSION_ID)———>|
5. session_start();
|<————-6.reponse(SESSION_ID)<———|
|————->7. request(SESSION_ID + logout)–>|
8. session_destroy();
|<————-9. reponse(删除cookie文件)<——-|
1)client打开网页,向server发出请求,client上由于没有相应的cookie文件存在,在请求中不输送SESSION_ID
2)服务器在接受到client的请求后,通过执行session_start()函数开始进行session的处理, 首先确认请求中有没有SESSION_ID,如果没有的话,发行一个新的SESSION_ID;如果有的话, 则调用那个存有SESSION_ID的文件,并把信息写入$_SESSION里去,并存入以sess_开头的文件里。
3)把写入信息的$_SESSION参数发回给client,client在GET服务器发来的信息后,把这些信息保存在cookie里。
4)client把cookie里的SESSION_ID一起写入header后再次向server发出请求。重复1-3的操作
5)client发出登出请求
6)服务器接受请求后,通过执行session_destroy()函数开始删除session文件处理
7)服务器向client发出删除保存在client上的cookie文件的命令: setcookie(session_name(), ”, time()-60, ‘/’);
优点:通过将对象存储在 Web服务器的内存中在整个用户会话过程中保持任何对象。
缺点:每个 Session 中保持许多对象,并且许多用户同时使用 Web应用程序(创建许多 Session),则用于 Session 持久性的服务器内存量可能会很大,从而影响了可伸缩性。
如何用session
- 1. 设置session过期时间
1)以分钟为单位
<web-app ...>
<session-config>
<session-timeout>20</session-timeout>
</session-config>
</web-app>
上面这种设置,对整个web应用生效。当客户端20分钟内都没有发起请求时,容器会将session干掉。
2) 通过编码方式,指定特定的session的过期时间,以秒为单位,设置为-1表示永不过期。
HttpSession session = request.getSession();
session.setMaxInactiveInterval(20*60);
注意:Session设置产生效果的优先循序是,先程序后配置,先局部后整体。
- 2. session监听
在javax.servlet.http包里一共定义了四个session监听器接口和与之关联的两个session事件。分别是:
HttpSessionAttributeListener and
HttpSessionBindingEvent;
HttpSessionBindingListener and HttpSessionBindingEvent;
HttpSessionListener and HttpSessionEvent;
HttpSessionActivationListener and HttpSessionEvent.
他们的继承关系是:
所有四个接口的父类是java.util.EventListener;
HttpSessionEvent扩展java.util.EventObject;
而HttpSessionBindingEvent又扩展了HttpSessionEvent。
以下分别详述:
HttpSessionAttributeListener
当session中的属性被添加,更改,删除时得到通知。这个接口上节讲过,主要看其它三个。
HttpSessionBindingListener
当一个实现了HttpSessionBindingListener的类被加入到HttpSession中(或从中移出)时,会产生HttpBindingEvent事件,而这些事件会被它本身接收到。
本接口定义了两个方法:
void valueBound(HttpSessionBindingEvent e);
void valueUnbound(HttpSessionBindingEvent e);
当多个实现了HttpSessionBindingListener的类被加入到HttpSession中时,各类的方法只对本类感兴趣,不会去理会其它类的加入。
即使是同一类的不同实例间,也是互不关心的(各扫门前雪)。
我们可以看到前两个接口都对HttpSessionBindingEvent事件做出反应,但机理不同。
HttpSessionAttributeListener是在web.xml中登记的,servlet容器仅创建一个实例,来为任何在session中增加属性的servlet服务。触发事件的对象是所有可以转换为Object的实例。
HttpSessionBindingListener不用在web.xml中登记,在每个servlet中用new创建实例,且仅对本实例向session中的加入(或移出)感兴趣。触发事件的对象仅仅是自己。
HttpSessionListener
对于session的创建和取消感兴趣。需要在web.xml中登记。
共有两个方法:
void sessionCreated(HttpSessionEvent se);
void sessionDestroyed(HttpSessionEvent se);
使用它我们可以容易的创建一个类来对session计数。
也许我们会简单的考虑使用sessionDestroyed方法来在session结束后做一些清理工作。但是,请注意,当这个方法被调用的时候,session已经结束了,你不能从中提取到任何信息了。因此,我们要另辟蹊径。
一种通常采用的方法是使用HttpSessionBindingListener接口。在session创建时增加一个属性,而在session结束前最 后一件事将这个属性删除,这样就会触发valueUnbound方法,所有对session的清理工作可以在这个方法中实现。
HttpSessionActivationListener
当session在分布式环境中跨JVM时,实现该接口的对象得到通知。共两个方法:
void sessionDidActivate(HttpSessionEvent se);
void sessionWillPassivate(HttpSessionEvent se);
- 3. 处理session为空时的情况
1)做一个过滤器,实现Filter接口,对指定路径下的请求进行session的失效验证,如失效则跳转到登录页面:
public class LoginInterceptor implements HandlerInterceptor {
// 日志
protected Logger log = Logger.getLogger(getClass());
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle) throws Exception {
// 创建session
HttpSession session = request.getSession();
// 无需登录,允许访问的地址
String[] allowUrls = new String[] { "/vcode", "/static", "/sso", "/login" };
// 获取请求地址
String url = request.getRequestURL().toString();
// 获得session中的用户
TuUser tuUser = (TuUser) session.getAttribute("USER_INFO");
for (String strUrl : allowUrls) {
if (url.contains(strUrl)) {
return true;
}
}
if (null == tuUser) {
throw new UnLoginException("您尚未登录!");
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
2)在spring_mvc.xml中配置
<!-- 拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截全部地址 -->
<mvc:mapping path="/**" />
<!-- 登录拦截类 -->
<bean id="loginInterceptor"
class="com.ucfgroup.framework.web.app.Interceptor.LoginInterceptor">
</bean>
</mvc:interceptor>
</mvc:interceptors>
<!-- 异常 -->
<bean id="exceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!-- <登录失败异常类> -->
<prop key="com.ucfgroup.framework.utils.UnLoginException"> redirect:/login</prop>
</props>
</property>
</bean>
4. 销毁session
1) session.invalidate的销毁是把这个session所带的用户彻底的销毁;
2) session.removeAttribute("sessionUserName");移除用户,但session不变;
3) session超时,自动销毁session;
4) 用户点击退出按钮,销毁session;
Cookie介绍
Cookie是什么
Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式,由 Web 服务器保存在用户浏览器(客户端)上的小文本文件
Cookie的作用
服务器可以利用Cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。
工作原理:
Cookie定义了一些HTTP请求头和HTTP响应头,通过这些HTTP头信息使服务器可以与客户进行状态交互。
客户端请求服务器后,如果服务器需要记录用户状态,服务器会在响应信息中包含一个Set-Cookie的响应头,客户端会根据这个响应头存储Cookie信息。再次请求服务器时,客户端会在请求信息中包含一个Cookie请求头,而服务器会根据这个请求头进行用户身份、状态等较验。
下面是一个实现Cookie机制的,简单的HTTP请求过程:
特点:Cookie具有不可跨域名性。在客户端,一个浏览器能创建的 Cookie 数量最多为 300 个,并且每个不能超过 4KB,每个 Web 站点能设置的 Cookie 总数不能超过 20 个 。
如何用cookie
1)创建Cookie
// new一个Cookie对象,键值对为参数
Cookie cookie = new Cookie("key", "cookie的value值");
如果cookie的值中含有中文时,需要对cookie进行编码,不然会产生乱码,使用
URLEncoder.encode("cookie的value值","utf-8");
// 设置Cookie最大生存时间,以秒为单位,负数的话为浏览器进程,关闭浏览器Cookie消失
cookie.setMaxAge(*24*60*60); // 一天
// 将Cookie添加到Response中,使之生效
response.addCookie(cookie); //addCookie后,如果已经存在相同名字的cookie,则最新的覆盖旧的cookie
注意:在Struts中可以使用 ServletActionContext.getResponse()获得respone对象
2)读取cookie
读取Cookie只能从request中获取全部Cookie,然后循环迭代。
在Struts中可以使用 ServletActionContext.getRequest()获得request对象
// 从request中获取Cookie,拿到的是一个Cookie数组
Cookie[] cookies = request.getCookies();
// 然后迭代之
if (cookies != null && cookies.length > 0) { //如果没有设置过Cookie会返回null
for (Cookie cookie : cookies) {...}
}
3)删除cookie
删除Cookie的话,只需要将Cookie的生存期设为0即可
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
for (Cookie cookie : cookies) {
String name = cookie.getName();
// 找到需要删除的Cookie
if (name.compareTo("target-key") == 0) {
// 设置生存期为0
cookie.setMaxAge(0);
// 设回Response中生效
response.addCookie(cookie);
}
}
}
注意:
1)setPath默认值是根路径
2)domain默认为请求的地址,如网址为www.jb51.net/test/test.aspx,那么domain默认为www.jb51.net。
3)cookie分为会话cookie和持久化cookie。会话cookie不设置过期时间,生命期为浏览器会话期;一般不保存在硬盘上而是保存在内存里。持久化cookie把cookie固化在用户的计算机上,在指定的到期日期,cookie将从磁盘中删除。
Cookie和Session区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中