1.问题发现:
最近开始为项目中类似QQ聊天功能模块做准备,实现多用户在线聊天等功能就需要多个用户来访问服务器,今天突然想到,我是把登录用户信息放到session中的,那我如果多用户访问,那岂不是前一个用户的信息会被后一个用户所顶替调,毕竟都存在了session中,主要是key都是叫“user”。我还上网查了相关的问题:
我试了一下,在同一个浏览器打开,的确信息只能是最后登录的一个用户的信息,前一个的用户登录信息总是被后一个所顶掉。然后我就看评论中说把session的key改成动态的,然后我也试了一下,我改成了:“user”+此时登录的用户id,后台改这个部分还是很好的改的。但是前段获取这个对应的session就让我犯难了:
静态的session获取可以这样写,那换做动态的,这部分我该怎么写呢?技术还是有点差,我也查了一下这个问题,奈何很少有相关的资料,我之后再找找吧…继续说正题,还有一条评论这样说的,引起了我的注意:
他这里说的两个唯一让我很疑惑,回想起之前学servlet的域对象到现在也挺久了,好多都忘了,现在趁着遇到这部分问题,就再回去总结一下这部分内容,温故知新,系统总结一下。
首先什么是域对象,域对象是一个有作用范围的对象,可以在范围内共享数据。
2.Request:
1.什么是request和response
request和response对象是由服务器创建,提供给我们使用的。request对象是用来获取请求消息,response对象是来设置响应消息。
2.request对象继承体系
request类实现了HttpServletRequest接口,而后者由继承了ServletRequest接口。
3.request对象功能
1.获取请求消息数据
1. 获取请求行数据
先看浏览器F12里面关于访问项目路径的一些信息:
针对于Get方法请求的路径:http://localhost:8080/manager/profilePage?id=2
我们可以通过request中的方法获取上述对应的信息:
- 获取请求方式 :GET
* String getMethod() - 获取虚拟目录: /manager
* String getContextPath() - 获取Servlet路径: /profilePage
* String getServletPath() - 获取get方式请求参数:id=2
* String getQueryString() - 获取请求URI:/manager/profilePage
* String getRequestURI(): /manager/profilePage
* StringBuffer getRequestURL() :http://localhost/manager/profilePage
* URL:统一资源定位符 : http://localhost/manager/profilePage
* URI:统一资源标识符 : /manager/profilePage - 获取客户机的IP地址:
* String getRemoteAddr()
2. 获取请求参数
-
- String getParameter(String name):根据参数名称获取参数值 username=lc&password=123
-
- String[] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=sleep&hobby=game
-
- Enumeration getParameterNames():获取所有请求的参数名称
-
- Map<String,String[]> getParameterMap():获取所有参数的map集合
3. 共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据,注意,转发时可以共享这个request,因为转发就是一次请求,而重定向是两次请求,所以是两个不同的request。
我们可以通过以下方法来实现数据共享:
-
- void setAttribute(String name,Object obj):存储数据
-
- Object getAttitude(String name):通过键获取值
-
- void removeAttribute(String name):通过键移除键值对
4.会话技术
一次会话包含多次请求与响应,我们怎么判定是一次会话呢?浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止,这就是一次会话。而我们这个项目中,当用户登陆以后,信息将被存到session中,那么在整个这次会话中,用户信息是都可以在多次请求中共享的,除非关闭浏览器或者关闭服务器。自动登陆模块用到的cookie,其实也是属于会话,只不过它是在客户端使用的会话技术,或者说浏览器,它将数据保存在客户端,而session属于服务器端的会话技术,将数据保存在服务器端的对象中。
4.1 cookie
-
- 创建Cookie对象,绑定数据
* new Cookie(String name, String value)
- 创建Cookie对象,绑定数据
-
- 发送Cookie对象
* response.addCookie(Cookie cookie)
- 发送Cookie对象
-
- 获取Cookie,拿到数据
* Cookie[] request.getCookies()
- 获取Cookie,拿到数据
-
- Cookie的特点和作用
a. cookie存储数据在客户端浏览器
b. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
- Cookie的特点和作用
4.2 session
-
- 获取HttpSession对象:
HttpSession session = request.getSession();
- 获取HttpSession对象:
-
- 使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
- 使用HttpSession对象:
注意:Session的实现是依赖于Cookie的。Session被创建后,同时还会有一个名为JSESSIONID的Cookie被创建。这个Cookie的默认时效就是当前会话。Session被创建后,对应的Cookie被保存到浏览器中,之后浏览器每次访问项目时都会携带该Cookie。当我们再次调用时会根据该JSESSIONID获取已经存在的Cookie,而不是在创建一个新的Cookie。如果Cookie中有JSESSIONID,但是JSESSIONID没有对应的Session存在,则会重新创建一个HttpSession对象,并重新设置JSESSIONID。
我们上面提到过,一次会话的结束是以客户端或者服务器端关闭而定义的。所以,当一方关闭以后,再次开启时,两次session不是同一个,这也是我们为什么当关闭浏览器后,再打开访问我们的项目时,需要重新登录,因为上一次存在session中的用户信息已经没有了,新创建的session中没有用户信息。当然,如果想要两次session是同一以session的话,我们可以通过其他方法实现,这里就不在延伸了。
那session什么时候会被销毁呢?有三种方式,第一种是关闭服务器,第二种是调用session对象的invalidate()方法来实现销毁,第三种时设置自动失效时间,默认是30分钟,即30分钟后,该session将被销毁。
- session与Cookie的区别:
1. session存储数据在服务器端,Cookie在客户端
2. session没有数据大小限制,Cookie有
3. session数据安全,Cookie相对于不安全
Session的活化和钝化
- 当访问应用的用户很多时,服务器上就会创建非常多的Session对象,如果不对这些Session对象进行处理,那么在Session失效之前,这些Session一直都会在服务器的内存中存在。这样是对内存不太友好的,所以就出现了Session活化和钝化的机制。
- Session钝化:Session在一段时间内没有被使用时,会将当前存在的Session对象序列化到磁盘上,而不再占用内存空间。
- Session活化:Session被钝化后,服务器再次调用Session对象时,将Session对象由磁盘中加载到内存中使用。
- 如果希望Session域中的对象也能够随Session钝化过程一起序列化到磁盘上,则对象的实现类也必须实现java.io.Serializable接口。不仅如此,如果对象中还包含其他对象的引用,则被关联的对象也必须支持序列化,否则会抛出异常:java.io.NotSerializableException
5.Application(ServletContext)
Web容器在启动时,它会为每个Web应用程序都创建一个对应的ServletContext对象,它代表当前Web应用——公司法人(所以它是单例的),在服务器关闭时销毁。由于一个Web应用程序中的所有Servlet都共享同一个ServletContext对象,所有的客户端在访问服务器时都共享同一个ServletContext对象,ServletContext对象一般用于在多个客户端间共享数据时使用。
回到这个项目上,我把用户信息放到session中,所以在同一个浏览器中,我先后登录两个用户,那么前一个用户信息总会被后一个信息所顶掉,而新打开另一个浏览器再登陆一个用户,则不会出现上述问题,两个用户信息会同时存在,因为这时我们创建的是两个session中,虽然key都叫“user”。但是如果我们将用户信息放在Application中,那么不管你换什么浏览器登录用户,前一个用户信息都将被后一个顶掉,毕竟服务器只有一个,所以Application只有那一个…
ps
以上便是我结合之前学习的笔记和网上一些资料总结的相关知识