Spring 中异常处理方法的总结

目录

最佳实践

前言

开始了

异常的抛出

异常的捕获

(2)全局捕获


最佳实践

直接搜 “方式二ExceptionResolver.java”

前言

在编程过程中,我们总是会遇到各种各样的一样,受检异常和非受检异常,也可以对这些异常进行重写或者扩展,总而言之,这就涉及到一个处理异常的问题。

好的异常处理方式既容易配置又可以保持使用端的友好交互,更为重要的是在出现问题的时候快速的帮助我们定位问题。

事实上,对代码的理解很总要,这样你就知道什么时候应该抛出什么异常了,比如数组越界,文件过大,栈越界,连接超时这些标准异常,等等。当然,在什么时候抛出什么异常不是本文的重点,网上同类的文章很多,传送门Java 基础 积累-不断更新:异常分类:Error,Exception,RuntimeException以及其子类,其他异常

本文主要着重于异常的抛出方式和捕获方式。

再一个,对于以接口对外提供服务的项目与以页面对外提供服务的项目侧重点也是不一样的。前者需要在遇到异常时继续返回接口出参,只不过是内容有所不同,而以页面交互

的在出现异常时,则可能是跳转到了不同的页面并且给予提示信息。

最后,异常的处理包括异常的抛出和处理,抛出异常是一个,捕获异常和接下来的处理是另一个。

(1)抛出异常——捕获异常——跳转页面

(2)抛出异常——捕获异常——接口出参

代码

本文代码已经上传git:https://github.com/Bestcxy/Spring-fileup-interceptor-filter-Exception

基础工作

(1)自定义的异常类

package com.bestcxx.stu.fileup.exception;

/**
 * 自定义的异常类
 * @author WuJieJecket
 *
 */
@SuppressWarnings("serial")
public class MyException extends Exception {
	public MyException(String string) {
		super(string);
	}

}

(2)页面等前端文件的位置-视图解析配置-关注页面基础位置WEB-INF/views

applicationContext-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:util="http://www.springframework.org/schema/util"  
    xmlns:orm="http://www.springframework.org/schema/orm"   
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd  
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd  
                        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd  
                        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd  
                        http://www.springframework.org/schema/orm http://www.springframework.org/schema/orm/spring-orm-4.3.xsd  
                        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd  
    ">
    <!-- 配置注解驱动 -->  
    <mvc:annotation-driven/>
    
    <!-- 定义默认访问 -->  
    <mvc:view-controller path="/" view-name="forward:home"/>
    
    <!-- 处理静态资源 -->
	<mvc:resources location="/WEB-INF/css/" mapping="/css/**" />
	<mvc:resources location="/WEB-INF/js/" mapping="/js/**" />
	
    <!-- 配置视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
        <property name="contentType" value="text/html"/>        
        <property name="prefix" value="/WEB-INF/views/"/>  
        <property name="suffix" value=".jsp"/>  
    </bean>
    
   
</beans>

开始了

异常的抛出

(1)局部方法抛出

	/**
	 * 异常处理测试
	 * @return
	 */
	@GetMapping("exception")
	public String exception() throws Exception{
		if(true){
			throw new MyException("报错");			
		}
		
		return "success";
	}

(2)拦截器抛出-类加配置文件

MyInterceptor.java

package com.bestcxx.stu.fileup.intercepter;

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

import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.bestcxx.stu.fileup.exception.MyException;

public class MyInterceptor implements HandlerInterceptor {
	private long maxSize;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println(this.getClass()+" preHandle开始:"+System.currentTimeMillis());
		System.out.println(this.getClass()+" 自定义拦截器访问前:"+maxSize);
		 if(request!=null && ServletFileUpload.isMultipartContent(request)) {
	            ServletRequestContext ctx = new ServletRequestContext(request);
	            long requestSize = ctx.contentLength();
	            if (requestSize > maxSize) {
	            	System.out.println(this.getClass()+" preHandle结束:"+System.currentTimeMillis()+" 文件太大主动抛出异常"); 
	            	//throw new MaxUploadSizeExceededException(maxSize);
	                throw new MyException(maxSize+"文件太大超了");
	            }
	        }
		System.out.println(this.getClass()+" preHandle结束:"+System.currentTimeMillis());
		return true;
		
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		System.out.println(this.getClass()+" postHandle开始:"+System.currentTimeMillis());
		System.out.println(this.getClass()+" 自定义拦截器访问中:"+maxSize);
		System.out.println(this.getClass()+" postHandle结束:"+System.currentTimeMillis());
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println(this.getClass()+" afterCompletion开始:"+System.currentTimeMillis());
		System.out.println(this.getClass()+" 自定义拦截器访问后:"+maxSize);
		System.out.println(this.getClass()+" afterCompletion结束:"+System.currentTimeMillis());

	}

	public void setMaxSize(long maxSize) {
		this.maxSize = maxSize;
	}
	
	

}


applicationContext-intercepter.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:util="http://www.springframework.org/schema/util"  
    xmlns:orm="http://www.springframework.org/schema/orm"   
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd  
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd  
                        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd  
                        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd  
                        http://www.springframework.org/schema/orm http://www.springframework.org/schema/orm/spring-orm-4.3.xsd  
                        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd  
    ">
    <!-- 拦截器配置 -->
     <mvc:interceptors>
     	<mvc:interceptor>
     		<mvc:mapping path="/**"/>
     		<bean class="com.bestcxx.stu.fileup.intercepter.MyInterceptor">
     			<!-- <property name="maxSize" value="5242880"></property> --><!-- 5mb -->
     			<property name="maxSize" value="5000"></property>
     		</bean>
     	</mvc:interceptor>
     </mvc:interceptors>
    
</beans>

(3)过滤器抛出-类加web.xml

(4)Spring 为文件上传大小限制单独提供的异常-MaxUploadSizeExceededException

需要增加配置文件

applicationContext-file.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:util="http://www.springframework.org/schema/util"  
    xmlns:orm="http://www.springframework.org/schema/orm"   
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd  
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd  
                        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd  
                        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd  
                        http://www.springframework.org/schema/orm http://www.springframework.org/schema/orm/spring-orm-4.3.xsd  
                        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd  
    ">
    <!--文件上传-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
		<!-- <property name="maxUploadSize"><value>1</value></property> -->
		<!-- <property name="maxUploadSize"><value>5242880</value></property> --><!-- 设置上传文件的最大尺寸为 5mb=5*1024kb=5*1024*1024b -->
		<property name="maxInMemorySize"><value>1</value></property><!-- 小于该尺寸的文件不生成临时文件 -->
		<property name="defaultEncoding"><value>UTF-8</value></property><!-- 默认上传格式为utf-8 -->
		<property name="resolveLazily"><value>true</value></property><!-- 延迟处理异常-将异常交予 controller 处理 -->
	</bean> 
</beans>

异常的捕获

(1)局部方法捕获-与抛出异常的方法处于同一个controller类-可接口可页面

这里是捕获异常后跳转到一个页面

/**
	 * 捕获本类的异常
	 * 优先级比全局异常高
	 * 针对页面请求的异常处理,默认返回error.jsp
	 * 一个类仅允许存在一个 @ExceptionHandler 标注的方法
	 * @param ex
	 * @param request
	 * @return
	 */
	@ExceptionHandler(Exception.class)
	public ModelAndView handlePageException(Exception ex, WebRequest request) {
	request.setAttribute("msg","异常捕获:"+this.getClass()+" "+ex.getMessage(), RequestAttributes.SCOPE_REQUEST);
	ModelAndView mav = new ModelAndView("error");
	mav.addObject("ex", ex);
	return mav;
	}
	
	
	
 

	/**
	 * 异常处理测试
	 * @return
	 */
	@GetMapping("exception")
	public String exception() throws Exception{
		if(true){
			throw new MyException("报错");			
		}
		
		return "success";
	}

WEB-INF/error.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 http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>error.jsp</title>
</head>
<body>
	<h1> ${msg} </h1>
	<h1> ${ex} </h1>
</body>
</html>

如果是返回一个接口的话

需要注意的是,一个类只能有一个方法被 @Exceptionhandler 注释

本文使用@ResponseBody 做实体与json转化。其他更便捷方法请参考Spring json和对象的自动转化

/**
	 * 捕获本类的异常
	 * 优先级比全局异常高
	 * 针对接口调动的异常处理
	 * 一个类仅允许存在一个 @ExceptionHandler 标注的方法
	 * @param ex
	 * @param request
	 * @return
	 */
	@ExceptionHandler(Exception.class)
	@ResponseBody
	public Object handleRestfulException(Exception ex, WebRequest request) {
		request.setAttribute("msg","异常捕获:"+this.getClass()+" "+ex.getMessage(), RequestAttributes.SCOPE_REQUEST);
		ModelAndView mav = new ModelAndView("error");
		mav.addObject("ex", ex);
		HashMap map=new HashMap();
		map.put("msg", "非 ModelAndView 的实体或者字符串");
		return map;
	}

(2)全局捕获

有三种方式,以为只需要一种就可以了,所以将他们统一罗列出来

applicationContext-exception.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:util="http://www.springframework.org/schema/util"  
    xmlns:orm="http://www.springframework.org/schema/orm"   
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd  
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd  
                        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd  
                        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd  
                        http://www.springframework.org/schema/orm http://www.springframework.org/schema/orm/spring-orm-4.3.xsd  
                        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd  
    ">
   <!-- 方式一 -->
   <!-- 全局异常捕获-针对页面访问 -->
    <!-- <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	     定义默认的异常处理页面
	    <property name="defaultErrorView" value="error"/>
	    定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception 
    	<property name="exceptionAttribute" value="ex"/>
    	设置日志输出级别,不定义则默认不输出警告等错误日志信息     
        <property name="warnLogCategory" value="WARN"></property> 
        默认HTTP状态码     
        <property name="defaultStatusCode" value="200"></property>     
         
    	对于需要特殊处理的异常
    	<property name="exceptionMappings">     
             <props>     
                 <prop key="java.lang.Exception">error</prop>     
                 <prop key="java.lang.Error">error</prop>
             </props>     
         </property>     
         <property name="statusCodes">     
             <props>     
                 <prop key="error">500</prop>/views/error.jsp
             </props>     
         </property>
	</bean> -->
    
    <!-- 方式二 -->
	<!-- Exception 类捕获-针对页面或者接口访问-->
   <!-- <context:component-scan base-package="com.bestcxx.stu.fileup.exception.ExceptionResolver"/>  -->
    
    <!-- 方式三 -针对页面或者接口访问-->
    <!-- 全局异常处理器只要你实现了HandlerExceptionResolver接口,这个类就是一个全局异常处理器-->  
    <bean class="com.bestcxx.stu.fileup.exception.GlobalExceptionResolver"></bean>
    
</beans>


方式一是针对页面访问的

方式二和方式三可以是页面也可以是接口(本例是页面处理)

且方式二和方式三需要单独提供处理类,在类内部写如下的内容,返回为null即可,网上也有返回json类型的view

@Override
	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		response.setContentType("application/json;charset=UTF-8");
		response.setCharacterEncoding("UTF-8");
		if(ex instanceof NoLoginException){
			PrintWriter writer=null;
			try {
				writer = response.getWriter();
				writer.write(((NoLoginException)ex).toString());
				writer.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				if(writer!=null){
					writer.close();
				}
			}
				
		}
		return null;
	}

方式二ExceptionResolver.java

package com.bestcxx.stu.fileup.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.ModelAndView;

/**
 * 全局异常配置
 * @author Administrator
 *
 */
@ControllerAdvice
public class ExceptionResolver {
	
	@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 instanceof Exception){
			return new ModelAndView("error").addObject("msg", ex);			
		}
		
		return new ModelAndView("error").addObject("msg", "未知错误:"+ex);	
		
    }

}


方式三GlobalExceptionResolver.java

package com.bestcxx.stu.fileup.exception;

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

import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

public class GlobalExceptionResolver implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
		ModelAndView modelAndView=new ModelAndView();  
		 System.out.println("异常信息输出:"+ex.toString());
		//如果是文件太大
		if (ex instanceof MaxUploadSizeExceededException) {
            long maxSize = ((MaxUploadSizeExceededException) ex).getMaxUploadSize();
            System.out.println(this.getClass()+" 上传文件太大,不能超过" + maxSize/1024/1024 + "mb"); // 打印错误信息
            
            //将错误信息传到页面  
            modelAndView.addObject("msg",this.getClass()+" 出现异常:"+"上传文件太大,不能超过" + maxSize/1024/1024 + "mb"+ex.getMessage()); 
            
            //指向到错误界面  
            modelAndView.setViewName("error");  
            return modelAndView;
        } 
		
		
        if(ex instanceof MyException){ //自定义异常
        	 modelAndView.addObject("msg","自定义异常:"+ex.getMessage());  
        }else{  
            //如果该 异常类型不是系统 自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)。  
        	modelAndView.addObject("msg","未知异常:"+ex.getMessage());  
        }  
		
        //将错误信息传到页面  
        modelAndView.addObject("msg","出现异常:"+ex.getMessage());  
          
        //指向到错误界面  
        modelAndView.setViewName("error");  
          
        return modelAndView;
	}

}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot异常处理是一个重要的方面,因为它可以帮助我们更好地理解应用程序的健康状况并处理异常。 以下是处理异常的步骤: 1. 创建自定义异常 首先,我们需要创建自定义异常来处理我们的异常。这个应该继承Exception或RuntimeException。这个应该包含构造函数和一个消息参数。 例如,我们可以创建一个名为MyException的自定义异常,如下所示: ``` public class MyException extends RuntimeException { public MyException(String message) { super(message); } } ``` 2. 创建全局异常处理器 在Spring Boot,我们可以使用@ControllerAdvice注解来标识一个作为全局异常处理器。这个应该包含@ExceptionHandler注解来处理特定型的异常。 例如,我们可以创建一个名为GlobalExceptionHandler的全局异常处理器,如下所示: ``` @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(value = MyException.class) public ResponseEntity<Object> handleMyException(MyException ex) { // 处理自定义异常 return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } @ExceptionHandler(value = Exception.class) public ResponseEntity<Object> handleException(Exception ex) { // 处理其他异常 return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } ``` 在上面的代码,我们使用@ExceptionHandler注解来处理MyException和其他型的异常。在处理自定义异常时,我们返回一个带有错误消息的ResponseEntity对象,并使用HttpStatus.INTERNAL_SERVER_ERROR状态代码。 在处理其他型的异常时,我们也返回一个带有错误消息的ResponseEntity对象,并使用HttpStatus.INTERNAL_SERVER_ERROR状态代码。 3. 抛出异常 现在,我们可以在我们的应用程序抛出MyException异常。例如,我们可以创建一个名为MyController的控制器,并在该方法抛出MyException异常,如下所示: ``` @RestController public class MyController { @GetMapping("/hello") public String hello() { throw new MyException("Something went wrong!"); } } ``` 在上面的代码,我们使用throw关键字来抛出MyException异常,并传递一个错误消息。 4. 测试 现在,我们可以测试我们的应用程序,看看它是否可以正确地处理我们的异常。我们可以使用Postman或任何其他HTTP客户端来测试我们的应用程序。 例如,我们可以向http://localhost:8080/hello端点发出GET请求,应该返回一个带有错误消息的响应。 ``` { "timestamp": "2021-09-01T10:25:50.140+00:00", "status": 500, "error": "Internal Server Error", "message": "Something went wrong!", "path": "/hello" } ``` 在上面的响应,我们可以看到错误消息被正确地返回了。 总结: 在Spring Boot,我们可以使用@ControllerAdvice和@ExceptionHandler注解来处理异常。我们应该创建自定义异常来处理我们的异常,并创建全局异常处理器来处理不同型的异常。最后,我们可以在我们的应用程序抛出异常,并测试它是否能够正确地处理异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值