深入理解session和过滤器(1)

2 篇文章 0 订阅
2 篇文章 0 订阅
第一节 状态管理-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对象),将对象关联给request
3.第三次,第四次以此类推
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: Administrator
  Date: 2020/2/27
  Time: 11:45
  To 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.οnclick=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");
        }
    }
}

第二节 过滤器
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 {

    //初始化过滤器
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器初始化了........init...  "+filterConfig);
    }

    //执行过滤
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("过滤前........doFilter ");
        //放行
        chain.doFilter(request, response);

        System.out.println("过滤后.......doFilter");

    }

    //销毁
    @Override
    public 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 stub
		System.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 here
		System.out.println("doFilter……过滤");
		// 是否继续---访问下一个
		chain.doFilter(request, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 * 初始化
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.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 stub
		System.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转换成HttpServletRequest
        HttpServletRequest 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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值