通常情况下,前后端调用关系如下:
后端服务的入口为Controller,然后调用Service,如涉及到数据库访问则调用DAO。在每一层都有可能抛出异常,有的是系统异常,有的是封装后的业务异常,例如用户密码错误,用户号码不存在都属于业务异常,需要封装后返回。为了方便异常处理,可以从底层一直向上抛,在返回客户端前再统一处理。
当所有的客户端调用的入口都必须经过Controller时,可以拦截Controller进行处理,类结构如下:
代码参考如下:
1.GlobalExceptionHandler.java
拦截返回给客户端的异常进行处理。
import com.javashizhan.domain.Response; import com.javashizhan.exception.ThrowableHandler; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; /** * @ClassName GlobalExceptionHandler * @Description 全局异常处理,捕捉所有Controller抛出的异常, @ResponseBody注解必须加上,否则会跳到默认的错误页 * @Author 铿燃一叶 * @Date 2019/9/28 23:24 * @Version 1.0 * javashizhan.com **/ @ControllerAdvice @ResponseBody public class GlobalExceptionHandler { /** * 默认返回HttpStatus.OK, 这里不是必须的,如果返回其他状态码才有必要加上 * @param e * @return 封装后的应答对象 */ @ResponseStatus(HttpStatus.OK) @ExceptionHandler({Throwable.class}) public Response handle(Throwable e) { return ThrowableHandler.handle(e); } } 复制代码
2.ThrowableHandler.java
对异常进行处理,和GlobalExceptionHandler类解耦,这样当非Controller作为调用入口类时也可以服用。
import java.io.PrintWriter; import java.io.StringWriter; import com.javashizhan.domain.Response; /** * @ClassName ThrowableHandler * @Description 异常处理类,将异常转换为统一应答对象 * @Author 铿然一叶 * @Date 2019/9/28 23:30 * @Version 1.0 * javashizhan.com **/ public class ThrowableHandler { private ThrowableHandler() {} public static Response handle(Throwable t) { Response response = new Response(); response.setStatus(Response.STAUTS_FAILED); response.setErrorMsg(t.getMessage()); response.setErrorStack(getErrorStack(t)); return response; } private static String getErrorStack(Throwable t) { if (null != t) { PrintWriter pw = null; StringWriter sw = new StringWriter(); pw = new PrintWriter(sw); t.printStackTrace(pw); return sw.toString(); } return ""; } } 复制代码
3.Response.java
异常转换结果,不管是否有异常,此类都可以使用。
/** * @ClassName A * @Description TODO * @Author 铿然一叶 * @Date 2019/9/28 23:24 * @Version 1.0 * javashizhan.com **/ public final class Response<T> { /** 应答状态-成功 */ public static final int STAUTS_OK = 0; /** 应答状态-失败 */ public static final int STAUTS_FAILED = 1; /** 默认错误码 */ public static final String DEFAULT_ERROR_CODE = "UNKNOWN-000"; /** 应答状态 */ private int status = STAUTS_OK; /** 应答错误码,有错误时返回 */ private String errorCode = DEFAULT_ERROR_CODE; /** 应答错误消息,有错误时返回 */ private String errorMsg; /** 应答错误码,有错误时返回 */ private String errorStack; /** 应答结果,存放业务应答内容 */ private T result; public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getErrorCode() { return errorCode; } public void setErrorCode(String errorCode) { this.errorCode = errorCode; } public String getErrorMsg() { return errorMsg; } public void setErrorMsg(String errorMsg) { this.errorMsg = errorMsg; } public String getErrorStack() { return errorStack; } public void setErrorStack(String errorStack) { this.errorStack = errorStack; } public T getResult() { return result; } public void setResult(T result) { this.result = result; } } 复制代码
4.TestGlobalExceptionController.java
验证类。
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @ClassName TestGlobalExceptionController * @Description TODO * @Author 铿然一叶 * @Date 2019/9/29 1:15 * @Version 1.0 * javashizhan.com **/ @RestController public class TestGlobalExceptionController { @GetMapping("testGlobalException") public void exec() throws Exception { throw new Exception("Error occurred"); } } 复制代码
end.
站点: javashizhan.com/
微信公众号: