在实际的J2EE项目中,系统内部难免会出现一些异常,就如Struts+Spring+Hibernate项目:通常一个页面请求到达后台以后,首先是到action(就是MVC中的controller),在action层会调用业务逻辑层service,而在service层会调用持久层dao进而获得数据,再将获得的数据一层一层返回到action层,然后通过action控制层转发到指定页面,而这期间都可能会发生异常,dao层可能会发生SQLException异常,service层可能会发生NullPointException异常,action层可能会发生IOException异常,如果这三层都不处理的话异常信息会抛到服务器,然后服务器会把异常信息打印到浏览器上(用户看不懂信息,体验十分不好,), 处理得好可以使开发效率快速提升。
通常处理这些异常有两种方法:①直接throws,②try...catch...在catch块中不做任何处理,或者仅仅printStackTrace()把异常信息打印出来。第一种就是会在浏览器上打印出用户看不懂的异常信息,第二种方法则是页面不报错也不执行用户的请求。
如何更好的解决这些异常?
首先,在action类、service类、dao类,如果有必要就try...catch...,catch块内不记录log,通常是抛出一个新异常
//action层执行数据添加操作 public String save(){ try{ //调用service的save方法 service.save(obj); }catch(Exception e){ //抛出Runtime异常可使得不必再方法后写throws xx throw new RuntimeException("添加数据时发生错误!",e); } return "success"; }
然后在异常拦截器对异常进行处理
public String intercept(ActionInvocation actioninvocation) { String result = null; // Action的返回值 try { // 运行被拦截的Action,期间如果发生异常会被catch住 result = actioninvocation.invoke(); return result; } catch (Exception e) { /** * 处理异常 */ String errorMsg = "未知错误!"; //通过instanceof判断到底是什么异常类型 if (e instanceof BaseException) { BaseException be = (BaseException) e; be.printStackTrace(); //开发时打印异常信息,方便调试 if(be.getMessage()!=null||Constants.BLANK.equals(be.getMessage().trim())){ //获得错误信息 errorMsg = be.getMessage().trim(); } } else if(e instanceof RuntimeException){ //未知的运行时异常 RuntimeException re = (RuntimeException)e; re.printStackTrace(); } else{ //未知的严重异常 e.printStackTrace(); } //把自定义错误信息 HttpServletRequest request = (HttpServletRequest) actioninvocation .getInvocationContext().get(StrutsStatics.HTTP_REQUEST); /** * 发送错误消息到页面 */ request.setAttribute("errorMsg", errorMsg); /** * log4j记录日志 */ Log log = LogFactory .getLog(actioninvocation.getAction().getClass()); if (e.getCause() != null){ log.error(errorMsg, e); }else{ log.error(errorMsg, e); } return "error"; }// ...end of catch }
需要注意的是,在使用instanceOf判断异常类型的时候一定要从子到父依次找,比如BaseException继承RunTimeException,则必须首先判断是否是 BaseException再判断是RunTimeException,最后在error jsp页面显示出具体的错误信息
<body> <s:if test="%{#request.errorMsg==null}"> <p>对不起,系统发生了未知的错误</p> </s:if> <s:else> <p>${requestScope.errorMsg}</p> </s:else> </body>
以上方式可以拦截后台代码所有的异常,但如果出现数据库链接时异常不能被捕捉的则可使用struts2的全局异常处理机制处理
<global-results> <result name="error" >/Web/common/page/error.jsp</result> </global-results> <global-exception-mappings> <exception-mapping result="error" exception="java.lang.Exception"></exception-mapping> </global-exception-mappings>
文章转自:http://my.oschina.net/u/817908/blog/158056
其他关于J2EE项目异常处理机制请看:http://www.iteye.com/topic/1073599