成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring MVC核心功能異常處理機(jī)制原理詳解

開發(fā) 架構(gòu)
如果在請(qǐng)求映射期間發(fā)生異常或從請(qǐng)求處理程序(例如@Controller)拋出異常,DispatcherServlet將委托給HandlerExceptionResolver bean鏈來(lái)解決異常并提供替代處理,這通常是一個(gè)錯(cuò)誤響應(yīng)。

概述

如果在請(qǐng)求映射期間發(fā)生異常或從請(qǐng)求處理程序(例如@Controller)拋出異常,DispatcherServlet將委托給HandlerExceptionResolver

下表列出了可用的HandlerExceptionResolver實(shí)現(xiàn):

HandlerExceptionResolver

描述

SimpleMappingExceptionResolver

異常類名和錯(cuò)誤視圖名之間的映射。用于在瀏覽器應(yīng)用程序中渲染錯(cuò)誤頁(yè)面。

DefaultHandlerExceptionResolver

解析Spring MVC引發(fā)的異常,并將其映射為HTTP狀態(tài)碼。另見可選的ResponseEntityExceptionHandler和REST API異常。

ResponseStatusExceptionResolver

使用@ResponseStatus注解解析異常,并根據(jù)注解中的值將異常映射為HTTP狀態(tài)碼。

ExceptionHandlerExceptionResolver

通過在@Controller或@ControllerAdvice類中調(diào)用@ExceptionHandler方法來(lái)解決異常。

異常解析器鏈

你可以在Spring配置中聲明多個(gè)HandlerExceptionResolver

HandlerExceptionResolver的約定規(guī)定它可以返回:

  • 指向錯(cuò)誤視圖的ModelAndView
  • 如果異常是在解析器中處理的,則返回空的ModelAndView
  • 如果異常仍然未解決,則為null,以便后續(xù)的解析器嘗試,如果異常在最后仍然存在,則允許它向上冒泡到Servlet容器。

MVC配置自動(dòng)為默認(rèn)的Spring MVC異常、@ResponseStatus注解的異常以及@ExceptionHandler方法聲明了內(nèi)置的解析器。

容器錯(cuò)誤頁(yè)配置

如果任何HandlerExceptionResolver都無(wú)法解決異常,因此需要傳播,或者響應(yīng)狀態(tài)被設(shè)置為錯(cuò)誤狀態(tài)(即4xx、5xx), Servlet容器可以在HTML中渲染一個(gè)默認(rèn)的錯(cuò)誤頁(yè)面。要定制容器的默認(rèn)錯(cuò)誤頁(yè)面,可以在web.xml中聲明錯(cuò)誤頁(yè)面映射。如下面的例子所示:?

<error-page>
<location>/error</location>
</error-page>

根據(jù)前面的示例,當(dāng)出現(xiàn)異常冒泡或響應(yīng)具有錯(cuò)誤狀態(tài)時(shí),Servlet容器將在容器中向配置的URL(例如/error)發(fā)送錯(cuò)誤。然后由DispatcherServlet處理,可能會(huì)將其映射到一個(gè)@Controller,這個(gè)@Controller可以實(shí)現(xiàn)為返回一個(gè)帶有模型的錯(cuò)誤視圖名稱,或者渲染一個(gè)JSON響應(yīng),如下面的例子所示:?

@RestController
public class ErrorController {


@RequestMapping(path = "/error")
public Map<String, Object> handle(HttpServletRequest request) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("status", request.getAttribute("javax.servlet.error.status_code"));
map.put("reason", request.getAttribute("javax.servlet.error.message"));
return map;
}
}

錯(cuò)誤處理原理

public class DispatcherServlet {
// 取得容器中所有的異常解析器
private List<HandlerExceptionResolver> handlerExceptionResolvers;
protected void initStrategies(ApplicationContext context) {
// 初始化異常解析器
initHandlerExceptionResolvers(context);
}
private void initHandlerExceptionResolvers(ApplicationContext context) {
this.handlerExceptionResolvers = null;
if (this.detectAllHandlerExceptionResolvers) {
// 獲取容器中所有的異常解析器
Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
}
}
}
}

發(fā)生異常后邏輯處理?

public class DispatcherServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {


boolean errorView = false;
// 判斷當(dāng)前調(diào)用是否發(fā)生了異常
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
} else {
// 獲取當(dāng)前處理句柄HandlerMethod
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
// 處理異常
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
}
}
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler, Exception ex) throws Exception {
request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
ModelAndView exMv = null;
if (this.handlerExceptionResolvers != null) {
// 遍歷在上面初始化查找到的所有異常解析器
for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
// 執(zhí)行異常解析
exMv = resolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
}
if (exMv != null) {
// ...
return exMv ;
}
// 如果所有的異常解析器都返回null,則直接拋出異常,該異常會(huì)被Servlet進(jìn)行處理
throw ex ;
}
}

異常解析器默認(rèn)配置

public class WebMvcAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(WebProperties.class)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
}
}
public class WebMvcConfigurationSupport {
@Bean
public HandlerExceptionResolver handlerExceptionResolver(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
// 處理自定義異常解析器的配置
configureHandlerExceptionResolvers(exceptionResolvers);
if (exceptionResolvers.isEmpty()) {
// 如果沒有異常解析器,那么添加默認(rèn)的異常解析器
addDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);
}
extendHandlerExceptionResolvers(exceptionResolvers);
HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
// 設(shè)置高優(yōu)先級(jí),Composite成為統(tǒng)一的入口
composite.setOrder(0);
composite.setExceptionResolvers(exceptionResolvers);
return composite;
}
// 默認(rèn)配置
protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers, ContentNegotiationManager mvcContentNegotiationManager) {
ExceptionHandlerExceptionResolver exceptionHandlerResolver = createExceptionHandlerExceptionResolver();
exceptionHandlerResolver.setContentNegotiationManager(mvcContentNegotiationManager);
exceptionHandlerResolver.setMessageConverters(getMessageConverters());
exceptionHandlerResolver.setCustomArgumentResolvers(getArgumentResolvers());
exceptionHandlerResolver.setCustomReturnValueHandlers(getReturnValueHandlers());
if (jackson2Present) {
exceptionHandlerResolver.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
}
if (this.applicationContext != null) {
exceptionHandlerResolver.setApplicationContext(this.applicationContext);
}
exceptionHandlerResolver.afterPropertiesSet();
exceptionResolvers.add(exceptionHandlerResolver);
ResponseStatusExceptionResolver responseStatusResolver = new ResponseStatusExceptionResolver();
responseStatusResolver.setMessageSource(this.applicationContext);
exceptionResolvers.add(responseStatusResolver);
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
}
}

完畢!!!

責(zé)任編輯:武曉燕 來(lái)源: 實(shí)戰(zhàn)案例錦集
相關(guān)推薦

2011-03-17 09:20:05

異常處理機(jī)制

2010-03-05 15:40:16

Python異常

2023-06-15 14:09:00

解析器Servlet容器

2011-07-21 15:20:41

java異常處理機(jī)制

2021-03-02 09:12:25

Java異常機(jī)制

2021-07-03 17:53:52

Java異常處理機(jī)制

2011-04-06 10:27:46

Java異常處理

2009-08-05 18:09:17

C#異常處理機(jī)制

2024-03-04 10:00:35

數(shù)據(jù)庫(kù)處理機(jī)制

2023-07-10 08:00:13

架構(gòu)Rest返回值

2011-05-24 09:22:44

Spring3異常處理

2021-12-27 08:27:17

SpringMVC面試

2023-02-08 08:11:58

Spring容器核心事件

2022-04-12 08:09:22

Nodejs前端面試題

2023-03-08 08:54:59

SpringMVCJava

2009-09-02 18:34:28

C#鼠標(biāo)事件

2021-03-25 07:44:39

C++異常處理開發(fā)技術(shù)

2024-04-23 00:00:00

SpringBoot監(jiān)聽器

2015-12-28 11:25:51

C++異常處理機(jī)制

2009-11-18 13:11:29

PHP核心
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩精品在线播放 | 欧美视频一区二区三区 | 久久免费精品 | 成人一区二区三区在线观看 | 国产精品99久久久久久www | 欧美美女被c | 午夜一区二区三区在线观看 | 毛片一级片 | 午夜三级视频 | 羞羞视频免费观 | 玖玖久久 | 中文字幕在线视频免费视频 | 久久综合亚洲 | 精品免费国产一区二区三区四区介绍 | 一区二区三区视频在线观看 | 国产美女视频黄a视频免费 国产精品福利视频 | 91麻豆精品国产91久久久资源速度 | www.天天操.com | 日本在线网站 | 成人美女免费网站视频 | 国产中文字幕亚洲 | 国产精品视频一区二区三区 | 国产精品一区二区视频 | 国产精品美女久久久久aⅴ国产馆 | 国产成人免费视频网站视频社区 | 一二区成人影院电影网 | 毛片久久久 | 一级日批片 | 久久综合九色综合欧美狠狠 | 凹凸日日摸日日碰夜夜 | 欧美中文字幕一区二区三区 | 成人网视频 | 欧美视频第三页 | 国产欧美精品区一区二区三区 | 国产日韩欧美在线观看 | 亚洲五码久久 | 一区二区三区高清不卡 | 欧美午夜在线 | 久久久精品一区二区三区 | 久久国产精品免费一区二区三区 | 九九热视频这里只有精品 |