一、异常类的定义
BizException --继承--> BaseException --继承--> NestedRuntimeException --继承--> RuntimeException
SysException --继承--> --|
二、异常处理类
实现HandlerExceptionResolver接口
三、这里异常分为两种
1、后台接口内抛出的异常,日志记录
2、controller层抛出的异常,日志记录和返回错误页面
四、添加异常类
1、建立com.study.base.exception包
2、建立NestedRuntimeException.java
package com.study.base.exception;
public abstract class NestedRuntimeException extends RuntimeException {
private static final long serialVersionUID = -6972683557406217498L;
public NestedRuntimeException() {
super();
}
public NestedRuntimeException(Throwable cause) {
super(cause);
}
public NestedRuntimeException(String message) {
super(message);
}
public NestedRuntimeException(String message, Throwable cause) {
super(message, cause);
}
public String getMessage() {
Throwable cause = getCause();
String message = super.getMessage();
if (cause != null) {
StringBuilder sb = new StringBuilder();
if (message != null)
sb.append(message).append("; ");
sb.append("nested exception is ").append(cause);
return sb.toString();
}
return message;
}
public Throwable getRootCause() {
Throwable rootCause = null;
for (Throwable cause = getCause(); cause != null && cause != rootCause; cause = cause.getCause())
rootCause = cause;
return rootCause;
}
}
3、建立BaseException.java
package com.study.base.exception;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
public class BaseException extends NestedRuntimeException {
private static final long serialVersionUID = 7724815658604611711L;
//static ResourceBundle bundle = ResourceBundle.getBundle("message", Locale.ENGLISH);
protected String errorCode;
protected String[] errorArgs;
public BaseException(Throwable cause) {
super(cause);
}
public BaseException(String errorCode) {
super();
this.errorCode = errorCode;
}
public BaseException(String errorCode, String... errorArgs) {
super();
this.errorCode = errorCode;
this.errorArgs = errorArgs;
}
public BaseException(String errorCode, Throwable cause) {
super(cause);
this.errorCode = errorCode;
}
public BaseException(String errorCode, Throwable cause, String... errorArgs) {
super(cause);
this.errorCode = errorCode;
this.errorArgs = errorArgs;
}
public String getMessage() {
String message = "";
try {
if (errorCode == null) {
message = super.getMessage();
} else {
for (String str : errorArgs) {
message = message + " " + str;
}
//message = bundle.getString(errorCode);
//message = MessageFormat.format(message, (Object[]) errorArgs);
}
} catch (MissingResourceException mse) {
message = "Can't get the message of the Error Code";
}
return message;
}
public String getStackMessage() {
String message = "";
Throwable cause = getCause();
if (cause != null) {
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
cause.printStackTrace(pw);
message = writer.toString();
}
return message;
}
public String getLocalizedMessage() {
String message = getMessage();
if (errorCode != null) {
message = "<" + errorCode + ">" + message;
}
return message;
}
public String getErrorMsg() {
return getMessage();
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String[] getErrorArgs() {
return errorArgs;
}
public void setErrorArgs(String[] errorArgs) {
this.errorArgs = errorArgs;
}
}
4、建立BizException.java
package com.study.base.exception;
import org.slf4j.MDC;
import com.study.base.common.Constants;
public class BizException extends BaseException {
private static final long serialVersionUID = 1L;
public BizException(String errorCode) {
super(errorCode);
setLog();
}
public BizException(String errorCode, String... errorArgs) {
super(errorCode, errorArgs);
setLog();
}
public BizException(String errorCode, Throwable cause) {
super(errorCode, cause);
setLog();
}
public BizException(String errorCode, Throwable cause, String... errorMsg) {
super(errorCode, cause, errorMsg);
setLog();
}
// 逻辑ID
private String logId;
// 业务ID
private String bizId;
// Session ID
private String sessionId;
// 设置LogId
public void setLog() {
this.logId = MDC.get(Constants.LOG_ID);
this.bizId = MDC.get(Constants.BIZ_ID);
this.sessionId = MDC.get(Constants.SESSION_ID);
}
public String getLogId() {
return logId;
}
public void setLogId(String logId) {
this.logId = logId;
}
public String getBizId() {
return bizId;
}
public void setBizId(String bizId) {
this.bizId = bizId;
}
/**
* @return the sessionId
*/
public String getSessionId() {
return sessionId;
}
/**
* @param sessionId
* the sessionId to set
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
}
5、建立SysException.java
package com.study.base.exception;
public class SysException extends BaseException {
private static final long serialVersionUID = 1L;
public SysException(String errorCode) {
super(errorCode);
}
public SysException(String errorCode, String... errorArgs) {
super(errorCode, errorArgs);
}
public SysException(String errorCode, Throwable cause) {
super(errorCode, cause);
}
public SysException(String errorCode, Throwable cause, String... errorMsg) {
super(errorCode, cause, errorMsg);
}
}
五、添加异常处理类ExceptionResolver.java
需要实现HandlerExceptionResolver接口
package com.study.base.exception;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
/**
* 全局异常捕获
*/
public class ExceptionResolver implements HandlerExceptionResolver {
private static Logger log = LoggerFactory.getLogger(ExceptionResolver.class);
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
if (ex instanceof BizException && !isAjax(request)) {
//业务异常
BizException bizException=(BizException) ex;
log.error("[业务异常]{} {}",bizException.getLocalizedMessage(), bizException.getRootCause());
log.error("errorCode:{} errorMsg:{}", bizException.getErrorCode(), bizException.getErrorArgs());
//其他处理
return new ModelAndView("exceptionPage");
} else {
//其他异常
log.error("其他异常: {}", ex.getMessage(), ex);
}
return new ModelAndView();
}
// 判断是否是Ajax请求
private boolean isAjax(HttpServletRequest request) {
return "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"));
}
}
六、编辑applicationContext.xml
<!--配置全局异常处理器-->
<bean class="com.study.base.exception.ExceptionResolver"/>
七、logback.xml检查日志配置
<!--异常信息 -->
<appender name="webapp2-exception"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.base}/webapp2-exception.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.base}/%d{yyyy-MM-dd}/webapp2-exception-%i.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>30MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<logger name="com.study.base.exception" additivity="false">
<level value="error" />
<appender-ref ref="webapp2-exception" />
</logger>
八、修改controller层类TestController.java
package com.study.web.resources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.study.base.exception.BizException;
import com.study.base.exception.SysException;
@Controller
@RequestMapping("mvc")
public class TestController {
private static Logger log = LoggerFactory.getLogger(TestController.class);
@RequestMapping("hello")
private String hello() {
log.info("hello in...");
log.info("hello out...");
return "hello";
}
@RequestMapping("testError")
public void testError() {
log.info("testError in...");
log.info("testError out...");
throw new BizException("1234567890", "报错信息1");
}
@RequestMapping("testError2")
public void testError2() {
log.info("testError2 in...");
log.info("testError2 out...");
throw new SysException("0987654321", "报错信息2");
}
}
九、访问测试链接
http://127.0.0.1:8080/webapp2/mvc/testError
http://127.0.0.1:8080/webapp2/mvc/testError2
webapp2-web.log日志记录:
2019-06-20 14:34:59.561 [] [] [] [] INFO [http-nio-8080-exec-2] com.study.web.resources.TestController [25]:testError in...
2019-06-20 14:34:59.562 [] [] [] [] INFO [http-nio-8080-exec-2] com.study.web.resources.TestController [26]:testError out...
2019-06-20 14:35:02.606 [] [] [] [] INFO [http-nio-8080-exec-9] com.study.web.resources.TestController [32]:testError2 in...
2019-06-20 14:35:02.607 [] [] [] [] INFO [http-nio-8080-exec-9] com.study.web.resources.TestController [33]:testError2 out...
webapp2-exception.log日志记录:
2019-06-20 14:34:59.570 [] [] [] [] ERROR [http-nio-8080-exec-2] com.study.base.exception.ExceptionResolver [25]:[业务异常]<1234567890> 报错信息1 null
2019-06-20 14:34:59.572 [] [] [] [] ERROR [http-nio-8080-exec-2] com.study.base.exception.ExceptionResolver [26]:errorCode:1234567890 errorMsg:[报错信息1]
2019-06-20 14:35:02.611 [] [] [] [] ERROR [http-nio-8080-exec-9] com.study.base.exception.ExceptionResolver [33]:其他异常: 报错信息2
com.study.base.exception.SysException: 报错信息2
at com.study.web.resources.TestController.testError2(TestController.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:849)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:760)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:94)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1132)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1539)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1495)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
十、参考资料
https://blog.csdn.net/eson_15/article/details/51731567
https://www.cnblogs.com/panxuejun/p/7089030.html
注:最新代码上传至https://github.com/csj50/webapp2.git