Java Web-Servlet的理解和使用以及相应的类Servlet类,Listener类,Filter类

Java Web

Servlet

什么是Servlet
  • Servlet是JavaEE规范之一。规范就是接口
  • Servlet就是javaWeb三大组件之一。三大组件分别是:Servlet程序,Filter过滤器,Listener监听器。
  • Servlet是运行在服务器上的一个java小程序,它可以接受客户端发送过来的其你去,并响应数据给客户端。
  • Servlet是Server和Applet的缩写,是服务端小程序的意思。使用Java语言编写的服务端程序,可以像生成动态动态的WEB页,Servlet主要运行在服务器端,并由服务器调用执行,是一种按照Servlet标准来开发的类。
Servlet的生命周期
  • 1.执行Servlet构造器方法

  • 2.执行init()初始化方法

    • 执行Servlet构造器和执行init()初始化方法,是在浏览器第一次访问的时候创建Servlet程序会调用的
    • 后续请求不会调用Servlet的构造器和init()方法
  • 3.执行service()方法

    • 每次访问都会调用Service方法
  • 4.执行destroy销毁方法

    • tomcat工程停止的时候会调用destroy方法
Servlet的GET和POST等请求的分发处理(自定义)
/**
 * service方法时专门用来处理请求和响应
 * @param req
 * @param res
 * @throws ServletException
 * @throws IOException
 */
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    HttpServletRequest httpServletRequest = (HttpServletRequest) req;
    if (httpServletRequest.getMethod().equals("GET")) {
        System.out.println("GET请求");
    }else if(httpServletRequest.getMethod().equals("POST")){
        System.out.println("POST请求");
    }
}
通过继承HttpServlet实现Servlet程序
  • 一般在实际项目开发中,都是使用继承HttpServlet类的方式实现Servlet程序。

  • 步骤

    • 1.编写一个类去继承HttpServlet类
    • 2.根据业务需要编写doGet或doPost方法
    • 3.到web.xml中配置Servlet程序的访问地址
  • 代码

    • /**
       * @author jiangl
       * @version 1.0
       * @date 2021/5/11 19:25
       */
      public class MyHttpServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              super.doGet(req, resp);
              System.out.println("MyHttpServlet-Get请求");
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              super.doPost(req, resp);
              System.out.println("MyHttpServlet-Post请求");
          }
      }
      
Servlet类的继承体系

在这里插入图片描述

ServletConfig类
  • ServletConfig类从类名上看,就知道是Servlet程序的配置信息类。

    • Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用。
    • ServletConfig的实现类是StandardWrapperFacade类
    • Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象
  • ServletConfig类的三大作用

    • 1.获取Servlet程序的别名servlet-name的值
    • 2.获取初始化参数init-param
    • 3.获取ServletContext对象
  • 代码

    • public class MyHttpServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              super.doGet(req, resp);
              //获取Servlet程序别名servlet-name的值
              System.out.println(this.getServletConfig().getServletName());
              //获取初始化参数init-param
              Enumeration<String> initParameterNames = this.getServletConfig().getInitParameterNames();
              while(initParameterNames.hasMoreElements()){
                  System.out.println(initParameterNames.nextElement());
              }
              System.out.println(this.getServletConfig().getInitParameter("username"));
              System.out.println(this.getServletConfig().getInitParameter("url"));
              //获取servletContext
              ServletContext servletContext = this.getServletConfig().getServletContext();
              System.out.println("MyHttpServlet-Get请求");
          }
      }
      
ServletContext类
  • 什么是ServletContext类

    • 1.ServletContext是一个接口,它表示Servlet上下文对象
    • 2.一个web工程,只有一个ServletContext对象实例。(实际返回的是ApplicationContextFacade类)
    • 3.ServletContext对象是一个域对象
    • 4.ServletContext对象是在web工程部署启动的时候创建。在web工程停止的时候销毁
  • ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。

  • 什么是域对象?

    • 域对象,是可以像Map一样存取数据的对象。
    • 这里的域指的是存取数据的操作范围
  • 存数据取数据删除数据
    Mapput()get()remove()
    域对象setAttribute()getAttribute()removeAttribute()
  • ServletContext类的四个作用

    • 1.获取web.xml中配置的上下文参数context-param
    • 2.获取当前的工程路径,格式:/工程路径
    • 3.获取工程部署后在服务器硬盘上的绝对路径
    • 4.像Map一样存取数据
  • ServletContext的线程安全问题

    • ServletContext是线程不安全的

    • 场景代码

      • public class UnSafeContextServlet1 extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                String servletName = "UnSafeContextServlet1:";
                this.getServletConfig().getServletContext().setAttribute("myName","B");
                this.getServletConfig().getServletContext().setAttribute("myName1","A");
                System.out.println(servletName+this.getServletConfig().getServletContext().getAttribute("myName"));
                try {
                    System.out.println(servletName+"睡眠");
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(servletName+"结束睡眠");
                System.out.println(servletName+this.getServletConfig().getServletContext().getAttribute("myName1"));
            }
        
            @Override
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
            }
        }
        
        public class UnSafeContextServlet2 extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                String servletName = "UnSafeContextServlet2:";
                this.getServletConfig().getServletContext().setAttribute("myName1","C");
                System.out.println(servletName+this.getServletConfig().getServletContext().getAttribute("myName"));
        
                System.out.println(servletName+this.getServletConfig().getServletContext().getAttribute("myName1"));
            }
        
            @Override
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
            }
        }
        
    • 通过先访问UnSafeContextServlet1,然后在五秒内访问UnSafeContextServlet2。得到的结果为:

      • UnSafeContextServlet1:B
        UnSafeContextServlet1:睡眠
        UnSafeContextServlet2:B
        UnSafeContextServlet2:C
        UnSafeContextServlet1:结束睡眠
        UnSafeContextServlet1:C
    • 由此发现,在并发访问的时候,对ServletContext内容的修改是线程不安全的。

    • 解决方案1

      • 使用synchronized(getContext()),通过加S锁来解决,但这样做性能较低(UnSafeContextServlet2会被阻塞等待获取锁)

        • @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              synchronized (this.getServletContext()) {
                  String servletName = "UnSafeContextServlet1:";
                  this.getServletConfig().getServletContext().setAttribute("myName", "B");
                  this.getServletConfig().getServletContext().setAttribute("myName1", "A");
                  System.out.println(servletName + this.getServletConfig().getServletContext().getAttribute("myName"));
                  try {
                      System.out.println(servletName + "睡眠");
                      Thread.sleep(5000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  System.out.println(servletName + "结束睡眠");
                  System.out.println(servletName + this.getServletConfig().getServletContext().getAttribute("myName1"));
              }
          }
          
          synchronized (this.getServletContext()){
                      String servletName = "UnSafeContextServlet2:";
                      this.getServletConfig().getServletContext().setAttribute("myName1","C");
                      System.out.println(servletName+this.getServletConfig().getServletContext().getAttribute("myName"));
          
                      System.out.println(servletName+this.getServletConfig().getServletContext().getAttribute("myName1"));
                  }
          
HttpServletRequest类
  • HttpServletRequest类有什么作用

    • 每次只要有请求进入tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中。
    • 然后传递到service()方法(doGet()和doPost())中给开发人员使用。
    • 可以通过HttpServletRequest对象获取到所有的请求信息
  • request请求的域对象,在同一次请求中的域对象是同一个。请求结束后,域对象被清除

  • HttpServletRequest类的常用方法

    • 方法名说明
      getRequestURI()获取请求的资源路径
      getRequestURL()获取请求的统一资源定位符(绝对路径)
      getRemotHost()获取客户端IP地址
      getHeader(String key)获取请求头
      getParameter(String key)获取请求参数
      getParameterValues(String key)获取请求参数(数组入参)
      getMethod()获取请求的方法
      setAttribute(key,value)设置请求的域数据
      getAttribute(key)获取请求的域数据
      getRequestDispatcher()获取请求转发对象
    • getRequestURI()

    • getRequestURL()

    • getRemoteHost()

    • getHeader()

    • getParameter()

    • getParameterValues()

    • getMethod()

    • setAttribute(key,value);

      • 底层是RequestFacade->Request
      • 在Request内部使用ConcurrentHashMap存储的域键值对
    • getAttribute(key);

    • getRequestDispatcher()

    • 代码

      • package com.jl.java.web.servlet; /**
         * @author jiangl
         * @date 2021/5/12 18:41
         * @version 1.0
         */
        
        import javax.servlet.*;
        import javax.servlet.http.*;
        import java.io.IOException;
        import java.util.Arrays;
        
        public class RequestTestServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                //获取请求的资源路径
                System.out.println("获取请求的资源路径:"+request.getRequestURI());
                //获取请求的统一资源定位符
                System.out.println("获取请求的统一资源定位符:"+request.getRequestURL());
                //获取客户端的ip
                System.out.println("获取客户端的ip:"+request.getRemoteHost());
                //获取请求头
                System.out.println("获取请求头:"+request.getHeader("Accept"));
                //获取请求参数
                System.out.println("获取请求参数:"+request.getParameter("name"));
                //获取请求参数 数组
                System.out.println("获取请求参数 数组:"+Arrays.toString(request.getParameterValues("id")));
                //获取请求的方法
                System.out.println(request.getMethod());
                //获取请求的域信息
                System.out.println("获取请求的域信息1:"+request.getAttribute("myname"));
                //设置请求的域信息
                request.setAttribute("myname","jl");
                //获取请求的域信息
                System.out.println("获取请求的域信息2:"+request.getAttribute("myname"));
        
            }
        
            @Override
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
            }
        }
        
  • 如何获取请求参数

    • url:http://localhost:8080/my_java_web/requestTestServlet?name=dfafas&&id=123&&id=123777

    • 通过request.getParameter(String key)方法获取

    • 如果参数有多个值时,通过使用request.getParameterValues(String key)获取

    • 代码

      • //获取请求参数
        System.out.println("获取请求参数:"+request.getParameter("name"));
        //获取请求参数 数组
        System.out.println("获取请求参数 数组:"+Arrays.toString(request.getParameterValues("id")));
        
  • post请求中的中文乱码解决

    • 通过调用request.setCharacterEncoding(“UTF-8”)设置请求体的字符集从而解决中文乱码问题

    • @Override
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          request.setCharacterEncoding("UTF-8");
          System.out.println(request.getParameter("username"));
      }
      
  • 请求的转发
    • 什么是请求的转发?

      • 请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作。
      • 无论转发了几次,都是一次请求
      • 在这里插入图片描述
    • 代码

      • //请求转发必须要以斜杠大头,斜杠表示地址为:http://ip:port/工程名/ 映射到代码的web目录
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/myHttpServlet2");
        //转发
        requestDispatcher.forward(request,response);
        
    • 转发后,在servlet2程序中可以获取到请求入参和request的域信息

    • 转发的特点

      • 浏览器的地址栏没有变化
      • 转发是一次请求
      • 转发共享request的域中的数据
      • 可以转发到WEB-INF目录下(浏览器不能访问web-inf下的目录)
      • 转发不能访问外部工程的资源
  • Web中的相对路径和绝对路径

    • 相对路径是:
      • . 表示当前目录
      • … 表示上一级目录
      • 资源面:表示当前目录/资源猫
    • 绝对路径
      • http://ip:port/工程路径/资源路径
  • Web中 / 斜杠的不用意义

    • 在web中 / 斜杠是一种绝对路径
      • / 斜杠如果被浏览器解析,得到是http://ip:port/
      • /斜杠如果被服务器解析,得到是http://ip:port/工程名路径
        • /servlet1
        • servletContext.getRealPath("/")
        • request.getRequestDispatcher("/")
      • 特殊情况
        • response.sendDirect("/") :把斜杠发送给浏览器解析。得到http://ip:port
HttpServletResponse类
  • HttpServletResponse类的作用

    • HttpServletResponse类和HttpServletRequest类一样。每次请求,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用。HttpServletResponse类表示所有响应的信息。
    • 如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置
  • HttpServletResponse类下的两个输出流的说明

    • 字节输出流OutputStream getOutputStream() 常用于下载(传递二进制数据)
    • 字符流Writer getWriter() 常用语回传字符串(常用)
    • 两个流同时只能使用一个,使用了字节流,就不能在使用字符流,反之亦然,否则就会报错。
  • 代码

    • package com.jl.java.web.servlet; /**
       * @author jiangl
       * @date 2021/5/12 20:04
       * @version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.IOException;
      
      public class ResponseTestServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              response.setCharacterEncoding("UTF-8");
              //setContentType()方法会同时设置服务器和客户端的字符集,还设置了响应头
              //此方法必须在获取流之前使用才有效
              response.setContentType("text/html;charset=utf-8");
              response.getWriter().write("你好");
          }
      
          /**
           * 读取配置文件web.xml
           * @param response
           * @throws IOException
           */
          private void responseWebXml(HttpServletResponse response) throws IOException {
              response.setCharacterEncoding("UTF-8");
              FileInputStream fileInputStream = new FileInputStream(
                      new File("D:\\personal\\ideaWorkspace\\Java-Web\\java-web-01-servlet\\src\\main\\webapp\\WEB-INF\\web.xml"));
              ServletOutputStream outputStream = response.getOutputStream();
              byte[] buffer = new byte[1024];
              int length;
              while((length = fileInputStream.read(buffer))!=-1){
                  outputStream.write(buffer,0,length);
              }
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
          }
      }
      
  • 请求重定向

    • 请求重定向,是指客户端给服务器发送请求,然后服务器提供给客户端一个新的地址,让客户端重新请求(因为之前的地址可能已经被废弃)
    • 请求重定向的特点
      • 1.浏览器地址栏会发生变化
      • 2.两次请求
      • 3.不共享request请求域信息
      • 4.不能访问WEB-INF目录下的资源
    • 在这里插入图片描述
  • 代码

    • package com.jl.java.web.servlet; /**
       * @author jiangl
       * @date 2021/5/12 20:04
       * @version 1.0
       */
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.IOException;
      
      public class ResponseTestServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //请求重定向方式一
              response.setStatus(302);
              response.setHeader("Location","http://www.baidu.com");
              //请求重定向 方式二
              response.sendRedirect("http://www.baidu.com");
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
          }
      }
      
请求的转发与重定向的对比
  • 转发是在服务器内部发生的,重定向是客户端重新发起的
  • 转发是一起请求,重定向是多次请求
  • 转发的参数和请求域信息是共享的,重定向由于是不同的请求所以参数和请求域信息不是共享的
  • 转发的速度快,重定向的速度慢(因为转发不用返回到客户端,重定向需要客户端重新发起,需要重新建立连接)
  • 转发的操作在浏览器的地址栏是不变的,重定向的操作在浏览器的地址是会改变的,改变成新的url
  • 转发的操作访问的只能是同一个工程下的资源,重定向可以访问不同工程下的资源
  • 转发不会执行转发操作后面的代码,重定向会执行重定向后的代码
EventListener监听器
  • 什么是Listener监听器

    • Listener监听器是JavaWeb三大组件之一。JavaWeb的三大组件分别是:Servlet程序,Filter过滤器,Listener监听器
    • Listener是JavaEE的规范,就是接口
    • 监听器的作用是,监听某种事物的变化。然后通过回调函数,反馈给客户(程序)去做一些响应的处理
  • servlet3.0为我们提供了8个监听器接口,按照它们的作用域来划分的话可以分为三类:

    • 1.servlet上下文相关监听接口,包括:ServletContextListener和ServletContextAttributeListener。
    • 2.http session相关监听接口,包括:HttpSessionListener、HttpSessionActivationListener、HttpSessionAttributeListener和HttpSessionBindingListener。
    • 3.servlet request相关监听接口,包括:ServletRequestListener和ServletRequestAttributeListener。
    • 详细说明
      • ServletContextListener:它主要实现监听ServletContext的创建和删除。该接口提供了两种方法
        • 1.contextInitialized(ServletContextEvent event):通知正在监听的对象ServletContext,应用程序已经被加载和初始化。
        • 2.contextDestroyed(ServletCotextEvent event):通知正在监听的对象ServletContext,应用程序已经被载出,即关闭。
      • ServletAttributeListener:主要实现监听ServletContext属性的增加,删除和修改。该接口提供了一下3个方法
        • 1.attributeAdded(ServletContextAttributeEvent event); 当有对象加入Application的范围时,通知正在收听的对象
        • 2.attributeReplaced(ServletContextAttributeEvent event); 当在application的范围有对象取代另一个对象的时,通知正在收听的对象
        • 3.attributeRemoved(ServletContextAttributeEvent event); 当有对象从application的范围移除时,通知正在收听的对象
      • HttpSessionListener:HTTP会话监听,该接口实现监听HTTP会话创建、销毁。该接口提供了一下两种方法
        • 1.sessionCreated(HttpSessionEvent event):通知正在收听的对象,session已经被加载及初始化
        • 2.sessionDestoryed(HttpSessionEvent event): 通知正在收听的对象,session已经被载出(HttpSessionEvent类的主要方法是getSession(),可以使用该方法回传一个session对象)
      • HttpSessionActivationListener:该接口实现监听HTTP会话active和passivate。 该接口提供了一下3个方法
        • 1.attributeAdded(HttpSessionBindingEvent event):当有对象加入session的范围时,通知正在收听的对象
        • 2.attributeReplaced(HttpSessionBindingEvent event): 当在session的范围有对象取代另一个对象时,通知正在收听的对象。
        • 3.attributeRemoved(HttpSessionBindingEvent event):当有对象从session的范围有对象取代另一个对象时,通知正在收听的对象 其中HttpSessionBindingEvent类主要有三个方法:getName()、getSession()和getValue()
      • HttpBindingListener:接口实现监听HTTP会话中对象的绑定信息。它是唯一不需要在web.xml中设定Listener的。该接口提供了以下2个方法
        • 1.valueBound(HttpSessionBindingEvent event):当有对象加入session的范围时会被自动调用
        • 2.valueUnBound(HttpSessionBindingEvent event):当有对象从session的范围内移除时会被自动调用
      • HttpSessionAttributeListener:该接口实现监听HTTP会话中属性的设置请求。该接口提供了以下两个方法。
        • 1.sessionDidActivate(HttpSessionEvent event):通知正在收听的对象,它的session已经变为有效状态。
        • 2.sessionWillPassivate(HttpSessionEvent event):通知正在收听的对象,它的session已经变为无效状态
      • ServletRequestListener:该接口实现监听ServletRequest的加载和销毁,该接口提供了以下两个方法。
        • 1.requestInitalized(ServletRequestEvent event) :通知正在收听的对象,ServletRequest已经被加载及初始化
        • 2.requestDestroyed(ServletRequestEvent event) :通知正在收听的对象,ServletRequest已经被载出,即关闭
      • ServletRequestAttributeListener:该接口实现监听Request域新的添加和删除,该接口提供了一下三种方法
        • 1.attributeAdded(ServletRequestAttributeEvent event); 当有对象加入request的范围时,通知正在收听的对象
        • 2.attributeReplaced(ServletRequestAttributeEvent event); 当在request的范围内有对象取代两一个对象时,通知正在收听的对象
        • 3.attributeRemoved(ServletRequestAttributeEvent event); 当有对象从request的范围移除时,通知正在收听的对
  • ServletContextListener监听器

    • ServletContextListener可以监听ServletContext对象的创建和销毁

    • ServletContext对象在web工程启动的时候创建,在web工程停止的时候销毁

    • 监听到创建和销毁之后都会分别调用ServletContextListener监听器的方法返回

      • public interface ServletContextListener extends EventListener {
        
            default public void contextInitialized(ServletContextEvent sce) {}
        
        
            default public void contextDestroyed(ServletContextEvent sce) {}
        }
        
    • ServletContextListener监听器的使用步骤

      • 编写一个类去实现ServletContextListener接口
      • 实现ServletContextListener接口下的两个方法contextInitialized()和contextDestroyed()
      • 到web.xml中配置监听器
Cookie
什么是Cookie
  • Cookie是服务器通知客户端保存键值对的一种技术。
  • 客户端有了Cookie之后,后续的每次请求都将Cookie发送回服务器
  • 每个Cookie的大小不能超过4kb
  • Cookie是Servlet发送到浏览器的少量信息,这些信息由浏览器保存后,然后再发送回服务器。Cookie的值可以唯一的标识客户端,因此Cookie常用于回话管理。
  • 一个Cookie拥有一个名称,一个值和一些可选用属性,比如注释、路径和域限定符、最大生存时间和版本号。
  • servlet通过使用HttpServletResponse.addCookie方法将cookie发送到客户端
  • 浏览器应该支持每台Web服务器有20个Cookie,总共有300个Cookie,并且可能将每个Cookie的大小限定为4KB
如何创建Cookie
  • 通过调用HttpServletResponse.addCookie()方法创建Cookie
  • Cookie的创建可以多个
  • 步骤
    • 创建Cookie对象
      • new Cookie(“key”,“value”);
    • 通知客户端保存Cookie
      • response.addCookie(cookie);
  • 在这里插入图片描述
Cookie的作用
  • 原因
    • Http协议是无状态的,也就导致服务器无法分辨是谁浏览了网页。为了维护用户在网站的状态,比如登录、购物车等,出现了四种技术,分别是隐藏表单域,URL重写、cookie、session
  • Cookie解决Http无状态
    • 为了解决Http协议无法维持状态的问题,1994年网景通讯的一名员工 Lou Montulli将 “magic cookies” 的概念应用到 Web 通讯中。他试图解决 Web 的第一个购物车应用,现在购物车成了购物网站的支柱。他的原始说明文档提供了 cookie 工作原理的基本信息,该文档后来被作为规范纳入到 RFC 2109(大多数浏览器的实现参考文档)中,最终被纳入到 RFC 2965 中。Montulli 也被授予 cookie 的美国专利。网景浏览器在它的第一个版本中就开始支持 cookie,现在所有 Web 浏览器都支持 cookie。(这里只介绍cookie与session)
如何获取Cookie
  • 服务器获取客户端的Cookie方式

    • HttpServletRequest.getCookies()

    • Cookie类没有重写ToString()方法

    • 代码

      • public class MyCookieServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                Cookie[] cookies = request.getCookies();
                System.out.println(Arrays.toString(cookies));
            }
        
            @Override
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
            }
        }
        
Cookie值的修改
  • 方案一(此操作核心是使用name相同的Cookie在浏览器中会覆盖旧值)
    • 1.先创建一个要修改的同名的Cookie对象
    • 2.在构造器,同时赋予新的Cookie的值
    • 3.调用response.addCookie(cookie)
  • 方案二
    • 1.先查找需要修改的Cookie对象
    • 2.调用setValue()方法赋予新的Cookie的值
    • 3.调用response.addCookie()通知用户
Cookie生命周期
  • Cookie的生命控制指的是如何管理Cookie什么时候被销毁(删除)
    • 如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。
    • 使用的是Cookie.setMaxAge(int expiry)
    • 正值表示 cookie 将在经过该值表示的秒数后过期。注意,该值是 cookie 过期的最大 生存时间,不是 cookie 的当前生存时间。
    • 负值意味着 cookie 不会被持久存储,将在 Web 浏览器退出时删除。0 值会导致删除 cookie。
      • expiry 指定 cookie 的最大生存时间(以秒为单位)的整数;
        • 如果为负数,代表关闭当前浏览器即失效。
        • 如果为 0,会马上在浏览器上删除指定的cookie
Cookie有效路径Path的设置
  • Cookie的Path属性可以有效的过滤哪些Cookie可以发送给服务器,哪些不发。

  • path属性是通过请求的地址来进行有效的过滤

  • 代码

    • protected void cookiePath(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          Cookie cookie = new Cookie("Cookie", "Cookie");
          cookie.setPath(request.getContextPath()+"/path");
          response.addCookie(cookie);
          Cookie cookie2 = new Cookie("Cookie2", "Cookie2");
          response.addCookie(cookie2);
      }
      
Session
什么是Session会话
  • Session就是一个接口(HttpSession)。
  • Session就是会话。它是用来维护一个客户端和服务器之间关联的一种技术
  • 每个客户端都有自己的一个Session会话
  • Session会话中,通常用来保存用户登录之后的信息
  • session的作用和cookie差不多,也是用来解决Http协议不能维持状态的问题。但是session只存储在服务器端的,不会在网络中进行传输,所以较cookie来说,session相对安全一些。但是session是依赖cookie的,当用户访问某一站点时,服务器会为这个用户产生唯一的session_id,并把这个session_id以cookie的形式发送到客户端,以后的客户端的所有请求都会自动携带这个cookie(前提是浏览器支持并且没有禁用cookie)。
如何创建Session和获取(id号,是否为新)
  • 如何创建和获取Session

    • 通过HttpServletRequest.getSession()

      • 第一调用是,创建Session会话
      • 之后调用;获取前面创建好的Session会话对象
    • 通过isNew():判断到底是否是新创建的Session对象

      • true:新创建
      • false:表示之前就创建好的
    • 每个Session都有一个唯一的SessionID

    • 通过HttpSession.getId()获取唯一的Id值

    • 代码

      • public class MySessionServlet extends BaseServlet {
        
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                //创建或获取Session
                HttpSession session = req.getSession();
                //获取Session的唯一标识ID
                System.out.println(session.getId());
                //判断Session是否是新创建的
                System.out.println(session.isNew());
            }
        }
        
Session域数据的存取
  • 通过调用HttpSession.setAttribute(String key1,String value)方法来设置Session的域数据

  • 通过调用HttpSession.getAttribute(String key)方法来获取Session中的指定的域信息

  • 代码

    • protected void sessionAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //创建或获取Session
          HttpSession session = req.getSession();
          //设置Session的域信息
          session.setAttribute("myName","nihao");
          //获取Session的域信息
          session.getAttribute("myName");
      }
      
Session生命周期控制
  • 通过调用HttpSession.setMaxIncativeInterval(int interval)方法设置Session的超时时间(以秒为单位),超过指定的时长,Session就会被销毁

    • Session默认的超时时间为30分钟
    • Tomcat 中 Session 的默认失效时间为 30 分钟。
  • 通过调用HttpSession.getMaxInactiveInterval() 获取Session的超时时间

  • 在Tomcat服务器的配置文件web.xml中默认有配置,这个配置表示当前tomcat服务器下所有的Session超时配置默认时长是30分钟

    • <session-config>
          <session-timeout>30</session-timeout>
      </session-config>
      
浏览器和Session之间的关联
  • 1.客户端第一发送请求的时候不带Cookie,不带Session
  • 2.服务器接收到第一次请求后调用request.getSession()方法,创建session,在创建httpSession对象的同时,也会创建一个Cookie对象
    • 这个Cookie对象的key永远是JSESSIONID
    • 这个Cookie对象的值是新创建出来的Session的id值。
  • 服务器通过响应把新创建的Session的id值方式Cookie中返回给客户端
  • 客户端接收到到服务器的响应获取Cookie 中的JSESSIONID,获取到Session的id
  • 后续客户端发送的请求都会带上Cookie-JSESSIONID,发送给服务器
  • 服务器接收到session的id就可以获取session,不再新创建session对象
  • 在这里插入图片描述
Session和Cookie的对比
  • Session是存在服务器的,Cookie是存在浏览器的
  • Cookie不是很安全,
  • Session存在服务器上的文件中,如果会话很多是,会占用服务器资源
  • 单个Cookie一般不能超过4kb,很多浏览器限制一个站点最多保存20个Cookie
  • Session依赖于Cookie中的SessionId,如果禁用了SessionId,可以通过在参数中添加sessionId作为替代方案
Filter过滤器
  • Filter什么是过滤器

    • Filter过滤器是Java web三大组件之一。三大组件分别是:Servlet程序。Listener监听器,Filter过滤器
    • Filter过滤器它是Java EE的规范,Filter是接口
    • Filter过滤器的作用是拦截请求,过滤响应。
      • 拦截请求常见的应用场景有
        • 权限检查
        • 日记操作
        • 事务管理
  • Filter的基本使用

    • Filter过滤器的使用步骤

      • 编写一个类实现Filter接口
      • 实现过滤方法doFilter()
      • 在web.xml中配置Filter的拦截路径
    • 示例:

      • 需求在web工程下,有一个admin目录,这个admin目录下的所有资源都必须是用户登录之后才允许访问

      • 创建一个MyFilter类实现Filter接口

      • 重写init(),destroy(),dofilter()方法

      • 在web.xml文件中配置 和

      • 代码

        • package com.jl.java.web.filter; /**
           * @author jiangl
           * @date 2021/5/13 17:29
           * @version 1.0
           */
          
          import javax.servlet.*;
          import javax.servlet.http.HttpFilter;
          import java.io.IOException;
          
          public class MyFilter extends HttpFilter {
              @Override
              public void init(FilterConfig config) throws ServletException {
                  System.out.println("MyFilter init");
          
              }
          
              @Override
              public void destroy() {
              }
          
              @Override
              public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
                  String aa = request.getParameter("aa");
                  if(aa == null){
          
                      response.setContentType("UTF-8");
                      response.getWriter().write("失败!");
                      return;
                  }
                  chain.doFilter(request, response);
              }
          }
          
           <filter>
                  <filter-name>MyFilter</filter-name>
                  <filter-class>com.jl.java.web.filter.MyFilter</filter-class>
              </filter>
              <filter-mapping>
                  <filter-name>MyFilter</filter-name>
                  <!--url-pattern配置拦截路径
                      / 表示请求地址为:http://ip:port/工程路径 映射到IDEA的web目录
                  -->
                  <url-pattern>/admin/*</url-pattern>
              </filter-mapping>
          
  • Filter的生命周期

    • Filter的生命周期包含几个方法
      • 构造器方法
      • init初始化方法
        • 第一,二步,在web工程启动的时候执行(Filter已经创建)
      • doFilter方法
        • 每次拦截到请求,就会执行
      • destroy销毁方法
        • 停止web工程的时候
  • FilterConfig类

    • FilterConfig类是,Filter过滤器的配置文件类
    • Tomcat每次创建Filter的时候,会同时创建一个FilterConfig类,这里包含了Filter配置文件的配置信息。
    • FilterConfig类的作用是获取filer过滤器的配置内容
      • 获取Filter的名称filer-name的内容
      • 获取Filter中配置的init-param初始化参数
      • 获取ServletContext对象
  • FilterChain过滤器链

    • FilterChain.doFilter()方法的作用
      • 执行下一个Filter过滤器(如果存在下一个过滤器)
      • 执行目标资源(没有下一个过滤器)
    • 在多个Filter过滤器执行的时候,它们的执行优先顺序是由他们在wen.xml中从上到小的配置顺序决定的
    • 多个Filter过滤器执行的特点
      • 所有Filter和目标资源默认都执行同一个线程中
      • 多个Filter共同执行的时候,它们都使用同一个Request对象。
  • Filter的拦截路径

    • –精确匹配
      • /target.jsp
      • 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp
    • –目录匹配
      • /admin/*
      • 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/*
    • –后缀名匹配
      • *.html
      • 以上配置的路径,表示请求地址必须以.html结尾才会拦截到
      • *.do
      • 以上配置的路径,表示请求地址必须以.do结尾才会拦截到
      • *.action
      • 以上配置的路径,表示请求地址必须以.action结尾
    • Filter过滤器只关心请求的地址是否匹配,并不关心请求的资源是否存在
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值