一、CheckedException和UnCheckedException
1.CheckedException已检查异常
CheckedException继承自Exception,程序内部无法控制,必须做处理,要么使用try-atch块捕获,要么throws抛给上一层。
2.UnCheckedException未检查异常
UnCheckedException继承自RuntimeException,一般是程序的逻辑问题引起的异常,不需要捕获,也不需要处理。比如空指针异常等
3.demo演示:
3.1首先自定义一个Checked异常类
/**
* @author 旺仔牛奶
* 自定义异常类
* 2018年1月25日 下午4:41:46
*/
public class MyCheckedException extends Exception {
private static final long serialVersionUID = 1L;
private Throwable cause;
public MyCheckedException(String exceptionMessage, Throwable cause) {
super(exceptionMessage, cause);
}
}
写一个方法处理异常
//处理异常
public void textException(String message) {
message = "";
try {
String exceptionMessage = readMessage(message);
} catch (MyCheckedException e) {
e.printStackTrace();
}
}
//抛出异常
public String readMessage(String message) throws MyCheckedException{
if (message == "") {
throw new MyCheckedException("message信息为空啦!",null);
}
return message;
}
以上的例子就是一个简单的checked异常的demo,方法readMessage是一个会抛出checked异常的方法,TextException方法调用readMessage方法,有两种选择,一种是向上抛出,即在TextException方法声明后添加throws MyChekedException;(但最终还是要在最外层对异常做处理的)另外一种是在当前方法中对异常做处理,如上面的例子。
对于unchecked异常,只需要将自定义异常继承的类修改为RuntimeException类。自定义异常类MyChekedException就变成了unchecked。例子如下:
/**
* @author 旺仔牛奶
* 自定义异常类
* 2018年1月25日 下午4:41:46
*/
public class MyCheckedException extends RuntimeException {
private static final long serialVersionUID = 1L;
private Throwable cause;
public MyCheckedException(String exceptionMessage, Throwable cause) {
super(exceptionMessage, cause);
}
}
方法抛出异常不需要对异常做处理(也可以去捕获异常,只是不再是必须要做的事情)
//处理异常
public void textException(String message) {
message = "";
String exceptionMessage = readMessage(message);
}
//抛出异常,不需要捕获和处理异常
public String readMessage(String message) {
if (message == "") {
throw new MyCheckedException("message信息为空啦!",null);
}
return message;
}
二、统一异常处理以及异常信息的封装
1.统一异常处理知识点介绍:
springMVC处理异常的3种方式:
(1) 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;
(2) 实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器
(3) 使用@ExceptionHandler注解实现异常处理
机制:系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理
2.以第二种方式为例的统一异常处理的完整实例。背景:判断字符串name是否为空
首先编写自定义异常类(这里是unchecked异常)
public class MyTextException extends RuntimeException {
/**
* 自定义异常类
*/
private static final long serialVersionUID = 1L;
private String messageError;//错误信息内容
private String massageKey;//错误信息内容对应的key。最后会把错误信息存到map中
private Throwable cause;//异常对象
public MyTextException(String massageKey, String messageError, Throwable throwable) {
this.massageKey = massageKey;
this.messageError = messageError;
this.cause = throwable;
}
public String getMassageKey() {
return massageKey;
}
public void setMassageKey(String massageKey) {
this.massageKey = massageKey;
}
public String getMessageError() {
return messageError;
}
public void setMessageError(String messageError) {
this.messageError = messageError;
}
public Throwable getCause() {
return cause;
}
public void setCause(Throwable cause) {
this.cause = cause;
}
}
controller层调用validatorIsNull方法。该方法的用来判断字符串name是否为空白字符或者为空。以下是controller实现。
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
@Controller
public class MyAppController {
protected static final Logger LOG = LoggerFactory.getLogger(MyAppController.class);
/**
* @param name
* @return
*/
public MyJson validatorName() {
String name = "";
MyJson jsonObject = new MyJson();
jsonObject.setResultString("true");
//如果成功继续执行,如果抛出异常,直接在统一异常处理器中通过ModelAndView把异常信息返回到前端
validatorIsNull(name);
return jsonObject;
}
public boolean validatorIsNull(String name) {
boolean flag = false;
if (StringUtils.isBlank(name)) {
flag = true;
throw new MyTextException("myExceptionKey", "名字为空啦啦啦啦啦", null);
}
return flag;
}
}
接下来是统一异常处理部分,在这里先采用比较常用的第二种方式做统一异常处理,我们需要把异常信息封装起来传递到前端,构造json对象。,通过ModelAndView传递到前端。思路如下:
a.构造json对象用来封装异常信息
b.定义异常处理器对异常进行处理,并把异常信息封装到ModelAndView返回到前端
import java.util.HashMap;
import java.util.Map;
/**
* 封装异常错误信息的类
*
* @author 旺仔牛奶 2018年1月25日 下午5:58:18
*/
public class MyJson {
// 存储数据结果的map
protected Map message = new HashMap();
// 是否执行成功标志,如果成功success的值为true
protected String resultString;
// 构造方法
public MyJson(String errorKey, String errorInfo) {
message.put(errorKey, errorInfo);
}
public MyJson() { }
public Map getMessage() {
return message;
}
public void setMessage(Map message) {
this.message = message;
}
public String getResultString() {
return resultString;
}
public void setResultString(String resultString) {
this.resultString = resultString;
}
}
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
/**
* 统一异常处理器
*
* @author 旺仔牛奶 2018年1月25日 下午7:46:44
*/
@Service
public class MyExceptionHandler implements HandlerExceptionResolver {
protected static final Logger LOG = LoggerFactory.getLogger(MyExceptionHandler.class);
// appliContext对象
protected ApplicationContext context;
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object o, Exception e) {
LOG.error("这里会在控制台打印异常信息", e);
if (e instanceof MyTextException) {
return paramErrorMessage(((MyTextException) e).getMassageKey(),
((MyTextException) e).getMessageError());
}
return null;
}
public ModelAndView paramErrorMessage(String massageKey, String messageError) {
MyJson jsonObject = new MyJson(massageKey, messageError);
jsonObject.setResultString("false");
return JsonObjectToModelView(jsonObject);
}
// 将异常信息封装到ModelAndView传给前端
public static ModelAndView JsonObjectToModelView(MyJson json) {
ModelAndView model = new ModelAndView(new MappingJackson2JsonView());
// 前端用success的值来判断是否抛出异常(这里省略了执行成功时的json封装实现,成功时success的值为true)
model.addObject("success", json.getResultString());
model.addObject("message", json.getMessage());
return model;
}
}
前端调用:
$.ajax({
url : 你的controller的访问url
type : "POST",
data : {
name : nameInput,
},
success : function(response) {
if (response.success == "true") {
alter("name 不为空")
} else {
alter(response.message.myExceptionKey)
}
}
});
关于第一种方式和第三种方式的实例后期补充。
关于对象信息的封装,基本思路是构造一个json基类,针对成功执行结果的返回参数和异常以及错误返回参数分别继承基类去实现,这里主要是为了方便,之定义了异常信息的封装。