欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

挑战常规--不要这样使用异常

程序员文章站 2023-12-02 11:53:04
不要这样使用异常 在一些使用spring框架的项目中,经常可以看到这样的代码: 在业务代码中抛出自定义异常,在全局异常控制中自定义输出 为什么说这不是一个好的做法呢?先看看正确的做法应该是: 定义全局输出封装类,正常或异常业务输出都由这个类封装 定义一个基础常规异常表 替换抛出异常的业务代码 抛出异 ......

不要这样使用异常

在一些使用spring框架的项目中,经常可以看到这样的代码:
在业务代码中抛出自定义异常,在全局异常控制中自定义输出

@restcontroller
@requestmapping("/api/testserver")
public class testserver
{
    @postget("getuser")
    public user getuser(string username)
    {
        //....
        
        throw new usernotfoundexception();
    }
    //....
}
public class usernotfoundexception extends runtimeexception
{
    public usernotfoundexception(){
        super("用户不存在");
    }
}
@restcontrolleradvice
public class myexceptionhandler
{
    @exceptionhandler
    map handleusernotfoundexception(usernotfoundexception ex)
    {
        map result=new hashmap();
        result.put("code",100);
        result.put("message","用户不存在");
        return result;
    }
    //...
}

为什么说这不是一个好的做法呢?先看看正确的做法应该是:
定义全局输出封装类,正常或异常业务输出都由这个类封装

public class message<t> 
{
    /**
     * 响应代码,0为正常
     */
    private int code;
    /**
     * 用于描述code对应信息
     */
    private string msg;
    //.....
}

定义一个基础常规异常表

public enum codeenu implements codeinter 
{
    /**正常返回*/ok, 
    /**未知异常时,最后返回*/other("其他异常"), 
    notempty("参数不能为空"), formaterror("参数格式不正确"), 
//....
}

替换抛出异常的业务代码

@restcontroller
@requestmapping("/api/testserver")
public class testserver
{
    @postget("getuser")
    public message<user> getuser(string username)
    {
        //....
        
        return message.error(codeenu.user_notfound_error);
    }
    //....
}
@restcontrolleradvice
public class myexceptionhandler
{
    @exceptionhandler
    message<void> handleexception(exception ex)
    {
        return message.error(codeenu.other); 
    }
}

抛出异常 vs 返回结果

有时候我们选择抛出异常,有时候选择返回结果。这要这两个者的优缺点说起:

  1. 异常能够详细的跟踪错误出处
  2. 抛出异常也意味着降低些性能

在业务中,抛出异常不好的点有:1.不需要详细的跟踪错误,最终也只是输出简要信息。2.是可预知的业务结果,而不是出现运行问题。3.重复的处理转发,由结果转异常抛出,再将异常抛出转结果输出,转了一圈又回来的浪费性能处理。

思考

  1. 在jdk8中,提供java.util.optional 类也是用来减少抛出nullpointerexception
  2. 经常需要用到将inputstream 读取出来的工具方法,如读取网络、文件,那么这个方法该抛出ioexception还是返回null?