会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。
会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自同一浏览器,以便在同一次会话的多次请求间实现资源共享。
因为http协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求,因此我们需要会话跟踪技术来实现会话内资源共享。
实现方式:1、客户端会话跟踪技术:Cookie,把数据存放到客户度浏览器中。2、服务端会话跟踪技术:Session,把数据存放到服务端servlet中。
Cookie:客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问。
发送Cookie:
@WebServlet("/aServlet")
public class aServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//发送Cookie
String value="张三";
String encode = URLEncoder.encode(value,"UTF-8");
//1.创建Cookie对象
Cookie cookie=new Cookie("username",encode);
cookie.setMaxAge(60*60*24*7);
//2.发送Cookie
response.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
接收Cookie:
@WebServlet("/bServlet")
public class bServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取Cookie
//1.获取Cookie数组
Cookie[] cookies = request.getCookies();
//2.遍历数组
for (Cookie cookie : cookies) {
//3.获取数据
String name = cookie.getName();
if ("username".equals(name)) {
String value = cookie.getValue();
String decode = URLDecoder.decode(value);
System.out.println(name+":"+decode);
}
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
默认情况下Cookie存放在浏览器内存中,当浏览器关闭,内存释放,则Cookie释放。但我们可以设置Cookie存活时间,运用cookie.setMaxAge()方法,参数单位为秒。当传入参数为正数时,即为存入浏览器内存的时间,秒数。为负数时,默认值,Cookie在浏览器内存中,浏览器关闭时,则Cookie被销毁。为零时:删除对应的Cookie。
Session:服务端会话跟踪技术,将数据存放到服务端:
发送Session
@WebServlet("/Session1")
public class Session1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取Session
//1.创建Session
HttpSession session = request.getSession();
//2.存储数据
session.setAttribute("username","zs");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
接收Session:
@WebServlet("/Session2")
public class Session2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取Session数据
//1.获取Session对象
HttpSession session = request.getSession();
//销毁
//session.invalidate();//此时访问该网页,会报错
//2.获取数据
Object username = session.getAttribute("username");
System.out.println(username);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
Session是基于Cookie实现的,来保证同一个浏览器获取的Session是同一个Session。获取的Session有一个id属性,tomcat在浏览器做出响应的时候会自动把这个id属性当作一个Cookie发送给浏览器键值对为set-cookie:JSESSIONID=...,然后客户端就把这个浏览器在带着cookie头访问服务端来获取Session对象。
Session使用细节:
Session钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘文件中。
Session活化:再次启动浏览器后,会从文件中加载数据到Session中。这时硬盘中的文件已经消失了。
浏览器重启后,虽然数据未丢失,但因为浏览器被关闭了,所以重启浏览器获取的Session也不是原来那个了。
默认情况下,Session会30分钟后自动销毁。
Cookie和Session区别:
存储位置:Cookie是将数据存储在客户端,Session是将数据存储在服务端。
安全性:Cookie不安全,Session安全
数据大小:Cookie最大3KB,Session无大小限制。
存储时间:Cookie可以长期存储,Session默认30分钟。
服务器性能:Cookie不占服务器资源,Session占用服务器资源。
Filter,过滤器:是Javaweb三大组件(Servlet,Filter,Listener)之一。过滤器可以把对资源的请求拦截下来,从而实现一些特殊功能。过滤器一般实现比较通用的操作,比如:权限控制,统一编码处理,敏感字符处理等等。
Filter的定义:
1、定义类,实现filter接口,并重写所有方法。
2、配置Filter拦截资源路径,需要在类上定义注解@WebFilter()
3、在doFiler方法中输出一句话,并放行,只有执行了chain.doFilter方法才会 被放行。
写在放行代码前的代码为放行前代码,后面的为放行后代码。
注意:
1、放行后访问对应资源,资源访问完后还会回到Filter中。就是浏览器发送请求的时候会经过Filter,服务端做出响应的时候也会经过Filter。
2、浏览器发送请求经过Filter时,只执行放行前代码。响应时返回Filter中,Filter中的代码,会从放行代码开始只执行放行后代码,不会从头开始执行。
Filter拦截路径设置
1、拦截具体路径:具体资源路径
2、目录拦截:/目录/* 访问该目录下的所有资源都会被拦截
3、后缀名拦截:*.jsp 访问后缀名为jsp的资源都会被拦截
4、拦截所有: /* 所有资源都会被拦截。
@WebFilter("/*")
public class loginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
//0.判断访问是否是跟登陆有关的资源
//是的话放行,不是就拦截
String []urls={"/login.jsp","register.jsp","/loginServlet","/register.jsp","/register.html","/SelectUserServlet"};
//获取资源访问路径
String url = req.getRequestURI();
//循环判断
for (String u : urls) {
if (url.contains(u)){
filterChain.doFilter(servletRequest,servletResponse);
return;
}
}
}
@Override
public void destroy() {
}
}
其中一些网站不需要被拦截,我们需要把不需要被拦截的网站写入一个数组。然后获取请求的网址,若请求的网址存在于数组中就会被放行,放行后直接return,这样后面的代码哪怕是响应时跳回Filter中都不会在被执行。
过滤器链:一个web应用,可以配置多个过滤器,这个过滤器称为过滤器链
注解配置的多个Filter,优先级按照过滤器类名(字符串)的自然排序,就是从a到z,从0到9。依次访问拦截。