JFinal Controller支持application/json请求的参数注入

1、首先需要重写HttpServletRequest, 能够让我们对Parameter做操作(格式化需要FastJSON)

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.StrKit;
import com.jfinal.render.ContentType;

public class ParameterRequestWrapper extends HttpServletRequestWrapper {

	private HttpServletRequest request;
	private Map<String, String[]> params = new HashMap<>();

	/**
	 * @param request
	 */
	@SuppressWarnings("unchecked")
	public ParameterRequestWrapper(HttpServletRequest request) {
		super(request);
		this.params.putAll(request.getParameterMap());
		this.request = request;
		initParameters(this.request);
	}
	
	/**
	 * 重写getParameterMap, 设置map从当前类获取
	 * 主要是jfinal的参数注入是从getParameterMap中获取注入的
	 */
	@Override
	public Map<String, String[]> getParameterMap() {
		return params;		
	}

	/**
	 * 重写getParameter, 设置参数从当前类获取
	 */
	@Override
	public String getParameter(String name) {
		String[] values = params.get(name);
		if (values == null || values.length == 0) {
			return null;
		}
		return values[0];
	}

	/**
	 * 获取当前类参数
	 */
	public String[] getParameterValues(String name) {
		return params.get(name);
	}

	/**
	 * 新增参数
	 * @param otherParams
	 */
	public void addParameter(Map<String, Object> otherParams) {
		for (Entry<String, Object> entry : otherParams.entrySet()) {
			addParameter(entry.getKey(), entry.getValue());
		}
	}

	/**
	 * 新增参数
	 * @param name
	 * @param value
	 */
	public void addParameter(String name, Object value) {// 增加参数
		if (value != null) {
			if (value instanceof String[]) {
				params.put(name, (String[]) value);
			} else if (value instanceof String) {
				params.put(name, new String[] { (String) value });
			} else {
				params.put(name, new String[] { String.valueOf(value) });
			}
		}
	}
	
	/**
	 * 初始化params, 格式化JSON
	 * @param request
	 */
	public void initParameters(HttpServletRequest request) {
		String contentType = request.getContentType();
		if (StrKit.isBlank(contentType)) return;
		
		if (contentType.equals(ContentType.JSON.toString())) {
			String rawData = HttpKit.readData(request);
			if (StrKit.isBlank(rawData)) return;
			
			Object requestParamObject = convertObject(rawData);
			if (requestParamObject == null) return;
			
			if (requestParamObject instanceof JSONObject) {
				JSONObject jsonObject = (JSONObject) requestParamObject;
				for (Entry<String, Object> entry : jsonObject.entrySet()) {
					addParameter(entry.getKey(), entry.getValue());
				}
				
			} else if (requestParamObject instanceof JSONArray) {
				
			} else return;
		}
	}
	
	/**
	 * 入参转为JSON
	 * @param rawData
	 * @return
	 */
	public Object convertObject(String rawData) {
		Object requestParamObject = null;
		try {
			requestParamObject = JSON.parseObject(rawData);
		} catch (Exception e) {
			requestParamObject = null;
		}
		
		return requestParamObject;
	}
}


2、编写BaseJsonHandler更改自定义的HttpServletRequest

public class BaseJsonHandler extends Handler{


	@Override
	public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
		if (target.indexOf(".") == -1) {
			request = new ParameterRequestWrapper(request);
		}
		
		next.handle(target, request, response, isHandled);
	}

}

3、在config中加入BaseJsonHandler

@Override
    public void configHandler(Handlers me) {
    	me.add(new BaseJsonHandler());
    }

使用:

         1、依然与正常的参数注入一样使用, Controller的方法添加入参

         微信截图_20181228151135.png

         2、具体的实现思路为:

        微信截图_20181229105709.png

        jfinal的参数注入是从HttpServletRequest Parameter中根据key获取值,但是原生的HttpServletRequest是不允许修改Parameter的, 所以需要重写, 重写后我们就可以拦截到json请求后从使用HttpKit.readData方法获取到json字符串,对json字符串进行格式化再放到Parameter中,这样就可以正常注入  到方法的入参中


代码略乱, 欢迎大神分享更加优雅的实现.

评论区

JFinal

2018-12-28 17:15

下面的这个用法很好:
if (target.indexOf(".") == -1) {
request = new ParameterRequestWrapper(request);
}

只在必要的时候做 wrapper 保障了性能。总体上简洁有力,感谢分享

快乐的蹦豆子

2018-12-29 09:35

用的时候是不是需要 public void xx(JsonObject abc){...}

快乐的蹦豆子

2018-12-29 10:00

@快乐的蹦豆子 貌似我说的不对,你这是把jsonbody的字段都分开了, 注入的时候只能一个个的 注入

冰雨

2018-12-29 11:24

感谢分享!点赞加收藏

热门分享

扫码入社