Java web项目创建笔记12 之《全局异常捕获》

一、异常类的定义
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
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值