遇一山,过一山,处处有风景;只要勇敢向前,一路尽是繁花盛开。 | (点击查看→)【测试干货】python/java自动化、持续集成、性能、测开、简历、笔试面试等

SpringMVC异常处理

简介

系统中异常包括:编译时异常和运行时异常RuntimeException;

编译异常就是检查异常,需要捕获;运行时异常可以捕获也可以不捕获。

 

异常处理思路

在springmvc中,异常处理的思路

 

系统的dao、service、controller出现异常都通过throwsException向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器进行统一异常处理。

 

异常处理结构体系

SpringMVC通过HandlerExceptionResolver处理程序的异常,HandlerExceptionResolver仅有一个接口方法:

/*
 * Copyright 2002-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Interface to be implemented by objects that can resolve exceptions thrown during
 * handler mapping or execution, in the typical case to error views. Implementors are
 * typically registered as beans in the application context.
 *
 * <p>Error views are analogous to JSP error pages but can be used with any kind of
 * exception including any checked exception, with potentially fine-grained mappings for
 * specific handlers.
 *
 * @author Juergen Hoeller
 * @since 22.11.2003
 */
public interface HandlerExceptionResolver {

	/**
	 * Try to resolve the given exception that got thrown during handler execution,
	 * returning a {@link ModelAndView} that represents a specific error page if appropriate.
	 * <p>The returned {@code ModelAndView} may be {@linkplain ModelAndView#isEmpty() empty}
	 * to indicate that the exception has been resolved successfully but that no view
	 * should be rendered, for instance by setting a status code.
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param handler the executed handler, or {@code null} if none chosen at the
	 * time of the exception (for example, if multipart resolution failed)
	 * @param ex the exception that got thrown during handler execution
	 * @return a corresponding {@code ModelAndView} to forward to, or {@code null}
	 * for default processing
	 */
	ModelAndView resolveException(
			HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

}

 

HandlerExceptionResolver拥有几个常见实现类:

 

异常处理方案

DefaultHandlerExceptionResolver

SpringMVC默认装配了DefaultHandlerExceptionResolver,它会将SpringMVC框架的异常转换为相应的相应状态码。

异常和相应状态码对应表:

 

在web.xml响应状态码配置一个对应页面,比如:

<error-page>
 <error>404</error>
 <location>/static/404.html</location>
</error-page>

 

示例

在webapp下,创建static文件夹,再创建404.html

404.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <h1>你来晚了,页面飞走了</h1>
</body>
</html>

 

web.xml中添加404页面

  <error-page>
    <error-code>404</error-code>
    <location>/static/404.html</location>
  </error-page>

  

springmvc.xml中添加如下内容,否则会被拦截

    <mvc:resources location="/static/" mapping="/static/**"/>

 

重启tomcat

请求一个不存在的页面

 

SimpleMappingExceptionResolver

如果希望当指定的异常发生时,把它映射到要显示的错误的网页中,此时用SimpleMappingExceptionResolver进行解析。DispatcherServlet中没有实现SimpleMappingExceptionResolver的Bean,所有需要在springmvc的配置文件中进行配置。

示例如下:

package com.qzcsbj.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Date;

@Controller
public class ExceptionController {
    @RequestMapping("/testSimpleMappingExceptionResolver")
    public String testSimpleMappingExceptionResolver() {
        String[] values = new String[10];
        // 下标越界了
        System.out.println(values[11]);
        return "success";
    }
}

  

重启tomcat

访问:http://localhost:8080/testSimpleMappingExceptionResolver

报500错误

  

处理异常

springmvc.xml中添加:

    <mvc:annotation-driven />
    <!-- 配置使用SimpleMappingExceptionResolver来映射异常 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!-- 给异常命名一个别名 -->
        <property name="exceptionAttribute" value="ex"/>
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
            </props>
        </property>
    </bean>

  

在/WEB-INF/jsp下新建一个error.jsp视图,error.jsp内容为:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>Error Page</h1>
    <h1>出现了异常</h1>
    ${requestScope.ex}
</body>
</html>

 

请求:http://localhost:8080/testSimpleMappingExceptionResolver

 

AnnotationMethodHandlerExceptionResolver

SpringMVC默认注册了AnnotationMethodHandlerExceptionResolver,它允许通过@ExceptionHandler注解指定处理特定异常的方法。

package com.qzcsbj.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ExceptionController2 {
    @ExceptionHandler(value = { RuntimeException.class })
    public ModelAndView handleArithmeticException2(Exception ex)
    {
        System.out.println("出异常了:" + ex);
        ModelAndView mv = new ModelAndView("error");
        mv.addObject("exception", ex);
        return mv;
    }

    @ExceptionHandler(value = { ArithmeticException.class })
    public ModelAndView handleArithmeticException(Exception ex) {
        System.out.println("出异常了,算术异常:" + ex);
        ModelAndView mv = new ModelAndView("error");
        mv.addObject("exception", ex);
        return mv;
    }

    @RequestMapping("/testExceptionHandler1")
    public String test1() {
        String s=null;
        System.out.println(s.length()); // 空指针异常
        return "success";
    }

    @RequestMapping("/testExceptionHandler2")
    public String test2() {
        int i=100/0;  // 算数异常
        return "success";
    }
}

  

error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>Error Page</h1>
    <h1>出现了异常</h1>
    ${requestScope.exception}
</body>
</html>

  

请求:http://localhost:8080/testExceptionHandler1


请求:http://localhost:8080/testExceptionHandler2

 

若将handleArithmeticException方法注释掉,则发生ArithmeticException异常将由handleArithmeticException2进行处理(handleArithmeticException2将处理下面两个异常)。

修改控制器 

package com.qzcsbj.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ExceptionController2 {
    @ExceptionHandler(value = { RuntimeException.class })
    public ModelAndView handleArithmeticException2(Exception ex)
    {
        System.out.println("出异常了:" + ex);
        ModelAndView mv = new ModelAndView("error");
        mv.addObject("exception", ex);
        return mv;
    }

    // @ExceptionHandler(value = { ArithmeticException.class })
    // public ModelAndView handleArithmeticException(Exception ex) {
    //     System.out.println("出异常了,算术异常:" + ex);
    //     ModelAndView mv = new ModelAndView("error");
    //     mv.addObject("exception", ex);
    //     return mv;
    // }

    @RequestMapping("/testExceptionHandler1")
    public String test1() {
        String s=null;
        System.out.println(s.length()); // 空指针异常
        return "success";
    }

    @RequestMapping("/testExceptionHandler2")
    public String test2() {
        int i=100/0;  // 算数异常
        return "success";
    }
}

  

重启tomcat

请求:http://localhost:8080/testExceptionHandler1

 

请求:http://localhost:8080/testExceptionHandler2

 

缺点:

  进行异常处理的方法必须与出错的方法在同一个Controller里面。

  不能全局控制异常,每个类都要写一遍。

 

全局异常处理

上文说到@ExceptionHandler需要进行异常处理的方法必须与出错的方法在同一个Controller里面。那么当代码加入了@ControllerAdvice,则不需要必须在同一个controller 中了。

修改控制器

package com.qzcsbj.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ExceptionController2 {
    // @ExceptionHandler(value = { RuntimeException.class })
    // public ModelAndView handleArithmeticException2(Exception ex)
    // {
    //     System.out.println("出异常了:" + ex);
    //     ModelAndView mv = new ModelAndView("error");
    //     mv.addObject("exception", ex);
    //     return mv;
    // }

    // @ExceptionHandler(value = { ArithmeticException.class })
    // public ModelAndView handleArithmeticException(Exception ex) {
    //     System.out.println("出异常了,算术异常:" + ex);
    //     ModelAndView mv = new ModelAndView("error");
    //     mv.addObject("exception", ex);
    //     return mv;
    // }

    @RequestMapping("/testExceptionHandler1")
    public String test1() {
        String s=null;
        System.out.println(s.length()); // 空指针异常
        return "success";
    }

    @RequestMapping("/testExceptionHandler2")
    public String test2() {
        int i=100/0;  // 算数异常
        return "success";
    }
}

 

package com.qzcsbj.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
@Controller
public class WebExceptionController {
    @ExceptionHandler(value = { RuntimeException.class })
    public ModelAndView handleRuntimeException2(Exception ex) {
        System.out.println("【全局异常处理】出异常了: " + ex);
        ModelAndView mv = new ModelAndView("error");
        mv.addObject("exception", ex);
        return mv;
    }
}

 

重启tomcat

请求:http://localhost:8080/testExceptionHandler1

 


请求:http://localhost:8080/testExceptionHandler2

 

【bak】 

原文会持续更新,原文地址:https://www.cnblogs.com/uncleyong/p/17060269.html

 

posted @ 2023-01-19 22:28  全栈测试笔记  阅读(118)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end