Анализ проблем обработки исключений
Как обрабатывать исключения
введение проблемы
-
Для исключений кода есть два обычных метода обработки для прямого броска бросков и еще один захват try..catch.
-
В java-проекте могут быть искусственные логические исключения, и второй метод обработки может быть принят для получения сведений об исключении или для обеспечения того, чтобы программа продолжала выполняться вниз при возникновении исключения.
-
Однако перехват каждого исключения в коде сделает код избыточным и не будет способствовать обслуживанию.
Решения
-
Определите глобальный класс обработки исключений для возврата унифицированной и стандартизированной информации об исключениях;
-
Логика обработки заключается в том, чтобы сначала определить, произойдет ли исключение, а затем выполнить последующую конкретную операцию.
бизнес-пример
В этой статье в основном реализована логика глобальной аномальной обработки, только простой бизнес
Департамент компании должен добавить сотрудников. Поток обработки: 1. Во-первых, запрашивает объект сотрудника в соответствии с номером сотрудника. 2. Определите, имеет ли объект сотрудника информацию, то есть ли не пусто. 3. Если есть Информация, это означает, что она уже существует, и не нужно его добавлять. Если нет, добавляется напрямую.
код показывает, как показано ниже:
public class MyService {
// 注入dao层
@Autowired
EmployeeecMapper employeeecMapper;
/**
* 添加员工信息
* @param employee 员工对象
* @return 影响的行数
*/
public int add(Employee employee) {
// 根据id查询员工对象
Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
// 判断是否已有该员工
if (emp != null){
// 已有,抛出异常,异常信息为已有该员工
throw new RuntimeException("异常代码:1201,错误信息:该员工已存在");
}
// 没有,插入该员工
return employeeecMapper.insert(emp);
}
}
Процесс обработки исключений
В бизнесе существуют исключения времени выполнения и исключения бизнес-логики.Первые трудно обнаружить, когда они не запущены, а вторые можно определить, когда они распространяются по всему бизнесу.Поэтому исключения делятся на непредсказуемые исключения и известные исключения. Процесс выглядит следующим образом:
- Настройте глобальный класс исключений, используйте
@ControllerAdvice
, усовершенствования контроллера - Настройте код ошибки и сообщение об ошибке. Два исключения в конечном итоге будут представлены в едином формате информации, код ошибки + сообщение об ошибке.
- Для предсказуемых исключений, которые активно создаются программистом в коде,
SpringMVC
Единый захват. - Непредсказуемые исключения обычно возникают из-за ошибок в системе или некоторых внешних факторов (таких как колебания сети, простои сервера и т. д.).
RuntimeException
Тип (исключение во время выполнения).
Известное исключение
Определите класс информации об исключении, переменные - это код ошибки и информация об ошибке, при перехвате пользовательского исключения возвращайте объект напрямую
Непредвиденное необычное
Определите карту, храните общие исключения в нем и определите коды ошибок. Для других необычных исключений, то есть те, которые не на карте, один и тот же объект исключения может быть возвращен.
Поток кода обработки исключений
Известное исключение
1. Определите интерфейс для печати информации об исключении и возврата результатов.
public interface ResultCode {
// 操作是否成功
boolean success();
// 操作结果代码
long code();
// 提示信息
String message();
}
public interface Response {
public static final boolean SUCCESS = true;
public static final int SUCCESS_CODE = 10000;
}
2. Определите класс перечисления и возвращайте класс результата для печати информации об исключении.
@ToString
public enum CommonCode implements ResultCode {
NO_PAGE(false,404,"没有信息"),
FAIL(false,500,"操作失败!"),
SUCCESS(true,200,"操作成功!");
// 结果信息
boolean success;
long code;
String message;
// 带参构造
CommonCode(boolean success, long code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
@Override
public boolean success() {
return true;
}
@Override
public long code() {
return code;
}
@Override
public String message() {
return message;
}
}
@Data
@ToString
public class ResponseResult implements Response {
boolean success = SUCCESS;
long code = SUCCESS_CODE;
String message;
public ResponseResult(ResultCode resultCode){
this.success = resultCode.success();
this.code = resultCode.code();
this.message = resultCode.message();
}
}
3. Определите класс исключений ошибок
public class CustomException extends RuntimeException{
@Autowired
ResultCode resultCode;
// 带参构造
public CustomException(ResultCode resultCode){
this.resultCode = resultCode;
}
// getter
public ResultCode getResultCode(){
return resultCode;
}
}
4. Определите класс генерации исключений
public class ExceptionCast {
// 静态方法
public static void cast(ResultCode resultCode){
throw new CustomException(resultCode);
}
}
5. Определите класс перехвата исключений, используйтеControllerAdvice
Расширенные контроллером аннотации и дополнительные методы, перехватывающие исключения CustomException.ExceptionHandler
Аннотация, вы можете перехватывать все исключения этого класса и возвращать данные json.
@ControllerAdvice
public class ExceptionCatch {
/**
* 捕获CustomException类异常
* @param customException
* @return 结果信息,json数据
*/
@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseResult customException(CustomException customException){
ResultCode resultCode = customException.getResultCode();
return new ResponseResult(resultCode);
}
}
6. Исключения в бизнесе
public class MyService {
@Autowired
EmployeeecMapper employeeecMapper;
public int add(Employee employee) {
Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
if (emp != null){
ExceptionCast.cast(CommonCode.FAIL);
}
return employeeecMapper.insert(emp);
}
}
Независимая обработка исключений
1. Как и в случае с известным исключением, сначала добавьте код ошибки в класс CommonCode, например
UNAUTHORISE(false,510,"没有权限"),
2. Добавление метода аномального захвата в класс аномального захвата. В этом методе определите сопоставление кода ошибки типа исключения хранилища MAP только для чтения, элементы на карте, унифицированное использование кода ошибки 999.
UNKNOWNERROR(false,999,"未知异常"),
@ControllerAdvice
public class ExceptionCatch {
// 定义map,存贮常见错误信息。该类map不可修改
private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
// 构建ImmutableMap
protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();
@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseResult customException(CustomException customException){
ResultCode resultCode = customException.getResultCode();
return new ResponseResult(resultCode);
}
/**
* 捕获非自定义类异常
* @param exception
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseResult exception(Exception exception){
// 记录日志
LOGGER.error("catch exception ==> ",exception.getMessage());
if (EXCEPTIONS == null){
EXCEPTIONS = builder.build();
}
ResultCode resultCode = EXCEPTIONS.get(exception.getClass());
if (resultCode != null){
return new ResponseResult(resultCode);
}else {
return new ResponseResult(CommonCode.UNKNOWNERROR);
}
}
static {
builder.put(HttpMessageNotReadableException.class, CommonCode.INVALID_PARAM);
}
}
готово~~