会话:用户打开一个浏览器,点击了很多超链接,访问了多个web资源,关闭浏览器,这个过程称之为会话(打开浏览器到关闭浏览器的过程)
有状态会话:
一个网站,如何证明访问过?
- 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了 这个就是cookie
- 服务器登记当前客户端访问过,下次来的时候直接进行匹配 这个就是session
cookie
客户端技术(响应,请求)
从请求中拿到cookie,服务器响应给客户端cookie
cookie是服务器通知客户端保存键值对的一种技术,客户端有了cookie后,每次请求都发送给服务器,每一个cookie 的大小不能超过4kb
常用方法
Cookie[] cookies = request.getCookies();//获得Cookie
cookie.getName();//获得cookie中的key
cookie.getValue();//获得cookie中的value
new Cookie("cookie的名称","cookie的值");//新建一个cookie 注意:这两个参数必须都是String类型
cookie.setMaxAge();//设置cookie的有效期 单位为秒
response.addcookie();//添加一个cookie并响应给客户端
cookie一般保存在本地的用户目录下appdata中
案例:保存用户访问上次访问的时间
package com.hty.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
//保存用户上次访问的时间
public class CookieDemo1Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//服务器告诉用户访问的时间,将这个时间进行封装
//解决中文乱码
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
//Cookie 服务器从客户端获取
Cookie[] cookies = request.getCookies();//返回数组说明 cookie可能返回多个
//判断cookie是存在
if(cookies!=null){
out.write("你上次访问的时间是:");
for(int i=0;i<cookies.length;++i){
Cookie cookie = cookies[i];
//获取cookie的名字
if(cookie.getName().equals("lastLoginTime")){
//获取cookie中的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
}else{
out.write("这是你第一次访问本站");
}
//服务器给客户端响应一个cookie 将本次访问的时间写入到cookie中
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
//给cookie设置有效时间 单位为 秒 此时的时间为一天
cookie.setMaxAge(24*60*60);
response.addCookie(cookie);
}
}
一个网站中cookie存在上限
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
- 浏览器的上限是300个cookie
- cookie的大小不能超过4kb
不设置有效期,关闭浏览器,cookie自动失效
设置有效期为0也可以实现自动删除
案例 中文乱码的解决方案
package com.hty.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
//中文数据的传递
public class CookieDemo2Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Cookie 服务器从客户端获取
Cookie[] cookies = request.getCookies();//返回数组说明 cookie可能返回多个
PrintWriter out = response.getWriter();
//判断cookie是存在
if(cookies!=null){
out.write("你上次访问的时间是:");
for(int i=0;i<cookies.length;++i){
Cookie cookie = cookies[i];
//获取cookie的名字
if(cookie.getName().equals("name")){
//获取cookie中的值
out.write(URLDecoder.decode(cookie.getValue(),"UTF-8"));
System.out.println(cookie.getValue());
}
}
}else{
out.write("这是你第一次访问本站");
}
//使用URLEncoder.encode()方法 这样可以让中文数据不乱码
Cookie cookie = new Cookie("name", URLEncoder.encode("你好","UTF-8"));
response.addCookie(cookie);
}
}
session
服务器技术,利用这个技术可以保存用户的会话信息
什么是session:
- 服务器会给每一个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
- 用户登录之后整个网站都可以访问—>保存用户信息;保存购物车信息
案例
package com.hty.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class SessionDemo1Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决乱码问题
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//得到session
HttpSession session = request.getSession();
//给session中存入信息
session.setAttribute("name","你好");//String Object
//获取session的id
String id = session.getId();
//判断是不是新的session
if(session.isNew()){
response.getWriter().write("session创建成功,id为"+id);
}else{
response.getWriter().write("session已经在服务器中存在了,id为"+id);
}
//Session创建的时候 将这个session值存入了Cookie
Cookie cookie = new Cookie("JSESSIONID",id);
response.addCookie(cookie);
}
}
package com.hty.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo2Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//取出SessionDemo1中的session
//解决乱码问题
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
HttpSession session = request.getSession();
String id = session.getId();
response.getWriter().write(id);
//首先需要访问SessionDemo1之后再访问2就可以得到name这个值
Object name = session.getAttribute("name");
System.out.println(String.valueOf(name));
}
}
session的销毁
package com.hty.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo3Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.removeAttribute("name");//除session中的某项属性
//手动注销session
session.invalidate();//销毁所有session
}
}
设置session失效时间 在web.xml中进行配置
<!--设置session默认失效时间-->
<session-config>
<!--15分钟后session失效 以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
Session和Cookie区别
- cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- session把用户的数据写到用户独占Session中,服务器端保存(保存重要信息,减少服务器资源浪费)
- session对象由服务器进行创建
Filter
用来过滤网站的数据
用途
- 处理中文乱码
- 登陆验证
在web服务器与servlet等资源之间交互的时候,需要使用过滤器来过滤掉不合理的请求
开发步骤
- 实现javax.servlet包下的Filter接口
- 重写方法
- 配置web.xml
package com.hty.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
//初始化 web服务器启动就已经初始化了,随时等待过滤对象出现
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化了");
}
//China : 链
/*
* 过滤中的代码,在过滤特定请求的时候都会执行(特定的请求就是在web.xml中配置的请求)
* */
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println("CharacterEncodingFilter执行前");
//需要使用filterChain这个对象执行doFilter这个方法才能让过滤器生效
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("CharacterEncodingFilter执行后");
}
//销毁 web服务器关闭的时候过滤器就会销毁
@Override
public void destroy() {
System.out.println("销毁了");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.hty.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
</web-app>
常见应用
实现权限拦截:用户登陆之后才能进入主页,用户注销之后就不能进入主页
- 用户登陆之后向Session中放入用户的数据
- 进入主页的时候要判断用户是否已经登陆
过滤器代码
package com.hty.filter;
import com.hty.util.Constant;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
Object user_session = request.getSession().getAttribute(Constant.USER_SESSION);
if(user_session != null){
response.sendRedirect("http://localhost:8080/filter_war_exploded/sys/success.jsp");
}else{
response.sendRedirect("http://localhost:8080/filter_war_exploded/login.jsp");
}
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
servlet代码
登陆
package com.hty.servlet;
import com.hty.util.Constant;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
if(username.equals("admin")){
//登陆成功
HttpSession session = request.getSession();
session.setAttribute(Constant.USER_SESSION,request.getSession().getId());
response.sendRedirect("http://localhost:8080/filter_war_exploded/sys/success.jsp");
}else{
response.sendRedirect("http://localhost:8080/filter_war_exploded/error.jsp");
}
}
}
注销
package com.hty.servlet;
import com.hty.util.Constant;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LogoutServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//注销的时候只需要将和这个session进行消除就可以了
Object user_session = request.getSession().getAttribute(Constant.USER_SESSION);
if(user_session != null){
request.getSession().removeAttribute(Constant.USER_SESSION);
response.sendRedirect("http://localhost:8080/filter_war_exploded/login.jsp");
}else{
response.sendRedirect("http://localhost:8080/filter_war_exploded/error.jsp");
}
}
}
常量类
package com.hty.util;
public class Constant {
public static String USER_SESSION = "USER_SESSION";
}
jsp页面
登陆页面
<%--
Created by IntelliJ IDEA.
User: 黄天佑
Date: 2022-02-16
Time: 15:24
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登陆</h1>
<form action="servlet/login" method="post">
<input type="text" name="username">
<input type="submit">
</form>
</body>
</html>
主页
<%--
Created by IntelliJ IDEA.
User: 黄天佑
Date: 2022-02-16
Time: 15:23
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
//最简单的过滤方法 但是应该使用过滤器来做
// Object user_session = request.getSession().getAttribute("USER_SESSION");
// if(user_session == null){
// response.sendRedirect("http://localhost:8080/filter_war_exploded/login.jsp");
// }
%>
<h1>主页</h1>
<a href="/filter_war_exploded/servlet/logout">注销</a>
</body>
</html>
错误页面
<%--
Created by IntelliJ IDEA.
User: 黄天佑
Date: 2022-02-16
Time: 15:30
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>错误</h1>
<h3>没有权限,用户名错误</h3>
<a href="http://localhost:8080/filter_war_exploded/login.jsp">返回登陆页面</a>
</body>
</html>
注:记得在web.xml中注册这个过滤器
Listener
实现一个监听器的接口
案例:统计在线人数
package com.hty.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
//统计在线人数 : 统计session的数量
public class OnlineCount implements HttpSessionListener {
//创建session监听 看你的一举一动
//一旦创建一个session就会触发一次这个事件
public void sessionCreated(HttpSessionEvent se){
ServletContext servletContext = se.getSession().getServletContext();
Integer onlinecount = (Integer)servletContext.getAttribute("onlinecount");
if(onlinecount == null){//说明还没有人访问过
onlinecount = new Integer(1);
}else{
onlinecount++;
}
servletContext.setAttribute("onlinecount",onlinecount);
}
//销毁session监听
//一旦Session销毁,就会触发一次这个事件
public void sessionDestroyed(HttpSessionEvent se){
ServletContext servletContext = se.getSession().getServletContext();
Integer onlinecount = (Integer)servletContext.getAttribute("onlinecount");
if(onlinecount == null){//说明还没有人访问过
onlinecount = new Integer(0);
}else{
onlinecount--;
}
servletContext.setAttribute("onlinecount",onlinecount);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--注册监听器-->
<listener>
<listener-class>com.hty.listener.OnlineCount</listener-class>
</listener>
</web-app>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>当前有<span><%=application.getAttribute("onlinecount")%></span>人在线</h1>
</body>
</html>