从零到一构建短链接系统(七)

news/2024/7/5 3:02:41

1.convention目录下创建exception目录,并创建AbstractException类,
ClientException类,ServiceException类,RemoteException类

/**
 * 抽象项目中三类异常体系,客户端异常、服务端异常以及远程服务调用异常
 *
 * @see ClientException
 * @see ServiceException
 * @see RemoteException
 */
@Getter
public abstract class AbstractException extends RuntimeException {
    public final String errorCode;
    public final String errorMessage;

    public AbstractException(String message, Throwable throwable, IErrorCode errorCode) {
        super(message, throwable);
        this.errorCode = errorCode.code();
        this.errorMessage = Optional.ofNullable(StringUtils.hasLength(message) ? message : null)
                .orElse(errorCode.message());
    }
}
/**
 * 客户端异常
 */
public class ClientException extends AbstractException {
    public ClientException(IErrorCode errorCode) {
        this(null, null, errorCode);
    }

    public ClientException(String message) {
        this(message, null, BaseErrorCode.CLIENT_ERROR);
    }

    public ClientException(String message, IErrorCode errorCode) {
        this(message, null, errorCode);
    }

    public ClientException(String message, Throwable throwable, IErrorCode errorCode) {
        super(message, throwable, errorCode);
    }

    @Override
    public String toString() {
        return "ClientException{" +
                "code='" + errorCode + "'," +
                "message='" + errorMessage + "'" +
                '}';
    }
}
/**
 * 远程服务调用异常
 */
public class RemoteException extends AbstractException {
    public RemoteException(String message) {
        this(message, null, BaseErrorCode.REMOTE_ERROR);
    }

    public RemoteException(String message, IErrorCode errorCode) {
        this(message, null, errorCode);
    }

    public RemoteException(String message, Throwable throwable, IErrorCode errorCode) {
        super(message, throwable, errorCode);
    }

    @Override
    public String toString() {
        return "RemoteException{" +
                "code='" + errorCode + "'," +
                "message='" + errorMessage + "'" +
                '}';
    }
}
/**
 * 服务端异常
 */
public class ServiceException extends AbstractException {
    public ServiceException(String message) {
        this(message, null, BaseErrorCode.SERVICE_ERROR);
    }

    public ServiceException(IErrorCode errorCode) {
        this(null, errorCode);
    }

    public ServiceException(String message, IErrorCode errorCode) {
        this(message, null, errorCode);
    }

    public ServiceException(String message, Throwable throwable, IErrorCode errorCode) {
        super(Optional.ofNullable(message).orElse(errorCode.message()), throwable, errorCode);
    }

    @Override
    public String toString() {
        return "ServiceException{" +
                "code='" + errorCode + "'," +
                "message='" + errorMessage + "'" +
                '}';
    }
}


2.UserServiceImpl就可以修改为

代码片段实现了UserService接口的一个方法getUserByUsername,该方法用于根据用户名获取用户信息,并返回一个UserRespDTO对象。在方法中有一个判断if (userDO == null)来处理当用户不存在时的情况(userDO对象如果为null,代表数据库中没有匹配的记录)。
如果去掉if (userDO == null)这个判断,当数据库中没有找到匹配的UserDO记录时,userDO变量会被赋值为null。随后的BeanUtils.copyProperties(userDO, result);调用将会失败,因为BeanUtils.copyProperties方法会尝试访问userDO的属性来复制到result对象,如果userDO是null,那么就会引发NullPointerException。


3.result目录下创建Results类,即可简化UserController

4.common目录下创建web目录,再创建GlobalExceptionHandler
全局异常拦截器,需要拦截器的原因在于,我们不可能在代码的逻辑上拦截所有异常,比如如果没写return null就会有空指针异常,这时拦截器可以拦截这样的错误,并报出异常

/**
 * 全局异常处理器
 *
 */
@Component
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 拦截参数验证异常
     */
    @SneakyThrows
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result validExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        FieldError firstFieldError = CollectionUtil.getFirst(bindingResult.getFieldErrors());
        String exceptionStr = Optional.ofNullable(firstFieldError)
                .map(FieldError::getDefaultMessage)
                .orElse(StrUtil.EMPTY);
        log.error("[{}] {} [ex] {}", request.getMethod(), getUrl(request), exceptionStr);
        return Results.failure(BaseErrorCode.CLIENT_ERROR.code(), exceptionStr);
    }

    /**
     * 拦截应用内抛出的异常
     */
    @ExceptionHandler(value = { AbstractException.class })
    public Result abstractException(HttpServletRequest request, AbstractException ex) {
        if (ex.getCause() != null) {
            log.error("[{}] {} [ex] {}", request.getMethod(), request.getRequestURL().toString(), ex.toString(),
                    ex.getCause());
            return Results.failure(ex);
        }
        log.error("[{}] {} [ex] {}", request.getMethod(), request.getRequestURL().toString(), ex.toString());
        return Results.failure(ex);
    }

    /**
     * 拦截未捕获异常
     */
    @ExceptionHandler(value = Throwable.class)
    public Result defaultErrorHandler(HttpServletRequest request, Throwable throwable) {
        log.error("[{}] {} ", request.getMethod(), getUrl(request), throwable);
        return Results.failure();
    }

    private String getUrl(HttpServletRequest request) {
        if (StringUtils.isEmpty(request.getQueryString())) {
            return request.getRequestURL().toString();
        }
        return request.getRequestURL().toString() + "?" + request.getQueryString();
    }
}


 


http://lihuaxi.xjx100.cn/news/2109259.html

相关文章

ch6文件操作和异常处理

os.listdir(path) 函数详解 功能: os.listdir(path) 函数用于返回指定目录下的所有文件和文件夹的名字列表,但不包括 . 和 ..。 参数: path: 要列出的目录的路径。 返回值: 一个包含目录下所有文件和文件夹名字的列表。 示例: import ospath "/home/u…

Unicode转码 [ASIS 2019]Unicorn shop1

打开题目 我们买最贵的试试看,结果提示只能输入一个字符 抓包分析一下看看 从中可以发现源代码是如何处理price的 使用的是unicodedata.numeric() 但是我们查看页面源代码,发现页面的编码是utf-8编码 所以,前端html使用的是utf-8&#xff0…

2024全国水科技大会【联合主办】福州水务集团有限公司

福州水务成立于2008年11月,AA信用评级,注册资本21.2亿元。下属各级企业70多家(包括3家国家级高新技术企业、1家A股上市企业)。集团主营供水、排水、环保、温泉文旅、综合服务五大板块,旗下运营自来水厂17座&#xff0c…

python 常用装饰器

文章目录 property的介绍与使用作用使用场景装饰方法防止属性被修改 实现setter和getter的行为 staticmethod 与 classmethod作用代码示例 两者区别使用区别代码演示 abstractmethod参考资料 property的介绍与使用 python的property是python的一种装饰器,是用来修饰…

【No.10】蓝桥杯构造法|两道例题(C++)

什么是构造 构造题 要求解题者通过观察问题的结构和规律,找到一种通用的方法或模式,使得在问题规模增大时,依然能够高效地得到答案。 在解决构造题时,以下几点思考是很重要的: 观察问题规模的增长:了解问题随着规模的增大&…

使用 mypy 做 type check

前言 完残!😂,最近看之前写的 Python 代码老得琢磨这比变量的类型是啥(Python 无类型系统xxx),不愧是我写的! 看段之前写的实现迭代器模式的代码: # 抽象迭代器类 class Iterator(…

HTML世界之标签Ⅴ

目录 一、meter 标签 二、nav 标签 三、noscript 标签 四、object 标签 五、ol 标签 六、optgroup 标签 七、option 标签 八、output 标签 九、param 标签 十、pre 标签 十一、picture 标签 一、meter 标签 <meter> 标签定义度量衡。仅用于已知最大和最小值的…

关于继承是怎么样的?那当然是很好理解之

本文描述了关于继承的大部分知识&#xff0c;但是并不全&#xff0c;每篇博客之间的知识都有互串&#xff0c;所以需要把几篇文章合起来看&#xff0c;学会融会贯通&#xff01; 温馨提示&#xff1a;使用PC端观看&#xff0c;效果更佳&#xff01; 目录 1.继承是什么 2.什…