SpringBoot-全局处理异常,时间格式,跨域,拦截器,监听器

news2024/11/18 1:27:41

1.全局异常处理

使用ControllerAdvice与ExceptionHandler注解

/**
 * 全局异常处理程序
 *
 * @author 
 * @date 
 */
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public JsonResult handleException(Exception e) {
        e.printStackTrace();
        return JsonResult.error(e.getMessage());
    }

    /**
     * 处理业务异常
     *
     * @param e
     * @return {@link JsonResult}
     */
    @ExceptionHandler(BusinessException.class)
    public JsonResult handleBusinessException(BusinessException e) {
        e.printStackTrace();
        return JsonResult.error(e.getMessage());
    }

    /**
     * handle 方法参数无效异常
     *
     * @param e e
     * @return {@link JsonResult}
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public JsonResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        e.printStackTrace();
        return JsonResult.error(e.getBindingResult().getFieldError().getDefaultMessage());
    }

}

2.全局时间格式处理

配合第一种@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")联合使用了,哪些字段需要特殊对待的,就可以单独使用这个@JsonFormat注解进行处理了。

  • 如果是后台接收前端的时间数据,前端传递string类型的时间数据,后端要转换成的Date类型数据,可以使用@DateTimeFormat注解来接收参数
  • 如果后端向前端传递数据,默认是返回时间戳,如果想要优雅的格式,可以在模型的Date字段或get方法上使用@JsonFormat注解,这个注解上可以指定时间格式和时区
/**
 * @description: 日期时间全局格式化
 * @auth: wujiangbo
 * @date: 2022-03-09 17:38
 */
@JsonComponent
public class LocalDateTimeSerializerConfig {

    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;

    /**
     * Date 类型全局时间格式化
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilder() {
        return builder -> {
            TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");//获取时区
            DateFormat df = new SimpleDateFormat(pattern);//设置格式化模板
            df.setTimeZone(tz);
            builder.failOnEmptyBeans(false)
                    .failOnUnknownProperties(false)
                    .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                    .dateFormat(df);
        }; }

    /**
     * LocalDate 类型全局时间格式化
     */
    @Bean
    public LocalDateTimeSerializer localDateTimeDeserializer() {
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
    }

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());
    }
}

3.跨域问题

@Configuration
/**
 * 告诉浏览器,我允许哪些服务器访问,哪些请求方式访问,是否运行携带请求头
 */
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //2.允许的域,不要写*,否则cookie就无法使用了
        //config.addAllowedOriginPattern("*");
        config.addAllowedOriginPattern("http://127.0.0.1:8081");
        config.addAllowedOriginPattern("http://localhost:8081");
        config.addAllowedOriginPattern("http://127.0.0.1:80");
        config.addAllowedOriginPattern("http://localhost:80");
        config.addAllowedOriginPattern("http://127.0.0.1");
        config.addAllowedOriginPattern("http://localhost");

        //3.是否允许发送Cookie信息
        config.setAllowCredentials(true);
        //4.允许的请求方式
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");
        //5.允许的头信息
        config.addAllowedHeader("*");

        //6.添加映射路径,我们拦截一切请求
        UrlBasedCorsConfigurationSource configSource = new
                UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        //7.返回新的CorsFilter.
        return new CorsFilter(configSource);
    }
}

4. 配置拦截器

如何定义SpringMVC的拦截器

SpringMVC 的拦截器主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、判断登录等功能上

第1步,定义拦截器:可以实现 HandlerInterceptor 接口来自定义拦截器,接口定义了三个方法,preHandler方法是在请求到达处理器之前执行,postHandler方法是在请求经过处理器之后、解析试图之前执行,afterCompletion方法是在视图渲染之后、返回客户端之前执行

第2步,配置拦截器:在springmvc的配置文件xml中或配置类中,配置所有拦截路径,以及需要放行的路径

SpringMVC的执行原理

  1. DispatcherServlet:请求打过来由DispatcherServlet处理,它是 SpringMVC 中的前端控制器(中央控制器), 负责接收 Request 并将 Request 转发给对应的处理组件
  2. HandlerMapping:HandlerMapping 维护了 url 和 Controller(Handler)的 映 射关系 。 DispatcherServlet 接 收 请求, 然 后 从 HandlerMapping 查找处理请求的Controller(Handler),标注了@RequestMapping 的每个 method 都可以看成是一个 Handler,HandlerMapping 在请求到达之后, 它的作用便是找到请求相应的处理器 Handler 和 Interceptors。
  3. HandlerAdapter:SpringMVC通过HandlerAdapter对Handler进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。它的作用就是按照特定的规则去执行 Controller (Handler)
  4. Handler : Controller (Handler)负责处理请求,Controller 执行后并返回 ModelAndView 对象,其中包括了数据模型和逻辑视图,ModelAndView 是封装结果 视图的组件。Handler把结果返回给HandlerAdapter,HandlerAdapter把结果返回给DispatcherServlet前端控制器。
  5. ViewResolver:DispatcherServlet收到ModelAndView,调用视图解析器(ViewResolver)来解析HandlerAdapter传递的ModelAndView。Handler执行完成后返回的是逻辑视图,也就是视图名字,一个String ,还有一个Model就是数据模型,封装成ModelAndView。ViewResolver视图解析的作用就是根据视图名,把本地模板文件(比如:xx.jsp;xx.ftl)解析为View视图对象。View用来渲染视图,也就是负责把Handler返回的数据模型model,填充到模板(jsp;ftl)形成html格式的静态内容。
  6. 最后就是把生成的html通过response写给浏览器,浏览器进行html渲染展示。

1.创建拦截器

  1. HandlerInterceptor是接口,我们可以实现该接口来定义拦截器,
  2. HandlerInterceptorAdapter是抽象类,它实现了HandlerInterceptor接口的子接口AsyncHandlerInterceptor,我们可以继承该类来定义拦截器,它简化拦截器的实现,默认preHandler返回true
/**
 * 登录拦截器
 *
 * @author 
 * @date 
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 前置拦截器
     *
     * @param request  请求
     * @param response 响应
     * @param handler  处理器
     * @return boolean
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        Boolean tag = false;
        if (token == null) {
            token = request.getParameter("token");
            tag = true;
        }
        Object tokenObj = redisTemplate.opsForValue().get(token);
        //token为null,说明没有登录,跳转到登录页面
        if (tokenObj == null) {
            responseMessage(response);
            if (tag) {
                response.sendRedirect("http://127.0.0.1/pages/login/login.html");
            }
            return false;
        }
        return true;
    }

    /**
     * 被拦截后的响应消息
     *
     * @param response 响应
     * @throws IOException ioexception
     */
    private static void responseMessage(HttpServletResponse response) throws IOException {
        //告诉浏览器响应数据类型
        response.setContentType("application/json;charset=UTF-8");
        //设置响应数据
        PrintWriter writer = response.getWriter();
        writer.write("{\"code\": \"403\", \"success\": false, \"msg\": \"请先登录\"}");
    }
}

2.添加拦截器,使用拦截器

/**
 * 登录拦截器配置类
 *
 * @author 
 * @date 2023/12/18
 */
@Configuration
public class LoginInterceptorConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //启用登录拦截器
        registry.addInterceptor(loginInterceptor)
                //拦截所有请求
                .addPathPatterns("/**")
                //登录放行
                .excludePathPatterns("/login/**");
    }
}

5.集成Servllet组件,配置监听器

第一步:继承ServletContextListener

public interface ServletContextListener extends EventListener {

    //当servlet初始化上下文容器时触发
    public default void contextInitialized(ServletContextEvent sce) {
        	// 获取Servlet上下文
            ServletContext servletContext = sce.getServletContext();
            // 获取springMVC上下文
            WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
    }

	//当servlet销毁上下文容器时触发
    public default void contextDestroyed(ServletContextEvent sce) {
    }
}

第二步:扫描监听器

@ServletComponentScan("cn.lgc.blog.listenter")//扫描servlet监听器
public class BlogApp {
    public static void main(String[] args) {
        SpringApplication.run(BlogApp.class, args);
    }
}

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

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

相关文章

Vue3 中 this 一分钟了解

Vue3 中 this 在Vue3的开发过程中,this的使用方式和Vue2有着显著的不同,特别是在组合式API(Composition API)的引入后。本文将深入探讨Vue3中this的使用,解析其底层源码,并探讨这种设计背后的原因&#xff…

Heart Animated Realistic 心脏运动模型素材带动画

Realistic Heart具有两个多边形质量的网格,具有详细的解剖结构,并配有高清纹理2048x2048,在高低多边形网格上具有高清法线贴图,可在教育、游戏和虚拟现实场景中获得更好、更真实的效果。 还具有完整的心动周期。 下载:​​Unity资源商店链接资源下载链接 效果图:

51单片机如何判断浮点数nan

使用这个函数进行判断 帮助信息内的描述如下 _chkfloat_ #include <intrins.h> unsigned char _chkfloat_ (float val); /* number for error checking */ Description: The _chkfloat_ function checks the status of a floating-point number. Return Value: The…

短视频去水印解析api接口使用文档

短视频去水印解析api接口&#xff0c;支持各大平台短视频和图集。 请求示例&#xff1a;https://www.dspqsy.vip/spapi?key密钥&url短视频链接 返回数据格式&#xff1a;JSON 请求方式&#xff1a;GET/POST 请求参数&#xff1a;url (短视频分享的URL) PHP 源码&…

C语言数组探秘:数据操控的艺术【下】

承接上篇&#xff0c;我们继续讲数组的内容。 八.二维数组的使用 当我们掌握了二维数组的创建和初始化&#xff0c;那我们怎么使用二维数组呢&#xff1f;其实二维数组访问也是使用下标的形式的&#xff0c;二维数组是有行和列的&#xff0c;只要锁定了行和列就能唯一锁定数组中…

Race Karts Pack 全管线 卡丁车赛车模型素材

是8辆高细节、可定制的赛车,内部有纹理。经过优化,可在手机游戏中使用。Unity车辆系统已实施-准备驾驶。 此套装包含8种不同的车辆,每种车辆有8-10种颜色变化,总共有75种车辆变化! 技术细节: -每辆卡丁车模型使用4种材料(车身、玻璃、车轮和BrakeFlare) 纹理大小: -车…

屏幕活动保存到NAS

目录 一、套件选择 二、员工机准备 1、下载安装ffmpeg 2、安装运行rtsp-simple-server 3、生成桌面流 4、接收查看桌面变化 三、NAS端配置 1、安装套件 2、配置Surveillence Station 3、实时监看 4、历史记录查看 5、录像文件操作 四、总结 朋友的朋友找上我,说到…

网络安全专业,在校大学生如何赚外快,实现财富自由?零基础入门到精通,收藏这一篇就够了

如今&#xff0c;计算机行业内卷严重&#xff0c;我们不找点赚外快的路子这么行呢&#xff1f; 今天就来说说网络安全专业平时都怎么赚外快。 一、安全众测 国内有很多成熟的src众测平台&#xff0c;如漏洞盒子、火线众测、补天、CNVD、漏洞银行等。一些大厂也有自己的src&a…

大厂必问 · 如何防止订单重复?

在电商系统或任何涉及订单操作的场景中&#xff0c;用户多次点击“提交订单”按钮可能会导致重复订单提交&#xff0c;造成数据冗余和业务逻辑错误&#xff0c;导致库存问题、用户体验下降或财务上的错误。因此&#xff0c;防止订单重复提交是一个常见需求。 常见的重复提交场…

Dapper介绍及特性

一、Dapper介绍及特性 Dapper是一个.NET平台上的轻量级对象关系映射&#xff08;ORM&#xff09;工具&#xff0c;它通过扩展IDbConnection接口&#xff0c;提供了一系列的扩展方法来执行SQL查询并将结果映射到.NET对象中。Dapper以其高性能和简单易用著称&#xff0c;特别适合…

springboot中有哪些方式可以解决跨域问题

文章目录 什么是跨域解决方案CrossOrigin注解实现WebMvcConfigurer接口CorsFilter过滤器如何选择&#xff1f; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 Talk is cheap &#xff0…

Keepalived+Nginx 高可用集群(双主模式)

1.基础环境配置 [rootlb1 ~]# systemctl stop firewalld # 关闭防火墙 [rootlb1 ~]# sed -i s/^SELINUX.*/SELINUXdisabled/ /etc/sysconfig/selinux # 关闭selinux&#xff0c;重启生效 [rootlb1 ~]# setenforce 0          …

计算机毕业设计 基于Hadoop的智慧校园数据共享平台的设计与实现 Python 数据分析 可视化大屏 附源码 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

深度拆解:如何在Facebook上做跨境电商?

国内社交媒体正在逐渐兴盛&#xff0c;海外也不例外。在数字营销的新时代&#xff0c;Facebook已成为跨境电商不可或缺的平台之一。通过Facebook的巨大流量&#xff0c;卖家可以更好的触及潜在消费者&#xff0c;以实现销售增长。本文就深度拆解一下&#xff0c;卖家如何利用Fb…

STM32基础学习笔记-DHT11单总线协议面试基础题7

第七章、DHT11: 单总线协!议 常见问题 1、DHT11是什么 &#xff1f;有什么特性 &#xff1f; 2、单总线协议是什么 &#xff1f;原理 &#xff1f;DHT11的单总线协议的组成 &#xff1f; ## 1、DHT11定义 单总线协议是一种用于在多个设备之间进行通信的协议&#xff0c;所有…

从 Shapley 到 SHAP — 数学理解

如何计算 SHAP 特征贡献的概述 假设你(玩家 1)和朋友(玩家 2)参加了一场 Kaggle 比赛,你最终赢得了 10,000 元的一等奖。现在,你想公平地分配这笔钱。你的朋友建议你平分。但是,你的超参数调整技能更出色。你相信你应该得到更大的份额,因为你为团队做出了更多贡献。考虑…

LeetCode每日一练 —— 88. 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 思路&#xff1a;用 下标充当指针&#xff0c;…

排序--希尔排序

希尔排序介绍 希尔排序核心思想就是:1,分组;2,直接插入排序:越有序越快 希尔排序就是多次利用直接插入排序的一个排序算法. 希尔排序的算法思想:间隔式分组,利用直接插入排序让组内有序,然后缩小分组再次排序,直到组数为1希尔排序的理论基础就是直接插入排序越有序越快; 希尔排…

《向量数据库指南》——Zilliz迁移服务:一键解锁跨平台数据迁移新纪元

在数据驱动的时代背景下&#xff0c;非结构化数据的处理与迁移已成为企业数字化转型中不可或缺的一环。随着向量数据库技术的飞速发展&#xff0c;尤其是像Milvus这样的高性能向量数据库系统的广泛应用&#xff0c;如何高效、安全、准确地实现数据在不同系统间的迁移&#xff0…

软考高级:系统设计 - MDA 模型 AI 解读

生活化例子 想象一下&#xff0c;你要建造一栋房子。建房子需要三个阶段&#xff1a; CIM (概念阶段)&#xff1a;这是你想象中的房子。你大概知道房子需要几间卧室、厨房、卫生间&#xff0c;但是还没有详细的设计图。就像在脑海中有个大概的想法&#xff1a;我要建个温馨的…