- Обработка исключений по умолчанию в Spring
- использовать
@ResponseStatusОбработка пользовательских исключений - использовать
try {…} catchПерехватывать исключения вручную - использовать
@ExceptionHandlerОбработка пользовательских исключений - использовать
@ControllerAdviceАннотация обрабатывает все исключения - Суммировать
- Ссылаться на
Обработка исключений по умолчанию в Spring
В Spring некоторые исключения по умолчанию сопоставляются с кодами состояния HTTP и не требуют программной обработки. В следующей таблице перечислены способы обработки исключений в Spring по умолчанию:
| Весеннее исключение | Коды состояния HTTP |
|---|---|
| BindException | 400 - Bad Request |
| ConversionNotSupportedException | 500 - Internal Server Error |
| HttpMediaTypeNotAcceptableException | 406 - Not Acceptable |
| HttpMediaTypeNotSupportedException | 415 - Unsupported Media Type |
| HttpMessageNotReadableException | 400 - Bad Request |
| HttpMessageNotWritableException | 500 - Internal Server Error |
| HttpRequestMethodNotSupportedException | 405 - Method Not Allowed |
| MethodArgumentNotValidException | 400 - Bad Request |
| MissingServletRequestParameterException | 400 - Bad Request |
| MissingServletRequestPartException | 400 - Bad Request |
| NoSuchRequestHandlingMethodException | 404 - Not Found |
| TypeMismatchException | 400 - Bad Request |
Исключения в приведенной выше таблице генерируются самой Spring, еслиDispatcherServletВозвращает напрямую, когда возникает проблема во время обработки или при выполнении проверки. Например, еслиDispatcherServletНевозможно найти подходящий метод контроллера для обработки запроса, выдастNoSuchRequestHandlingMethodExceptionИсключение, конечным результатом является ответ с кодом состояния 404 (не найдено).
использовать@ResponseStatusОбработка пользовательских исключений
Но он не может обрабатывать пользовательские исключения, создаваемые внутри приложения. Например, в службе выдается пользовательское исключение (NullOrgException),МыNullOrgExceptionДобавлено исключение@ResponseStatusАннотация, вы можете присвоить ей код состояния.
Например, следующий код:
package com.rebecca.springmvc.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
* 自定义异常
* @Author: Rebecca
* @Description:
* @Date: Created in 2019/6/14 17:04
* @Modified By:
*/
@ResponseStatus(value = HttpStatus.NO_CONTENT, reason = "No Content")
public class NullOrgException extends RuntimeException {
}
использоватьtry {…} catchПерехватывать исключения вручную
После определения вышеупомянутого исключения, пока в приложении есть бросокNullOrgExceptionИсключения перехватываются и сопоставляются с соответствующими кодами состояния. Что делать, если программе нужен не только код состояния, но и сгенерированная ошибка? На данный момент мы больше не можем обрабатывать исключения как ошибки HTTP, а обрабатывать исключения так же, как мы обрабатываем запросы.
package com.rebecca.springmvc.controller.exception;
import com.rebecca.springmvc.org.bean.Org;
import com.rebecca.springmvc.org.service.OrgService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@RequestMapping("test/exception")
public class ExceptionTestController {
private Logger logger = LoggerFactory.getLogger(ExceptionTestController.class);
@Autowired
private OrgService service;
@RequestMapping(value = "orgs", method = RequestMethod.GET)
@ResponseBody
public List<Org> getOrgs () {
List<Org> orgs = null;
try {
orgs = service.getOrgs();
} catch (NullOrgException e) {
logger.error("无组织机构相关数据!",e);
}
return orgs;
}
}
Например, в коде вышеNullOrgExceptionИсключение, в Spring нет сопоставления по умолчанию, самый простой способ -try {…} catch (NullOrgException e) {…}.
использовать@ExceptionHandlerОбработка пользовательских исключений
вышесказанноеtry {…} catchЭтот метод не способствует сопровождению кода, к счастью, Spring предоставляет механизм, который можно использовать.@ExceptionHandlerАннотации сопоставляют исключения с кодами состояния HTTP. Ниже приведено использование@ExceptionHandlerАннотированный способ:
package com.rebecca.springmvc.controller.exception;
import com.rebecca.springmvc.org.bean.Org;
import com.rebecca.springmvc.org.service.OrgService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@RequestMapping("test/exception")
public class ExceptionTestController {
private Logger logger = LoggerFactory.getLogger(ExceptionTestController.class);
@Autowired
private OrgService service;
@RequestMapping(value = "orgs", method = RequestMethod.GET)
@ResponseBody
public List<Org> getOrgs () {
List<Org> orgs = service.getOrgs();
return orgs;
}
@ExceptionHandler(NullOrgException.class)
public String handleNullOrgException() {
return "无组织机构相关数据!";
}
}
В приведенном выше коде мыhandleNullOrgException()добавлен метод@ExceptionHandlerаннотацию, когда программа выбрасываетNullOrgExceptionКогда возникает исключение, этот метод будет делегирован для обработки. Его возвращаемое значение — String, вы также можете изменить его на другие типы возвращаемых значений в соответствии с потребностями приложения. для использования@ExceptionHandlerДля методов, аннотированных аннотациями, он может обрабатывать исключения, создаваемые всеми методами-обработчиками в одном и том же контроллере (контроллере).
Чтобы избежать записи дубликатов в нескольких контроллерах@ExceptionHandlerAnnotation, мы создадим базовый класс контроллера, все классы контроллера должны расширять этот класс, поэтомунаследоватьуниверсальный@ExceptionHandlerметод.
использовать@ControllerAdviceАннотация обрабатывает все исключения
Ранее мы говорили использовать@ExceptionHandlerАннотации могут обрабатывать только исключения, генерируемые всеми методами обработчика в контроллере (контроллере), поэтому есть ли способ обрабатывать исключения, генерируемые методами обработчика во всех контроллерах, без интеграции?
Ответ: да! Начиная с Spring 3.2 это определенно возможно, нам просто нужно определить это в классе уведомлений контроллера.
После Spring 3.2 для такого рода проблем было введено новое решение: совет контроллера.
Совет диспетчера относится к любому@ControllerAdviceАннотированный класс.
Этот класс будет содержать один или несколько из следующих типов методов:
-
@ExceptionHandlerАннотационный метод аннотации; -
@InitBinderАннотационный метод аннотации; -
@ModelAttributeАннотационный метод аннотации.
в с@ControllerAdviceВ аннотированном классе вышеуказанные методы будут применяться ко всем контроллерам с@RequestMappingпо методу аннотации.@ControllerAdviceСама аннотация уже используется@Component,следовательно@ControllerAdviceКласс, отмеченный аннотацией, будет автоматически получен при сканировании компонента, и есть@ComponentАннотированные классы одинаковы.@ControllerAdviceОдин из наиболее практичных сценариев — объединить все@ExceptionHandlerМетоды собраны в класс, чтобы исключения от всех контроллеров можно было обрабатывать единообразно в одном месте. Например, мы хотимNullOrgExceptionМетод обработчика используется на всех контроллерах во всем приложении. Следующий листинг программы показываетAppWideExceptionHandlerможет выполнить эту задачу, это@ControllerAdviceАннотированный класс. Используйте следующий код@ControllerAdvice, для обработки исключений для всех контроллеров:
package com.rebecca.springmvc.controller.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
/**
* 控制器通知类
* @Author: Rebecca
* @Description:
* @Date: Created in 2019/6/14 16:30
* @Modified By:
*/
@ControllerAdvice // 定义控制器类
public class AppWideException {
// 定义异常处理方法
@ExceptionHandler(NullOrgException.class)
public String handleNullOrgException() {
return "无组织机构相关数据!";
}
}
Теперь, если какой-либо метод контроллера выдает исключение DuplicateSpittleException, для обработки исключения будет вызываться метод DuplicateSpittleHandler() независимо от того, в каком контроллере находится этот метод. Мы можем писать аннотированные методы @ExceptionHandler так же, как мы пишем аннотированные методы @RequestMapping. Как показано в листинге 7.10, он возвращает "error/duplicate" в качестве имени логического представления, поэтому пользователю будет представлена удобная страница с ошибкой.
Суммировать
Обработка исключений в Spring:
- Определенные исключения Spring будут автоматически сопоставлены с указанными кодами состояния HTTP;
-
аномальныйможно добавить на
@ResponseStatusАннотация для сопоставления с кодом состояния HTTP; - существуетметодможно добавить на
@ExceptionHandlerАннотация, чтобы ее можно было использовать для обработки исключений. - будет
@ExceptionHandlerАннотированный метод исключения извлекается в@ControllerAdviceВ аннотированном классе действует все приложение (этот метод применим только к Spring 3.2+).
Самый простой способ обработки исключений — сопоставить их с кодами состояния HTTP и поместить в ответ.
Ссылаться на
«Весна в действии, 4-е издание»