JF默认的全局框架异常会输出500、404、401、403的常见HTTP异常信息,里面也携带了JFianl的官网链接,在正式项目中,这个是需要去掉的;
目前的前端框架大部分都是HTML、JSON格式混合使用的,比如请求页面是HTML,在HTML中的加载可能是AJAX加载的JSON字符串;那么,默认的异常处理是不够用的!
所以,这里分享一个自定义全局异常处理。这部分异常是指框架异常,Filter、Handler层的异常会直接在Filter层抛Servlet异常,由容器处理;框架异常是指经Interceptor层、Controller层、Service层异常,这块是需要我们处理的!Render层异常,目前最好的办法就是不要写错!因为模板边解析边输出,输出中途出错的话,响应是不完整的,此时无法再返回一个错误信息给前端!所以,在页面写模板的时候,要注意避免!
package com.ipan.jfinal.handler; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest; import com.jfinal.render.Render; import com.jfinal.render.RenderException; import com.jfinal.render.RenderManager; /** * 自定义异常渲染 根据前端请求的是HTML、Json来做不同的渲染; * * @author iPan * @version 2018-05-06 */ public class MyErrorRender extends Render { protected static final String htmlContentType = "text/html; charset=" + getEncoding(); protected static final String jsonContentType = "application/json; charset=" + getEncoding(); // protected static final String version = "<center><a href='http://www.jfinal.com?f=ev-" + Const.JFINAL_VERSION // + "' target='_blank'><b>Powered by JFinal " + Const.JFINAL_VERSION + "</b></a></center>"; protected static final String version = ""; protected static final String html404 = "<html><head><title>404 Not Found</title></head><body bgcolor='white'><center><h1>404 Not Found</h1></center><hr>" + version + "</body></html>"; protected static final String html500 = "<html><head><title>500 Internal Server Error</title></head><body bgcolor='white'><center><h1>500 Internal Server Error</h1></center><hr>" + version + "</body></html>"; protected static final String html401 = "<html><head><title>401 Unauthorized</title></head><body bgcolor='white'><center><h1>401 Unauthorized</h1></center><hr>" + version + "</body></html>"; protected static final String html403 = "<html><head><title>403 Forbidden</title></head><body bgcolor='white'><center><h1>403 Forbidden</h1></center><hr>" + version + "</body></html>"; protected static final String json404 = "{\"code\": 404, \"msg\": \"404 请求失败\"}"; protected static final String json500 = "{\"code\": 500, \"msg\": \"500 操作失败\"}"; protected static final String json401 = "{\"code\": 401, \"msg\": \"401 未授权\"}"; protected static final String json403 = "{\"code\": 403, \"msg\": \"403 权限不足\"}"; protected int errorCode; public MyErrorRender(int errorCode, String view) { this.errorCode = errorCode; this.view = view; } public void render() { // render with view String view = getView(); if (view != null) { response.setStatus(getErrorCode()); // HttpServletResponse.SC_XXX_XXX RenderManager.me().getRenderFactory().getRender(view).setContext(request, response).render(); return; } // render with html content PrintWriter writer = null; try { String wrBody = null; if (isAjax(request)) { // ajax请求,这里是json请求;如果是XML,自己定义! wrBody = getErrorJson(); response.setStatus(200); // ajax请求响应必须是200才能正常接收 response.setContentType(jsonContentType); } else { wrBody = getErrorHtml(); response.setStatus(getErrorCode()); // HttpServletResponse.SC_XXX_XXX response.setContentType(htmlContentType); } writer = response.getWriter(); writer.write(wrBody); writer.flush(); } catch (IOException e) { throw new RenderException(e); } } public String getErrorHtml() { int errorCode = getErrorCode(); if (errorCode == 404) return html404; if (errorCode == 500) return html500; if (errorCode == 401) return html401; if (errorCode == 403) return html403; return "<html><head><title>" + errorCode + " Error</title></head><body bgcolor='white'><center><h1>" + errorCode + " Error</h1></center><hr>" + version + "</body></html>"; } public String getErrorJson() { int errorCode = getErrorCode(); if (errorCode == 404) return json404; if (errorCode == 500) return json500; if (errorCode == 401) return json401; if (errorCode == 403) return json403; return String.format("{code: %d, msg: '%d操作失败'}", errorCode, errorCode); } public int getErrorCode() { return (errorCode != 0) ? errorCode : 100; // 对应BaseController中的retFail方法,失败返回code=100; } public boolean isAjax(HttpServletRequest request) { return ("XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"))) ? true : false; } } package com.ipan.jfinal.handler; import com.jfinal.render.Render; import com.jfinal.render.RenderFactory; /** * 自定义渲染工厂 * Constants中setErrorView/getErrorView可以自定义全局异常Html页面,但是不能同时支持Html与Json的异常响应; * 所以,Constants的这一功能暂时不使用,全局Html页面直接定义在MyErrorRender中并且支持Json格式的响应; * * @author iPan * @version 2018-05-06 */ public class MyRenderFactory extends RenderFactory { @Override public Render getErrorRender(int errorCode, String view) { return new MyErrorRender(errorCode, view); } @Override public Render getErrorRender(int errorCode) { return new MyErrorRender(errorCode, constants.getErrorView(errorCode)); } } // 在JFinalConfig中设置自定义的渲染工厂 public void configHandler(Handlers me) { RenderManager.me().setRenderFactory(new MyRenderFactory()); // 自定义渲染工厂 me.add(DruidKit.getDruidStatViewHandler()); // druid 统计页面功能 me.add(new MyBaseHandler()); // 添加ctx上下文路径;对静态资源直接返回; }