【Spring】统一功能处置惩罚

打印 上一主题 下一主题

主题 887|帖子 887|积分 2661



目录

前言
拦截器
什么是拦截器?
拦截器的利用
自定义拦截器
注册并配置拦截器
拦截器详解
拦截路径
 拦截器实行流程
适配器模式
统一数据返回格式
优点
统一异常处置惩罚


前言

在前面中,我们已经学习了spring中的一些常用操纵,那么本篇,我们就继续往下深入学习。
我们在做一些小项目的时间,假如我们想要判定用户是否已经登录,按照我们前面的学习,我们就需要用到seesion来举行判定。设想一下,我们有几个界面,而这几个界面都需要在用户登录后才能举行检察的,就想淘宝,如果我们未登录,那么他就跳转到登录界面。

 对于这样的操纵,我们的界面不止一个,那么我们对应的在每个页面调用后端的API,此中的方法每次都需要判定用户是否登录,这样会让代码冗余,以是,在Spring中,给我们提供了一种功能,能够让我们将这些重复的代码举行抽取——拦截器。
拦截器

什么是拦截器?

拦截器(Interceptor)是一种在哀求处置惩罚流程中,对哀求和响应举行拦截和预处置惩罚的机制。它允许开发者在哀求到达目标处置惩罚器(如控制器方法)之前或之后实行统一的逻辑,从而实现诸如权限校验、日记纪录、性能监控、哀求过滤等功能。

拦截器的利用

拦截器的利用步骤分为两步:
   

  • 定义拦截器
  • 注册并配置拦截器 
  自定义拦截器

在Spring  MVC框架中,拦截器通过实现 HandlerInterceptor  接口来定义拦截逻辑
  1. package com.example.demo.interceptor;
  2. import com.example.demo.Result.Results;
  3. import com.example.demo.constant.Constants;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import jakarta.servlet.http.HttpServletRequest;
  6. import jakarta.servlet.http.HttpServletResponse;
  7. import jakarta.servlet.http.HttpSession;
  8. import lombok.extern.slf4j.Slf4j;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.http.HttpStatus;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.web.servlet.HandlerInterceptor;
  13. import org.springframework.web.servlet.ModelAndView;
  14. /**
  15. * 登录拦截器,用于在请求处理前验证用户是否已登录
  16. */
  17. @Slf4j
  18. @Component
  19. public class LoginInterceptor  implements HandlerInterceptor {
  20.     @Autowired
  21.     private ObjectMapper objectMapper;
  22.    
  23.     /**
  24.      * 在请求处理之前进行拦截
  25.      *
  26.      * @param request  HttpServletRequest对象,用于获取请求信息
  27.      * @param response HttpServletResponse对象,用于设置响应信息
  28.      * @param handler  请求处理器,可以是HandlerMethod或RequestMappingHandler等
  29.      * @return boolean 表示是否继续执行其他拦截器和目标方法。返回true表示继续执行,返回false表示中断执行。
  30.      * @throws Exception 抛出异常表示拦截器处理出现错误
  31.      */
  32.     @Override
  33.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  34.         log.info("方法执行前");
  35.         //进行登录校验
  36.         HttpSession session= request.getSession(false);
  37.         if(session!=null&&"true".equals(session.getAttribute(Constants.USER_SESSION_KEY))){
  38.             // 用户已登录,继续执行请求
  39.             return true;
  40.         }
  41.         // 用户未登录,返回未授权错误信息
  42.         Results results=Results.unLogin();
  43.         response.setStatus(HttpStatus.UNAUTHORIZED.value());
  44.         response.getOutputStream().write(objectMapper.writeValueAsString(results).getBytes());
  45.         response.setContentType("application/json;charset=UTF-8");
  46.         response.getOutputStream().close();
  47.         return false;
  48.     }
  49.     /**
  50.      * 在请求处理之后,视图渲染之前进行拦截
  51.      *
  52.      * @param request  HttpServletRequest对象,用于获取请求信息
  53.      * @param response HttpServletResponse对象,用于设置响应信息
  54.      * @param handler  请求处理器,可以是HandlerMethod或RequestMappingHandler等
  55.      * @param modelAndView ModelAndView对象,用于添加模型数据或修改视图
  56.      * @throws Exception 抛出异常表示拦截器处理出现错误
  57.      */
  58.     @Override
  59.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  60.         log.info("方法执行后");
  61.         HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
  62.     }
  63.     /**
  64.      * 在请求完成之后执行的方法
  65.      *
  66.      * @param request 传入的HTTP请求对象,包含请求相关数据
  67.      * @param response 传入的HTTP响应对象,包含响应相关数据
  68.      * @param handler 处理请求的处理器对象,可以是任何类型的对象
  69.      * @param ex 请求处理过程中发生的异常,如果没有异常,则为null
  70.      * @throws Exception 根据具体实现可能会抛出的异常
  71.      *
  72.      * 此方法主要用于在请求处理完成后进行一些清理工作,例如关闭数据库连接、释放资源等
  73.      * 它是在请求处理的最后一步调用的,确保了所有处理逻辑已经执行完毕
  74.      */
  75.     @Override
  76.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  77.         HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
  78.     }
  79. }
复制代码
  

  • preHandler():该方法是在目标方法实行前实行的。若返回true,则继续实行后续的业务逻辑,返回false,则中断后续的操纵。
  • postHandler():该方法是在目标方法实行后再实行的。
  • afterCompletion():该方法是在视图渲染之后实行的,在postHandler()方法之后实行,但由于现在前后端分离,以是后端根本上接触不到视图的渲染,这个方法用的少。
  注册并配置拦截器

注册配置拦截器我们需要实现 WebMvcConfiguer 接口,并实现此中的 addInterceptors 方法。
  1. package com.example.demo.config;
  2. import com.example.demo.interceptor.LoginInterceptor;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  7. /**
  8. * 配置类用于配置Web相关的设置
  9. */
  10. @Configuration
  11. public class WebConfig implements WebMvcConfigurer {
  12.     /**
  13.      * 登录拦截器,用于拦截请求以进行登录验证
  14.      */
  15.     @Autowired
  16.     private LoginInterceptor loginInterceptor;
  17.     /**
  18.      * 添加拦截器以配置请求的预处理和后处理
  19.      *
  20.      * @param registry 拦截器注册对象,用于注册自定义拦截器
  21.      */
  22.     @Override
  23.     public void addInterceptors(InterceptorRegistry registry) {
  24.         //注册拦截器
  25.         registry.addInterceptor(loginInterceptor)
  26.                 //拦截以"/book/"开头的所有请求
  27.                 .addPathPatterns("/book/**")
  28.                 //排除"/user/login"请求,使其不被拦截
  29.                 .excludePathPatterns("/user/login");
  30.     }
  31. }
复制代码
假如此时我们未登录,调用一下查询功能:

可以看到,会对哀求举行拦截。
 知道了拦截器的是怎样利用的,那么就来进一步了解拦截器。
拦截器详解

拦截器的利用细节我们讲以下两个部门:
   

  • 拦截路径配置
  • 拦截器实现原理
  拦截路径

拦截路径指的是我们定义的拦截器对哪些哀求生效,我们在注册配置拦截器的时间,通过 addPathPatterns() 方法就可以来指定要拦截哪些哀求,也可以通过 excludePathPatterns() 方法来指定哪些哀求不需要拦截
关于拦截路径设置的规则,有以下几种:
拦截路径含义举例
/*

一级路径
能匹配/user,/book,但不能匹配/book/getList等

/**恣意级路径能匹配/user,/user/login,即恣意路径都可以匹配
/book/*/book下的一级路径能匹配/book/addBook,不能匹配/book/addBook/get,/book
/book/**/book下的恣意级路径能匹配/book,/book/addBook,/book/addBook/2,不能匹配/user/login
   上面的这些拦截规则可以拦截项目中的URL,包括静态文件(如图片文件、JS和CSS等文件).
  如果我们利用下面这种拦截规则,就会将前端界面的哀求也给拦截住。 

 我们可以通过设置前端界面不拦截:
  1. package com.example.demo.config;
  2. import com.example.demo.interceptor.LoginInterceptor;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  7. import java.util.ArrayList;
  8. import java.util.Arrays;
  9. import java.util.List;
  10. /**
  11. * 配置类用于配置Web相关的设置
  12. */
  13. @Configuration
  14. public class WebConfig implements WebMvcConfigurer {
  15.     /**
  16.      * 登录拦截器,用于拦截请求以进行登录验证
  17.      */
  18.     @Autowired
  19.     private LoginInterceptor loginInterceptor;
  20.    
  21.     public List<String> excludePath= Arrays.asList("/user/*",
  22.             "/css/**",
  23.             "/js/**",
  24.             "/img/**",
  25.             "/**/*.html");//放行路径
  26.     /**
  27.      * 添加拦截器以配置请求的预处理和后处理
  28.      *
  29.      * @param registry 拦截器注册对象,用于注册自定义拦截器
  30.      */
  31.     @Override
  32.     public void addInterceptors(InterceptorRegistry registry) {
  33.         //注册拦截器
  34.         registry.addInterceptor(loginInterceptor)
  35.                 //拦截以"/book/"开头的所有请求
  36.                 .addPathPatterns("/**")
  37.                 //排除"/user/login"请求,使其不被拦截
  38.                 .excludePathPatterns(excludePath);
  39.     }
  40. }
复制代码

这样,就可以获取到前端界面。
 拦截器实行流程

在没有添加拦截器之前,我们调用顺序是:

在添加拦截器后:

   

  • 在添加完拦截器后,实行Controller中的方法之前,哀求会先被拦截器拦截住,实行preHandler() 方法,这个方法会返回一个布尔范例的值。如果返回true,说明要放行,继续访问controller中的方法;如果返回false,则不会放行(controller中的方法不会实行).
  • controller中的方法实行完后,会继续实行 postHandler() 方法以及 afterCompletion() 方法,实行完毕后,终极给浏览器响应数据。
  
我们通过观察日记,可以看到当Tomcat在启动之后,会有核心的类 DispatcherServlet 来控制程序的实行顺序。

   全部的哀求都会先进入到DispatcherServlet 中,实行 doDispatch() 调度方法,如果有拦截器,就会先实行拦截器中 preHandle() 方法中的代码,如果 preHandle() 返回true,那么就会继续访问controller中的方法,当controller中的方法实行完毕,就会再回过来实行 postHandle() 和 afterCpmpletion() 方法,返回给DispatcherServlet,终极给浏览器响应数据。
  

   我们观察 DispatcherServlet 中的源码,就可以看到这三个方法的实行流程:

DispatcherServlet  源码中,我还可以看到利用了适配器模式:
适配器模式


    适配器模式也叫包装器模式。将一个类的接口,转换成客户期望的另有一个接口,适配器让本来接口不兼容的类可以合作无间。
  简单来说:就是目标类不能直接利用,通过一个新类举行包装,适配调用方利用,把两个不兼容的接口通过一定的方式使之兼容

 利用适配器来使两个接口兼容:

实在在我们前面学习Spring日记的时间,此中的 slf4j 就利用到了适配器模式,我们想要打印日记的时间,只需要调用slf4j的API,而它会自动去调用底层的 log4j 大概 logback 来打印日记。
示例:
  1. package com.example.demo.config;
  2. /**
  3. * Slf4j接口定义了打印日志的方法
  4. */
  5. public interface Slf4j {
  6.     /**
  7.      * 打印日志信息
  8.      * @param message 需要打印的日志信息
  9.      */
  10.     void print(String message);
  11. }
  12. /**
  13. * Log4j类提供了具体的日志打印实现
  14. */
  15. class Log4j{
  16.     /**
  17.      * 打印日志信息
  18.      * @param message 需要打印的日志信息
  19.      */
  20.     void log4jPrint(String message){
  21.         System.out.println("Log4j: "+message);
  22.     }
  23. }
  24. /**
  25. * Slf4jAdapter类是Slf4j接口与Log4j类之间的适配器
  26. * 它使得Log4j可以通过Slf4j接口来打印日志
  27. */
  28. class Slf4jAdapter  implements Slf4j{
  29.    
  30.     /**
  31.      * log4j实例用于实际的日志打印
  32.      */
  33.     private Log4j log4j;
  34.    
  35.     /**
  36.      * 构造函数,接收一个Log4j实例
  37.      * @param log4j Log4j实例,用于实际的日志打印
  38.      */
  39.     public Slf4jAdapter(Log4j log4j) {
  40.         this.log4j = log4j;
  41.     }
  42.    
  43.     /**
  44.      * 实现Slf4j接口的print方法,通过Log4j实例来打印日志
  45.      * @param message 需要打印的日志信息
  46.      */
  47.     @Override
  48.     public void print(String message) {
  49.         log4j.log4jPrint(message);
  50.     }
  51. }
  52. /**
  53. * Demo类包含主程序,用于演示Slf4jAdapter的使用
  54. */
  55. class Demo{
  56.     /**
  57.      * 主函数,创建Log4j实例并通过Slf4jAdapter适配,然后打印日志信息
  58.      * @param args 命令行参数
  59.      */
  60.     public static void main(String[] args) {
  61.         Log4j log4j = new Log4j();
  62.         Slf4j slf4j = new Slf4jAdapter(log4j);
  63.         slf4j.print("Hello World");
  64.     }
  65. }
复制代码
可以看到,我们不需要修改log4j的api,只需要利用适配器,就可以更换日记框架,维护系统。
那么为什么不直接调用Log4j呢? 
    适配器模式实在可以看做一种“赔偿模式”,用来调停计划上的缺陷,利用这种模式是无奈之举。如果在计划初期,能够规避接口不兼容的问题,那么就不需要利用适配器模式了。
  统一数据返回格式

我们在做项目的时间,如果前端调用后端返回的数据格式都差别,后序如果修改起来,就显得有点杂乱,以是我们可以对返回的数据格式举行统一——统一数据返回格式
在SpringBoot,如果我们想要在返回数据响应之前对数据举行一些逻辑操纵,那么我们就需要利用到注解 @ControllerAdvice ResponseBodyAdvice 接口的实现。
定义下存常量的类:
  1. package com.example.demo.constant;
  2. public class Constants {
  3.     public static final String USER_SESSION_KEY = "user";
  4.     public static final Integer SUCCESS_CODE = 200;//成功
  5.     public static final Integer FAIL_CODE = -2;//失败
  6.     public static final Integer UNLOGIN_CODE = -1;//未登录
  7. }
复制代码
统一返回数据格式:
  1. package com.example.demo.Result;
  2. import com.example.demo.constant.Constants;
  3. import lombok.Data;
  4. @Data
  5. public class Results<T> {
  6.     private Integer code;//200成功,-1未登录,-2程序异常
  7.     private String msg;
  8.     private  T data;
  9.     public static <T> Results success(T data){
  10.         Results results=new Results();
  11.         results.setCode(Constants.SUCCESS_CODE);
  12.         results.setMsg("");
  13.         results.setData(data);
  14.         return results;
  15.     }
  16.     public static  Results unLogin(){
  17.         Results results=new Results();
  18.         results.setCode(Constants.UNLOGIN_CODE);
  19.         results.setMsg("用户未登录");
  20.         return results;
  21.     }
  22.     public static <T> Results fail(String msg){
  23.         Results results=new Results();
  24.         results.setCode(Constants.FAIL_CODE);
  25.         results.setMsg(msg);
  26.         return results;
  27.     }
  28.     public static <T> Results fail(){
  29.         Results results=new Results();
  30.         results.setCode(Constants.FAIL_CODE);
  31.         results.setMsg("程序出现异常");
  32.         return results;
  33.     }
  34. }
复制代码
响应处置惩罚:
  1. package com.example.demo.config;
  2. import com.example.demo.Result.Results;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import lombok.SneakyThrows;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.core.MethodParameter;
  7. import org.springframework.http.MediaType;
  8. import org.springframework.http.server.ServerHttpRequest;
  9. import org.springframework.http.server.ServerHttpResponse;
  10. import org.springframework.web.bind.annotation.ControllerAdvice;
  11. import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
  12. /**
  13. * 全局响应处理,统一处理所有响应
  14. * 该类实现了ResponseBodyAdvice接口,用于自定义响应体
  15. */
  16. @ControllerAdvice
  17. public class ResponseAdvice implements ResponseBodyAdvice {
  18.     @Autowired
  19.     private ObjectMapper objectMapper;
  20.     /**
  21.      * 判断是否支持当前的返回类型和转换器类型
  22.      * 该方法始终返回true,表示支持所有类型的响应处理
  23.      */
  24.     @Override
  25.     public boolean supports(MethodParameter returnType, Class converterType) {
  26.         return true;
  27.     }
  28.     /**
  29.      * 在写入响应体前处理数据
  30.      * 该方法根据返回的数据类型,进行相应的处理和封装
  31.      * 如果返回类型是String,则将其作为成功消息封装进Results对象
  32.      * 如果返回类型已经是Results,则直接返回
  33.      * 否则,将返回值作为成功数据封装进Results对象
  34.      */
  35.     @SneakyThrows
  36.     @Override
  37.     public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
  38.         if(body instanceof String){
  39.             return  objectMapper.writeValueAsString(Results.success(body));
  40.         }
  41.         if(body instanceof Results){
  42.             return body;
  43.         }
  44.         return Results.success(body);
  45.     }
  46. }
复制代码
调用一下看看:


可以看到,这样的话,如果前端想要获取到我们后端的数据,以及后续修改操纵等,就更加清晰容易操纵了。
我们再来看一处地方:

   这里为什么要这样写呢?
   SpringMVC默认会注册一些自导的HttpMessageConverter(从先后顺序排序分别为ByteArrayHttpMessageConverter、StringHttpMessageConverter、SourceHttpMessageConverte、SourceHttpMessageConverterr、AllEncompassingFormHttpMessageConverter)
  

  而此中的 AllEncompassingFormHttpMessageConverter  会根据项目依靠环境添加对应的HttpMessageConverter。
  

  在依靠中引⼊jackson包后,容器会把 MappingJackson2HttpMessageConverter ⾃动注册到
messageConverters 链的末尾。Spring会根据返回的数据范例,从 messageConverters 链选择合适的 HttpMessageConverter。当返回的数据是⾮字符串时,使⽤的MappingJackson2HttpMessageConverter 写⼊返回对象当返回的数据是字符串时, StringHttpMessageConverter 会先被遍历到,这时会以为
StringHttpMessageConverter 可以利用

  

  可以看到子类StringHttpMessageConverter中的addDefaultHeaders()方法接收的参数为String,但我们需要返回的范例为Results范例,以是这里我们就需要利用SpringBoot内置提供的Jackson来实现信息的序列化。即:
  

  

  • @SneakyThrows是 Lombok 提供的一个注解,用于简化 Java 中的异常处置惩罚。它允许开发者在方法中抛出受检异常(checked exceptions),而无需在方法签名中显式声明 throws,也不需要利用 try-catch块。
  优点

   

  • ⽅便前端程序员更好的接收息争析后端数据接口返回的数据
  • 低沉前端程序员和后端程序员的沟通本钱,按照某个格式实现就可以了,由于全部接口都是这样返回的
  • 有利于项目统⼀数据的维护和修改
  • 有利于后端技术部⻔的统⼀规范的标准制定,不会出现特别古怪的返回内容
  统一异常处置惩罚

 当我们的程序出现异常时,我们也可以对这些异常举行统一处置惩罚。
统一异常处置惩罚利用的是 @ControllerAdvice@ExceptionHandler 来实现的。
   

  • @ControllerAdvice 表⽰控制器关照类
  • @ExceptionHandler 是异常处置惩罚器,两个联合表示当出现异常的时间实行某个关照,也就是执⾏某个⽅法变乱
  1. package com.example.demo.config;
  2. import cn.hutool.core.io.resource.NoResourceException;
  3. import com.example.demo.Result.Results;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.springframework.http.HttpStatus;
  6. import org.springframework.web.bind.annotation.ControllerAdvice;
  7. import org.springframework.web.bind.annotation.ExceptionHandler;
  8. import org.springframework.web.bind.annotation.ResponseBody;
  9. import org.springframework.web.bind.annotation.ResponseStatus;
  10. import org.springframework.web.servlet.resource.NoResourceFoundException;
  11. /**
  12. * 全局异常处理类
  13. * 用于统一处理项目中的异常,提高代码的健壮性和用户体验
  14. */
  15. @ControllerAdvice
  16. @Slf4j
  17. @ResponseBody
  18. public class ErrorAdviceHandler {
  19.     /**
  20.      * 处理通用异常
  21.      * @param e 异常对象
  22.      * @return 返回处理结果
  23.      */
  24.     @ExceptionHandler
  25.     public Object handler(Exception e){
  26.         log.error("异常信息:{}",e.getMessage());
  27.         return Results.fail(e.getMessage());
  28.     }
  29.     /**
  30.      * 处理数组越界异常
  31.      * @param e 异常对象
  32.      * @return 返回处理结果
  33.      */
  34.     @ExceptionHandler
  35.     public Object handler(ArrayIndexOutOfBoundsException e){
  36.         log.error("异常信息:{}",e.getMessage());
  37.         return Results.fail(e.getMessage());
  38.     }
  39.     /**
  40.      * 处理空指针异常
  41.      * @param e 异常对象
  42.      * @return 返回处理结果
  43.      */
  44.     @ResponseStatus
  45.     @ExceptionHandler
  46.     public Object handler(NullPointerException e){
  47.         log.error("异常信息:{}",e.getMessage());
  48.         return Results.fail(e.getMessage());
  49.     }
  50.     /**
  51.      * 处理算数异常
  52.      * @param e 异常对象
  53.      * @return 返回处理结果
  54.      */
  55.     @ExceptionHandler
  56.     public Object handler(ArithmeticException e){
  57.         log.error("异常信息:{}",e.getMessage());
  58.         return Results.fail(e.getMessage());
  59.     }
  60.     /**
  61.      * 处理资源未找到异常
  62.      * @param e 异常对象
  63.      * @return 返回处理结果
  64.      */
  65.     @ResponseStatus(HttpStatus.NOT_FOUND)
  66.     @ExceptionHandler
  67.     public Object handler(NoResourceFoundException e){
  68.         log.error("异常信息:{}  path:{}",e.getDetailMessageCode(),e.getResourcePath());
  69.         return Results.fail(e.getMessage());
  70.     }
  71. }
复制代码
 测试案例:
  1. package com.example.demo.Controller;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. /**
  5. * Demo控制器类,用于处理演示项目的HTTP请求
  6. */
  7. @RestController
  8. @RequestMapping("/demo")
  9. public class DemoController {
  10.    
  11.     /**
  12.      * 处理/t1请求的方法
  13.      * 该方法演示了未处理的除零异常,用于教学或测试目的
  14.      *
  15.      * @return 成功信息字符串,但在执行中将引发除零异常
  16.      */
  17.     @RequestMapping("/t1")
  18.     public String t1(){
  19.         // 该行代码将产生除零异常
  20.         int a=1/0;
  21.         return "success";
  22.     }
  23.    
  24.     /**
  25.      * 处理/t2请求的方法
  26.      * 该方法演示了未处理的空指针异常,用于教学或测试目的
  27.      *
  28.      * @return 成功信息字符串,但在执行中将引发空指针异常
  29.      */
  30.     @RequestMapping("/t2")
  31.     public String t2(){
  32.         // 该行代码将产生空指针异常
  33.         String str=null;
  34.         str.length();
  35.         return "success";
  36.     }
  37.    
  38.     /**
  39.      * 处理/t3请求的方法
  40.      * 该方法演示了未处理的数组越界异常,用于教学或测试目的
  41.      *
  42.      * @return 成功信息字符串,但在执行中将引发数组越界异常
  43.      */
  44.     @RequestMapping("/t3")
  45.     public String t3(){
  46.         // 初始化一个包含三个元素的数组
  47.         int[] arr={1,2,3};
  48.         // 该行代码将产生数组越界异常
  49.         arr[3]=4;
  50.         return "success";
  51.     }
  52. }
复制代码

   此外,如果发生空指针异常大概其他异常,异常处置惩罚中有Exception和NullPointerException的话,优先实行具体的异常,即实行NullPointerException异常。
  具体异常优先于通用异常
  

以上就是本篇全部内容~
如有不敷,欢迎指正~ 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

石小疯

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表