Filter 处理 request 和 response
背景:在 Filter 根据请求参数,判断用户登陆是否有效。后来是想就请求参数和返回值之间的关系做一个缓存。至于为什么不用 Spring … 因为公司不用。所以项目都是 Servlet + Filter …
-
session:
关于这个,有必要提一下:所谓的 session 失效是在一定时间内没有 session 活动,然后 session 失效。浏览器的 Cookie 中 JSESSIONID 就是保存当前会话的 sessionId, 每一次浏览器请求服务器时,服务器根据 JSESSIONID 中的值来查找当前有效的 session,若存在则把上下文切换到该 session,否则创建一个新的 session 并生产一个新的 sessionId。 -
登陆 PC
PC 成功登陆的时候记录当前的账户 Id 和 sessionId,sessionId 为 key;并会根据账户 Id 清除此前已经记录的 sessionId 。在 Filter 中根据当前的 sessionId 去查找记录的账户 Id,如果找不到或者找到的与当前发起请求的 账户 Id 不匹配,则判断用户需要登陆。(虽然有点儿 low 但貌似也保证了只能在一个浏览器登陆) -
移动终端
思路具是一样的,在成功登陆之后会把当前的 sessionId 返回给移动端。然后每次请求的时候把 获取到的 sessionId 加入 header 中,并把获取到的 sessionId 加入传入参数中(个人觉得没必要加入参数中,服务端可以通过读取 cookie 来获取移动端传入的 sessionId)。然后通过比较 参数中的 sessionId 和 服务器中的 sessionId 来判断是否登陆超时。 -
缓存
这个预想是根据 request 中的参数和请求的方法,来缓存一部分数据。这样就没必要每次去查数据库了。
问题
- 毫无疑问是流,因为流在被读了一次之后第二次就不能读了
-
request:
需要包装一下:下面的类,把流信息读取后存入 byte 数组,然后重写了getInputStream
方法,当获取流的时候就读取 byte 数组的数据。// 略 BodyReaderHttpServletRequestWrapper requestWrapper = new BodyReaderHttpServletRequestWrapper(hrequest); // 略
然后通过
chain.doFilter(requestWrapper, response);
调用就不会存在重复读流的问题。// BodyReaderHttpServletRequestWrapper.java public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper{ private byte[] body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); InputStream is = request.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte buff[] = new byte[ 1024