JavaEE学习日志(五十九): 过滤器,监听器,Servlet抽取

JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇)

过滤器

过滤器:符合条件的过去,不符合条件的不能过。
客户端需要访问目标资源,在客户端和资源之间设置过滤器。
符合则放行。

过滤器快速入门

  • 定义类,实现接口Filter
  • 重写抽象方法
  • 在web.xml配置(注解)

现在有一个servlet1

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("servlet1");
        System.out.println("servlet1");
    }

servlet2

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("servlet2");
        System.out.println("servlet2");
    }

过滤器1

package com.itheima.filter;

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

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器MyFilter");
        //放行,允许访问目标资源
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

过滤器2

package com.itheima.filter;

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

public class MyFilter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器MyFilter2");
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

配置xml:过滤器1对所有servlet进行过滤;过滤器2只对servlet2进行过滤

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!--
        过滤器配置
        和Servlet配置方式基本一致
    -->
    <filter>
        <filter-name>my</filter-name>
        <filter-class>com.itheima.filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>my</filter-name>
        <!--
            配置的是过滤器需要配置的资源
            /* 过滤WEB应用下的所有资源
        -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>my2</filter-name>
        <filter-class>com.itheima.filter.MyFilter2</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>my2</filter-name>
        <!--
            只过滤Servlet2
        -->
        <url-pattern>/servlet2</url-pattern>
    </filter-mapping>
</web-app>

过滤器的执行过程

在这里插入图片描述

过滤器的生命周期

  • 过滤器对象的创建:Tomcat服务器启动
    init(FilterConfig config)过滤器对象被创建时调用,FilterConfig对象由Tomcat引擎创建
  • 过滤器执行过滤的方法:过滤被访问的资源时执行,资源必须被过滤器过滤
doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
  • 过滤器销毁的方法:销毁之前调用,服务器关闭之前(或项目删除)调用
    destroy()

过滤器的配置

  • 完全匹配:只过滤指定的资源
<url-pattern>/servlet2</url-pattern>
  • 目录匹配(最实用):/abc/* 过滤abc目录下的所有资源
<url-pattern>/abc/*</url-pattern>
  • 后缀名匹配:一般不使用*.jsp 访问所有的jsp文件都过滤
<url-pattern>*.jsp</url-pattern>

过滤器的注解配置

@WebFilter(urlPatterns="/过滤资源 ")

过滤器的执行顺序

web.xml配置:配置文件的编写顺序决定运行的顺序。准确的说,根据mapping的顺序决定。

注解开发:按照类名的自然顺序运行,如AFilter比BFilter先运行。

注意:

  • 如果有配置文件,则配置文件优先执行。
  • 如果配置文件和注解并存,则两者都会运行。

过滤器的拦截方式

默认方式一:REQUEST,请求时拦截

<filter-mapping>
        <filter-name>my</filter-name>
        <!--
            配置的是过滤器需要配置的资源
            /* 过滤WEB应用下的所有资源
        -->
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

方式二:FORWARD,转发时拦截

<dispatcher>FORWARD</dispatcher>

方式三:INCLUDE,包含时拦截

<dispatcher>INCLUDE</dispatcher>

方式三:ERROR,错误时拦截

<dispatcher>ERROR</dispatcher>

拦截方式写在注解中

@WebFilter(urlPatterns = "/*",dispatcherTypes = {DispatcherType.FORWARD})

过滤器解决全站中文乱码

package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class ChinaFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //设置request对象的编码表
        servletRequest.setCharacterEncoding("utf-8");
        //设置response缓冲区的编码表,并通知浏览器解码
        servletResponse.setContentType("text/html;charset=utf-8");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

监听器

监听器:监听某个组件变化的对象,事件源是固定的,主要是request,session,servletContext域对象

监听的是域对象的变化:

  • 域对象的创建和销毁
  • 域对象中存储数据的变化
    在这里插入图片描述

ServletContext监听器入门

实现步骤

  • 创建类实现监听器接口ServletContextListener
  • 重写抽象方法
  • web.xml配置(注解)
package com.itheima.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyServletContextListener implements ServletContextListener {
    @Override
    /*
        ServletContext对象被创建时调用
     */
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext域对象创建");
    }
    /*
        被销毁前调用
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext域对象销毁");
    }
}

如果使用配置文件

<listener>
        <listener-class>com.itheima.listener.MyServletContextListener</listener-class>
</listener>

ServletContextEvent对象方法

  • Object getSource() 获取到被监听的事件源
  • ServletContext getServletContext() 获取到被监听的事件源
    除了返回值以外,这两个方法的功能一样。这样设计的目的是为了通用性。其他监听器事件对象,都有一个共同的方法getSource();
package com.itheima.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyServletContextListener implements ServletContextListener {
    @Override
    /*
        ServletContext对象被创建时调用
        ServletContextEvent方法参数:ServletContext域对象的事件对象
        此方法由Tomcat引擎创建
        ServletContextEvent方法:
            Object getSource() 获取到被监听的事件源
            ServletContext getServletContext() 获取到被监听的事件源
            除了返回值以外,功能一样。这样设计的目的是为了通用性。其他监听器事件对象,
            都有一个共同的方法getSource();
     */
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext context = (ServletContext)servletContextEvent.getSource();
        System.out.println(context);

        ServletContext context2= servletContextEvent.getServletContext();
        System.out.println(context2);
        System.out.println("ServletContext域对象创建");
    }
    /*
        被销毁前调用
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext域对象销毁");
    }
}

Servlet抽取

对于一个商品数据,基本的功能有4个,增删改查。
会有一个问题:Servlet会越来越多
解决方法:Servlet抽取。

基本抽取

package com.itheima.servlet;

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;


/*
    用户操作Servlet
    登录      login
    注册      register
    修改密码  updatePassword
    退出      loginOut

    共性:接收请求,实现响应
    4个方法的参数:request,response

    需要客户端配合:使用功能的时候,提交一个参数
    Servlet判断参数是什么,选择调用哪个方法
 */
@WebServlet(urlPatterns = "/user")
public class UserServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取提交的参数
        String md = request.getParameter("method");
        //判断参数,调用不同的方法
        if("login".equals(md)){
            login(request,response);
        }else if ("register".equals(md)){
            register(request,response);
        }else if ("updatePassword".equals(md)){
            updatePassword(request,response);
        }else if ("loginOut".equals(md)){
            loginOut(request,response);
        }
    }
    //登录 login
    public void login(HttpServletRequest request, HttpServletResponse response){
        System.out.println("登录");
    }
    //注册      register
    public void register(HttpServletRequest request, HttpServletResponse response){
        System.out.println("注册");
    }
    //改密     updatePassword
    public void updatePassword(HttpServletRequest request, HttpServletResponse response){
        System.out.println("修改密码");
    }
    //登出     loginOut
    public void loginOut(HttpServletRequest request, HttpServletResponse response){
        System.out.println("登出");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

<%--超链接,服务器端的提交,在请求地址上用?拼接参数--%>
<a href="${pageContext.request.contextPath}/user?method=login">登录</a><br>
<a href="${pageContext.request.contextPath}/user?method=register">注册</a><br>
<a href="${pageContext.request.contextPath}/user?method=updatePassword">修改密码</a><br>
<a href="${pageContext.request.contextPath}/user?method=loginOut">退出</a><br>

基本抽取优化

使用反射进行优化:不写一个if语句

@WebServlet(urlPatterns = "/user")
public class UserServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            //获取提交的参数
            String md = request.getParameter("method");
            //换一个思考方式:不写if 使用反射
            //反射技术获取方法执行
            Class clazz = this.getClass();
            //获取方法
            Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
            //执行方法,对象,实际参数
            method.invoke(this,request,response);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //登录 login
    public void login(HttpServletRequest request, HttpServletResponse response){
        System.out.println("登录");
    }
    //注册      register
    public void register(HttpServletRequest request, HttpServletResponse response){
        System.out.println("注册");
    }
    //改密     updatePassword
    public void updatePassword(HttpServletRequest request, HttpServletResponse response){
        System.out.println("修改密码");
    }
    //登出     loginOut
    public void loginOut(HttpServletRequest request, HttpServletResponse response){
        System.out.println("登出");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

BaseServlet抽取

BaseServlet

public abstract class BaseServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            //获取提交的参数
            String md = request.getParameter("method");
            //换一个思考方式:不写if 使用反射
            //反射技术获取方法执行
            Class clazz = this.getClass();
            //获取方法
            Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
            //执行方法,对象,实际参数
            method.invoke(this,request,response);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

其他的Servlet继承BaseServlet,不再继承HttpServlet

@WebServlet(urlPatterns = "/product")
public class ProductServlet extends BaseServlet {
    //添加 addProduct
    public void addProduct(HttpServletRequest request, HttpServletResponse response){
        System.out.println("添加商品");
    }
    //添加 addProduct
    public void updateProduct(HttpServletRequest request, HttpServletResponse response){
        System.out.println("更新商品");
    }
    //添加 addProduct
    public void delProduct(HttpServletRequest request, HttpServletResponse response){
        System.out.println("删除商品");
    }

}

@WebServlet(urlPatterns = "/user")
public class UserServlet extends BaseServlet {
    //登录 login
    public void login(HttpServletRequest request, HttpServletResponse response){
        System.out.println("登录");
    }
    //注册      register
    public void register(HttpServletRequest request, HttpServletResponse response){
        System.out.println("注册");
    }
    //改密     updatePassword
    public void updatePassword(HttpServletRequest request, HttpServletResponse response){
        System.out.println("修改密码");
    }
    //登出     loginOut
    public void loginOut(HttpServletRequest request, HttpServletResponse response){
        System.out.println("登出");
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值