springboot项目处理异常流程

后端项目分层一般如下:

  • 控制层:controller

  • 业务层:service

  • 数据访问层:dao

下面演示在实际项目中,移除统一处理流程:

这篇文章的处理原则:controller负责异常统一处理,业务层负责把异常抛至控制层

  • dao层:

该层直接与数据库交互,而dao层由service调用,因此该层异常在service中处理即可

  • service层

业务层数据牵扯到业务处理流程,所有很容易出现异常,在方法后统一抛出一个Exception的方式。(对于某些代码明确其异常(或需自定义异常)时,可以使用try...catch来处理)

  • controller层

控制层来接收业务层处理的结果,当业务层出现异常且通过抛出异常的方式,那么异常会交由控制层处理,在控制层中,一旦出现异常,需要在该层处理,不能再往外抛,否则能影响服务器性能。

案例:

模拟一个service----controller流程,来处理异常,如下:

1、service层:

接口层:模拟一个testException方法,并在接口后抛出统一的异常Exception

package com.shuizhu.service;

import java.util.Map;

/**
 * @author 睡竹
 * @date 2023/3/20
 */
public interface TestService {
    Map testException() throws Exception;
}

接口实现层:

package com.shuizhu.service.impl;

import com.shuizhu.service.TestService;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author 睡竹
 * @date 2023/3/20
 */
@Service
public class TestExceptionImpl implements TestService {
    @Override
    public Map testException() throws Exception{
        //1/0 会出现异常,当出现异常时,会抛至controller层进行统一处理
        int i = 1/0;
        Map map = new LinkedHashMap();
        map.put("result",i);
        return map;
    }
}

2、前后端统一响应的工具类

package com.shuizhu.utils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.HashMap;
import java.util.Map;

/**
 * 返回数据
 *
 * @author 睡竹
 */
public class R extends HashMap {
    private static final long serialVersionUID = 1L;
    private static final Integer METHOD_INDEX = 1;
    private static final Logger logger= LogManager.getLogger();

    public R() {
        put("code", 0);
        put("msg", "success");
    }
    //测试获取的code
    public Integer getCode() {
        return (Integer) this.get("code");
    }

    public static R error() {
        return error(500, "未知异常,请联系管理员");
    }
    
    public static R error(String msg) {
        return error(500, msg);
    }
    
    public static R error(int code, String msg) {
        R r = new R();
        r.put("code", code);
        r.put("msg", msg);
        return r;
    }

    public static R errorApi(Exception e) {
        /** 通过getStackTrace获取controller中的方法名称 */
        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
        String method = "";
        if (stackTrace.length > 0) {
            /** 获取方法名称 */
            method = stackTrace[METHOD_INDEX].getMethodName();
        }
        /** 把错误日志打印至控制台,按文本形式可以提高系统性能 */
        logger.error(method + "接口异常->",e);
        /**
         *  日志输出格式:"方法名称  接口异常->  异常重要的信息"
         *  前提:接口名称需要与controller方法名称一致
         */
        return error(method + "接口异常->" + e.getMessage());
    }

    public static R ok(String msg) {
        R r = new R();
        r.put("msg", msg);
        return r;
    }
    
    public static R ok(Map map) {
        R r = new R();
        r.putAll(map);
        return r;
    }
    
    public static R ok() {
        return new R();
    }

    @Override
    public R put(String key, Object value) {
        super.put(key, value);
        return this;
    }
}

3、controller层

package com.shuizhu.controller;

import com.shuizhu.service.TestService;
import com.shuizhu.utils.R;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * @author 睡竹
 * @date 2023/3/20
 */
@RestController
public class TestController {

    @Resource
    TestService testService;

    @RequestMapping("/testException")
    public R testException(){
        try {
            Map map = testService.testException();
            return R.ok(map);
        } catch (Exception e) {
            return R.errorApi(e);
        }
    }
}

4、测试

接口为:http://127.0.0.1:8080/testException

springboot项目处理异常流程_第1张图片

接口返回了异常中的getMessage()信息,再来看控制台打印日志:

springboot项目处理异常流程_第2张图片

上述日志是通过logger进行日志打印输出的

下面改下代码,直接打印堆栈信息至控制台(这种方式不能出现在生产环境中):

    try {
            Map map = testService.testException();
            return R.ok(map);
        } catch (Exception e) {
            e.printStackTrace();//直接打印堆栈信息,会影响性能
            return R.error(e.getMessage());
        }

可以再控制台中看到明显的区别:

springboot项目处理异常流程_第3张图片

你可能感兴趣的:(springboot,spring,boot,java,spring)