SpringBoot自定义/error路径失效的解决

 更新时间:2022年01月27日 14:20:56   作者:虎口脱险OvO  
这篇文章主要介绍了SpringBoot自定义/error路径失效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

SpringBoot自定义/error路径失效

背景

最近使用SpringBoot做controller统一异常处理的时候,配置好映射路径(/error),使用SpringBoot自带的异常通知注解@ControllerAdvice配置好异常处理类,按理说在Controller发生异常的时候重定向到自定义错误页面(这里是重定向到SpringMVC的映射路径),可实际调试的时候却定向到了SpringBoot默认的错误页面。

配置信息

此处配置只是一个小示例,省略了对异常的处理。

@ControllerAdvice(annotations = Controller.class)
public class ExceptionAdvice {    
    @ExceptionHandler({Exception.class})
    // 此方法参数有多个,具体可参考相关文档
    public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
       response.sendRedirect(request.getContextPath() + "/error");
    }
}
@Controller
public class HomeController {
    @GetMapping("/error")
    public String getErrorPage(){
        // 此处使用了Thymeleaf模板,返回的是页面
        return "/site/error/500";
    }
}

解决思路

由于我在controller中配置了/error的映射路径,我通过网页路径直接访问该路径也是上面那个错误页面,断点调试也没有进入我自定义的controller。

再看页面显示的状态码,不是404,说明该路径是没有问题的。

这个问题困惑了我很久,一开始没转过弯来。

说下我的解决思路,因为我在使用的SpringBoot配置文件是application.yml,这个文件在idea中会有提示,我在该配置文件中输入了error,如下图:

这里有一个server.error.path=/error,看到这个就大概知道原因了,路径冲突了,我在SpringMVC中配置的映射路径也是error。

尝试验证一下,将SpringMVC的路径修改了一下,果然可以正常访问了。

有没有可以不改变SpringMVC路径的方法呢?我一开始是在application.yml中加入下面这段配置:

server:
  error:
    # 此处可随便写一个路径,或者留空也行,只有不和自定义的error路径冲突
    path: 

这样确实可以解决路径冲突的问题,可是这只是去忽略它,而不是去修改它。

通过查阅资料发现,SpringBoot会为我们创建一个叫BasicErrorController的类,该类由Spring创建并默认用来处理Controller中的异常,如果能替换掉该类,就可以解决我们的问题。

如何替换?Spring提供的方法提供一个类型实现ErrorController接口,其实BasicErrorController也是实现了该类。

所有我们只需要将我们自定义ExceptionAdvice类实现该接口,实现相应方法即可,修改后代码如下:

@ControllerAdvice(annotations = Controller.class)
public class ExceptionAdvice implements ErrorController{    
    private static final String ERROR_PATH = "/error";    
    @ExceptionHandler({Exception.class})
    // 此方法参数有多个,具体可参考相关文档
    public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
       response.sendRedirect(request.getContextPath() + "/error");
    }
    
    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }
}

小结:其实就是一个很简单的问题,而我在一开始的时候却在纠结是不是注解使用错误之类的事,debug方向是对的,就是一时间没转过弯来,导致这个问题困扰了我挺长的时间,好在及时理清思路后能解决该问题。

SpringBoot的/error的自定义处理

在springboot项目里,如果没有统一异常处理,或者如果没有处理全面,又或者在springCloud zuul中调用微服务接口出错时,spring会自动把错误转发到默认给/error处理。

正常情况下,可以配置错误页面来给用户提示错误,如404,500等。但是在前后分离项目中,可能更期望给前台返回一个特定格式的json来展示错误信息。所以可以用代码来自定义异常错误信息。

/error端点的实现来源于SpringBoot的org.springframework.boot.autoconfigure.web.BasicErrorController,

它的具体定义如下

@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
    Map<String, Object> body = getErrorAttributes(request,isincludeStackTrace(request, MediaType.ALL)) ;
    HttpStatus status = getStatus(request);
    return new ResponseEntity<Map<String, Object>>(body, status);}

通过调用 getErrorAtt豆butes 方法来根据请求参数组织错误信息的返回结果,而这里的 getErrorAtt豆bu七es 方法会将具体组织逻辑委托给 org.springframework.boot.autoconfigure.web.ErrorAttributes接口提供的 ge七ErrorAttributes 来实现。

在 Spring Boot 的自动化配置机制中,默认会采用 org.springframework.boot.autoconfigure.web.DefaultErrorAttribut作为该接口的实现。

在spring注册这个bean的时候,使用了注解@ConditionalOnMissingBean(value = ErrorAttributes.class, search =SearchStrategy.CURRENT)

说明只有在不存在ErrorAttributes的bean的时候,才会使用DefaultErrorAttributes来处理,如果我们可以自定义一个,就可以使用我们的类来处理异常了。

编写一个类继承DefaultErrorAttributes

他有三个方法

public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex)
public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace)
public Throwable getError(RequestAttributes requestAttributes)

他们的执行顺序就如上述顺序。

我们可以在getErrorAttributes方法中拿到所有的异常信息,展示如下:

{"timestamp":1528190975129,"status":200,"error":"OK","exception":"java.lang.RuntimeException","message":"error............","path":"/a/b"}

可以在resolveException中拿到异常信息,如果需要返回json,则可以利用response来输出到前台,比如:

    

/* 使用response返回 */
        response.setStatus(HttpStatus.OK.value()); // 设置状态码
        response.setContentType(MediaType.APPLICATION_JSON_VALUE); // 设置ContentType
        response.setCharacterEncoding("UTF-8"); // 避免乱码
        response.setHeader("Cache-Control", "no-cache, must-revalidate");
 
        try {
            response.getWriter().print("json..........");
            response.getWriter().flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                response.getWriter().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

这样,当有异常发生时,就可以在前台收到异常的json信息,而这个也可以代替统一异常处理使用。同时在springCloud zuul中可以用来自定义异常。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java利用异常中断当前任务的技巧分享

    Java利用异常中断当前任务的技巧分享

    在日常开发中,我们经常遇到调用别人的代码来完成某个任务,但是当代码比较耗时的时候,没法从外部终止该任务,所以本文为大家介绍了如何利用异常中断当前任务,需要的可以参考下
    2023-08-08
  • SpringBoot详解自定义Stater的应用

    SpringBoot详解自定义Stater的应用

    Springboot的出现极大的简化了开发人员的配置,而这之中的一大利器便是springboot的starter,starter是springboot的核心组成部分,springboot官方同时也为开发人员封装了各种各样方便好用的starter模块
    2022-07-07
  • Java中常用的数据库连接池_动力节点Java学院整理

    Java中常用的数据库连接池_动力节点Java学院整理

    数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
    2017-08-08
  • 深入理解Java注解类型(@Annotation)

    深入理解Java注解类型(@Annotation)

    这篇文章主要介绍了深入理解Java注解类型(@Annotation),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • IDEA提示:Boolean method ‘xxx‘ is always inverted问题

    IDEA提示:Boolean method ‘xxx‘ is always&nb

    这篇文章主要介绍了IDEA提示:Boolean method ‘xxx‘ is always inverted问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • idea快速实现将SpringBoot项目打包Docker镜像并部署

    idea快速实现将SpringBoot项目打包Docker镜像并部署

    本文主要介绍了idea快速实现将SpringBoot项目打包Docker镜像并部署,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Swagger2配置Security授权认证全过程

    Swagger2配置Security授权认证全过程

    这篇文章主要介绍了Swagger2配置Security授权认证全过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Java spring的三种注入方式详解流程

    Java spring的三种注入方式详解流程

    Spring框架由Rod Johnson开发,2004年发布了Spring框架的第一版。Spring是一个从实际开发中抽取出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅仅是与特定应用相关的部分,从而大大提高了企业应用的开发效率
    2021-10-10
  • Jenkins环境搭建实现过程图解

    Jenkins环境搭建实现过程图解

    这篇文章主要介绍了Jenkins环境搭建实现过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Java gbk转utf-8

    Java gbk转utf-8

    本文主要介绍了Java gbk转utf-8的方法,具有一定的参考价值,下面跟着小编一起来看下吧
    2017-02-02

最新评论