Jfinal处理application/json 类型请求的另一种方法

改造目的:

  1. 实现json body参数可以通过action自动注入以及可以通过getPara/getBean进行获取

  2. 实现Validator对json对象的校验

实现:

  1. 自定义RestController继承Controller 重写getPara getBean相关方法


package com.qtgl.controller;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.jfinal.core.Controller;


/**
 * @author 
 * @version 1.0
 * @date 2019/12/1 10:45
 */
public class RestController extends Controller {
    private final static String POST = "post";
    private final static String CONTENT_TYPE_JSON = "application/json";
    private JSONObject paras = null;

    @Override
    public String getPara(String name) {
        initParas();
        return paras == null ? super.getPara(name) : paras.getStr(name);
    }

    @Override
    public <T> T getBean(Class<T> beanClass) {
        return getBean(beanClass, null, false);
    }

    @Override
    public <T> T getBean(Class<T> beanClass, String beanName, boolean skipConvertError) {
        initParas();
        return paras == null ? super.getBean(beanClass, beanName, skipConvertError) : JSONUtil.toBean(paras, beanClass, skipConvertError);
    }

    @Override
    public <T> T getBean(Class<T> beanClass, String beanName) {
        return getBean(beanClass, beanName, false);
    }

    /**
     * 初始化paras
     */
   private void initParas() {
    if (paras == null) {
        boolean flag = POST.equalsIgnoreCase(getRequest().getMethod()) && ContentType.JSON.value().equalsIgnoreCase(getRequest().getContentType().split(";")[0]);
        if (flag) {
            String rawData = getRawData();
            try {
                paras = JSONUtil.parseObj(rawData);
            } catch (Exception e) {
                renderError(415);
            }
        }
    }
}
}

   2.创建ApiController继承RestController

package com.qtgl.controller;

import com.jfinal.aop.Before;
import com.jfinal.aop.Inject;
import com.jfinal.core.paragetter.Para;
import com.jfinal.ext.interceptor.POST;

import com.qtgl.interceptor.ParaValidator;
import com.qtgl.model.ReqPara;
import com.qtgl.model.Result;
import com.qtgl.service.ApiService;

/**
 * @author 
 * @version 1.0
 * @date 2019/11/29 12:36
 */

public class ApiController extends RestController {
    @Inject
    private ApiService apiService;

    @Before({POST.class, ParaValidator.class})
    public void queryTasks(@Para("") ReqPara reqPara) {
        Result result = apiService.queryTasks(reqPara);
        renderJson(result);
    }
}

总结:自我感觉对比社区众多方案是一个比较优雅的实现方式,并且也没有用到Handler和Interceptor,依赖于第三方工具包Hutool

评论区

chcode

2019-12-01 14:11

另外 @JFinal controller getParaToXXX 方法应该直接调用getPara方法而不是调用request.getParameter,这样只需要重写getPara就行了,否则还需要重写一堆getParaToXXX

JFinal

2019-12-01 15:04

@chcode getParaToXXX 方法一直都是调用的 getPara 方法,而不是调用的 request.getParameter,所以,何出此言:
https://gitee.com/jfinal/jfinal/blob/master/src/main/java/com/jfinal/core/Controller.java

你这个方案确实好,简单而且性能比 handler 要好, 因为 handler 会接管所有请求,必然会拉低一点性能

有一个小建议, initParas 可以重构一下提升性能:
private void initParas() {
if (paras == null) {
boolean flag = getRequest().getMethod().equalsIgnoreCase(POST) &&
getRequest().getContentType().equalsIgnoreCase(CONTENT_TYPE_JSON);
if (flag) {
String rawData = getRawData();
paras = JSONUtil.parseObj(rawData);
}
}
}

JFinal

2019-12-01 15:05

点赞 + 收藏

chcode

2019-12-01 15:12

@JFinal 可是我看源码
/**
* Returns the value of a request parameter and convert to Integer.
* @param name a String specifying the name of the parameter
* @return a Integer representing the single value of the parameter
*/
public Integer getParaToInt(String name) {
return toInt(request.getParameter(name), null);
}
是这样的

铁马红尘

2019-12-04 05:50

getRequest().getContentType()得到内容是application/json;charset=UTF-8,initParas里面的判断可能就由问题

chcode

2019-12-04 16:04

@铁马红尘 感谢,已修改