向成为一名不加班的程序员进发,从简单的开始。
怎么办,又有报异常?
大佬:你看一下log,这里报异常了,你怎么不提醒?
小糖:哦哦,我把bug改一下。
大佬:不是,你怎么不提醒有异常。
小糖:嗯?
异常是要报出来的
刚刚接触后台的时候,因为有过Android工作的编程经历,java还算是顺手,编码工作还算顺利。但对于异常,我常做的就是不让它报出来,封得死死的(小白写法),一个App报出了异常,一定不让用户发现。但是后台就不是这么回事了。有了问题一定让他报错来,记录在log里面看,也要给前端提醒。返回类有返回码。我的成功返回码是000000。其他的返回码都是异常,不管是查不到改用户,还是手机号码输入错误,这些都可以用来异常来处理。
定义异常
所报的异常都是所知道的层,比如没有该资源,比如,找不到该用户。虽然他们是可以按照顺利的流程返回到Controller层,但是这么本可以在查询不到该用户的时候就结束流程,再一步步返回到controller层是不是太浪费了。
给出一个规则:在不符合正常路线的流程都可视为异常。
异常正确处理
这里用到了spring的拦截异常处理,通过他返回所有的异常。
拦截异常
spring中,有一个抽象类,HandlerExceptionResolver可以拦截到系统中报出的所有异常
public class HealthHandlerExceptionResolver implements HandlerExceptionResolver {
public Logger logger = Logger.getLogger(this.getClass());
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
}
}复制代码
所有爆出来的异常都会再次到这个方法来。Exception 这个字段 就是我们报错的异常。
而我们做的就是正确处理这个异常字段
异常的特别关照
在拦截异常中,是Exception类型,提醒的也自然是这个类型。我们对这个类进行处理
继承此类,子类BaseException
public class BaseException extends Exception {
private static final long serialVersionUID = 1L;
private String logMsg;
//错误码 枚举
private ErrorCode code;
public BaseException(ErrorCode code) {
super();
this.code = code;
}
public BaseException(ErrorCode code,String logMsg,String msg){
super();
this.code = code;
this.code.setMsg(msg);
this.logMsg=logMsg;
}
public BaseException(ErrorCode code,String logMsg) {
super();
this.code = code;
this.logMsg=logMsg;
}
public String getLogMsg() {
return logMsg;
}
public void setLogMsg(String logMsg) {
this.logMsg = logMsg;
}
public ErrorCode getCode() {
return code;
}
public void setCode(ErrorCode code) {
this.code = code;
}
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
public String parseString() {
//ResponseInfo 是返回类
return JSONObject.toJSONString(new ResponseInfo(code));
}
}复制代码
错误码的枚举类
public enum ErrorCode {
companyError("70006+","手机号码错误"),
weChatLoginError("600002","微信登录异常"),
permissionDenied("900005","没有权限,拒绝访问" );
private String code;
private String msg;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
private ErrorCode(String code, String msg) {
this.code = code;
this.msg = msg;
}
}复制代码
在BaseException类的构造方法中
public BaseException(ErrorCode code) {
super();
this.code = code;
}复制代码
通过填入对应的错误码,再通过spring的拦截器,识别并返回json
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
String returnInfo=null;
if(ex instanceof TTException) { //识别出对应的异常
logger.info(ex.toString());
returnInfo=((BaseException)ex).parseString(); //返回String类型 json
}else {
logger.error("SystemException!", ex);
returnInfo= "{\"returnCode\":\"999999\",\"returnMsg\":\"系统错误\"}";
}
try {
//利用HttpServletResponse 返回
ResponseWriteUtil.writerJSONInfo(returnInfo, response);
} catch (IOException e1) {
e1.printStackTrace();
}
return new ModelAndView();
}复制代码
给前端输出数据的方法
public static void writerJSONInfo(String json,HttpServletResponse response) throws IOException {
PrintWriter pw=getWriter(response,"application/json;charset=utf-8");
logger.info("return info is "+json);
pw.print(json);
pw.flush();
pw.close();
}复制代码
继承BaseException的的login登录异常类
public class TTException extends BaseException {
//query_not_found_openId 可以用做log记录
public TTException(ErrorCode code, String query_not_found_openId) {
super(code);
}
@Override
public String toString() {
return "LoginException : "+this.getLogMsg();
}
}复制代码
使用
throw new TTException(ErrorCode.nosuchuser,phone + "未注册");
{"returnCode":"800001","returnMsg":"手机号码未被注册","serialNum":"957c0d76-2d7e-45cd-898c-f49e0d74e6cc"}复制代码
一个错误码,多种提示
现在有了新的需求,比如:A用手机号注册一个身份证,发现被占用了,要提示出176****被占用。这个该怎么办呢,枚举类都已经定了版。这个时候,我要做的是对这个提示做一下手脚了。错误枚举类,只要它的错误码,提示类容另外填入。
同样是实现BaseException的继承
public class RegisterDulipcaException extends BaseException{
private String msg;
private static final long serialVersionUID = 1L;
public ZCRegisterDulipcaException(ErrorCode code) {
super(code);
}
public ZCRegisterDulipcaException(ErrorCode code,String logMsg,String msg) {
super(code,logMsg);
this.msg=msg; //变动的提示信息
}
//对错误数据进行处理
public String parseString() {
ResponseInfo returnResponseInfo=new ResponseInfo(getCode());
returnResponseInfo.setReturnMsg(msg);
return JSONObject.toJSONString(returnResponseInfo);
}
}复制代码
返回类关于ErrorCode的构造方法
public ResponseInfo(ErrorCode responseCode) {
super();
this.returnCode = responseCode.getCode();
this.returnMsg = responseCode.getMsg();
this.serialNum = UUID.randomUUID().toString();
}复制代码
修改掉returnMsg
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}复制代码
这样子就能做大灵活变动。
------------------------------------------------------------------------------------------------
以上就是本次的总结,都是看大佬的代码,我只是给自己做个总结,学习。谢谢观看