自定义JFinal框架异常

      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上下文路径;对静态资源直接返回;
		
	}


评论区

JFinal

2018-05-16 17:41

这个分享填补了 ErrorRender 扩展的空白,点赞、收藏

lyh061619

2018-05-16 17:49

@JFinal 这个确实是需要的呢,生产环境安全起见,一般都会隐藏掉使用框架信息的,信息公布的越多,被人玩的机率就越高。

AI-wen

2018-07-17 14:07

@JFinal RenderManager这个类来自哪里呢!我怎么没啊

JFinal

2018-07-17 14:09

@AI-wen 在 com.jfinal.render 包下面,注意不能是很老的 jfinal 版本,大概 jfinal 3.0 版本就有了

AI-wen

2018-07-17 14:13

@JFinal 我的版本太老了,刚才注意到了,谢谢波总这么快的回复!

HingLo

2018-10-26 18:06

这个就是真的非常的棒了,根据此文章,我修改我的项目,但是新版本中有了ErrorRender 了,继承这个方法,就可以省去一些代码,同时在configConstant 中配置就新的RenderFactory就好了

热门分享

扫码入社