Java Web error/exception handling page (Updated)-Alibaba Cloud Developer Community

UPDATE!! The previous code was severely overdesigned!! The modification is just a jsp.

<%@page pageEncoding="UTF-8" isErrorPage="true" import="java.io.*"%>
<%!/**
	 * 收集错误信息 输出到网页
	 * 
	 * @param request
	 *            请求对象
	 */
	public static OutputStream getError(HttpServletRequest request, Throwable ex) {
		try(
			OutputStream os = new ByteArrayOutputStream();// 创建一个空的字节流,保存错误信息
			PrintStream ps = new PrintStream(os);
		){
			// 收集错误信息
			ps.println("错误代码: " +     request.getAttribute("javax.servlet.error.status_code")); 
			ps.println("异常 Servlet: " + request.getAttribute("javax.servlet.error.servlet_name"));
			ps.println("出错页面地址: " + request.getAttribute("javax.servlet.error.request_uri"));
			ps.println("访问的路径: " + 	 request.getAttribute("javax.servlet.forward.request_uri"));
			ps.println();
	
			for (String key : request.getParameterMap().keySet()) {
				ps.println("请求中的 Parameter 包括:");
				ps.println(key + "=" + request.getParameter(key));
				ps.println();
			}
			
			for (Cookie cookie : request.getCookies()) {
				ps.println("请求中的 Cookie 包括:");
				ps.println(cookie.getName() + "=" + cookie.getValue());
				ps.println();
			}
	
			// javax.servlet.jspException 等于 JSP 里面的 exception 对象
			if (ex != null) { 
				ps.println("堆栈信息");
				ex.printStackTrace(ps);
				ps.println();
			}

			return os; 
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}
%>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<title>错误页面 code:${requestScope['javax.servlet.error.status_code']}</title>
	<style>
		body {
			max-width: 600px;
			min-width: 320px;
			margin: 0 auto;
			padding-top: 2%;
		}
		textarea {
			width: 100%;
			min-height: 300px;
			outline:none;
			border:1px solid gray;
			padding:1%;
		}
		h1 {
			text-align: right;
			color: lightgray;
		}
		div {
			margin-top: 1%;
		}
	</style>
</head>
<body>
	<h1>抱 歉……</h1>
	<div style="padding:2% 0;text-indent:2em;">尊敬的用户:我们致力于提供更好的服务,但人算不如天算,有些错误发生了,希望是在控制的范围内。如果问题重复出现,请向系统管理员反馈。</div>
	<textarea><%
	 out.print(getError(request, exception));
%></textarea>
	<div align="center">
			<a href="${pageContext.request.contextPath}">回首页</a> | <a href="javascript:history.go(-1);">上一页</a>
	</div>
</body>
</html>
------------------------------------------------------------------------------------------------------------------------------------

server 500 exception occurs. If The exception is handled by default, the system captures the exception and jumps to the Tomcat default exception page, as shown in the following figure.

No matter which website is the same, Tomcat also allows custom styles to meet custom needs. In the web.xml file, configure the following parameters:

<error-page>
	<error-code>500</error-code>
	<location>/error.jsp</location>
</error-page>

first, let's talk about the built-in logic. If an error occurs on a JSP page during execution, the JSP Engine automatically generates an exception object. If the JSP page specifies another JSP page as the error handler, the JSP Engine puts the exception object into the request object and transmits it to the error handler. If you have the impression of writing Servlet, this is the same idea as javax.servlet.forward.request_uri, which turns to the template JSP, and retains the original request path instead of the path of the JSP page. In the error handler, because the value of the isErrorPage attribute of the page Compilation instruction is set to true, the JSP Engine automatically declares an exception object, this exception object is obtained from the HTTP parameters contained in the request object.

The request object contains a wide range of exception information, as shown in the following figure:

javax.servlet.error.status_code             类型为Integer        错误状态代码
javax.servlet.error.exception_type          类型为Class          异常的类型
javax.servlet.error.message                 类型为String         异常的信息
javax.servlet.error.exception               类型为Throwable      异常类
javax.servlet.error.request_uri             类型为String         异常出现的页面
javax.servlet.error.servlet_name            类型为String         异常出现的servlet名
you can use the Java statement request.getAttribute("javax.servlet.error.status_code") can also be obtained through EL expressions on JSP pages, such as ${requestScope["javax.servlet.error.status_code"]}.

Although this custom error page is simple, JSP itself also has good encapsulation results. I have seen many other people's resources, but there are also many "knowledge" in a closer look ", so I want to" grind the wheel "again -- first of all, location is a jsp page or a servlet, however, if the servlet may not start up, then use a simple JSP page. We define internal classes through JSP pages to separate pages from logic (without writing servlet). Other ideas are as follows:

  • complete ErrorHandler class in JSP, and call this ErrorHandler class on other pages
  • it can not only accept JSP page errors, but also accept errors transmitted by servlet controller, and extract as much information as possible.
  • All content is written to the memory first, and then output from two output streams to the page and file respectively.
  • When the error message is output to the webpage, simply add a few words to write a copy of the information on the webpage to the database or text.
  • HTML/JSON/XML

the implementation code is as follows:

	
/**
 * 异常处理类
*/
class ErrorHandler {
	// 全部内容先写到内存,然后分别从两个输出流再输出到页面和文件
	private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
	private PrintStream printStream = new PrintStream(byteArrayOutputStream);

	/**
	 * 收集错误信息
	 * @param request
	 * @param exception
	 * @param out
	 */
	public ErrorHandler(HttpServletRequest request, Throwable exception, JspWriter out) {
		setRequest(request);
		setException(exception);

		if(out != null) {
			try {
				out.print(byteArrayOutputStream); // 输出到网页
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		 log(request);
		
		if(byteArrayOutputStream != null)
			try {
				byteArrayOutputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		if(printStream != null) printStream.close();
	}

	/**
	 * 
	 * @param request
	 */
	private void setRequest(HttpServletRequest request) {
		printStream.println();
		printStream.println("用户账号:" + request.getSession().getAttribute("userName"));
		printStream.println("访问的路径: "   + getInfo(request, "javax.servlet.forward.request_uri", String.class));
		printStream.println("出错页面地址: " + getInfo(request, "javax.servlet.error.request_uri", String.class));
		printStream.println("错误代码: "     + getInfo(request, "javax.servlet.error.status_code", int.class));
		printStream.println("异常的类型: "   + getInfo(request, "javax.servlet.error.exception_type", Class.class));
		printStream.println("异常的信息: "   + getInfo(request, "javax.servlet.error.message", String.class));
		printStream.println("异常servlet: "  + getInfo(request, "javax.servlet.error.servlet_name", String.class));
		printStream.println();
		
		// 另外两个对象
		getInfo(request, "javax.servlet.jspException", Throwable.class);
		getInfo(request, "javax.servlet.forward.jspException", Throwable.class);

		Map<String, String[]> map = request.getParameterMap();

		for (String key : map.keySet()) {
			printStream.println("请求中的 Parameter 包括:");
			printStream.println(key + "=" + request.getParameter(key));
			printStream.println();
		}
		
		for (Cookie cookie : request.getCookies()){  // cookie.getValue()
			printStream.println("请求中的 Cookie 包括:");
			printStream.println(cookie.getName() + "=" + cookie.getValue());
			printStream.println();
		}

	}

	/**
	 * 
	 * @param exception
	 */
	private void setException(Throwable exception) {
		if (exception != null) {
			printStream.println("异常信息");
			printStream.println(exception.getClass() + " : " + exception.getMessage());
			printStream.println();

			printStream.println("堆栈信息");
			exception.printStackTrace(printStream);
			printStream.println();
		}
	}

		/**
		 * 
		 * @param request
		 */
		private void log(HttpServletRequest request) {
 			File dir = new File(request.getSession().getServletContext().getRealPath("/errorLog"));
 			if (!dir.exists()) {
 				dir.mkdir();
 			}
			
 			String timeStamp = new java.text.SimpleDateFormat("yyyyMMddhhmmssS").format(new Date());
 			File file = new File(dir.getAbsolutePath() + File.separatorChar + "error-" + timeStamp + ".txt");
			
//  			try(FileOutputStream fileOutputStream = new FileOutputStream(file);
//  				PrintStream ps = new PrintStream(fileOutputStream)){// 写到文件
//  				ps.print(byteArrayOutputStream);
//  			} catch (FileNotFoundException e) {
//  				e.printStackTrace();
//  			} catch (IOException e) {
//  				e.printStackTrace();
//  			} catch (Exception e){
//  				e.printStackTrace();
//  			}
		}

		/**
		 * 
		 * @param request
		 * @param key
		 * @param type
		 * @return
		 */
		@SuppressWarnings("unchecked")
		private <T> T getInfo(HttpServletRequest request, String key, Class<T> type){
			Object obj = request.getAttribute(key);
			return obj == null ? null : (T) obj;
		} 
}

in this way, the exception control can be completed. The following defines web.xml to lead tomcat errors to the page error.jsp that we just specified.

<!-- 404 页面不存在错误 -->
<error-page>
	<error-code>404</error-code>
	<location>/WEB-INF/jsp/common/default/error.jsp</location>
</error-page>
<!-- // -->

<!-- 500 服务器内部错误 -->
<error-page>
	<error-code>500</error-code>
	<location>/WEB-INF/jsp/common/default/error.jsp</location>
</error-page>
<!-- // -->

We arrange a default page as follows

source code:

<%@page pageEncoding="UTF-8" isErrorPage="true"%>
<%@ include file="/WEB-INF/jsp/common/ClassicJSP/util.jsp"%>
<!DOCTYPE html>
<html>
<head>
	<title>错误页面</title>
	<style>
		body {
			max-width: 600px;
			min-width: 320px;
			margin: 0 auto;
			padding-top: 2%;
		}
		
		textarea {
			width: 100%;
			min-height: 300px;
		}
		
		h1 {
			text-align: right;
			color: lightgray;
		}
		
		div {
			margin-top: 1%;
		}
	</style>
</head>
<body>
	<h1>抱 歉!</h1>
	<div style="padding:2% 0;text-indent:2em;">尊敬的用户:我们致力于提供更好的服务,但人算不如天算,有些错误发生了,希望是在控制的范围内……如果问题重复出现,请向系统管理员反馈。</div>
	<textarea><%
           	new ErrorHandler(request, exception, out);
           %></textarea>
	<div>
		<center>
			<a href="${pageContext.request.contextPath}">回首页</a> | <a href="javascript:history.go(-1);">上一页</a>
		</center>
	</div>
</body>
</html>
Selected, One-Stop Store for Enterprise Applications
Support various scenarios to meet companies' needs at different stages of development

Start Building Today with a Free Trial to 50+ Products

Learn and experience the power of Alibaba Cloud.

Sign Up Now