当前位置: 首页 > news >正文

做网站实训心得龙岗网络公司

做网站实训心得,龙岗网络公司,福州网络推广建站,抢车票网站怎么做使用注解方式处理全局异常使用 ControllerAdvice (RestControllerAdvice) 配合 ExceptionHandler适用于返回数据的请求(一般是RESTful接口规范下的JSON报文)package com.example.exception;import org.slf4j.Logger; import org.s…

使用注解方式处理全局异常

  1. 使用 @ControllerAdvice (@RestControllerAdvice) 配合 @ExceptionHandler

适用于返回数据的请求(一般是RESTful接口规范下的JSON报文)

package com.example.exception;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.example.exception.ControllerController.MyException1;@RestControllerAdvice
public class RestControllerExceptionAdvice {private static transient Logger logger = LoggerFactory.getLogger(RestControllerExceptionAdvice.class);@ExceptionHandler(MyException1.class)public String MyException1(MyException1 e) {logger.info("RestControllerExceptionAdvice MyException1 异常->{}", e.getMessage());return "error";}
}
  1. 适用于返回视图的请求,方法返回值如果不是ModelAndView而是字符串时,字符串会被解析成视图名

package com.example.exception;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import com.example.exception.ControllerController.MyException1;
import com.example.exception.ControllerController.MyException3;@ControllerAdvice
public class ControllerExceptionAdvice {private static transient Logger logger = LoggerFactory.getLogger(ControllerExceptionAdvice.class);@ExceptionHandler(MyException1.class)public String uploadException(MyException1 e) {logger.info("ControllerExceptionAdvice MyException1 异常->{}", e.getMessage());return "this is a viewName1";}@ExceptionHandler(MyException3.class)public ModelAndView uploadException(MyException3 e) {logger.info("ControllerExceptionAdvice MyException3 异常->{}", e.getMessage());return new ModelAndView("this is a viewName3");}
}
  1. 也可以@ControllerAdvice配合使用@ResponseBody完成和@RestControllerAdvice一样的效果(不建议这样使用,个人感觉会使代码很混乱)

package com.example.exception;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.example.exception.ControllerController.MyException1;
import com.example.exception.ControllerController.MyException2;
import com.example.exception.ControllerController.MyException3;@ControllerAdvice
public class ControllerExceptionAdvice {private static transient Logger logger = LoggerFactory.getLogger(ControllerExceptionAdvice.class);@ExceptionHandler(MyException2.class)@ResponseBodypublic String uploadException(MyException2 e) {logger.info("ControllerExceptionAdvice MyException2 异常->{}", e.getMessage());return "this is a rsp";}
}
  1. 控制器私有的异常处理器,优先级高于全局异常处理器

package com.example.exception;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class RestControllerController {private static transient Logger logger = LoggerFactory.getLogger(RestControllerController.class);@GetMapping("/test")@ResponseBodypublic String testExceptionResolver() {throw new RuntimeException("这是测试控制器异常");}// 只针对当前控制器,优先级高于全局异常处理器@ResponseBody@ExceptionHandler(RuntimeException.class)public String uploadException(RuntimeException e) {logger.info("RestControllerController RuntimeException 异常->{}", e.getMessage());return "error";}
}

使用HandlerExceptionResolver接口实现处理全局异常

package com.example.exception;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;@Component
public class ExceptionResolver1 implements HandlerExceptionResolver {private static transient Logger logger = LoggerFactory.getLogger(ExceptionResolver1.class);@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {ModelAndView mv = new ModelAndView();logger.info("ExceptionResolver 异常->{}", ex.getMessage());return mv;}
}
package com.example.exception;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;@Component
public class ExceptionResolver2 implements HandlerExceptionResolver {private static transient Logger logger = LoggerFactory.getLogger(ExceptionResolver1.class);@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {ModelAndView mv = new ModelAndView();logger.info("ExceptionResolver2 异常->{}", ex.getMessage());return mv;}
}
  • HandlerExceptionResolver接口是没有排序的,所以应用程序无法保证执行顺序

  • 如果第一个执行的HandlerExceptionResolver已经返回了ModelAndView,那么后续所有的HandlerExceptionResolver都将不会被执行;返回null会使得后续HandlerExceptionResolver继续执行,一直到返回ModelAndView的HandlerExceptionResolver结束(如果你的所有实现全部返回null值也没有意义)

  • @ControllerAdvice (@RestControllerAdvice) 配合 @ExceptionHandler的全局异常处理会先于HandlerExceptionResolver执行,所以@ExceptionHandler注解方法中的异常可以由HandlerExceptionResolver处理(保证@ExceptionHandler注解方法不抛出异常才是正确的)

核心源码位置

  1. Spring MVC在 DispatcherServlet#processHandlerException()方法中使用上述的异常解析器,关于异常处理返回值解析的问题以及异常处理顺序的问题都可以以该方法为起点打断点DEBUG

@Nullableprotected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,@Nullable Object handler, Exception ex) throws Exception {// Success and error responses may use different content typesrequest.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);// Check registered HandlerExceptionResolvers...ModelAndView exMv = null;//就在这个位置if (this.handlerExceptionResolvers != null) {for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {exMv = resolver.resolveException(request, response, handler, ex);if (exMv != null) {break;}}}if (exMv != null) {if (exMv.isEmpty()) {request.setAttribute(EXCEPTION_ATTRIBUTE, ex);return null;}// We might still need view name translation for a plain error model...if (!exMv.hasView()) {String defaultViewName = getDefaultViewName(request);if (defaultViewName != null) {exMv.setViewName(defaultViewName);}}if (logger.isTraceEnabled()) {logger.trace("Using resolved error view: " + exMv, ex);}else if (logger.isDebugEnabled()) {logger.debug("Using resolved error view: " + exMv);}WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());return exMv;}throw ex;}
  1. Spring MVC在WebMvcConfigurationSupport#handlerExceptionResolver()方法中处理异常解析器的注入,该方法返回的是一个包装器HandlerExceptionResolverComposite,该包装器持有HandlerExceptionResolver

    @Beanpublic HandlerExceptionResolver handlerExceptionResolver(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();configureHandlerExceptionResolvers(exceptionResolvers);if (exceptionResolvers.isEmpty()) {addDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);}extendHandlerExceptionResolvers(exceptionResolvers);HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();composite.setOrder(0);composite.setExceptionResolvers(exceptionResolvers);return composite;}

WebMvcConfigurationSupport#configureHandlerExceptionResolvers()方法是一个空实现,需要子类实现去注入自定义的HandlerExceptionResolver

protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {}

如果没有提供自定义的异常解析器,会默认使用WebMvcConfigurationSupport#addDefaultHandlerExceptionResolvers()方法加载异常解析器

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());}

ExceptionHandlerExceptionResolver类的exceptionHandlerAdviceCache属性中存储的就是@ExceptionHandler注解的异常处理器,初始化核心代码

    @Overridepublic void afterPropertiesSet() {// Do this first, it may add ResponseBodyAdvice beansinitExceptionHandlerAdviceCache();if (this.argumentResolvers == null) {List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.returnValueHandlers == null) {List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);}}
private void initExceptionHandlerAdviceCache() {if (getApplicationContext() == null) {return;}List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());for (ControllerAdviceBean adviceBean : adviceBeans) {Class<?> beanType = adviceBean.getBeanType();if (beanType == null) {throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);}ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);if (resolver.hasExceptionMappings()) {this.exceptionHandlerAdviceCache.put(adviceBean, resolver);}if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {this.responseBodyAdvice.add(adviceBean);}}if (logger.isDebugEnabled()) {int handlerSize = this.exceptionHandlerAdviceCache.size();int adviceSize = this.responseBodyAdvice.size();if (handlerSize == 0 && adviceSize == 0) {logger.debug("ControllerAdvice beans: none");}else {logger.debug("ControllerAdvice beans: " +handlerSize + " @ExceptionHandler, " + adviceSize + " ResponseBodyAdvice");}}}

注意:自定义实现WebMvcConfigurationSupport可能会导致 @ExceptionHandler异常处理器失效,比如重写WebMvcConfigurationSupport#configureHandlerExceptionResolvers()方法并添加了自己的异常处理器

package com.example.config;import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration
public class WebMvcConfigurationSupportTest extends WebMvcConfigurationSupport {@Overrideprotected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {exceptionResolvers.add(new HandlerExceptionResolver() {@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) {System.out.println("resolveException.......................");return new ModelAndView();}});}
}

http://www.hkea.cn/news/894453/

相关文章:

  • 预付网站制作费怎么做凭证如何自制网站
  • 定制网站多少钱北京seo网站管理
  • 南昌做网站公司哪家好如何建立独立网站
  • 成都解放号网站建设什么是百度竞价
  • 网站优化的基本思想与原则百度号码
  • 沧州网站建设制作设计优化深圳seo优化推广
  • 建立一个网站需要什么技术网上培训机构
  • 网站设计与管理论文百度账号注册平台
  • 网站空间商推荐seo是什么职位缩写
  • 怎么建设boss网站文件外链
  • 百度推广网站建设费百度搜索引擎的网址是多少
  • php 手机网站 上传图片定制网站建设
  • 关于网站建设的问题百度关键词分析
  • 登录官方网站装修公司网络推广方案
  • 设计网站官网入口网站搜索优化方法
  • 网站优化qq群山东做网站
  • wordpress icomoon太原seo快速排名
  • 中华建设杂志网站记者数据指数
  • 网站开发测试情况南召seo快速排名价格
  • 上海仓储公司小红书seo优化
  • 南京建设公司网站网络营销整合推广
  • wordpress更改语言沈阳seo优化
  • wordpress免费网站世界大学排名
  • 做网站的属于什么专业?百度爱采购竞价推广
  • 网站建设一年多少恰东莞网站到首页排名
  • 新企业网站应该怎么做SEO优化广告联盟有哪些
  • 手机app开发网站建设软文推广文章案例
  • 网站自然排名百度经验官网登录
  • dz网站模板沧州网站优化公司
  • 桂林论坛天涯社区培训行业seo整站优化