美文网首页
解决wiremock中velocity脚本(.vm)中文编码乱码

解决wiremock中velocity脚本(.vm)中文编码乱码

作者: chzphoenix | 来源:发表于2017-08-18 10:17 被阅读83次

    WireMock 是一个轻量级的服务器,可以快速的实现接口服务和部署。在前端开发中,如果服务接口未实现,可以使用这个工具来模拟接口。关于wiremock的使用网上又不少文章了,可以自行搜索,有时间我会出一篇详细的使用教程。

    在wiremock中可以使用velocity脚本来编写数据文件(.vm),这样可以生产动态的数据。
    但是wiremock中如果在velocity脚本中存在中文,就会出现编码错乱。而直接使用静态的json数据文本(.json)就不会出问题。
    这是因为.vm文件在读取后需要进行转换生产最终的数据,所以wiremock需要wiremock-velocity-transformer-x.x.jar和
    wiremock-velocity-transformer-standalone-x.x.jar这两个jar包。

    就是在velocity转换的过程中出现了编码问题。

    实际上,velocity转换后的数据返回的编码不是utf-8,所以我们用utf-8来处理就会有问题,我们在拿到这种数据可用单独做些处理就能得到正常的数据,比如:
    new String(text.getBytes(Charsets.ISO_8859_1), Charsets.UTF_8)
    注意:在我的电脑上velocity转换后的数据的编码是ISO_8859_1,这个编码是否固定和是否依赖终端类型还不确定,所以可能在其他机器上又是另外一个编码,如gbk。

    但是由于我们服务api基本上都使用的utf-8,所以如果wiremock不能提供utf-8的数据,那么我们在代码中就要根据环境来做一些特殊处理。所以最好的办法就是让velocity转换后的数据使用utf-8编码。

    转换的代码在
    wiremock-velocity-transformer-x.x.jar和
    wiremock-velocity-transformer-standalone-x.x.jar这两个jar包中,其中
    wiremock-velocity-transformer-x.x.jar只有一个类
    VelocityResponseTransformer,而wiremock-velocity-transformer-standalone-x.x.jar很大包含了很多不同的包。

    为了修改我们要拿到源码,在GitHub上可以找到
    wiremock-velocity-transformer的源码
    https://github.com/adamyork/wiremock-velocity-transformer

    下载源码后打开项目,这时要注意当前一定是最新版本的代码,而自己使用的wiremock未必是最新版本的,所以要将代码切到正确的tag下,比如使用的是wiremock-velocity-transformer-1.2.jar和
    wiremock-velocity-transformer-standalone-1.2.jar,那么checkout到1.2-release的tag上。否则会因为代码的不同导致运行出错。

    打开项目后可能会有一些依赖的问题,因为这个build.gradle将所有层次依赖都列出的,而不是利用gradle来自动管理依赖,这样当依赖版本不同时会出现依赖问题。解决方法就是去掉不必要的依赖,只保留velocity-tools和wiremock这两个依赖即可(也要保留junit用于测试),最终如下:

    dependencies {
    //    compile         group: "org.apache.velocity",           name: "velocity",             version: "1.7"
        compile         group: "org.apache.velocity",           name: "velocity-tools",       version: "2.0"
        compile         group: "com.github.tomakehurst",        name: "wiremock",             version: "1.57"
    //    compile         group: "org.mortbay.jetty",             name: "jetty",                version: "6.1.26"
    //    compile         group: "com.google.guava",              name: "guava",                version: "18.0"
    //    compile         group: "com.fasterxml.jackson.core",    name: "jackson-core",         version: "2.4.2"
    //    compile         group: "com.fasterxml.jackson.core",    name: "jackson-annotations",  version: "2.4.2"
    //    compile         group: "com.fasterxml.jackson.core",    name: "jackson-databind",     version: "2.4.2"
    //    compile         group: "org.apache.httpcomponents",     name: "httpclient",           version: "4.3.5"
    //    compile         group: "org.skyscreamer",               name: "jsonassert",           version: "1.2.3"
    //    compile         group: "xmlunit",                       name: "xmlunit",              version: "1.5"
    //    compile         group: "com.jayway.jsonpath",           name: "json-path",            version: "0.8.1"
    //    compile         group: "org.slf4j",                     name: "slf4j-api",            version: "1.7.6"
    //    compile         group: "net.sf.jopt-simple",            name: "jopt-simple",          version: "4.7"
        compile ("junit:junit:4.11") {
            exclude group: "org.hamcrest", module: "hamcrest-core"
        }
        testCompile "org.hamcrest:hamcrest-all:1.3"
        testCompile ("org.jmock:jmock:2.5.1") {
            exclude group: "junit", module: "junit-dep"
            exclude group: "org.hamcrest", module: "hamcrest-core"
            exclude group: "org.hamcrest", module: "hamcrest-library"
        }
        testCompile ("org.jmock:jmock-junit4:2.5.1") {
            exclude group: "junit", module: "junit-dep"
            exclude group: "org.hamcrest", module: "hamcrest-core"
            exclude group: "org.hamcrest", module: "hamcrest-library"
        }
        testCompile "net.sf.json-lib:json-lib:2.4:jdk15"
        testCompile "com.googlecode.jarjar:jarjar:1.3"
        testCompile "commons-io:commons-io:2.4"
    }
    

    在这个项目中也只有VelocityResponseTransformer类,转换就是在这里进行的,关键方法如下:

    private void transformResponse(final ResponseDefinition response) throws Exception {
        final String templatePath = fileSource.getPath().concat("/" + response.getBodyFileName());
        final Template template = Velocity.getTemplate(templatePath);
        StringWriter writer = new StringWriter();
        template.merge(context, writer);
        final byte[] fileBytes = String.valueOf(writer.getBuffer()).getBytes();
        response.setBody(fileBytes);
        response.setBodyFileName(null);
    }
    

    问题就出现在Velocity.getTemplate(templatePath)这句
    这里没有指定编码,则会使用默认编码,实际上Velocity提供了附带编码的方法,所以修改为
    Velocity.getTemplate(templatePath, "utf-8")
    即可,在项目的resource下的文件中添加中文,运行测试用例VelocityResponseTransformerTest就会发现可以获得正常的中文了。

    最后就是要打包jar,通过测试发现wiremock-velocity-transformer-x.x.jar和
    wiremock-velocity-transformer-standalone-x.x.jar这两个jar包中都有
    VelocityResponseTransformer类,所以这两个jar包都需要替换。但是项目中只有一个类,打出wiremock-velocity-transformer-x.x.jar这个jar包还比较容易,但是
    wiremock-velocity-transformer-standalone-x.x.jar很难手动打出。

    其实在build.gradle中已经有了打包的task,本来的目的是为了打包上传到仓库。代码如下:

    fatJar {
        archiveName = "wiremock-velocity-transformer-standalone-" + fatJar.version + ".jar"
        manifest {
            attributes "Implementation-Title"   : "wiremock-velocity-transformer-standalone",
                       "Implementation-Version" : version
        }
    }
    
    task cleanFunctional(type: Delete) {
        delete fileTree(dir: "functional", include: "*-velocity-transformer-*.jar", exclude: "wiremock-1.55-standalone.jar")
    }
    
    task copyFunctional(type: Copy) {
         from "build/libs/"
         include "*.jar"
         exclude "*-sources.jar","*-javadoc.jar"
         into "functional/"
    }
    
    task javadocJar(type: Jar, dependsOn: javadoc) {
        classifier = "javadoc"
        from "build/docs/javadoc"
    }
    
    task sourcesJar(type: Jar) {
        from sourceSets.main.allSource
        classifier = "sources"
    }
    
    jar {
        dependsOn fatJar
        dependsOn cleanFunctional
        dependsOn copyFunctional
        cleanFunctional.shouldRunAfter fatJar
        copyFunctional.dependsOn cleanFunctional
        copyFunctional.shouldRunAfter cleanFunctional
        archiveName = "wiremock-velocity-transformer-" + jar.version + ".jar"
        manifest {
            attributes "Implementation-Title"   : "wiremock-velocity-transformer",
                       "Implementation-Version" : version
        }
    }
    
    artifacts {
        archives jar
        archives javadocJar
        archives sourcesJar
    }
    

    我们只需要打包,而不需要上传,所以要在uploadArchives中做手脚,代码如下

    uploadArchives {
        repositories {
            mavenDeployer {
    
                beforeDeployment {
                    MavenDeployment deployment -> signing.signPom(deployment)
                }
    
                repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
                  authentication(userName: "", password: "")
                }
    
                pom.project {
                   name "wiremock-velocity-transformer"
                   packaging "jar"
                   description "transformer used to render velocity templates for stubbed responses."
                   url "https://github.com/radAdam/wiremock-velocity-transformer"
    
                   scm {
                       url "scm:git@github.com:radAdam/wiremock-velocity-transformer.git"
                       connection "scm:git@github.com:radAdam/wiremock-velocity-transformer.git"
                       developerConnection "scm:git@github.com:radAdam/wiremock-velocity-transformer.git"
                   }
    
                   licenses {
                       license {
                           name "The Apache Software License, Version 2.0"
                           url "http://www.apache.org/licenses/LICENSE-2.0.txt"
                           distribution "repo"
                       }
                   }
    
                   developers {
                       developer {
                           id "adamcyork"
                           name "Adam York"
                       }
                   }
               }
            }
        }
    }
    

    在uploadArchives这个task下,我们将仓库的账号和密码随便修改(本来也没有账号和密码,但是之前的两个变量如果不删掉则gradle无法成功),这样在上传时就会失败停下,但是前面的步骤都会完成。

    运行uploadArchives这个task,完成后在项目中build/libs下就可以看到打好的jar包,将wiremock-velocity-transformer-x.x.jar和
    wiremock-velocity-transformer-standalone-x.x.jar替换掉wiremock中原有的。

    在.vm文件中添加中文,启动wiremock,访问对应接口就会发现中文数据不再乱码了。

    相关文章

      网友评论

          本文标题:解决wiremock中velocity脚本(.vm)中文编码乱码

          本文链接:https://www.haomeiwen.com/subject/bhworxtx.html