利用Spring进行统一异常处理的两种方式

1.自定义统一异常处理器

自定义Exception实现 HandlerExceptionResolver接口或继承AbstractHandlerExceptionResolver类

1.实现接口HandlerExceptionResolver

package com.jay.platform.exception.handler;

import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.Date;

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

import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.jay.platform.exception.AjaxException;
import com.jay.platform.exception.BusinessException;

/**
 *
 * @ClassName: ExceptionHandler
 * @Description: 统一异常处理 , 注意这里可以处理Controller层抛出的异常,但不处理Controller捕获的异常(Controller捕获的异常,这里不再处理)
 * @author Jay He
 * @date 2014年11月4日 上午10:22:11
 *
 */
public class ExceptionHandler implements HandlerExceptionResolver {
    private static final Logger LOGGER = Logger
	    .getLogger(ExceptionHandler.class);

    @Override
    public ModelAndView resolveException(HttpServletRequest request,
	    HttpServletResponse response, Object handler, Exception ex) {
	LOGGER.error(new Date().toLocaleString() + "异常信息", ex);
	if (ex instanceof NumberFormatException) {
	    return new ModelAndView("exception/number");
	} else if (ex instanceof NullPointerException) {
	    return new ModelAndView("exception/null");
	} else if (ex instanceof BusinessException) {
	    return new ModelAndView("exception/business");
	} else if (ex instanceof SocketTimeoutException
		|| ex instanceof ConnectException) {
	    try {
		response.getWriter().write("网络异常");
	    } catch (IOException e) {
		e.printStackTrace();
	    }
	    return new ModelAndView("exception/net_error");
	}else if(ex instanceof AjaxException){
	   System.out.println("-=-=");
	}
	return new ModelAndView("exception/exception");
    }

}

2.继承AbstractHandlerExceptionResolver类

package com.jay.platform.exception.handler;

import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.Date;

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

import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;

import com.jay.platform.exception.AjaxException;
import com.jay.platform.exception.BusinessException;

/**
 *
 * @ClassName: ExceptionHandler
 * @Description: 统一异常处理 , 注意这里可以处理Controller层抛出的异常,但不处理Controller捕获的异常(Controller捕获的异常,这里不再处理)
 * @author Jay He
 * @date 2014年11月4日 上午10:22:11
 *
 */
public class ExceptionHandler extends AbstractHandlerExceptionResolver{
    private static final Logger LOGGER = Logger
	    .getLogger(ExceptionHandler.class);

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request,
	    HttpServletResponse response, Object handler, Exception ex) {
	<pre name="code" class="java">LOGGER.error(new Date().toLocaleString() + "异常信息", ex);
	if (ex instanceof NumberFormatException) {
	    return new ModelAndView("exception/number");
	} else if (ex instanceof NullPointerException) {
	    return new ModelAndView("exception/null");
	} else if (ex instanceof BusinessException) {
	    return new ModelAndView("exception/business");
	} else if (ex instanceof SocketTimeoutException
		|| ex instanceof ConnectException) {
	    try {
		response.getWriter().write("网络异常");
	    } catch (IOException e) {
		e.printStackTrace();
	    }
	    return new ModelAndView("exception/net_error");
	}else if(ex instanceof AjaxException){
	   System.out.println("-=-=");
	}
	return new ModelAndView("exception/exception");

}}


在配置文件中添加自定义异常处理模块

 <!-- Spring MVC的统一异常处理 -->
    <bean id="exceptionResolver" class="com.jay.platform.exception.handler.ExceptionHandler"/>  

错误页面展示:

error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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页面</title>
</head>
<body>
<center>
<h1>Error页面</h1><br>
<h2>出错信息</h2>
<br><br>
错误描述
<br>
${errorTips }
<br><br>
<br><br>
错误异常信息栈
<br><br>
${ex }
</center>
</body>
</html>

eception.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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>Exception页面</title>
</head>
<body>
<center>
<h1>Exception页面</h1><br>
<h2>模块开发中,请稍后。。。。。。</h2>
</center>
</body>
</html>

2.基于@ControllerAdvice注解实现统一异常处理,可方便返回普通异常和Ajax异常信息

自定义Web层异常处理

WebExceptionHandler.java

package com.jay.platform.exception.handler;

import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;

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

import org.apache.log4j.Logger;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.servlet.ModelAndView;

import com.jay.platform.exception.AjaxException;
import com.jay.platform.utils.DateUtil;

/**
 * @ClassName: WebExceptionHandler
 * @Description: Web层异常处理器,  -- 这里可以根据不同的异常,写多个方法去处理, 可以处理跳转页面请求,跳到异常指定的错误页,
 *                                                       也可以处理Ajax请求,根据不通过异常,在页面输出不同的提示信息
 *                operateExp          :   处理普通请求
 *                operateExpAjax      :       处理Ajax请求
 * @author Jay He
 * @date 2015年5月27日 下午5:16:37
 *
 */
@ControllerAdvice
public class WebExceptionHandler {

    Logger logger =  Logger.getLogger(WebExceptionHandler.class);
    /*
     * 如果抛出UnauthorizedException,将被该异常处理器截获来显示没有权限信息
     */
    @ExceptionHandler({ UnauthorizedException.class })
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ModelAndView unauthenticatedException(NativeWebRequest request,
	    UnauthorizedException e) {
	ModelAndView mv = new ModelAndView();
	mv.addObject("exception", e);
	mv.setViewName("base/exception/unauthorized");
	return mv;
    }

    /**
     * @Title: operateExp
     * @Description: 全局异常控制,记录日志
     *              任何一个方法发生异常,一定会被这个方法拦截到。然后,输出日志。封装Map并返回给页面显示错误信息:
     *              特别注意:返回给页面错误信息只在开发时才使用,上线后,要把错误页面去掉,只打印log日志即可,防止信息外漏
     * @param: @param ex
     * @param: @param request
     * @return: String
     * @throws:
     */
    @ExceptionHandler(RuntimeException.class)
    public String operateExp(RuntimeException ex, HttpServletRequest request) {
	logger.error(ex.getMessage(), ex);
	logger.info("************* ------ 异常信息已记录(" + DateUtil.getNow("yyyy-MM-dd HH:mm:ss")+ ") ------- ***********");
	request.setAttribute("errorTips", ex.getMessage());
	request.setAttribute("ex", ex);
	return "exception/error";
    }

    /*
     * 记录Ajax异常日志,并将错误Ajax错误信息传递(回写)给前台展示,
     * 前台的jQuery的Ajax请求error中,可以打印错误提示信息   --  data.responseText   : 这里即是后台传递的错误提示
     * eg:
     * $.ajax({
	            type : 'get',
	            dataType : "json",
	            url : ctx + '/test/test',
	            accept:"application/json",
	            success : function(data) {
	            	console.log(data);
	            },
	            error : function(data, errorThrown) {
	                console.log(data);
	                alert("error" + data.responseText);
	            }
	        });
     */
    @ExceptionHandler(AjaxException.class)
    public void operateExpAjax(AjaxException ex, HttpServletResponse response) throws IOException {
	logger.error(ex.getMessage(), ex);
	logger.info("************* ------ 异常信息已记录(" + DateUtil.getNow("yyyy-MM-dd HH:mm:ss")+ ") ------- ***********");
	//将Ajax异常信息回写到前台,用于页面的提示
	response.getWriter().write("sorry,Ajax请求出错!!!");
    }

    @ExceptionHandler(ConnectException.class)
    public void operateExpNetException(ConnectException ex, HttpServletResponse response) throws IOException {
	logger.error(ex.getMessage(), ex);
	logger.info("************* ------ 异常信息已记录(" + DateUtil.getNow("yyyy-MM-dd HH:mm:ss")+ ") ------- ***********");
	//将Ajax异常信息回写到前台,用于页面的提示
	    response.getWriter().write("sorry,网络连接出错!!!");
    }
}

异常测试

package com.jay.platform.controller.test;

import java.net.ConnectException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.jay.platform.annotation.AjaxExceptionHandler;
import com.jay.platform.exception.AjaxException;

@Component
@Controller()
@RequestMapping("exception")
public class ExceptionHandlerTestController {

    @RequestMapping("test")
    public String getIt(){
	return "exception/test/test";
    }

    @RequestMapping(value="/common",method=RequestMethod.GET)
    public Map<String, Object> commonExcetion() throws RuntimeException{
	Map<String, Object> map = new HashMap<String, Object>();
	int i=10;

	if(i==10){
	throw new RuntimeException("运行时异常");
	}

	return map;
    }

    @AjaxExceptionHandler(tips="试一把", description="哈啊")
    @RequestMapping(value="/ajax/net",method=RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> AjaxConnectionExcetion() throws ConnectException{
	Map<String, Object> map = new HashMap<String, Object>();
	int i=10;

	if(i==10){
	throw new ConnectException("测试    网络连接     异常");
	}

	return map;
    }

    @RequestMapping(value="/ajax/common",method=RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> AjaxExcetion() throws AjaxException{
	Map<String, Object> map = new HashMap<String, Object>();
	int i=10;

	if(i==10){
	throw new AjaxException("测试Ajax异常");
	}

	return map;
    }
}

前台页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>Insert title here</title>
<%@ include file="../../common/meta.jsp"%>
<script src="${jqueryCtxPath }/jquery-ui-1.11.2.custom/jquery-ui.min.js"></script>
<link href="${jqueryCtxPath }/jquery-ui-1.11.2.custom/jquery-ui.min.css" rel="stylesheet" type="text/css" />
<link href="${jqueryCtxPath }/jquery-ui-1.11.2.custom/jquery-ui.theme.min.css" rel="stylesheet" type="text/css" />

</head>
<body class="index-main">
<button id="test"><a href="http://localhost:8080/JayPlatform/exception/common">普通的异常处理测试</a></button>

<button id="test1">网络连接异常的Ajax测试</button>

<button id="test2">普通异常的Ajax测试</button>

<script type="text/javascript">
$(document).ready(function() {

	$("#test1").click(function(){
		  $.ajax({
	            type : 'get',
	            dataType : "json",
	            url : ctx + '/exception/ajax/net',
	            accept:"application/json",
	            success : function(data) {
	            	console.log(data);
	            },
	            error : function(data, errorThrown) {
	                console.log(data);
	                alert("error" + data.responseText);
	            }
	        });
	});

	$("#test2").click(function(){
        $.ajax({
              type : 'get',
              dataType : "json",
              url : ctx + '/exception/ajax/common',
              accept:"application/json",
              success : function(data) {
                  console.log(data);
              },
              error : function(data, errorThrown) {
                  console.log(data);
                  alert("error" + data.responseText);
              }
          });
  });
});
</script>
</body>
</html>

页面结果演示

时间: 2024-10-08 19:22:10

利用Spring进行统一异常处理的两种方式的相关文章

Spring Boot 整合 Shiro ,两种方式全总结!

在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro. 今天松哥就来和大家聊聊 Spring Boot 整合 Shiro 的话题! 一般来说,Spring Security 和 Shiro 的比较如下: Spring Security 是一个重量级的安全管理框架:Shiro 则是一个轻量级的安全管理框架 Spring Security 概念复杂,配置繁琐:Shiro 概念简单.配置简单 Spring

(001)spring容器创建bean的两种方式

简单记录一下spring容器创建.装配.管理bean 1.使用@Configuration.@Bean的注解组合创建bean 可以用两种方法获取bean,根据类名或者创建bean的方法名,如果不指定bean的名字,默认bean的名字是该方法名. pom.xml文件如下: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.

创建 Spring Boot 项目常用的两种方式

在开发中,常用的创建的 Spring Boot 项目方式有两种,一种是使用 Spring Initializr , 一种是创建一个 Maven 工程,导入 Spring Boot 的依赖 使用 IDEA 的 Spring Initializr 的方式 选择 IDEA 的 File -> New -> Project 选择 Spring Initializr ,如下图: 在 Project Metadata 页面,输入 Group, Artifact ,Version, Name, Descri

配置Spring项目上传的两种方式(全解析)

欢迎查看Java开发之上帝之眼系列教程,如果您正在为Java后端庞大的体系所困扰,如果您正在为各种繁出不穷的技术和各种框架所迷茫,那么本系列文章将带您窥探Java庞大的体系.本系列教程希望您能站在上帝的角度去观察(了解)Java体系.使Java的各种后端技术在你心中模块化:让你在工作中能将Java各个技术了然于心:能够即插即用.本章我们来一起了解Spring的文件上传全解析. 首先对于Spring的文件上传,我们仅仅需要关注三点 Spring需要具备解析Multipart能力 前端需要文件转换为

python-异常处理及异常处理的两种方式对比

1,python解释器检测到错误,触发异常:程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关呢,与异常处理有关) 如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理. 2,处理方式: 1)使用if判断式(降低程序的可读性) 2)python本身对错误有异常处理机制,包括异常类:ValueError.KeyError.IndexError python的特定的用来进行异常处理的语法结构:try:      except:  (except +

spring boot返回Josn的两种方式

1.Controller类上加@RestController注解 2.Controller类上加@Controller注解,Action接口上加@ResponseBody注解 @Responsebody与@RequestBody @Responsebody表示该方法的返回结果直接写入HTTP response body中 一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径, 加上@Responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP

springMVC --全局异常处理(两种方式)

首先看springMVC的配置文件: <!-- 全局异常配置 start --> <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <pro

spring加载配置文件的两种方式

一 . <bean id="jdbcProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">       <property name="locations">           <list>               <value>classpath:jdbc.prop

Java知识点16 Spring创建IOC容器的两种方式

1.直接得到 IOC 容器对象 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 封装起来: 1 public class ApplicationContextUtil { 2 private static ApplicationContext applicationContext = null; 3 public Applicati