zoukankan      html  css  js  c++  java
  • SpringMVC 全局异常处理

    (一)、SpringMVC全局异常快速入门 

     

     (二)、Spring及SpringMVC扫描包隔离及配置文件优化 

              1、删除applicationContext-datasource.xml文件里context:component-scan        

     <context:component-scan base-package="com.mmall" annotation-config="true"/>

              2、applicationContext.xml文件          

    <!-- 扫描com.mmall包下的注解,就可以很方便的在类中进行注入-->
        <!-- 排除controller注解-->
        <!-- ApplicationContext.xml  是spring 全局配置文件,用来控制spring 特性的-->
        <!-- dispatcher-servlet.xml 是spring mvc里面的,控制器、拦截uri转发view  Controller扫描放到这里,其他扫描放到ApplicationContext.xml-->
    
        <context:component-scan base-package="com.mmall" annotation-config="true">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>

               3、dispatcher-servlet.xml文件

               

    <!--  只扫描controller注解,其他bean的applicationContext.xml  扫描放到 只要有方法使用了@Controller,就会扫描到-->
        <!-- use-default-filter 关闭默认扫描-->
        <context:component-scan base-package="com.mmall.controller" annotation-config="true" use-default-filters="false">
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>

    备注:

    转载地址:https://www.cnblogs.com/parryyang/p/5783399.html

    applicationContext.xml和dispatcher-servlet.xml的区别

    在SpringMVC项目中我们一般会引入applicationContext.xml和dispatcher-servlet.xml两个配置文件,这两个配置文件具体的区别是什么呢?

      Spring 官方文档介绍如下:

    Spring lets you define multiple contexts in a parent-child hierarchy.  
        The applicationContext.xml defines the beans for the "root webapp context", i.e. the context associated with the webapp.  
        The spring-servlet.xml (or whatever else you call it) defines the beans for one servlet's app context. There can be many of these in a webapp, one per Spring servlet (e.g. spring1-servlet.xml for servlet spring1, spring2-servlet.xml for servlet spring2).  
        Beans in spring-servlet.xml can reference beans in applicationContext.xml, but not vice versa.  
        All Spring MVC controllers must go in the spring-servlet.xml context.  
        In most simple cases, the applicationContext.xml context is unnecessary. It is generally used to contain beans that are shared between all servlets in a webapp. If you only have one servlet, then there's not really much point, unless you have a specific use for it.

    可见, applicationContext.xml 和 dispatch-servlet.xml形成了两个父子关系的上下文。

      1) 一个bean如果在两个文件中都被定义了(比如两个文件中都定义了component scan扫描相同的package), spring会在application context和 servlet context中都生成一个实例,他们处于不同的上下文空间中,他们的行为方式是有可能不一样的。

      2) 如果在application context和 servlet context中都存在同一个 @Service 的实例, controller(在servlet context中) 通过 @Resource引用时, 会优先选择servlet context中的实例。

      不过最好的方法是:在applicationContext和dispatcher-servlet定义的bean最好不要重复, dispatcher-servlet最好只是定义controller类型的bean。

      ----------------------------------------------------------------------------------------------------------------------------------------

      applicationContext.xml  是spring 全局配置文件,用来控制spring 特性的

      dispatcher-servlet.xml 是spring mvc里面的,控制器、拦截uri转发view

    Contronller bean放在dispatcher-servlet.xml,其他bean放在applicationContext.xml 

    (三)、 SpringMVC全局异常实战

             新建ExceptionResolver文件

              

    @Slf4j
    @Component
    public class ExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
            // 必须加e,不然在控制台不会输出完整的错误
            log.error("{} Exception", httpServletRequest.getRequestURI(), e);
    
            // 当使用jackjson2.x的时候使用MappingJackson2JsonView,课程中使用的是1.9,所以使用MappingJacksonJsonView
            // MappingJacksonJsonView是为了将model转换成json
            ModelAndView modelAndView = new ModelAndView(new MappingJacksonJsonView());
            modelAndView.addObject("status", ResponseCode.ERROR.getCode());
            modelAndView.addObject("msg", "接口异常,详细请查看服务端日志的异常信息");
            modelAndView.addObject("data", e.toString());
            return modelAndView;
        }
    }

       (四)、上面的全局异常用的是HandlerExceptionResolver,实际中还有一种方法,是用 @ExceptionHandler和@controlleradvice 

         转载:https://www.cnblogs.com/xiang--liu/p/11422504.html     

    把 @ExceptionHandler、HandlerExceptionResolver、@controlleradvice 三兄弟放在一起来写更有比较性。这三个东西都是用来处理异常的,但是它们使用的场景都不一样。看本文给你详细的讲解,再也不怕面试被问到了!

    这三个注解都是来自于 SpringMVC 的,都能进行异常处理。

    Java 程序员都非常的痛恨异常,很多人讨厌 Java 就是因为它的异常处理机制。到处的 try-catch-finally,再不是就是到处抛出异常。

    所以 Spring 深知 Java 的疼点,推出了:@ExceptionHandler、HandlerExceptionResolver、@controlleradvice 来方便我们处理一些异常!

    @ExceptionHandler 注解

    用于局部方法捕获,与抛出异常的方法处于同一个 Controller 类。源码如下:

    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ExceptionHandler {
        Class<? extends Throwable>[] value() default {};
    }

    从源码中可以看出,@ExceptionHandler 注解只能作用为对象的方法上,并且在运行时有效,value() 可以指定异常类。由该注解注释的方法可以具有灵活的输入参数。

    异常参数可以包括一般的异常或特定的异常(即自定义异常),如果注解没有指定异常类,会默认进行映射。

    用法代码如下:

    @Controller
    public class XttblogController {
        @ExceptionHandler({NullPointerException.class})
        public String exception(NullPointerException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            return "null pointer exception";
        }
        @RequestMapping("test")
        public void test() {
            throw new NullPointerException("出错了!");
        }
    }

    上面这段代码只会捕获 XttblogController 类中的 NullPointerException 异常。

    HandlerExceptionResolver 接口

    HandlerExceptionResolver 是 Spring 提供的一个接口。它可以用来处理全局异常!

    @Component
    public class GlobalExceptionResolver implements HandlerExceptionResolver{
        private ObjectMapper objectMapper;
        public CustomMvcExceptionHandler() {
            objectMapper = new ObjectMapper();
        }
        @Override
        public ModelAndView resolveException(HttpServletRequest request, 
            HttpServletResponse response,Object o, Exception ex) {
            response.setStatus(200);
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Cache-Control", "no-cache, must-revalidate");
            Map<String, Object> map = new HashMap<>();
            if (ex instanceof NullPointerException) {
                map.put("code", ResponseCode.NP_EXCEPTION);
            } else if (ex instanceof IndexOutOfBoundsException) {
                map.put("code", ResponseCode.INDEX_OUT_OF_BOUNDS_EXCEPTION);
            } else {
                map.put("code", ResponseCode.CATCH_EXCEPTION);
            }
            try {
                map.put("data", ex.getMessage());
                response.getWriter().write(objectMapper.writeValueAsString(map));
            } catch (Exception e) {
                e.printStackTrace();
            }
            return new ModelAndView();
        }
    }

    在 Spring 源码中,我们可以看出它会获取一个实现了 HandlerExceptionResolver 接口的列表 List<HandlerExceptionResolver> resolvers; 如果这个列表不为空,则循环处理其中的异常。

    HandlerExceptionResolve 虽然能够处理全局异常,但是 Spring 官方不推荐使用它。

    @controlleradvice 注解

    另外一个能够处理全局异常的就是 @controlleradvice 注解了。

    @controlleradvice 注解根据它的源码,我们知道它也只能作用在类上,并且作用于运行时。下面我们来看一个例子。

    @ControllerAdvice
    public class ExceptionController {
        @ExceptionHandler(RuntimeException.class)
        public ModelAndView handlerRuntimeException(RuntimeException ex) {
            if (ex instanceof MaxUploadSizeExceededException) {
                return new ModelAndView("error").addObject("msg", "文件太大!");
            }
            return new ModelAndView("error").addObject("msg", "未知错误:" + ex);
        }
        @ExceptionHandler(Exception.class)
        public ModelAndView handlerMaxUploadSizeExceededException(Exception ex) {
            if (ex != null) {
                return new ModelAndView("error").addObject("msg", ex);
            }
            return new ModelAndView("error").addObject("msg", "未知错误:" + ex);
        }
    }

    需要注意的是,@ControllerAdvice 一般是和 @ExceptionHandler 组合在一起使用的。官方也推荐用这种方式处理统一全局异常。

  • 相关阅读:
    parted 2T以上磁盘分区和挂载
    MySQL 表空间恢复
    MySQL 绿色版安装
    EF core
    让vs自动提示没有using的类
    Android Studio 的 Gradle 面板没有 Task
    JMS微服务远程调用性能测试 vs .Net Core gRPC服务
    electron打包,使用electron-packager
    EasyNetQ(RabbitMQ)在处理消息时,如果抛出异常,继续不断发送到订阅队列,不断处理(也就是不自动确认消息已到达)
    调用系统默认浏览器,打开网页
  • 原文地址:https://www.cnblogs.com/zhaobao1830/p/12672511.html
Copyright © 2011-2022 走看看