SpringBoot初始教程之統(tǒng)一異常處理詳解
1.介紹
在日常開(kāi)發(fā)中發(fā)生了異常,往往是需要通過(guò)一個(gè)統(tǒng)一的異常處理處理所有異常,來(lái)保證客戶端能夠收到友好的提示。SpringBoot在頁(yè)面發(fā)生異常的時(shí)候會(huì)自動(dòng)把請(qǐng)求轉(zhuǎn)到/error,SpringBoot內(nèi)置了一個(gè)BasicErrorController對(duì)異常進(jìn)行統(tǒng)一的處理,當(dāng)然也可以自定義這個(gè)路徑
application.yaml
server: port: 8080 error: path: /custom/error
BasicErrorController提供兩種返回錯(cuò)誤一種是頁(yè)面返回、當(dāng)你是頁(yè)面請(qǐng)求的時(shí)候就會(huì)返回頁(yè)面,另外一種是json請(qǐng)求的時(shí)候就會(huì)返回json錯(cuò)誤
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml(HttpServletRequest request,
HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
return (modelAndView == null ? new ModelAndView("error", model) : modelAndView);
}
@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = getStatus(request);
return new ResponseEntity<Map<String, Object>>(body, status);
}
分別會(huì)有如下兩種返回

{
"timestamp": 1478571808052,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/rpc"
}
2.通用Exception處理
通過(guò)使用@ControllerAdvice來(lái)進(jìn)行統(tǒng)一異常處理,@ExceptionHandler(value = Exception.class)來(lái)指定捕獲的異常
下面針對(duì)兩種異常進(jìn)行了特殊處理分別返回頁(yè)面和json數(shù)據(jù),使用這種方式有個(gè)局限,無(wú)法根據(jù)不同的頭部返回不同的數(shù)據(jù)格式,而且無(wú)法針對(duì)404、403等多種狀態(tài)進(jìn)行處理
@ControllerAdvice
public class GlobalExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "error";
@ExceptionHandler(value = CustomException.class)
@ResponseBody
public ResponseEntity defaultErrorHandler(HttpServletRequest req, CustomException e) throws Exception {
return ResponseEntity.ok("ok");
}
@ExceptionHandler(value = Exception.class)
public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
return mav;
}
}
3.自定義BasicErrorController 錯(cuò)誤處理
在初始介紹哪里提到了BasicErrorController,這個(gè)是SpringBoot的默認(rèn)錯(cuò)誤處理,也是一種全局處理方式。咱們可以模仿這種處理方式自定義自己的全局錯(cuò)誤處理
下面定義了一個(gè)自己的BasicErrorController,可以根據(jù)自己的需求自定義errorHtml()和error()的返回值。
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
private final ErrorProperties errorProperties;
private static final Logger LOGGER = LoggerFactory.getLogger(BasicErrorController.class);
@Autowired
private ApplicationContext applicationContext;
/**
* Create a new {@link org.springframework.boot.autoconfigure.web.BasicErrorController} instance.
*
* @param errorAttributes the error attributes
* @param errorProperties configuration properties
*/
public BasicErrorController(ErrorAttributes errorAttributes,
ErrorProperties errorProperties) {
this(errorAttributes, errorProperties,
Collections.<ErrorViewResolver>emptyList());
}
/**
* Create a new {@link org.springframework.boot.autoconfigure.web.BasicErrorController} instance.
*
* @param errorAttributes the error attributes
* @param errorProperties configuration properties
* @param errorViewResolvers error view resolvers
*/
public BasicErrorController(ErrorAttributes errorAttributes,
ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) {
super(errorAttributes, errorViewResolvers);
Assert.notNull(errorProperties, "ErrorProperties must not be null");
this.errorProperties = errorProperties;
}
@Override
public String getErrorPath() {
return this.errorProperties.getPath();
}
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml(HttpServletRequest request,
HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
insertError(request);
return modelAndView == null ? new ModelAndView("error", model) : modelAndView;
}
@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = getStatus(request);
insertError(request);
return new ResponseEntity(body, status);
}
/**
* Determine if the stacktrace attribute should be included.
*
* @param request the source request
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the stacktrace attribute should be included
*/
protected boolean isIncludeStackTrace(HttpServletRequest request,
MediaType produces) {
ErrorProperties.IncludeStacktrace include = getErrorProperties().getIncludeStacktrace();
if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
return true;
}
if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) {
return getTraceParameter(request);
}
return false;
}
/**
* Provide access to the error properties.
*
* @return the error properties
*/
protected ErrorProperties getErrorProperties() {
return this.errorProperties;
}
}
SpringBoot提供了一種特殊的Bean定義方式,可以讓我們?nèi)菀椎母采w已經(jīng)定義好的Controller,原生的BasicErrorController是定義在ErrorMvcAutoConfiguration中的
具體代碼如下:
@Bean
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
return new BasicErrorController(errorAttributes, this.serverProperties.getError(),
this.errorViewResolvers);
}
可以看到這個(gè)注解@ConditionalOnMissingBean 意思就是定義這個(gè)bean 當(dāng) ErrorController.class 這個(gè)沒(méi)有定義的時(shí)候, 意思就是說(shuō)只要我們?cè)诖a里面定義了自己的ErrorController.class時(shí),這段代碼就不生效了,具體自定義如下:
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
@AutoConfigureBefore(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties(ResourceProperties.class)
public class ConfigSpringboot {
@Autowired(required = false)
private List<ErrorViewResolver> errorViewResolvers;
private final ServerProperties serverProperties;
public ConfigSpringboot(
ServerProperties serverProperties) {
this.serverProperties = serverProperties;
}
@Bean
public MyBasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
return new MyBasicErrorController(errorAttributes, this.serverProperties.getError(),
this.errorViewResolvers);
}
}
在使用的時(shí)候需要注意MyBasicErrorController不能被自定義掃描Controller掃描到,否則無(wú)法啟動(dòng)。
3.總結(jié)
一般來(lái)說(shuō)自定義BasicErrorController這種方式比較實(shí)用,因?yàn)榭梢酝ㄟ^(guò)不同的頭部返回不同的數(shù)據(jù)格式,在配置上稍微復(fù)雜一些,但是從實(shí)用的角度來(lái)說(shuō)比較方便而且可以定義通用組件
本文代碼:SpringBoot-Learn_jb51.rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
springboot如何設(shè)置請(qǐng)求參數(shù)長(zhǎng)度和文件大小限制
這篇文章主要介紹了springboot如何設(shè)置請(qǐng)求參數(shù)長(zhǎng)度和文件大小限制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
如何去掉IntelliJ IDEA中mybatis對(duì)應(yīng)的xml文件警告
這篇文章主要介紹了如何去掉IntelliJ IDEA中mybatis對(duì)應(yīng)的xml文件警告問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
如何使用MybatisPlus快速進(jìn)行增刪改查詳解
增刪改查在日常開(kāi)發(fā)中是再正常不多的一個(gè)需求了,下面這篇文章主要給大家介紹了關(guān)于如何使用MybatisPlus快速進(jìn)行增刪改查的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
基于SSM框架+Javamail發(fā)送郵件的代碼實(shí)例
本篇文章主要介紹了基于SSM框架+Javamail發(fā)送郵件的代碼實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-12-12
Java通過(guò)Socket實(shí)現(xiàn)簡(jiǎn)單多人聊天室
這篇文章主要為大家詳細(xì)介紹了Java通過(guò)Socket實(shí)現(xiàn)簡(jiǎn)單多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
MyBatis中${}?和?#{}?有什么區(qū)別小結(jié)
${}?和?#{}?都是?MyBatis?中用來(lái)替換參數(shù)的,它們都可以將用戶傳遞過(guò)來(lái)的參數(shù),替換到?MyBatis?最終生成的?SQL?中,但它們區(qū)別卻是很大的,今天通過(guò)本文介紹下MyBatis中${}?和?#{}?有什么區(qū)別,感興趣的朋友跟隨小編一起看看吧2022-11-11
對(duì)java for 循環(huán)執(zhí)行順序的詳解
今天小編就為大家分享一篇對(duì)java for 循環(huán)執(zhí)行順序的詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06
Spring系列中的beanFactory與ApplicationContext
這篇文章主要介紹了Spring系列中的beanFactory與ApplicationContext,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09

