springMVC的几种异常处理方式

1.web.xml中异常处理

通常为了给用户提供良好的人机接口,我们都会为整个web应用,提供处理异常或者 错误的通用页面,而这些通用页面需要在web.xml中进行配置。
主要是两种方式:其一根据HTTP响应状态码;其二是根据异常类名进行配置。

<error-page> 
     <exception-type>完整的异常类名</exception-type> 
     <location>以”/”开头的异常处理页面路径</location> 
  </error-page> 
  <error-page> 
     <error-code>HTTP响应状态码</error-code> 
     <location>以”/”开头的异常处理页面路径</location> 
  </error-page> 

项目案例:

@Controller
@RequestMapping(value="/exception")
public class TestException {

	@RequestMapping("/exception/{id}")
    @ResponseBody
    public Object hello(@PathVariable String id)  {

        if (id.equals("1")) {//NullPointerException控制值异常
            throw new NullPointerException("空指针异常");
        } else if (id.equals("2")) {//数学运算异常
            int value = 1 / 0;
            return "java.lang.ArithmeticException";
        } else {
            return "ok";
        }
    }

代码分析:
http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/1
输入1到浏览器,程序出现空指针异常;
http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/2
输入2到浏览器,程序出现空指针异常
http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/3
输入其它到浏览器,程序正常运行

在这里插入图片描述
错误展示页面和页面对应错误信息
error_web_404.jsp :对应404错误
error_web_null.jsp :对应空指针异常
error_spring_404.jsp :对应404错误
error_spring_null.jsp :对应空指针异常

如下图代码,相应的错误信息指向对应的错误提示页面

	<!-- 异常处理 -->
	<!-- 接收空指针错误 -->
	<error-page>
		<exception-type>java.lang.NullPointerException</exception-type>
		<location>/WEB-INF/views/commons/error/error_web_null.jsp</location>
	</error-page>
	<!-- 404 页面不存在错误 -->
	<error-page>
		<error-code>404</error-code>
		<location>/WEB-INF/views/commons/error/error_web_404.jsp</location>
	</error-page>
	<!-- 接收405错误 -->
	<error-page>
		<error-code>405</error-code>
		<location>/WEB-INF/views/commons/error/error405.jsp</location>
	</error-page>
	<!--  500 服务器内部错误 -->
	<error-page>
		<error-code>500</error-code>
		<location>/WEB-INF/views/commons/error/error500.jsp</location>
	</error-page>

启动项目:
1.输入http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/1
这里写图片描述

结果分析:web.xml中接收到空指针异常,指向error_web_null.jsp页面

2.输入http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/2
这里写图片描述

严重: Servlet.service() for servlet [spring] in context with path [/maven-springmvc-spring-springjdbc] threw exception [Request processing failed; nested exception is java.lang.ArithmeticException: / by zero] with root cause
java.lang.ArithmeticException: / by zero
at com.controller.test.exception.TestException.hello(TestException.java:28)

结果分析:页面未跳转到任何错误提示页面,这是因为我们没有在web.xml中配置ava.lang.ArithmeticException相关错误的异常处理界面

3.输入http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/3
这里写图片描述
结果分析:根据程序代码运行结果得知程序正常执行

4.输入http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exceptionss
这里写图片描述
结果分析:web.xml中接收到404错误,跳转指向error_web_404.jsp页面

备注:在web.xml中配置的异常处理信息,使用error-page节点。


2.在springmvc上配置全局异常(配置文件的方式)

在spring-servlet.xml(springmvc的配置文件)中配置

 <!-- Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver-全局异常配置 start -->     
      <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
       <!--   默认的错误信息页面 -->
        <property name="defaultErrorView" value="error"/>
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.NullPointerException">commons/error/error_spring_null</prop>
                <prop key="java.lang.ArithmeticException">commons/error/error_spring_math</prop>
            </props>
        </property>
    </bean>   
     <!-- 全局异常配置 end -->     

TestException .java 异常测试类

@Controller
@RequestMapping(value="/exception")
public class TestException {

	@RequestMapping("/exception/{id}")
    @ResponseBody
    public Object hello(@PathVariable String id)  {

        if (id.equals("1")) {//NullPointerException控制值异常
            throw new NullPointerException("空指针异常");
        } else if (id.equals("2")) {//数学运算异常
            int value = 1 / 0;
            return "java.lang.ArithmeticException";
        } else {
            return "ok";
        }
    }

代码分析:
http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/1
输入1到浏览器,程序出现空指针异常;
http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/2
输入2到浏览器,程序出现空指针异常
http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/3
输入其它到浏览器,程序正常运行

在这里插入图片描述
错误展示页面和页面对应错误信息
error.jsp :默认异常处理页面
error_spring_404.jsp :对应404错误
error_spring_null.jsp :对应空指针异常

1.输入http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/1
在这里插入图片描述
结果分析:spring-servlet.xml中接收到空指针异常,指向error_spring_null.jsp页面

2.输入http://127.0.0.1:8080/maven-springmvc-spring-springjdbc/exception/exception/2
在这里插入图片描述
结果分析:spring-servlet.xml中接收到数学算术运算异常,指向error_spring_math.jsp页面

总结点
如果同时使用web.xml和spring-servlet.xml配置同样的异常,会出现什么结果,web.xml 和spring-servlet.xml配置会不会冲突?

这涉及到web.xml中元素的加载顺序
元素节点的加载顺序与它们在 web.xml 文件中的先后顺序无关,通常是
ServletContext -> listener -> filter -> servlet---->------>error-page
web.xml中部分代码段

	<!-- springmvc -->
	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- 自定义spring mvc的配置文件名称和路径 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springMVC/spring-servlet.xml</param-value>
		</init-param>
		<!-- 自定义启动顺序,让这个Servlet随Servlet容器一起启动 -->
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
		<!-- 异常处理 -->
	<!-- 接收空指针错误 -->
	<error-page>
		<exception-type>java.lang.NullPointerException</exception-type>
		<location>/WEB-INF/views/commons/error/error_web_null.jsp</location>
	</error-page>
	<!-- 404 页面不存在错误 -->
	<error-page>
		<error-code>404</error-code>
		<location>/WEB-INF/views/commons/error/error_web_404.jsp</location>
	</error-page>
	<!-- 接收405错误 -->
	<error-page>
		<error-code>405</error-code>
		<location>/WEB-INF/views/commons/error/error405.jsp</location>
	</error-page>
	<!--  500 服务器内部错误 -->
	<error-page>
		<error-code>500</error-code>
		<location>/WEB-INF/views/commons/error/error500.jsp</location>
	</error-page>

结果显而易见,spring-servlet.xml的加载顺序比error-page的快,异常会当有相同配置的错误时,会优先spring-servlet.xml中配置。只有当spring-servlet.xml没有处理的错误异常,才会在web.xml的error-page节点中查找对应异常。

spring-servlet.xml采用配置文件的方式的缺点:配置文件可以根据抛出的异常类的类信息配置错误的页面。但是这样我们无法手动对其定制异常。
故出现第三种方式


3.第三种方式采用自定义异常类,定制异常集中处理

ExceptionUtil .java 自定义的异常处理类

//自己手动编写Java代码来实现定制异常信息处理
package com.util.exception;
/**
 * 所属类别:工具类
 * 用途:自定义的异常类
 * @author yilei
 * version:1.0
 */
public class ExceptionUtil extends RuntimeException {
	public ExceptionUtil(String string) {
		super(string);
	}

}


在spring-servlet.xml ,相比于第二种方法多了com.util.exception.ExceptionUtil,可以配置自定义异常处理类进行接收异常

     <!-- Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver-全局异常配置 start -->     
      <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
       <!--  默认的错误信息页面-->
        <property name="defaultErrorView" value=">commons/error/error"/>
        <property name="exceptionMappings">
            <props>
                <!-- 自定义的异常类 -->
                <prop key="com.util.exception.ExceptionUtil">commons/error/error_spring_ExceptionUtil</prop> 
                <!-- 空指针异常 -->
                <prop key="java.lang.NullPointerException">commons/error/error_spring_null</prop>
                <!-- 数学算术异常 -->
                <prop key="java.lang.ArithmeticException">commons/error/error_spring_math</prop>
            </props>
        </property>
    </bean>    
     <!-- 全局异常配置 end -->   

error_spring_ExceptionUtil.jsp 自定义异常处理jsp页面

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
error_spring_ExceptionUtil.jsp<br>
spirngmvc配置异常-自定义异常
</body>
</html>

TestException.java 进行异常测试的类,throw new ExceptionUtil(“自定义有异常”);这段代码用于抛出自定义异常类,springmvc中配置自动跳转到commons/error/error_spring_ExceptionUtil页面

package com.controller.test.exception;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.util.exception.ExceptionUtil;

@Controller
@RequestMapping(value = "/exception")
public class TestException   {

	@RequestMapping("/exception/{id}")
	@ResponseBody
	public Object hello(@PathVariable String id) {
        if(id.equals("0")){
        	 throw new ExceptionUtil("自定义有异常");
        }else if (id.equals("1")) {// NullPointerException控制值异常
			throw new NullPointerException("空指针异常");
		} else if (id.equals("2")) {// 数学运算异常
			int value = 1 / 0;
			return "java.lang.ArithmeticException";
		} else {
			return "ok";
		}
	}
}

4.第四种方式去实现自定义异常处理(基于注解的方式)

ExceptionUtil .java 自定义的异常处理类

//自己手动编写Java代码来实现定制异常信息处理
package com.util.exception;
/**
 * 所属类别:工具类
 * 用途:自定义的异常类
 * @author yilei
 * version:1.0
 */
public class ExceptionUtil extends RuntimeException {
	public ExceptionUtil(String string) {
		super(string);
	}

}


TestException.java 异常测试类,使用注解ExceptionHandler来标识,在每个需要使用此异常处理的类中添加handleLocalException方法,在使用 throw new ExceptionUtil(“自定义有异常”);代码时候,就算同时配置上面第三种方法来自定义了异常处理界面,但是也不会生效,而是由方法handleLocalException中决定异常处理结果,本类中最终有error.jsp页面来进行异常显示。

package com.controller.test.exception;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.util.exception.ExceptionUtil;

@Controller
@RequestMapping(value = "/exception")
public class TestException   {

	@RequestMapping("/exception/{id}")
	@ResponseBody
	public Object hello(@PathVariable String id) {
        if(id.equals("0")){
        	 throw new ExceptionUtil("自定义有异常");
        }else if (id.equals("1")) {// NullPointerException控制值异常
			throw new NullPointerException("空指针异常");
		} else if (id.equals("2")) {// 数学运算异常
			int value = 1 / 0;
			return "java.lang.ArithmeticException";
		} else {
			return "ok";
		}
	}
	
    //异常处理,基于注解的方式,但是需要进行自定义异常的类中都写一个相同的方法才可生效。如果使用这种方式。
    @ExceptionHandler(value={ExceptionUtil.class})
    public String handleLocalException(ExceptionUtil e, HttpServletRequest req){
        req.setAttribute("error", e);
        return "error/error";
    }

}

error.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>
    异常抛出处理
</title>
</head>
<body>
    <h1>${error.message}</h1>
</body>
</html>

**

总结

**
第一种web.xml配置和第二种基于springmvc中配置的方式是最常见的异常处理方法,通常项目中是结合一起使用

第三种和第四中方式主要是为了定制异常,为了满足项目上一些特殊需求,
相对第四种方式,更建议采用第三种的方式来自定义异常处理,主要是因为第四种(采用注解的方式),需要在每个使用了自定义异常类中都需要类似以下代码的方法来处理异常,对程序来说比较冗余。

    //异常处理,基于注解的方式,但是需要进行自定义异常的类中都写一个相同的方法才可生效。如果使用这种方式。
    @ExceptionHandler(value={ExceptionUtil.class})
    public String handleLocalException(ExceptionUtil e, HttpServletRequest req){
        req.setAttribute("error", e);
        return "error/error";
    }

而第三种,在第二种方法的基础上,实现全局的配置,更便捷,因此,如果需要使用自定义异常的话,建议使用第三种方式,同时第一种和第二种相结合。

大家可以参考我的另一篇博文,在实际项目中运用到了异常处理
https://blog.csdn.net/qq_29914837/article/details/82686202

  • 12
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值