关于groovy:Y-分钟速成-Groovy

源代码下载: learngroovy-cn.groovy Groovy - Java 平台的动静语言,理解更多。 /* 装置: 1) 装置 GVM - http://gvmtool.net/ 2) 装置 Groovy: gvm install groovy 3) 启动 groovy 控制台,键入: groovyConsole*/// 双斜线开始的是单行正文/*像这样的是多行正文*/// Hello Worldprintln "Hello world!"/* 变量: 能够给变量赋值,以便稍后应用*/def x = 1println xx = new java.util.Date()println xx = -3.1499392println xx = falseprintln xx = "Groovy!"println x/* 汇合和映射*///创立一个空的列表def technologies = []/*** 往列表中减少一个元素 ***/// 和Java一样technologies.add("Grails")// 左移增加,返回该列表technologies << "Groovy"// 减少多个元素technologies.addAll(["Gradle","Griffon"])/*** 从列表中删除元素 ***/// 和Java一样technologies.remove("Griffon")// 减号也行technologies = technologies - 'Grails'/*** 遍历列表 ***/// 遍历列表中的元素technologies.each { println "Technology: $it"}technologies.eachWithIndex { it, i -> println "$i: $it"}/*** 查看列表内容 ***///判断列表是否蕴含某元素,返回booleancontained = technologies.contains( 'Groovy' )// 或contained = 'Groovy' in technologies// 查看多个元素technologies.containsAll(['Groovy','Grails'])/*** 列表排序 ***/// 排序列表(批改原列表)technologies.sort()// 要想不批改原列表,能够这样:sortedTechnologies = technologies.sort( false )/*** 列表操作 ***///替换列表元素Collections.replaceAll(technologies, 'Gradle', 'gradle')//打乱列表Collections.shuffle(technologies, new Random())//清空列表technologies.clear()//创立空的映射def devMap = [:]//增加值devMap = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy']devMap.put('lastName','Perez')//遍历映射元素devMap.each { println "$it.key: $it.value" }devMap.eachWithIndex { it, i -> println "$i: $it"}//判断映射是否蕴含某键assert devMap.containsKey('name')//判断映射是否蕴含某值assert devMap.containsValue('Roberto')//获得映射所有的键println devMap.keySet()//获得映射所有的值println devMap.values()/* Groovy Beans GroovyBeans 是 JavaBeans,但应用了更简略的语法 Groovy 被编译为字节码时,遵循下列规定。 * 如果一个名字申明时带有拜访修饰符(public, private, 或者 protected), 则会生成一个字段(field)。 * 名字申明时没有拜访修饰符,则会生成一个带有public getter和setter的 private字段,即属性(property)。 * 如果一个属性申明为final,则会创立一个final的private字段,但不会生成setter。 * 能够申明一个属性的同时定义本人的getter和setter。 * 能够申明具备雷同名字的属性和字段,该属性会应用该字段。 * 如果要定义private或protected属性,必须提供申明为private或protected的getter 和setter。 * 如果应用显式或隐式的 this(例如 this.foo, 或者 foo)拜访类的在编译时定义的属性, Groovy会间接拜访对应字段,而不是应用getter或者setter * 如果应用显式或隐式的 foo 拜访一个不存在的属性,Groovy会通过元类(meta class) 拜访它,这可能导致运行时谬误。*/class Foo { // 只读属性 final String name = "Roberto" // 只读属性,有public getter和protected setter String language protected void setLanguage(String language) { this.language = language } // 动静类型属性 def lastName}/* 逻辑分支和循环*///Groovy反对常见的if - else语法def x = 3if(x==1) { println "One"} else if(x==2) { println "Two"} else { println "X greater than Two"}//Groovy也反对三元运算符def y = 10def x = (y > 1) ? "worked" : "failed"assert x == "worked"//for循环//应用区间(range)遍历def x = 0for (i in 0 .. 30) { x += i}//遍历列表x = 0for( i in [5,3,2,1] ) { x += i}//遍历数组array = (0..20).toArray()x = 0for (i in array) { x += i}//遍历映射def map = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy']x = ""for ( e in map ) { x += e.value x += " "}assert x.equals("Roberto Grails Groovy ")/* 运算符 在Groovy中以下罕用运算符反对重载: http://www.groovy-lang.org/operators.html#Operator-Overloading 实用的groovy运算符*///开展(spread)运算符:对聚合对象的所有元素施加操作def technologies = ['Groovy','Grails','Gradle']technologies*.toUpperCase() // 相当于 technologies.collect { it?.toUpperCase() }//平安导航(safe navigation)运算符:用来防止NullPointerExceptiondef user = User.get(1)def username = user?.username/* 闭包 Groovy闭包好比代码块或者办法指针,它是一段代码定义,能够当前执行。 更多信息见:http://www.groovy-lang.org/closures.html*///例子:def clos = { println "Hello World!" }println "Executing the Closure:"clos()//传参数给闭包def sum = { a, b -> println a+b }sum(2,4)//闭包能够援用参数列表以外的变量def x = 5def multiplyBy = { num -> num * x }println multiplyBy(10)// 只有一个参数的闭包能够省略参数的定义def clos = { print it }clos( "hi" )/* Groovy能够记忆闭包后果 [1][2][3]*/def cl = {a, b -> sleep(3000) // 模仿费时操作 a + b}mem = cl.memoize()def callClosure(a, b) { def start = System.currentTimeMillis() mem(a, b) println "Inputs(a = $a, b = $b) - took ${System.currentTimeMillis() - start} msecs."}callClosure(1, 2)callClosure(1, 2)callClosure(2, 3)callClosure(2, 3)callClosure(3, 4)callClosure(3, 4)callClosure(1, 2)callClosure(2, 3)callClosure(3, 4)/* Expando Expando类是一种动静bean类,能够给它的实例增加属性和增加闭包作为办法 http://mrhaki.blogspot.mx/2009/10/groovy-goodness-expando-as-dynamic-bean.html*/ def user = new Expando(name:"Roberto") assert 'Roberto' == user.name user.lastName = 'Pérez' assert 'Pérez' == user.lastName user.showInfo = { out -> out << "Name: $name" out << ", Last name: $lastName" } def sw = new StringWriter() println user.showInfo(sw)/* 元编程(MOP)*///应用ExpandoMetaClass减少行为String.metaClass.testAdd = { println "we added this"}String x = "test"x?.testAdd()//拦挡办法调用class Test implements GroovyInterceptable { def sum(Integer x, Integer y) { x + y } def invokeMethod(String name, args) { System.out.println "Invoke method $name with args: $args" }}def test = new Test()test?.sum(2,3)test?.multiply(2,3)//Groovy反对propertyMissing,来解决属性解析尝试class Foo { def propertyMissing(String name) { name }}def f = new Foo()assertEquals "boo", f.boo/* 类型检查和动态编译 Groovy天生是并将永远是一门动静语言,但也反对类型检查和动态编译 更多: http://www.infoq.com/articles/new-groovy-20*///类型查看import groovy.transform.TypeCheckedvoid testMethod() {}@TypeCheckedvoid test() { testMeethod() def name = "Roberto" println naameee}//另一例子import groovy.transform.TypeChecked@TypeCheckedInteger test() { Integer num = "1" Integer[] numbers = [1,2,3,4] Date date = numbers[1] return "Test"}//动态编译例子import groovy.transform.CompileStatic@CompileStaticint sum(int x, int y) { x + y}assert sum(2,5) == 7进阶资源Groovy 文档 ...

November 28, 2022 · 3 min · jiezi

关于groovy:初探Groovy

初探Groovy简介Groovy 是一门 JVM 语言,因而只有有JVM即可执行。而且Groovy与Java能够互相调用,亲测丝滑。 丝滑到什么水平呢?就是在Java我的项目我的项目中能够同时并存.java和.groovy文件,能够互相调用。 Groovy 是动静语言,引入很多有意思的个性。如果将Java比喻为楷书,则Groovy是行书,开发效率很高。而且Groovy JDK中蕴含很多实用工具,开发舒服。 指标Groovy is an optionally typed, dynamic language for the Java platform with many features that are inspired by languages like Python, Ruby, and Smalltalk, making them available to Java developers using a Java-like syntax. Unlike other alternative languages, it is designed as a companion, not a replacement for Java. —— Groovy In Action (page 44) 咱们的指标不是要替换Java,而是成为Java的搭档。将一些用Java解决起来很简单的工序,交给Groovy解决。 运行形式简略而言有两种形式: compile:编译期编译为 .class文件runtime:作为脚本由GroovyShell动静执行 毕竟是动静语言,出于性能思考,倡议外围代码、底层代码,用Java。业务逻辑、须要疾速变动的逻辑,尝试用Groovy。 ...

September 9, 2022 · 2 min · jiezi

关于groovy:Groovy-Java-混合编程方案GMaven

Groovy + Java 混合编程计划:GMavenHava a look先看成果。在我的项目中轻易创立一个 SayHiUtil.groovy,而后在main外面增加个执行打印一下 package com.cmb.lr20.zxb.dialog.utilsclass SayHIUtil { static def sayHi() { println "Hi groovy" }}public class DialogApplication { public static void main(String[] args) { SayHIUtil.sayHi(); SpringApplication.run(DialogApplication.class, args); }} DO IT!应用GMavenPlus,只需加个 plugin 和 dependency 即可: <dependencies> <!-- Groovy --> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy</artifactId> <version>3.0.9</version> </dependency> </dependencies><build> <plugins> <plugin> <groupId>org.codehaus.gmavenplus</groupId> <artifactId>gmavenplus-plugin</artifactId> <version>1.13.1</version> <executions> <execution> <goals> <goal>addSources</goal> <goal>addTestSources</goal> <goal>generateStubs</goal> <goal>compile</goal> <goal>generateTestStubs</goal> <goal>compileTests</goal> <goal>removeStubs</goal> <goal>removeTestStubs</goal> </goals> </execution> </executions> </plugin> <plugin> <!-- if including source jars, use the no-fork goals otherwise both the Groovy sources and Java stub sources will get included in your jar --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <!-- source plugin \> = 2.1 is required to use the no-fork goals --> <version>3.2.1</version> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar-no-fork</goal> <goal>test-jar-no-fork</goal> </goals> </execution> </executions> </plugin> </plugins></build>

September 7, 2022 · 1 min · jiezi

关于groovy:有道词典Android客户端包体积优化之路

1 背景有道词典从挪动互联网之初就凭借玲珑疾速、功能强大的印象让用户爱上翻译查词,爱上学习。随着业务一直地迭代以及性能不断完善,有道词典不再是单纯的查词软件,而是变成了用户的综合学习平台。咱们摸索过社区、问答、直播、信息流等业务,目前也承载着音频、视频、课程、背单词、写作批改等等的性能。词典曾经倒退成为一个综合性的学习平台,玲珑疾速的初心依然指引着咱们一直进行启动速度以及包体积优化。 通过了一直的性能优化,目前咱们的冷启动工夫曾经能维持在业界规范程度3s以内。咱们近一个季度次要的性能优化工作集中在安装包体积优化下面。通过一系列的致力,咱们包体积缩小了23.7%,安装包体积从177MB缩小到135MB,整体少了42MB。 以下具体介绍咱们的剖析以及实现细节。 2 剖析介绍下包体积蕴含的内容以及优化办法概述 个别的APK安装包蕴含了以下一些目录和资源: META-INF/ 签名文件 assets/ 程序应用的辅助资源文件 res/ 没有编译进入resources.arsc 资源文件,个别是图片 lib/ 依赖的不同native平台的库文件 resource.arsc 编译之后的文案、色值、大小、主题等资源索引 classes.dex 编译后的代码 AndroidMenifest.xml 利用的名称、版本、拜访权限和援用的库文件信息 能够看出占比拟大的局部次要是别离是assets/、lib/、res/、classes.dex以及resources.arsc,大略对应的就是资源、库文件、代码以及资源索引。咱们次要的优化思路如下(其中蓝色框局部为目前曾经解决局部): 3 技术实现细节3.1 图片压缩在APK打包的过程中,aapt 工具会默认对图片进行无损压缩,不过默认的压缩并不能达到一个很好的压缩成果,通过了比照webp以及tinypng的压缩成果,咱们最终抉择了应用tinypng对图片进行压缩。并且咱们编写了编译工具,对图片进行自动化压缩。 有损webp > tinypng > 无损webp 比方这张启动图,原大小724KB,压到75%左右的品质只有23.7KB。成果上有一点点差别,但能够承受。那么咱们是否能够把全副png图压成有损webp呢?答案是否定的,能够看看上面的例子: 压缩前: 压缩后: 能够看到,雷同的压缩品质下(75%),这个图就变得非常含糊,哪怕抉择到了99%的压缩品质,突变区域仍然会呈现一些没有天然过渡的条纹。 对于上述的状况,用tinypng计划更好 原图:643KB, tinypng: 152KB, webp:339KB 综上,对于有损webp,无奈找到一个固定的压缩品质来适配所有场景。有损webp有些时候甚至比tinypng还大,但显示品质更差。 咱们最后应用的抖音的McImage插件对图片进行解决,不过这个计划存在一些显著的问题: 计划采纳有损webp,有损webp无奈定一个通用的压缩品质适应所有场景。每次打包都要对所有图进行压缩,重大影响迭代效率。打包机要40分钟,且常常OOM。没有对assets目录的图片进行解决。针对以上问题,咱们本人开发了一套应用tinypng的自动化图片压缩工具,做出以下调整: 1.对于大图png,用手工压成有损webp。收益大,且危险可控。2.对于非大图,开发了一个image-optimization插件进行压缩。该插件计划为: · png转tinypng。尽管是有损的,但从抽样来看,肉眼齐全看不到显著变动。 · 对assets进行解决。assets内有前端png图,转tinypng不转webp的益处是不须要独自改html、js等文件,且对低版本零碎兼容性更敌对。flutter相干我的项目的flutter_assets图片比拟大且没留神压缩。插件对立解决能够不须要关上flutter工程独自优化、从新打包。 · 对于已压缩的图片,做缓存解决,不须要从新压缩,打包的时候动静替换。压缩缓存追随词典工程提交到gitlab对立治理。 以下是咱们图片自动化压缩插件解决的流程图: 这里压缩图是否可用判断,次要是大小判断,如果压出来比原图大,那么将舍弃。比方crunchPng压缩就存在这种状况 附加1:因为曾经用了tinypng对立压缩,那么google官网自带的crunchPng倡议敞开,否则打包速度变慢,而且优化好的图片也可能又变大,退出这行即可: buildTypes.all {\ isCrunchPngs = false\}附加2:无损webp和tinypng比照 如图所示,全量换tinypng比全量换webp(蕴含assets)少7.7MB。如果思考到assets内的14.7MB其实是不能简略换webp的,差距会更大。 附加3:tinypng曾经是最好的计划吗? 参考另一个ImageOptim工具,它联合OptiPNG, PNGCrush, AdvanceComp, PNGOUT, Jpegoptim + Jpegtran, 和 Gifsicle 等几个工具提供最好的优化成果,而且是简直无损的。对于小局部图片ImageOptim压出来小,看起来没有差异。不过压缩速度十分慢。 ...

April 21, 2022 · 2 min · jiezi

解决moco框架API在cycle方法缺失的问题

我在使用moco框架过程中,遇到一个问题,在官方文档中给出了cycle的方法,表示循环返回一个数组里面的response,但是在查看API的时候并没有发现这个cycle()方法,所以觉得自己写了一个responsehandle,并且重写了cycle()方法。 cycle方法主要用在请求次数相关的内容,比如订单提交、资源删除等场景。 package com.fun.moco.support;import com.github.dreamhead.moco.MocoConfig;import com.github.dreamhead.moco.ResponseHandler;import com.github.dreamhead.moco.handler.AbstractResponseHandler;import com.github.dreamhead.moco.internal.SessionContext;import com.google.common.base.Function;import com.google.common.collect.FluentIterable;import com.google.common.collect.ImmutableList;import com.google.common.collect.Iterables;import static com.google.common.base.Preconditions.checkArgument;import static com.google.common.collect.FluentIterable.from;import static com.google.common.collect.ImmutableList.copyOf;/** * 循环的responsehandle */@SuppressWarnings("all")public class CycleHandle extends AbstractResponseHandler { private final ImmutableList<ResponseHandler> handlers; private int index; private CycleHandle(final Iterable<ResponseHandler> handlers) { this.handlers = copyOf(handlers); } public static ResponseHandler newSeq(final Iterable<ResponseHandler> handlers) { checkArgument(Iterables.size(handlers) > 0, "Sequence contents should not be null"); return new CycleHandle(handlers); } @Override public void writeToResponse(final SessionContext context) { handlers.get((index++) % handlers.size()).writeToResponse(context); } @Override public ResponseHandler apply(final MocoConfig config) { if (config.isFor(MocoConfig.RESPONSE_ID)) { return super.apply(config); } FluentIterable<ResponseHandler> transformedResources = from(copyOf(handlers)).transform(applyConfig(config)); return new CycleHandle(transformedResources.toList()); } private Function<ResponseHandler, ResponseHandler> applyConfig(final MocoConfig config) { return new Function<ResponseHandler, ResponseHandler>() { @Override public ResponseHandler apply(final ResponseHandler input) { return input.apply(config); } }; }}使用方法如下(groovy,有兴趣可以转成java):/** * 循环返回 * @param content * @param contents * @return */ static ResponseHandler cycle(String content, String... contents) { CycleHandle.newSeq(FluentIterable.from(asIterable(content, contents)).transform(textToResource())) }/** * 循环返回 * @param handler * @param handlers * @return */ static ResponseHandler cycle(final ResponseHandler handler, final ResponseHandler... handlers) { CycleHandle.newSeq(asIterable(handler, handlers)) }groovy是一种基于JVM的动态语言,我觉得最大的优势有两点,第一:于java兼容性非常好,大部分时候吧groovy的文件后缀改成java直接可以用,反之亦然。java的绝大部分库,groovy都是可以直接拿来就用的。这还带来了另外一个有点,学习成本低,非常低,直接上手没问题,可以慢慢学习groovy不同于Java的语法;第二:编译器支持变得更好,现在用的intellij的ide,总体来说已经比较好的支持groovy语言了,写起代码来也是比较顺滑了,各种基于groovy的框架工具也比较溜,特别是Gradle构建工具,比Maven爽很多。----此段文字为了撑字数强加的,与内容无关。 ...

July 16, 2019 · 1 min · jiezi

解决moco框架API在post请求json参数情况下query失效的问题

在使用moco API做接口虚拟化的过程中遇到一个比较棘手的问题,就是根据官方文档提供的案例,并不能跑通post请求在处理json传参格式的虚拟化。经过查询源码,发现了一个问题:源码:···public class ParamRequestExtractor extends HttpRequestExtractor<String[]> { private final String param;public ParamRequestExtractor(final String param) { this.param = param;}@Overrideprotected Optional<String[]> doExtract(final HttpRequest request) { String[] reference = request.getQueries().get(this.param); return fromNullable(reference);}}··· 在获取请求的内容时,发现该方法不能获取到正确的请求参数,后来索性自己重写了一个Extractor类,内容如下: ···package com.fun.moco.support; import com.github.dreamhead.moco.HttpRequest;import com.github.dreamhead.moco.HttpRequestExtractor;import com.github.dreamhead.moco.RequestExtractor;import com.google.common.base.Optional;import net.sf.json.JSONObject; import static com.github.dreamhead.moco.util.Preconditions.checkNotNullOrEmpty;import static com.google.common.base.Optional.fromNullable; /** json数据格式参数值的获取*/@SuppressWarnings("all")public class JsonExtractor extends HttpRequestExtractor<String[]> { private final String param;public JsonExtractor(final String param) { this.param = param;}@Overrideprotected Optional<String[]> doExtract(HttpRequest request) { try { String s = request.getContent().toString(); String value = JSONObject.fromObject(s).getString(param); return fromNullable(new String[]{value}); } catch (Exception e) { return fromNullable(new String[]{""}); }}/** * 获取参数的value * * @param param * @return */public static RequestExtractor<String[]> queryJson(final String param) { return new JsonExtractor(checkNotNullOrEmpty(param, "参数不能为空!"));}}··· ...

July 16, 2019 · 1 min · jiezi

groovy使用stream语法递归筛选法求N以内的质数素数附冒泡排序和插入排序练习

本人最近读完一本书《质数的孤独》,里面讲到孪生质数,就想查一下孪生质数的分布情况。其中主要用到了计算质数(素数)的方法,搜了一下,排名前几的都是用for循环来做的,感觉略微麻烦了一些,在比较一些还是觉得用递归筛选法来解决这个问题。 新建List<Integer>,然后从第0位开始,如果后面的能被这个数整除,则从数组中移除改元素,以此类推,最后留下的就是质数(素数)。代码如下: static void get(List<Integer> list, int tt) { int num = list.get(tt); for (int i = tt + 1; i < list.size(); i++) { if (list.get(i) % num == 0) list.remove(i--); } if (list.size() > ++tt) get(list, tt); }然后再去做相邻元素差求得孪生质数(孪生素数),贴一下求10000以内孪生质数(孪生素数)全部的代码: List<Integer> list = new ArrayList<>(); for (int i = 2; i < 10000; i+=2) { list.add(i); } get(list, 0); for (int i = 0; i < list.size() - 1; i++) { Integer integer = list.get(i); Integer integer1 = list.get(i + 1); if (integer1 - integer == 2) outputData(TEST_ERROR_CODE, "孪生质数:", integer + TAB + TAB + integer1); }最后附上一份冒泡排序和插入排序的练习代码: ...

July 15, 2019 · 1 min · jiezi

一个时间计数器timewatch辅助性能测试

在做性能测试的时候,经常需要去记录一些方法的执行时间,这期间用到了stopwatch的类,但是有些功能自定义起来不太好,比如自定义标记的名称一类,而且split方法也有点不顺手,所以产生了自己写一个简单的时间计数器。 语言使用groovy写的,java框架可以使用。 v1.0已经完成,目前只有一些简单的功能,下一步打算弄一下多线程使用兼容问题。 package com.fun.utilsimport com.fun.frame.SourceCodeimport org.slf4j.LoggerFactoryimport java.text.DecimalFormat/** * 时间观察者类,用于简单记录执行时间 */class TimeWatch extends SourceCode { static def logger = LoggerFactory.getLogger(TimeWatch.class)/** * 默认的名称 */ def name = "default"/** * 纳秒 */ def startTime /** * 标记集合 */ def marks = new HashMap<String, Mark>() /** * 毫秒 */ def startTimeMillis/** * 无参创建方法,默认名称 * @return */ public static TimeWatch create() { final TimeWatch timeWatch = new TimeWatch() timeWatch.start() return timeWatch }/** * 创建方法 * @param name * @return */ public static TimeWatch create(def name) { final TimeWatch timeWatch = new TimeWatch() timeWatch.start() return timeWatch } private TimeWatch() { }/** * 开始记录 * @return */ def start() { reset() }/** * 重置 */ def reset() { startTime = getNanoMark() startTimeMillis = Time.getTimeStamp() }/** * 标记 * @param name * @return */ def mark(def name) { marks.put(name, new Mark(name)) }/** * 标记 * @return */ def mark() { marks.put(name, new Mark(name)) }/** * 获取标记时间 * @return */ def getMarkTime() { if (marks.containsKey(name)) { def diff = Time.getTimeStamp() - marks.get(name).getStartTimeMillis() logger.info(LINE + "观察者:{}的标记:{}记录时间:{} ms", name, name, diff) } else { logger.warn("没有默认标记!") } }/** * 获取标记时间 * @return */ def getMarkNanoTime() { if (marks.containsKey(name)) { def diff = getNanoMark() - marks.get(name).getStartTime() logger.info(LINE + "观察者:{}的标记:{}记录时间:{} ns", name, name, diff) } else { logger.warn("没有默认标记!") } }/** * 获取某个标记的记录时间 * @param name * @return */ def getMarkTime(String name) { if (marks.containsKey(name)) { def diff = Time.getTimeStamp() - marks.get(name).getStartTimeMillis() logger.info(LINE + "观察者:{}的标记:{}记录时间:{} ms", name, name, diff) } else { logger.warn("没有{}标记!", name) } }/** * 获取某个标记的记录时间 * @param name * @return */ def getMarkNanoTime(String name) { if (marks.containsKey(name)) { def diff = getNanoMark() - marks.get(name).getStartTime() logger.info(LINE + "观察者:{}的标记:{}记录时间:{} ns", name, name, diff) } else { logger.warn("没有{}标记!", name) } }/** * 获取记录时间 * @return */ def getTime() { def diff = Time.getTimeStamp() - startTimeMillis logger.info(LINE + "观察者:{},记录时间:{} ms", getName(), diff) return diff }/** * 获取记录时间纳秒 * @return */ def getNanoTime() { long diff = getNanoMark() - startTime DecimalFormat format = new DecimalFormat("#,###") logger.info(LINE + "观察者:{},记录时间:{} ns", getName(), format.format(diff)) return diff } @Override public String toString() { return "时间观察者:" + this.name } @Override public TimeWatch clone() { def watch = new TimeWatch() watch.name = getName() + "_c" watch.startTime = getStartTime() watch.startTimeMillis = getStartTimeMillis() return watch }/** * 标记类 */ class Mark { public Mark(def name) { this.name = name reset() } def name def startTime def startTimeMillis def lastTime def l def reset() { this.startTime = getNanoMark() this.startTimeMillis = Time.getTimeStamp() } }}groovy是一种基于JVM的动态语言,我觉得最大的优势有两点,第一:于java兼容性非常好,大部分时候吧groovy的文件后缀改成java直接可以用,反之亦然。java的绝大部分库,groovy都是可以直接拿来就用的。这还带来了另外一个有点,学习成本低,非常低,直接上手没问题,可以慢慢学习groovy不同于Java的语法;第二:编译器支持变得更好,现在用的intellij的ide,总体来说已经比较好的支持groovy语言了,写起代码来也是比较顺滑了,各种基于groovy的框架工具也比较溜,特别是Gradle构建工具,比Maven爽很多。----此段文字为了撑字数强加的,与内容无关。欢迎有兴趣的童鞋一起交流 ...

July 14, 2019 · 2 min · jiezi

Grails32新增了一些新东西

记录一下一些坑Grails3.2-版可以直接在domain中注入service,在Grails3.2+中默认关闭了自动注入功能开启方式方式一在application.groovy中配置全局映射,若没有此脚本需新建grails.gorm.default.mapping = { autowire true}方式二在需要注入bean的domain中添加映射static mapping = { autowire true}方式三在application.yml中新增或修改配置---grails: gorm: autowire: true参考

June 12, 2019 · 1 min · jiezi