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一样存取数据的对象。
- 这里的域指的是存取数据的操作范围
-
存数据 取数据 删除数据 Map put() 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
- UnSafeContextServlet1:B
-
由此发现,在并发访问的时候,对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
- 在web中 / 斜杠是一种绝对路径
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:它主要实现监听ServletContext的创建和删除。该接口提供了两种方法
-
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对象
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
- expiry 指定 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工程的时候
- Filter的生命周期包含几个方法
-
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对象。
- FilterChain.doFilter()方法的作用
-
Filter的拦截路径
- –精确匹配
- /target.jsp
- 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp
- –目录匹配
- /admin/*
- 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/*
- –后缀名匹配
- *.html
- 以上配置的路径,表示请求地址必须以.html结尾才会拦截到
- *.do
- 以上配置的路径,表示请求地址必须以.do结尾才会拦截到
- *.action
- 以上配置的路径,表示请求地址必须以.action结尾
- Filter过滤器只关心请求的地址是否匹配,并不关心请求的资源是否存在
- –精确匹配