Springboot基础------控制器、过滤器、拦截器、监视器

news2024/9/24 19:29:01

控制器

控制器用于接收和响应用户发送的请求,一个控制器类需要被@Controller注解:(即controller层)

@Controller
class TestController {
}

注: @RestController实际上是@Controller和@ResponseBody的简化版,被这个注解标注的控制器类的方法默认向客户端直接返回字符串。

过滤器

介绍

过滤器可以在调用控制器方法之前进行一些操作,是基于Servlet规范的。过滤器类一般放在filter包下。(过滤器是处于客户端与服务器资源文件之间的一道过滤网,帮助我们过滤一些不符合要求的请求。通常用作:
统一设置字符编码
过滤敏感字符
进行登录校验以及 url 级别的访问权限控制。
大白话:过滤器就是一道上了锁的密码门,进入都需要指定密码才能进入,密码不对就进不去)。

生命周期

主要遵循Java Servlet规范中定义的过滤器生命周期。一个实现了javax.servlet.Filter接口的类,在Spring Boot应用中作为过滤器使用时,会经历以下生命周期阶段:

  1. 初始化阶段
    init(FilterConfig filterConfig):当Servlet容器(如Tomcat)启动时,会初始化在web.xml中或通过注解配置的过滤器。此方法在过滤器实例化后立即被调用,用于执行一些初始化操作,如加载配置文件、初始化资源等。如果初始化失败,会抛出ServletException。
  2. 过滤阶段
    doFilter(ServletRequest request, ServletResponse response, FilterChain chain):此方法在每次请求到达时都会被调用。它允许过滤器对请求和响应进行预处理和后处理。在doFilter方法中,可以通过调用chain.doFilter(request, response)将请求传递给下一个过滤器或目标Servlet,也可以决定不调用此方法以中断请求处理流程。
  3. 销毁阶段
    destroy():当Servlet容器关闭或Web应用被卸载时,会调用此方法。它用于释放过滤器所占用的资源,如关闭数据库连接、释放内存等。

实现过滤器

通过@WebFilter注解实现过滤器

在springboot 启动类添加该注解@ServletComponentScan
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan
public class LogbackApplication {

    public static void main(String[] args) {
        SpringApplication.run(LogbackApplication.class, args);
    }

}

创建过滤类实现Filter接口

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

/**
 * @author zjh
 * @className AnnotateFilter
 * @date 2024/7/26
 * @description TODO
 **/


// urlPatterns 过滤路径  filterName 过滤器name
@WebFilter(urlPatterns = "/zjh/*" ,filterName = "urlFilter")
public class AnnotateFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //过滤逻辑

    }
    
    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

使用非注解方式实现过滤器(直接注入到spring中)

实现类
import javax.servlet.*;
import java.io.IOException;

/**
 * @author zjh
 * @className NoAnnotateFilter
 * @date 2024/7/26
 * @description TODO
 **/
public class NoAnnotateFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //过滤逻辑
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
Filter配置文件
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author zjh
 * @className FilterConfig
 * @date 2024/7/26
 * @description TODO
 **/
@Configuration
public class FilterConfig {
    @Bean
    public NoAnnotateFilter noAnnotateFilter(){
        return new NoAnnotateFilter();
    }


    @Bean
    public FilterRegistrationBean getFilterRegistrationBean(NoAnnotateFilter noAnnotateFilter) {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(noAnnotateFilter);
        filterRegistrationBean.setOrder(2);
        filterRegistrationBean.addUrlPatterns("/zjh/*");
        filterRegistrationBean.setName("noAnnotateFilter");
        return filterRegistrationBean;
    }

}

拦截器

介绍

是Spring MVC框架中的一个重要特性,它允许你在请求处理流程中的特定点执行自定义逻辑。拦截器主要用于在控制器(Controller)处理请求之前和之后执行一些预处理和后处理工作。拦截器的主要目的是在不修改原有代码的情况下,实现对请求和响应的统一处理。

作用

拦截器的本质上是面向切面编程 AOP,符合切面编程的关注点都可以通过拦截器来实现。它通常用于以下场景:
权限控制: 拦截器可以在请求到达处理器之前进行权限验证,从而实现对不同用户的访问控制。
日志记录: 拦截器可以在请求处理过程中记录请求和响应的详细信息,便于后期分析和调试(可实现日志的脱敏)。
接口幂等性校验: 拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。
数据校验: 拦截器可以在请求到达处理器之前对请求数据进行校验,确保数据的合法性。
缓存处理: 拦截器可以在请求处理之后对响应数据进行缓存,提高系统性能。
通用行为: 读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现)

拦截器执行顺序

当有多个拦截器时,它们的执行顺序取决于注册顺序。先注册的拦截器先执行,后注册的拦截器后执行。在请求处理过程中,拦截器的preHandle方法按注册顺序执行,而postHandle和afterCompletion方法按注册顺序的逆序执行。
当有多个拦截器时,它们的执行流程如下:

执行所有拦截器的preHandle方法,按注册顺序执行。如果某个拦截器的preHandle方法返回false,则中断请求处理,直接执行该拦截器的afterCompletion方法。
执行处理器的处理方法。
执行所有拦截器的postHandle方法,按注册顺序的逆序执行。
渲染视图。
执行所有拦截器的afterCompletion方法,按注册顺序的逆序执行。

在这里插入图片描述

生命周期

拦截器的生命周期由Spring容器管理。当Spring容器启动时,拦截器会被实例化并初始化;当Spring容器关闭时,拦截器会被销毁。

拦截器的实现

拦截器编写(实现HandlerInterceptor接口)

在更高版本中HandlerInterceptorAdapter已经弃用,推荐实现HandlerInterceptor接口。实现拦截类的拦截逻辑。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author zjh
 * @className LogbackInterceptor
 * @date 2024/7/29
 * @description 拦截器处理类
 **/
@Component
public class LogbackInterceptor implements HandlerInterceptor {
    /**
     * 在 controller 执行之前进行拦截,返回结果将决定后续操作是否执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 编写拦截器逻辑
        System.out.println("===拦截器1前处理===");
        return true;
    }
    /**
     * 在执行完 controller 的方法后进行拦截,可对 model 和 view 进行修改
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("===拦截器1后处理===");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
    /**
     * 在整个请求完成之后执行,即视图渲染之后执行,若返回 json 数据则不会执行此方法
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

注: preHandle方法的返回值如果为true表示正常执行,如果为false表示阻止请求正常执行

HandlerInterceptorAdapter内含方法介绍

预处理preHandle()方法

用户发送请求时,先执行preHandle()方法。会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则执行用户请求的url方法。

后处理postHandle()方法

调用了Service并返回ModelAndView,但未进行页面渲染,可以在这里继续修改ModelAndView或者返回值

返回处理afterCompletion()方法

已经渲染了页面,在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。

注: 一般使用preHandle这个拦截器进行预处理,对url进行请求拦截

拦截器注册(实现WebMvcConfigurer接口)

需要继承WebMvcConfigurerAdapter类,在更高版本WebMvcConfigurerAdapter已经弃用。推荐实现WebMvcConfigurer接口,并重写addInterceptors(InterceptorRegistry registry)方法。也可以通过继承WebMvcConfigurationSupport类来实现,但是只能继承一次,而且会导致其他不注册在此类中的拦截器失效,不建议使用。

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author zjh
 * @className InterceptorConfig
 * @date 2024/7/29
 * @description 拦截器注册
 **/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    private final LogbackInterceptor logbackInterceptor;
    public InterceptorConfig(LogbackInterceptor logbackInterceptor) {
        this.logbackInterceptor = logbackInterceptor;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        //注册自己的拦截器并设置拦截的请求路径
     registry.addInterceptor(logbackInterceptor).addPathPatterns("/**");
    }
}

性能优化策略

拦截器在请求处理过程中可能会影响系统性能,以下是一些性能优化策略:

减少拦截器数量:尽量将相关功能集中到一个拦截器中,避免创建过多的拦截器。
精确配置拦截规则:通过addPathPatterns和excludePathPatterns方法精确配置拦截规则,避免不必要的拦截。
使用异步处理:在拦截器中使用异步处理,避免阻塞请求处理过程。
使用缓存:在拦截器中使用缓存,减少对数据库或其他资源的访问。

监听器

介绍

在Spring Boot中,监听器(Listener)的概念并不直接等同于传统Java EE或Servlet环境中的监听器,如ServletContextListener、HttpSessionListener等。Spring Boot作为一个现代化的、基于Spring框架的简化开发平台,它更多地依赖于Spring的事件发布-监听机制(Application Events)来处理类似监听器的功能。

Spring的事件发布-监听机制

Spring的事件发布-监听机制允许应用程序组件之间进行解耦的通信。当一个组件发生某个特定事件时,它可以发布一个事件,然后其他组件可以监听这个事件并做出响应。这种机制是通过ApplicationEvent类和ApplicationListener接口实现的。

ApplicationEvent:所有Spring事件类的基类。自定义事件需要继承这个类。
ApplicationListener:这是一个泛型接口,用于监听特定类型的事件。实现这个接口的类必须指定它们希望监听的事件类型。

SpringBoot提供的内置监听器

ApplicationStartingEvent:应用程序开始启动时触发
ApplicationEnvironmentPreparedEvent:应用程序环境准备好时触发,此时上下文还没有创建
ApplicationContextInitializedEvent:应用程序上下文创建之前触发
ApplicationPreparedEvent:应用程序上下文创建完成后触发,此时所有的bean已经加载完成
ApplicationStartedEvent:应用程序启动完成时触发
ApplicationReadyEvent:应用程序已经准备好接收请求时触发
ApplicationFailedEvent:应用程序启动失败时触发

实现监听的器的方法

实现ApplicationListener

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * @author zjh
 * @className CustomEventListener
 * @date 2024/7/29
 * @description TODO
 **/
@Component
public class CustomEventListener implements ApplicationListener<ApplicationEvent> {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        // 处理事件逻辑
        System.out.println("Spring Boot 应用启动... " + event.toString());
    }
}

注: @Component 是 Spring 框架中的一个核心注解,它用于标记一个类作为 Spring 容器中的一个组件(Bean),以便 Spring 可以自动检测到它,并对其进行管理。当 Spring 容器启动时,它会扫描带有 @Component 注解的类,并将其实例化、组装成 Spring 应用上下文(ApplicationContext)中的 Bean。

使用@EventListener注解

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyEventListener {

    @EventListener
    public void handleContextRefreshedEvent(ContextRefreshedEvent event) {
        // 你的逻辑
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2070948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据仓库系列 3:数据仓库的主要组成部分有哪些?

你是否曾经好奇过,当你在网上购物或使用手机应用时,背后的数据是如何被存储和分析的?答案就在数据仓库中。本文将为你揭开数据仓库的神秘面纱,深入探讨其核心组成部分,以及这些组件如何协同工作,将海量数据转化为有价值的商业洞察。 目录 引言:数据仓库的魔力1. 数据源和数据…

STM32 | STM32 FLASH第十二天(实现代码STM32CUBEMX)

点击上方"蓝字"关注我们 01、FLASH >>> 1、STM32 FLASH Flash内部存储器,内存器件的一种,是一种非易失性( Non-Volatile )内存。 flash闪存是非易失存储器,可以对称为块的存储器单元块进行擦写和再编程。任何flash器件的写入操作只能在空或已擦除的单元…

mac 虚拟机PD19运行E-prime实验遇到E-prime unable to set display mode:0*80004001问题解决

作者&#xff1a;50% unable to set display mode问题 总结&#xff1a; 1. 修改该Experiment的Devices中的Dispaly为640*680,或800*600。 2. 右键开始菜单中的E-Studio程序&#xff0c;打开文件所在位置&#xff0c;然后右键该文件&#xff0c;选择属性-兼容性&#xff0c;勾选…

【内网渗透】ICMP隧道技术,ICMP封装穿透防火墙上线MSF/CS

~ 会当凌绝顶&#xff0c;一览众山小 ~ 前言 博客主页&#xff1a;h0ack1r丶羽~ 从0到1~ 渗透测试中&#xff0c;如果攻击者使用各类上层隧道(例如&#xff1a;HTTP隧道、DNS隧道、常规正/反向端口转发等)进行的操作都失败了&#xff0c;常常会通过ping命令访问远程计算机&am…

医疗多模态大模型是什么?医学多模态模型总结:算法其实很简单,拼的就是硬件算力的问题!多模态大模型(医疗影像分析)

概念 医学多模态大模型是指利用多种不同的医学数据源和模型&#xff0c;通过深度学习和人工智能技术&#xff0c;构建一个综合性的大型模型&#xff0c;以实现更加准确和全面的医学数据分析和预测。 这种模型可以同时处理多种医学数据类型&#xff0c;如医学图像、病历文本、…

自动驾驶---各大车企的端到端之旅

1 背景 端到端技术的落地速度确实有些超出预料&#xff0c;随着以ChatGPT为代表的AI大模型的快速发展&#xff0c;使得自动驾驶系统也能够像人一样进行“思考”&#xff0c;推动了自动驾驶技术的迭代升级。 特斯拉端到端技术的落地&#xff0c;自动驾驶在这一技术上的变化使得自…

<C++> 二叉搜索树

目录 二叉搜索树 1. 概念 2. 二叉搜索树操作 2.1 基础结构 2.2 非递归版 1. 查找 2. 插入 3. 删除 2.3 递归版 1. 查找 2. 插入 3. 删除 2.4 拷贝构造函数 2.5 赋值运算符重载 2.6 析构函数 2.7 完整代码 3. 二叉搜索树的应用 4. 二叉搜索树的性能 二叉搜索树 1. 概念 二叉搜索…

机器学习算法那些事 | 这是我见过最通俗易懂的SVD(奇异值分解)算法介绍

本文来源公众号“机器学习算法那些事”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;这是我见过最通俗易懂的SVD&#xff08;奇异值分解&#xff09;算法介绍 线性代数是机器学习领域的基础&#xff0c;其中一个最重要的概念是奇…

手机号归属地查询如何用Java进行调用

一、什么是手机号归属地查询接口&#xff1f; 手机号归属地查询接口又叫手机号归属地、手机号信息查询、手机号查询&#xff0c;通过手机号查询归属地信息、是否虚拟运营商等。该接口可支持三大运营商&#xff0c;移动、电信、联通等。 二、手机号归属地查询接口适用场景有哪…

OpenCV+Python识别机读卡

背景介绍 正常机读卡是通过读卡机读取识别结果的&#xff0c;目前OpenCV已经这么强大了&#xff0c;尝试着用OpenCVPython来识别机读卡。要识别的机读卡长这样&#xff1a; 我们做以下操作&#xff1a; 1.识别答题卡中每题选中项结果。 不做以下操作&#xff1a; 1.不识别准…

【数据分析:RFM客户价值度模型】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本阶段和大家一起分享和探索大数据技术RFM客户价值度模型&#xff0c;本篇文章主要讲述了&#xff1a;RFM客户价值度模型等等。欢迎大家一起探索讨论&#xff01;&#xff01;&#xff01…

大数据-99 Spark 集群 Spark Streaming DStream 文件数据流、Socket、RDD队列流

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

GATK ReadsPathDataSource类介绍

GATK(Genome Analysis Toolkit)是一个广泛使用的基因组分析工具包,它的核心库之一是htsjdk,用于处理高通量测序数据。在GATK中,ReadsPathDataSource类是负责管理和提供读取高通量测序数据文件(如BAM、SAM、CRAM)的类。 常见使用场景 数据加载:在GATK的基因组分析工具链…

MySQL的MRR(Multi-Range Read)优化原理详解

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

LeetCode:反转区间内的链表

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 反转区间内的链表题目链接方法一&#xff1a;拆开反转…

【TB作品】PIC16F1719单片机,EEPROM,PFM,读写

对于PIC16F1719单片机&#xff0c;没有直接的EEPROM&#xff0c;而是使用高耐久度的程序闪存&#xff08;PFM&#xff09;作为非易失性数据存储区域。这个区域特别适合存储那些需要频繁更新的数据。读写这个内存区域需要操作一些特殊功能寄存器&#xff0c;比如用于地址的PMADR…

2.K8s集群搭建

K8s搭建 搭建方案kubeadm搭建系统初始化操作k8s Master节点初始化将node节点加入集群安装网络插件Calico集群测试 搭建方案 minikube&#xff1a;轻量化的Kubernetes集群&#xff0c;为了能够更好学习和体验k8s功能而推出的&#xff0c;借助个人PC的虚拟化环境就可以实现Kuber…

如何使用ssm实现基于java web的网上书城系统的设计与实现+vue

TOC ssm123基于java web的网上书城系统的设计与实现vue JAVA简介 Java主要采用CORBA技术和安全模型&#xff0c;可以在互联网应用的数据保护。它还提供了对EJB&#xff08;Enterprise JavaBeans&#xff09;的全面支持&#xff0c;java servlet API&#xff0c;JSP&#xff…

【Redis】Redis客户端——Jedis(Java)

Redis Java使用案例 环境配置引入依赖配置端⼝转发连接 Redis Server Java基础代码操作Redisset 和 getexsits 和 del 环境配置 引入依赖 Java 操作 redis 的客⼾端有很多. 其中最知名的是 jedis. 创建 maven 项⽬, 把 jedis 的依赖拷⻉到 pom.xml 中. <!-- https://mvnr…

ssrf--web-ssrfme例题

将web-ssrfme.zip解压缩在Ubuntu下 Docker-compose up -d 更新后的镜像重新启动容器 可以看到已经拉取成功ssrfme镜像 我们使用端口访问文件&#xff0c;可以看到有一个过滤条件&#xff0c;它限制了file&#xff0c;dict协议&#xff0c;127.0.0.1和localhost 也不能用&…