Servlet下篇

1 - Servlet规范扩展 -- 监听器接口

1介绍:

  1)一组来自于Servlet规范下接口,共有8个接口,在Tomcat存在servlet-api.jar包

  2)监听器接口需要由开发人员亲自实现,http服务器提供jar包并没有对应的实现类

  3)监听器接口用于监控【作用域对象生命周期变化时刻】以及【作用域对象共享数据变化时刻】

2.作用域对象:

  1)在servlet规范中,认为在服务端内存可以在某些条件下为两个servlet之间提供数据共享方案的对象,被称为【作用域对象】

  2)Servlet规范下作用域对象:

    ServletContext:全局作用域对象

    HttpSession:会话作用域对象

    HttpServletRequest:请求作用域对象

3.监听器接口实现类开源规范:三步

  1)根据监听的实际情况,选择对应监听器接口进行实现

  2)重写监听器接口声明【监听事件处理方法】

  2)在web.xml文件将监听器接口实现类注册到http服务器

4.ServletContextListener接口:

  1)作用:通过这个接口合法的检测全局作用域对象被初始化时刻以及被销毁时刻

  2)监听事件处理方法:

    public void contextInitialized(ServletContextEvent sce) 在全局作用域对象被Http服务器初始化被调用

    public void contextDestroyed(ServletContextEvent sce) 在全局作用域对象被Http服务器销毁时候触发调用

5.ServletContextAttributeListener接口:

  1)作用:通过这个接口合法的检测全局作用域对象共享数据变化时刻

  2)监听事件处理方法:

    public void contextAdd() 在全局作用域对象添加共享数据

    public void contextReplaced() 在全局作用域对象更新共享数据

    public void contextRemove() 在全局作用域对象删除共享数据

6.全局作用域对象共享数据变化时刻

ServletContext application = request.getServletContext();

application.setAttribute("key",100); // 新增共享数据

application.setAttribute("key",200); // 更新共享数据

application.removeAttribute("key"); // 删除共享数据

2 - Servlet规范扩展 -- 过滤器(Filter)接口

1.介绍:

  1)Servlet规范扩展,来自于Servlet规范下接口,在Tomcat中存在于servlet-api.jar包

  2)Filter接口实现类由开发人员负责提供,http服务器不负责提供

  3)Filter接口在http服务器调用资源文件之前,对http服务器进行拦截

2.具体作用

  1.拦截http服务器,帮助http服务器检测当前请求合法性

 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 1.通过拦截请求对象得到请求包参数信息,从而得到来访用户的真实年龄
        String age = servletRequest.getParameter("age");
        // 2.根据年龄,帮助http服务器判断本次请求合法性
        if(Integer.valueOf(age) < 70){
            // 请求合法
            // 将拦截请求对象和响应对象交还给http服务器(Tomcat),http继续调用资源文件
            filterChain.doFilter(servletRequest,servletResponse); // 放行
        } else{
            // 过滤器代替http服务器拒绝本次请求
            servletResponse.setContentType("text/html;charset=utf-8");
            PrintWriter out = servletResponse.getWriter();
            out.print("<center><font style='color:red;font-size:40px'>真爱生命啊</font></center>");
        }
    }
部分代码示例

  2.拦截http服务器,对当前请求进行增强操作

 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws Exception{
        // 通知拦截的请求对象,使用utf-8字符集对当前请求信息进行一次重新编辑
        servletRequest.setCharacterEncoding("utf-8"); // 进行增强操作
        filterChain.doFilter(servletRequest,servletResponse);

        // **********最后别忘记将过滤器接口实现类注册到http服务器************
        /*
        <filter-mapping>
            <filter-name>OneFilter</filter-name>
            <url-pattern>/*</url-pattern> <!--通知Tomcat在调用所有资源文件前都需要OneFilter过滤器进行拦截-->
        </filter-mapping>
         */
    }
部分代码示例

3.Filter接口实现类开发步骤:三步

  1)创建一个Java实现类Filter接口

  2)重写Filter接口中的doFilter方法

  3)在web.xml将过滤器接口实现类注册到http服务器

4.Filter拦截地址格式

  1)命令格式:

    <filter-mapping>

      <filter-name>oneFilter</filter-name>

      <url-pattern>拦截地址</url-pattern>

    </filter-mapping>

  2)命令作用:拦截地址通知Tomcat在调用何种资源文件之前需要调用OneFilter过滤器进行拦截

  3)要求Tomcat在调用某一个具体文件之前,来调用OneFilter拦截

    <url-pattern>/img/mm.jpg</url-pattern>

  4)要求Tomcat在调用某一个文件夹下所有的资源文件之前,来调用OneFilter拦截

    <url-pattern>/img/*</url-pattern>

  5)要求Tomcat在调用任意文件夹下某种类型文件之前,来调用OneFilter拦截

    <url-pattern>*.jpg</url-pattern>

  6)要求Tomcat在调用网站中任意文件时,来调用OneFilter拦截

    <url-pattern>/*</url-pattern>

3 - 过滤器防止用户恶意登录行为

①解决用户恶意登录行为解决1:不使用过滤器,在登录成功后在,LoginServlet里设置session的id,通过id判断是否是合法用户,但是此方法也有很大的缺点,见图。

② 使用过滤器

 部分代码实现

package com.howie.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class OneFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 1.拦截后,通过请求对象向Tomcat索要当前用户的HttpSession
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpSession session = request.getSession(false);
        // 2.判断来访用户合法性
        if(session == null){
            request.getRequestDispatcher("/login.html").forward(servletRequest,servletResponse);
            return;
        }
        // 放行
        filterChain.doFilter(servletRequest,servletResponse);
        // 把过滤器注册到服务器即可
    }
}
View Code

说明:使用此方法时,对网站形成 "绝对保护" 没有一种请求可以访问得到服务端资源,因为每次访问服务端资源文件时过滤器都会进行拦截,连登陆和登陆验证都会进行拦截,所以无法访问得到服务端资源文件。顾对此方需要改进。

改进后部分过滤器代码实现

 

  @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpSession session = null;
        // 1.调用请求对象读取请求包中请求行中URI,了解用户访问的资源文件是谁?
        String requestURI = request.getRequestURI(); // 网站名/资源文件名 /myWeb/login.html or /myWeb/login
        // 2.如果本次请求资源文件与登录相关[login.html] 或者 [LoginServlet] 此时应该无条件放行
        System.out.println("login".indexOf(requestURI)); // 获取"login" 第一次出现的位置
        if(requestURI.indexOf("login") != -1 || "/myWeb/".equals(requestURI)){
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        // 3.如果本次请求访问的是其他资源文件,需要得到用户在服务端的HttpSession
        session = request.getSession(false);
        if(session != null){
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        // 做拒绝请求
        request.getRequestDispatcher("/login.html").forward(servletRequest,servletResponse);
    }
View Code

 

4 - 互联网通信流程图最终版

 

 

posted @ 2020-07-28 19:47  赖正华  阅读(88)  评论(0编辑  收藏  举报