JavaEEDay45 过滤器

JavaEEDay45 过滤器

@toc

一、复习

(一)WEB 基础:

  • HTML + CSS + js : 做一个前端页面展示
  • XML:做一个配置文件
  • MySQL:数据库
  • Servlet:运行在服务器的 Java 小程序,用于处理客户端请求,产生相应;
  • Tomcat:所有想要被客户端访问的资源都需要部署到 Tomcat 下:包括:html/js/css/servlet/jsp/图片;

(二)Servlet生命周期

1.什么时候初始化:
在客户端第一次访问某一个Servlet的时候,此Servlet会初始化,并且调用init方法;
注:init在一个生命周期只会调用一次,每次访问该Servlet重复执行的是service方法。

2.什么时候销毁:
直到服务器(tomcat)关闭的时候Servlet才会销毁。

二、过滤器

本质上是一个接口,用于拦截客户端的请求,对请求进行过滤,还可以对响应进行处理;

  • 过滤器的用途:拦截、验证、统一管理
    • 用户认证权限管理
    • 统计访问量和访问命中率,形成访问报告
    • 请求编码转换
    • 数据加密
    • 日志记录和审核过滤器
    • 拦截敏感词汇

(一)前言引导

场景设置:部分网页需要登录之后才可以访问;
思路:
1.用户填写用户名、密码进行判断,根据判断结果进行页面跳转;
2.用户登录成功之后,再 session 中保存一个变量,要表示用户是否已经登录;
3.在登录成功之后才能够访问的资源中判断 session 中变量;

代码:
index.jsp :页面主页
web.xml :配置文件
login.jsp :登录页面
index2.jsp :备用主页
loginServlet.java 程序

index.jsp

<body>
<%--  在jsp中判断session中是否存在islogin,并且还为true--%>

  <%
    // 因为后面返回值为Object类型,因此强转应该是Boolean类型,不是boolean
    Boolean islogin = (Boolean)session.getAttribute("islogin");
    if (islogin == null || !islogin) {
      // 用户未登录
      response.sendRedirect("login.jsp");
    }
  %>

  </body>

web.xml

    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>gjxaiou.LoginServlet</servlet-class>

    </servlet>

    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

login.jsp

<body>
    <%--这里点击登录离职后跳转到Servlet--%>
    <form action="login" method="post">
        请输入账号密码:
        <input type="text" name="username"/>
        <input type="text" name="password"/>
        <input type="submit" value="登录">


    </form>

</body>

index2.jsp

<body>
<%--  在jsp中判断session中是否存在islogin,并且还为true--%>

<%
    // 因为后面返回值为Object类型,因此强转应该是Boolean类型,不是boolean
    Boolean islogin = (Boolean)session.getAttribute("islogin");
    if (islogin == null || !islogin) {
        // 用户未登录
        response.sendRedirect("login.jsp");
    }
%>

</body>

LoginServlet.java

/**
 * @author GJXAIOU
 * @create 2019-08-12-18:46
 */
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.获取前端传送过来的数据
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        // 2.判断数据是否正确,可以采用数据库验证
        if ("gjxaiou".equals(username) && "123456".equals(password)){
            // 登录成功,跳转到首页
            // 这里使用重定向
            resp.sendRedirect("index.jsp");

            // 在回话中保存一个变量,来表示用户已经登录
            HttpSession session = req.getSession();
            // 在session中保存一个变量
            session.setAttribute("islogin", true);
        }else {
            // 登录失败,重新回到登录页面,即回到上一页面
            resp.getWriter().print("<script>window.history.back()</script>");
        }

        // 3. 根据判断结果进行页面跳转,见上;
    }
}

(二)使用迭代器实现

  • 步骤:
    • 1.新建类并实现 Filter 接口;
    • 2.重写 init()、doFilter()、destroy()方法;
    • 3.在 doFilter()中进行过滤;
    • 4.在 web.xml 中配置 Filter;

首先可以将 index.jsp 和 index2.jsp 放在 main 文件下,即将需要保护的资源放入过滤器,在过滤器中判断是否已经登录;
判断是否已经登录方法:因为在登录成功之后,在 session 中保存了 islogin,通过判断 islogin 的值是否为空即可
AuthorFilter.java

@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest= (HttpServletRequest)servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;

        HttpSession session = httpServletRequest.getSession();

        if (session.getAttribute("islogin") == null){
            // 没有登录,跳转回登录界面重新登录
            // 参数里面的相对路径:相对于过滤器当前处理的请求的路径,当前为 main/*
            httpServletResponse.sendRedirect("../login.jsp");
        }else {
            // 用户登录,放行
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

对应的 web.xml 中只要设置 url-pattern 值为:/main/*其他一样;

使用过滤器实现将所有文件编码统一改为 utf-8

EncodingFilter.java

package filter.demo;

import javax.servlet.*;
import java.io.IOException;

/** 实现编码的过滤器
 * @author GJXAIOU
 * @create 2019-08-12-20:12
 */
public class EncodingFilter implements Filter {

    // 使用全局变量,因为所有的都要改变编码
    String encode = null;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
       encode = filterConfig.getInitParameter("encoding");

    }

    /** 书写一个过滤器考虑问题:
     * 1.过滤器的范围;
     * 2.过滤器拦截之后需要做什么事情
     * 这里需求是做一个统一编码的过滤器
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //  这里设置代码的编码是写死的,可以在xml中设置,方便更改
        //        // 1.设置请求编码
        //servletRequest.setCharacterEncoding("utf-8");

        servletRequest.setCharacterEncoding(encode);

        // 2.放行
        filterChain.doFilter(servletRequest, servletResponse);

    }

    @Override
    public void destroy() {

    }
}

web.xml

  <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>filter.demo.EncodingFilter</filter-class>
        <!-- 这里将需要制定的字符集编码当做初始化参数传入过滤器 ,在过滤器的init方法中读取-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

过滤器 URL 路径 设置

1。常见的设置:

  • 映射到具体的某一个资源:<url-pattern>/contact.jsp</url-pattern>
  • 映射到某一路径下所有请求:<url-pattern>/*</url-pattern><url-pattern>/main/*</url-pattern>
  • 映射到结尾相同的一类请求:<url-pattern>*.jsp</url-pattern>
  • 不支持路径下的某一类请求这种形式:例如:/main/*.jsp是不支持的;
    2.代码示例
    web.xml
<filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>filter.demo.EncodingFilter</filter-class>
        <!-- 这里将需要制定的字符集编码当做初始化参数传入过滤器 ,在过滤器的init方法中读取-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
        <!-- 一个filter可以对应多个 filter-mapping,多个 url-pattern直接是并集的关系,满足其中任意一个即可  -->
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/main/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/hello/*</url-pattern>
    </filter-mapping>

Encoding.java

 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //  这里设置代码的编码是写死的,可以在xml中设置,方便更改
        //        // 1.设置请求编码
        //servletRequest.setCharacterEncoding("utf-8");

        servletRequest.setCharacterEncoding(encode);

        // 2.只针对hello文件下的.jsp文件放行
        // 思路:获取当前请求路径,通过判断路径后缀的方式,判断后缀为.jsp的文件
        // 2-1: 因为ServletRequest是HttpServletRequest的父接口,先进行强转
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        // 2-2:获取当前请求完整路径
        String requestURI = httpServletRequest.getRequestURI();

        // 2-3: 判断文件结尾
        if (requestURI.endsWith(".jsp")){
            filterChain.doFilter(servletRequest, servletResponse);
        }


    }

多个过滤器

先后通过,不是同时通过;
如果第一个通过的拦截器选择拦截,那么后面所有的都没用了;
dofilter 是将请求交个下一个过滤器进行处理;

一个应用可以有多个过滤器,一个过滤器执行完毕放行之后到下一个过滤器,过滤器执行的顺序是按照在 web.xml 中声明的先后顺序;

建议范围较大的过滤器优先通过,因为最外层的过滤器拦截,后续所有的过滤器都会拦截,只有所有的过滤器都放行才会到达资源;
过滤器实现方法 doFilter()方法转给你的 chain.doFilter()实际上是将其交给下一个过滤器使用,只有所有的过滤器都放行才会到达具体的资源;

属性:dispatcher

访问一个页面的三种方式:
直接访问
通过转发
通过包含
通过失败
目前是通过转发和包含,仍然 能够通过过滤器;

例如:including.jsp 里面包含 index.html 文件

<body>
这里是include.jsp文件,下面是引用
  <jsp:include page="index.html"></jsp:include>
</body>

转发方式:myServlet.java

// 通过注解指定Servlet路径,效果和在xml中配置Servlet,servletmappring效果一样
@WebServlet("/my")
public class myServlet extends HttpServlet{
  @override
  protected void doget(){
    req.getRequesDispatcher("index.html").forward(req, resp)

}


}

将以上两种方式也进行过滤,在 web.xml 中设置为:

<filter-mapping>
  <!--dispatcher 默认值即为REQUEST-->
  <dispatcher>REQUEST</dispatcher>
  <!--转发的方式进入资源也会被过滤-->
  <dispatcher>FORWARD</dispatcher>
  <!--引用方式进入资源也会被过滤-->
  <dispatcher>INCLUDE</dispatcher>
</filter-mapping>
  • ERROR 方式,通过 ERROR 方式触发,注意:使用此属性,就不能正常使用;

统计 main 文件夹所有页面访问量

包含:index.jsp 和 index2.jsp
页面的访问量其实就是在已经访问过的次数上+1

之前访问的次数应该是多个客户端共享的,这里使用 application 作用域,在其中保存数值,所有的人都可以访问和进行操作

  • 方案一:在每一个页面中都加入统计,在每一个页面中加入下面代码
<%
  Integer in = (Integer)application.getAttribute("count");
  if(in == null){
    // 即从没有在application中保存该键值对,即没有登录过
    // 第一次访问就添加一个键值对
    application.setAttribute("conut", 1);
  } else {
    // 有人访问过,在此基础上+1
    application.setAttribute("count", ++in);
  }
%>
  • 方案二:使用迭代器,因为所有页面位于 main 文件夹下:
    web.xml 配置
<filter>
        <filter-name>countFilter</filter-name>
        <filter-class>filter.demo.CountFilter</filter-class>
</filter>
<filter-mapping>
        <filter-name>countFilter</filter-name>
        <url-pattern>/main/*</url-pattern>
</filter-mapping>

CountFilter.java 中 doFilter 中代码

HttpServletRequest request = (HttpServletRequest)servletRequest;
// 在代码中获取application对象
ServletContext application = request.getServletContext();

 Integer in = (Integer)application.getAttribute("count");
  if(in == null){
    // 即从没有在application中保存该键值对,即没有登录过
    // 第一次访问就添加一个键值对
    application.setAttribute("conut", 1);
  } else {
    // 有人访问过,在此基础上+1
    application.setAttribute("count", ++in);
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值