session和过滤器
回顾
1.无查询分页,pageIndex,pageSize,pageMax,==>分页语句的算法2.模糊查询分页a.刚进入页面应该就是一个模糊查询,“%%”b.查询条件的保存,分页插件传值时记得传查询条件拓展:在传值时,出现类参数太多的问题?形参太多?放到request域中的值太多了?封装===》pageBean==>javaBean3.http请求的无状态性4.解决无状态性的方案:将状态保持在客户端(cookie),或者将状态保存在服务器(session)5.cookie的工作原理:自动发送原则,cookie是根据url来匹配路径,自动发送6.cookie的简单用法,怎么存?response中add进去,怎么取?requset去取,有效时间:默认值-1网络编程里面叫做URLEncoder这个类进行编码和URLDecoder进行解码编码:URLEncoder.encode(中文,编码类型);解码:URLDecoder.decode(中文,解码类型);
1.什么是session2.session的工作原理3.了解session超时4.验证码登录5.什么是过滤器6.过滤器链===》shiro的核心知识点7.过滤器的应用
1.熟悉什么是session2.熟悉session的工作原理3.了解session超时4.验证码登录5.掌握什么是过滤器6.掌握过滤器链===》shiro的核心知识点7.过滤器的应用
第一节 状态管理-Session
1.1 Session概述
1.1.1 什么是Session
Session用于跟踪客户的状态。Session指的是在一段时间内,单个客户与Web服务器的一连串相关的交互过程。在一个Session中,客户可能会多次请求访问同一个网页,也有可能请求访问各种不同的服务器资源。表示的是会话,session域中存的值,他的有效范围是一次会话,浏览器代开访问服务器到访问结束关闭浏览器这段时间,这就是使用session去解决无状态性。session他的是属于服务器的
1.1.2 Session工作原理
1.当浏览器第一发送请求给服务器时,那么服务器会在内存中开辟一个对象(session),通过hash算法得到这个对象的内存地址(eac123456),此时服务器会new cookie对象(new Cookie("JsessionId","eac123456")),将cookie添加到response中响应给浏览器进行存储。2.当同一个浏览器第二次访问同一台服务器,根据cookie的自动发送原则,会将匹配到url的cookie封装到request请求中,那么此时服务器回去解析cookie,拿到JsessionId所对应的内存地址eac123456,根据内存地址找到原来new的对象(session对象),将对象关联给request3.第三次,第四次以此类推
1.1.3 如何获得Session
//获取Session对象HttpSession session=request.getSession();System.out.println("Id:"+session.getId());//唯一标记,和jSessionId不一样System.out.println("getLastAccessedTime:"+session.getLastAccessedTime());//最后一次访问时间,毫秒System.out.println("getMaxInactiveInterval:"+session.getMaxInactiveInterval());//获取最大的空闲时间,单位秒System.out.println("getCreationTime:"+session.getCreationTime());//获取Session的创建,单位毫秒
1.1.4 如何使用Session绑定对象
使用HttpSession的setAttribute(属性名,Object)方法
1.1.5 如何删除Session
使用HttpSession的invalidate方法
注意:如何理解session的作用范围是一次会话
1.session有着自己的生命周期,可以自己设定时长2.是因为存放原来JsessionId的那个cookie的maxAge=-1;浏览器关闭了,这个cookie还能使用吗?3.由于存放JsessionId的cookie被销毁类,所以你找不到原来的session对象类,但是那个对象还会在内存中存在
1.2 Session超时
1.2.1 什么是Session超时
HttpSession的最后一程访问时间和当前时间的差距大于了指定的最大空闲时间,这时服务器就会销毁Session对象。默认的空闲时间为30分钟。
1.2.2 如何修改Session的缺省时间限制
1 使用HttpSession的session.setMaxInactiveInterval(20*60);设置,单位秒2 在web.xml中配置 ,单位分钟<session-config><session-timeout>20</session-timeout></session-config>
1.2.3 Session失效的几种情况
1、超过了设置的超时时间2、主动调用了invalidate方法3、服务器主动或异常关闭注意:浏览器关闭并不会让Session失效注意的点:session失效不失session对象被销毁了,他还在内存中,只是不能用了。监听器去解决
总结:
1.session的工作原理2.如何去理解session的作用范围是一次会话3.sesssio这个对象本质是一个键值对的容器,通过get/setAttribute方法可以往容器中放值取值,这些值的作用范围是一次会话,主要应用,整个web去存放登录信息
2.4 Session的典型应用
2.4.1 验证登录
记得导jar包:
<%--Created by IntelliJ IDEA.User: AdministratorDate: 2020/2/27Time: 11:45To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %><html><head><title>Title</title></head><body><body><form action="login" method="post"><label>邮箱:</label><input name="email"><br/><label>密码:</label><input type="password" name="psw"><br/><label>验证码:</label><input type="text" name="code"><br/><img src="code" id="img"><input type="submit" value="登录"></form><script type="text/javascript">var img=document.getElementById("img");//这是浏览器的一个缓存问题,静态资源的缓存问题//表现形式:当链接地址没有发生变化时,他不会去发送请求var num=1;img.onclick=function () {num++;//没有实际的意义,只是去迷惑浏览器,使其认为这不是同一个请求img.src="code?num="+num;}</script></body></html>package com.qf.controller;import cn.dsna.util.images.ValidateCode;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class CodeServlet 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 {// public ValidateCode(int width, int height, int codeCount, int lineCount)//width:验证码图片的宽度//height:验证码图片的高度//codeCount:验证码的个数//lineCount:文字行高ValidateCode vc=new ValidateCode(200,30,4,10);System.out.println("验证码为"+vc.getCode()+"======================================");//当同一个session对象重复添加键时,新加的会把原来的覆盖掉request.getSession().setAttribute("code",vc.getCode());//将图片通过响应的输出流响应给浏览器展示vc.write(response.getOutputStream());}}package com.qf.controller;import com.qf.model.User;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;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 {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");String email = request.getParameter("email");String psw = request.getParameter("psw");String code = request.getParameter("code");//想办法拿到原来生成的code,在session里面String trueCode= (String) request.getSession().getAttribute("code");if(trueCode.equals(code)){//模拟去数据库查//User u=service.login();User u=new User("zhangsan@qq.com","1234");if(u!=null){//登录成功之后一定要记得将登录信息放到session域中request.getSession().setAttribute("user",u);response.sendRedirect("index.jsp");}else{response.getWriter().println("密码失败");response.sendRedirect("error.jsp");}}else{response.getWriter().println("验证码失败");response.sendRedirect("error.jsp");}}}
作业:
1.总结session和cookie的区别(重要!重要!重要!)
第二节 过滤器
2.1 什么是过滤器
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。
2.2 如何编写过滤器
1、编写java类实现Filter接口2、重写doFilter方法3、设置拦截的url
入门案例:
package com.qf.web.filter;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import java.io.IOException;/*** @author wgy 2018/11/28 9:23* @version 1.0*/@WebFilter("/myservlet1")//过滤路径public class MyFilter1 implements Filter {//初始化过滤器@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("过滤器初始化了........init... "+filterConfig);}//执行过滤@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("过滤前........doFilter ");//放行chain.doFilter(request, response);System.out.println("过滤后.......doFilter");}//销毁@Overridepublic void destroy() {System.out.println("销毁了.....destroy");}}
2.3 过滤器的配置
2.3.1 注解式配置
在自定义的Filter类上使用注解@WebFilter(“/*”)
2.3.2 xml配置
在web.xml中进行过滤器的配置:
<!--过滤器的xml配置 --><filter><!--名称--><filter-name>sf</filter-name><!--过滤器类全称--><filter-class>com.qf.web.filter.SecondFilter</filter-class></filter><!--映射路径配置--><filter-mapping><!--名称--><filter-name>sf</filter-name><!--过滤的url匹配规则和Servlet的一模一样--><url-pattern>/*</url-pattern></filter-mapping>
2.4 过滤器链
(在资源放行前,过滤请求,在资源放行后,过滤响应,多个过滤器之间过滤成链)
通常客户端对服务器请求之后,服务器调用Servlet之前会执行一组过滤器(多个过滤器),那么这组过滤器就称为一条过滤器链。每个过滤器实现某个特定的功能,一个过滤器检测多个Servlet。(匹配几个,检测几个)。一组过滤器中的执行顺序与<filter-mapping>的配置顺序呢有关。当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源
2.5 过滤器的优先级
在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter。当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源如果为注解的话,是按照类名的字符串顺序进行起作用的如果web.xml,按照 filter-mapping注册顺序,从上往下web.xml配置高于注解方式推荐使用xml方式进行配置
2.6 过滤器的初始化参数
在过滤器的创建的时候,可以传递初始化参数
第一种:基于注解的
/*** Servlet Filter implementation class FirstFilter 创建过滤器*/@WebFilter(value="/*",initParams= {@WebInitParam(name = "version", value = "1.0")})public class FirstFilter implements Filter {/*** Default constructor.*/public FirstFilter() {// TODO Auto-generated constructor stub}/*** @see Filter#destroy() 销毁*/public void destroy() {// TODO Auto-generated method stubSystem.out.println("destroy销毁……");}/*** @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) 过滤*/public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// TODO Auto-generated method stub// place your code hereSystem.out.println("doFilter……过滤");// 是否继续---访问下一个chain.doFilter(request, response);}/*** @see Filter#init(FilterConfig)* 初始化*/public void init(FilterConfig fConfig) throws ServletException {// TODO Auto-generated method stubSystem.out.println("init……初始化");System.out.println("初始化参数:版本号:"+fConfig.getInitParameter("version"));}}
第二种:基于xml配置
/*** 创建过滤器*/public class SecondFilter implements Filter {/*** Default constructor.*/public SecondFilter() {// TODO Auto-generated constructor stub}/*** @see Filter#destroy() 销毁*/public void destroy() {// TODO Auto-generated method stub}/*** @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) 过滤*/public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 是否继续---访问下一个chain.doFilter(request, response);}/*** @see Filter#init(FilterConfig)* 初始化*/public void init(FilterConfig fConfig) throws ServletException {// TODO Auto-generated method stubSystem.out.println("初始化参数:版本号:"+fConfig.getInitParameter("version"));}}
Web.xml实现配置:
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"><display-name>Web_Day</display-name><!--过滤器的xml配置 --><filter><filter-name>myfilter</filter-name><filter-class>com.qf.web.filter.SecondFilter</filter-class><!--过滤器的初始化参数 --><init-param><param-name>version</param-name><param-value>1.0</param-value></init-param></filter><filter-mapping><filter-name>myfilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><welcome-file-list><welcome-file>index.html</welcome-file></welcome-file-list></web-app>
2.7 过滤器的优点
可以实现 Web 应用程序中的预处理和后期处理逻辑
chain.doFilter(req, resp);//资源放行如果不去执行这一句话,那么请求就会被拦截,不再继续往下走在资源放行的前后,我们可以对请求进行处理和对响应进行处理
2.8 过滤器的典型应用
过滤器的作用来看
1.过滤所有的请求,因为他是在servlet.jsp.html等资源执行之前执行,可以类似封装的作用,比如处理乱码2.可以在资源放行之前,对request进行处理,过滤敏感词3.我们可以在资源放行之后,对资源响应给浏览器的response进行相关处理:压缩响应内容
案例1禁用浏览器缓存
web对静态资源有缓存作用(img,html,js,css)
对于目前现在的浏览器,get请求动态资源缓存问题已经解决。
max-age<=0 时 向server 发送http 请求确认 ,该资源是否有修改
对于静态资源部分浏览器使用Cache-Control头和Expires头设置缓存时间。
对于静态资源服务器会采用304状态码控制是否再次发送数据,从而节省带宽;可以通过Cache-Control=no-store,Expires=-1,Pragma=no-cache控制304无效。
package com.qf.filter;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class CacheFilter implements Filter {public void destroy() {}public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {//将req转换成HttpServletRequestHttpServletRequest request= (HttpServletRequest) req;HttpServletResponse response= (HttpServletResponse) resp;//通过以下参数的设置,可以禁用浏览器缓存response.setDateHeader("Expires",-1);response.setHeader("Cache-Control","no-store");response.setHeader("Pragma","no-cache");chain.doFilter(req, resp);}public void init(FilterConfig config) throws ServletException {//获取初始化参数String driverClassName = config.getInitParameter("driverClassName");System.out.println(driverClassName+"============================================");}}
作业:如何设置浏览器缓存时间
案例2 自动登录
案例3 过滤脏词
案例4 过滤器解决编码
案例五:对响应内容进行压缩
作业题
1.总结session和cookie的区别(重要!重要!重要!)2.如何设置浏览器缓存时间3.session的工作原理抄写三遍
