SpringBoot2.0系列教程(五)Springboot框架添加全局异常处理

Hello大家好,本章我们添加全局异常处理。另求各路大神指点,感谢

一:为什么需要定义全局异常

在互联网时代,我们所开发的应用大多是直面用户的,程序中的任何一点小疏忽都可能导致用户的流失,而程序出现异常往往又是不可避免的,所以我们需要对异常进行捕获,然后给予相应的处理,来减少程序异常对用户体验的影响

二:添加业务类异常

在前面说过的ret文件夹下创建ServiceException

package com.example.demo.core.ret;

import java.io.Serializable;

/**
 * @Description: 业务类异常
 * @author 张瑶
 * @date 2018/4/20 14:30
 *
 */
public class ServiceException extends RuntimeException implements Serializable{

   private static final long serialVersionUID = 1213855733833039552L;

   public ServiceException() {
   }

   public ServiceException(String message) {
      super(message);
   }

   public ServiceException(String message, Throwable cause) {
      super(message, cause);
   }
}

三:添加异常处理配置

打开上篇文章创建的WebConfigurer,添加如下方法

@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
    exceptionResolvers.add(getHandlerExceptionResolver());
}

/**
 * 创建异常处理
 * @return
 */
private HandlerExceptionResolver getHandlerExceptionResolver(){
    HandlerExceptionResolver handlerExceptionResolver = new HandlerExceptionResolver(){
        @Override
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
                                             Object handler, Exception e) {
            RetResult<Object> result = getResuleByHeandleException(request, handler, e);
            responseResult(response, result);
            return new ModelAndView();
        }
    };
    return handlerExceptionResolver;
}

/**
 * 根据异常类型确定返回数据
 * @param request
 * @param handler
 * @param e
 * @return
 */
private RetResult<Object> getResuleByHeandleException(HttpServletRequest request, Object handler, Exception e){
    RetResult<Object> result = new RetResult<>();
    if (e instanceof ServiceException) {
        result.setCode(RetCode.FAIL).setMsg(e.getMessage()).setData(null);
        return result;
    }
    if (e instanceof NoHandlerFoundException) {
        result.setCode(RetCode.NOT_FOUND).setMsg("接口 [" + request.getRequestURI() + "] 不存在");
        return result;
    }
    result.setCode(RetCode.INTERNAL_SERVER_ERROR).setMsg("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员");
    String message;
    if (handler instanceof HandlerMethod) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s", request.getRequestURI(),
                handlerMethod.getBean().getClass().getName(), handlerMethod.getMethod() .getName(), e.getMessage());
    } else {
        message = e.getMessage();
    }
    LOGGER.error(message, e);
    return result;
}

/**
 * @Title: responseResult
 * @Description: 响应结果
 * @param response
 * @param result
 * @Reutrn void
 */
private void responseResult(HttpServletResponse response, RetResult<Object> result) {
    response.setCharacterEncoding("UTF-8");
    response.setHeader("Content-type", "application/json;charset=UTF-8");
    response.setStatus(200);
    try {
        response.getWriter().write(JSON.toJSONString(result,SerializerFeature.WriteMapNullValue));
    } catch (IOException ex) {
        LOGGER.error(ex.getMessage());
    }
}

四:添加配置文件

Spring Boot 中, 当用户访问了一个不存在的链接时, Spring 默认会将页面重定向到 **/error** 上, 而不会抛出异常. 

既然如此, 那我们就告诉 Spring Boot, 当出现 404 错误时, 抛出一个异常即可.

在 application.properties 中添加两个配置:

spring.mvc.throw-exception-if-no-handler-found=true 

spring.resources.add-mappings=false 

上面的配置中, 第一个 spring.mvc.throw-exception-if-no-handler-found 告诉 SpringBoot 当出现 404 错误时, 直接抛出异常. 第二个 spring.resources.add-mappings 告诉 SpringBoot 不要为我们工程中的资源文件建立映射.

五:创建测试接口

package com.example.demo.service.impl;

import com.example.demo.core.ret.ServiceException;
import com.example.demo.dao.UserInfoMapper;
import com.example.demo.model.UserInfo;
import com.example.demo.service.UserInfoService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author 张瑶
 * @Description:
 * @time 2018/4/18 11:56
 */
@Service
public class UserInfoServiceImpl implements UserInfoService{

    @Resource
    private UserInfoMapper userInfoMapper;

    @Override
    public UserInfo selectById(Integer id){
        UserInfo userInfo = userInfoMapper.selectById(id);
        if(userInfo == null){
            throw new ServiceException("暂无该用户");
        }
        return userInfo;
    }
}

UserInfoController.java

package com.example.demo.controller;

import com.example.demo.core.ret.RetResponse;
import com.example.demo.core.ret.RetResult;
import com.example.demo.core.ret.ServiceException;
import com.example.demo.model.UserInfo;
import com.example.demo.service.UserInfoService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author 张瑶
 * @Description:
 * @time 2018/4/18 11:39
 */
@RestController
@RequestMapping("userInfo")
public class UserInfoController {

    @Resource
    private UserInfoService userInfoService;

    @PostMapping("/hello")
    public String hello(){
        return "hello SpringBoot";
    }

    @PostMapping("/selectById")
    public RetResult<UserInfo> selectById(Integer id){
        UserInfo userInfo = userInfoService.selectById(id);
        return RetResponse.makeOKRsp(userInfo);
    }

    @PostMapping("/testException")
    public RetResult<UserInfo> testException(Integer id){
        List a = null;
        a.size();
        UserInfo userInfo = userInfoService.selectById(id);
        return RetResponse.makeOKRsp(userInfo);
    }

}

六:接口测试

访问192.168.1.104:8080/userInfo/selectById参数 id:3

{
    "code": 400,
    "data": null,
    "msg": "暂无该用户"
}

访问192.168.1.104:8080/userInfo/testException

{
    "code": 500,
    "data": null,
    "msg": "接口 [/userInfo/testException] 内部错误,请联系管理员"
}

项目地址

码云地址: https://gitee.com/beany/mySpringBoot

GitHub地址: https://github.com/MyBeany/mySpringBoot

写文章不易,如对您有帮助,请帮忙点下star?

结尾

springboot添加全局异常处理已完成,后续功能接下来陆续更新。另求各路大神指点,感谢大家。

原文地址:https://www.cnblogs.com/mrBeany/p/10649623.html

时间: 2024-07-29 19:48:58

SpringBoot2.0系列教程(五)Springboot框架添加全局异常处理的相关文章

Influx Sql系列教程五:insert 添加数据

接下来开始进入influxdb的curd篇,首先我们看一下如何添加数据,也就是insert的使用姿势 在进入本篇之前,对于不了解什么是retention policy, tag, field的同学,有必要快速过一下这几个基本概念,可以参考文后的系列教程 I. Insert 使用说明 基本语法 insert into <retention policy> measurement,tagKey=tagValue fieldKey=fieldValue timestamp 1. 基本写数据姿势 当m

SpringBoot2.0系列教程(六)Springboot框架添加Swagger2来在线自动生成接口的文档+测试功能

Hello大家好,本章我们添加Swagger2来在线自动生成接口的文档+测试功能.有问题可以联系我[email protected].另求各路大神指点,感谢 一:什么是Swagger Swagger是一款通过我们添加的注解来对方法进行说明,来自动生成项目的在线api接口文档的web服务. 二:添加Swagger2依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swag

SpringBoot2.0系列教程(七)Springboot框架添加PageHelper分页查询功能

Hello大家好,本章我们添加PageHelper分页查询功能.另求各路大神指点,感谢 一:什么是PageHelper PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件 物理分页 支持常见的 12 种数据库.Oracle,MySql,MariaDB,SQLite,DB2,PostgreSQL,SqlServer 等 支持多种分页方式 支持常见的RowBounds(PageRowBounds),PageHelper.startPage 方法调用,Mapper 接口参数调用

Enterprise Library 5.0 系列教程

1. Microsoft Enterprise Library 5.0 系列教程(一) Caching Application Block (初级) 2. Microsoft Enterprise Library 5.0 系列教程(一) Caching Application Block (高级) 3. Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (初级) 4. Microsoft Enterpr

Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型

Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型 在这一节中,你将添加用于管理数据库中电影的类.这些类是ASP.NET MVC应用程序的模型部分. 你将使用.NET Framework框架下的实体框架(Entity Framework)数据访问技术,与模型类协同工作.实体框架(常简称为EF)支持一种称之为编码先行(Code First)的开发模式.编码先行使你通过编写简单的类(简称为POCO类,全称为"plain-old CLR objects."),来创建模型对象

[译]JavaFX 2.0+系列教程-使用内置的布局面板(4)-垂直盒子(VBox)

[译]JavaFX 2.0+系列教程-使用内置的布局面板(4)-垂直盒子(VBox) 垂直盒子 VBox 和水平盒子 HBox 很类似,只是其包含的节点是在单列中进行排列.图 1-4 显示了一个VBox的示例. 图 1-4 VBox示例 内边距(Padding)属性可以设置节点到VBox边缘的空隙.空间(Spacing)属性可以设置节点之间的间隙.边缘(Margin)属性可以为每个节点增加额外的环绕空间. 代码片段 例 1-3 创建了一个VBox,其中包含了一系列的选项. 例 1-3 创建VBo

C#微信公众号开发系列教程五(接收事件推送与消息排重)

微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C#微信公众号开发系列教程四(接收普通消息) C#微信公众号开发系列教程五(接收事件推送与消息排重) 在上一篇的博文中讲到,微信的消息可以大体分为两种类型,一种是包括:文本,语音,图片等的普通消息,另一种就是本篇要将的事件类型.包括:关注/取消关注事件,扫描带参数二维码事件,上报地理位置事件,自定义菜

[译]JavaFX 2.0+系列教程-使用内置的布局面板(3)-水平盒子(HBox)

[译]JavaFX 2.0+系列教程-使用内置的布局面板(3)-水平盒子(HBox) 水平盒子 HBox 为多个节点排列在一行中提供了一个简单的方法. 图 1-2 是HBox的一个示例. 图 1-2 HBox示例 内边距(Padding)属性可以设置节点到HBox边缘的空隙.空间(Spacing)属性可以设置节点之间的间隙.样式(Style)属性可以设置背景颜色. 代码片段 例 1-2 创建了一个HBox,实现了一个工具栏(ToolBar)的效果,其中包含了两个按钮. 例 1-2 创建HBox

[译]JavaFX 2.0+系列教程-使用内置的布局面板(2)-边框面板(BorderPane)

[译]JavaFX 2.0+系列教程-使用内置的布局面板(2)-边框面板(BorderPane) 边框面板 BorderPane 将面板划分为5个区域来放置界面元素:上.下.左.右.中. 图 1-1 显示了边框面板的布局示意图.每个区域的大小是没有限制的.在你使用边框面板时,如果不需要某个区域,你只要不为该区域设置内容,该区域则不会被分配显示空间,自然也就不会显示. 图 1-1 边框面板布局示意图 边框面板是我们经常见到的一个非常经典的布局效果:上面是菜单栏和工具栏,下面是状态栏,左边是导航面板