用Groovy实现类似Spring对application/json的处理插件

    最近要写个公司内部使用的代码生成器,想学习新东西,打算 用 Groovy 和 JFinal。

    发现JFinal对body中json处理不如Spring那样方便,无法自动将json转成bean传入action中, 就研究源码,写了一个插件,将相关操作进行封装,工程中只要引入插件就可以了。

    有两个前提条件, 如果你也用Groovy开发JFinal,这个插件可以直接使用,否则需要改写成java版本,由于Groovy的语法挺好理解的(我最后这版使用比较多的Groovy的特性,原先java版本写法的注释为了代码的简洁,我都删除了),这个改写并不难,我就不实现了;另一个是我发现Groovy有原生的Json实现,我将原先的fastjson改成了 GroovyJson,如果java要用请自行改成FastJson或者其他json实现。

    在我的基础上还可以增加对更多contentType 类型的处理。

插件代码:

/**
 * 对ContentType的处理插件
 * @author MRZC
 *
 */
class ContentTypePlugin implements IPlugin{

    @Override
    public boolean start() {
        // 引入FastJson作为Json转换的实现
        Config.constants.jsonFactory = new GroovyJsonFactory()
        // 引入 ContentType 的拦截器
        Config.interceptors.addGlobalActionInterceptor new ContentTypeInterceptor()
        return true
    }

    @Override
    public boolean stop() {
        // 没有释放的资源
        true
    }
}

import com.jfinal.aop.Interceptor as JfianlInterceptor

/**
 * 对application/json的拦截器
 * @author MRZC
 *
 */
class ContentTypeInterceptor implements JfianlInterceptor {
    @Override
    public void intercept(Invocation inv) {
        def controller = inv.controller
        def contentType = controller.request.contentType
        def parameterTypes = inv.method.parameterTypes
        // 判断contentType 是否包含 application/json,并且action函数是否只有一个参数
        if(contentType?.indexOf("application/json") > -1 && parameterTypes.length == 1) {
            // 将body体中的json转成bean
            def arg = JsonKit.parse(controller.rawData, parameterTypes[0])
            // 替换原先的参数
            inv.setArg(0, arg)
        }
        inv.invoke()
    }
}
/**
 * Groovy版本IJsonFactory实现
 * @author MRZC
 *
 */
class GroovyJsonFactory implements IJsonFactory {

    @Override
    public Json getJson() {
        new GroovyJson();
    }
}

/**
 * Json 转换 Groovy 实现
 * @author MRZC
 *
 */
class GroovyJson extends Json {

    @Override
    public String toJson(Object o) {
        JsonOutput.toJson o
    }

    @Override
    public <T> T parse(String json, Class<T> t) {
        def jsonSlurper = new JsonSlurper()
        def map = jsonSlurper.parseText json
        if(t == Object || t == GroovyObject)
        {
            return map
        }
        t.newInstance map
    }
}



使用样例:

class Main extends JFinalConfig{
    static void main(args) {
        UndertowServer.start(Main, 80, true);
    }

    @Override
    public void configConstant(Constants me) {
        me.devMode = true
    }

    @Override
    public void configRoute(Routes me) {
        me.add("/", Index);
    }

    @Override
    public void configEngine(Engine me) {}

    @Override
    public void configPlugin(Plugins me) {
        // 引入对ContentType的处理插件
        me.add new ContentTypePlugin()
    }

    @Override
    public void configInterceptor(Interceptors me) {}

    @Override
    public void configHandler(Handlers me) {}
}

class Index extends Controller {
    public index(User u) {
        // 将请求Json再转成Json输出,用于验证
        renderJson(JsonKit.toJson(u))
    }
    public groovy(o) {
        // 验证默认的Map类型
        renderText o.getClass().toString() + " " + o.name
    }
}

class User {
    def name;
}

评论区

快乐的蹦豆子

2019-08-03 16:28

good,目前也只能这么处理了