虽然现在已经进入了.NET FrameWork 4.0的时代,WebService也已经逐渐被淘汰,取而代之的是WCF。 但在工作中难免遇到需要兼容旧版本程序和按照以前的文档进行开发。 一般一个已经实现功能的WebService会发布自己的WSDL文件,供客户端调用生成代理类。 但有时是先有server与client交互的接口定义(WSDL)文件,然后由server和client端分别写程序,一个提供web服务,一个使用web服务。 最近,我也遇到了这个问题。由于业务方仅提供了WSDL文件并确定了其规范,需要我们开发服务端供调用。 1、使用VS2010提供的工具wsdl.exe由WSDL文件生成cs文件 使用wsdl.exe的/serverInterface选项(或缩写的 /si)指定输入的wsdl文件(注意,如果要转换的wsdl文件中import了其他wsdl文件,则所有文件都应列出,包括使用到的xsd文件也应列出)。输出将是 一个代码文件(默认是C#的,如果需要别的语言,参考MSDN中wsdl.exe的使用说明),其中包含每个 wsdl 绑定的接口。 示例:假设有ServerInterfaceSample.wsdl wsdl.exe /si ServerInterfaceSample.wsdl 如果使用Service.xsd作为schema文件,则改为 wsdl.exe /si ServerInterfaceSample.wsdl Service.xsd 生成代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
//------------------------------------------------------------------------------ // <auto-generated> // 此代码由工具生成。 // 运行时版本:4.0.30319.239 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // </auto-generated> //------------------------------------------------------------------------------ using System; using System.ComponentModel; using System.Diagnostics; using System.Web.Services; using System.Web.Services.Protocols; using System.Xml.Serialization; // // 此源代码由 wsdl 自动生成, Version=4.0.30319.1。 // /// <remarks/> [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.1")] [System.Web.Services.WebServiceBindingAttribute(Name="WebServiceSoap", Namespace="http://tempuri.org/")] public interface IWebServiceSoap { /// <remarks/> [System.Web.Services.WebMethodAttribute()] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/sendSMS", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] long sendSMS(InfoHeader header, string sessionId, string sender, string smsContent, string receiverList, string productCode, string pseudoFlag); } |
2、使用以上生成的文件进行修改,实现你的WebService方法即可. from:https://www.cnblogs.com/anbylau2130/p/3481804.html 2、使用以上生成的文件进行修改,实现你的WebService方法即可.
View DetailsKaptcha 简介 Kaptcha 是一个可高度配置的实用验证码生成工具,可自由配置的选项如: 验证码的字体 验证码字体的大小 验证码字体的字体颜色 验证码内容的范围(数字,字母,中文汉字!) 验证码图片的大小,边框,边框粗细,边框颜色 验证码的干扰线 验证码的样式(鱼眼样式、3D、普通模糊、…) Kaptcha 详细配置表 kaptcha.border 图片边框,合法值:yes , no yes kaptcha.border.color 边框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue. black kaptcha.image.width 图片宽 200 kaptcha.image.height 图片高 50 kaptcha.producer.impl 图片实现类 com.google.code.kaptcha.impl.DefaultKaptcha kaptcha.textproducer.impl 文本实现类 com.google.code.kaptcha.text.impl.DefaultTextCreator kaptcha.textproducer.char.string 文本集合,验证码值从此集合中获取 abcde2345678gfynmnpwx kaptcha.textproducer.char.length 验证码长度 5 kaptcha.textproducer.font.names 字体 Arial, Courier kaptcha.textproducer.font.size 字体大小 40px. kaptcha.textproducer.font.color 字体颜色,合法值: r,g,b 或者 white,black,blue. black kaptcha.textproducer.char.space 文字间隔 2 kaptcha.noise.impl 干扰实现类 com.google.code.kaptcha.impl.DefaultNoise kaptcha.noise.color 干扰 颜色,合法值: r,g,b 或者 white,black,blue. black kaptcha.obscurificator.impl 图片样式:<br />水纹 com.google.code.kaptcha.impl.WaterRipple <br /> 鱼眼 com.google.code.kaptcha.impl.FishEyeGimpy <br /> 阴影 com.google.code.kaptcha.impl.ShadowGimpy com.google.code.kaptcha.impl.WaterRipple kaptcha.background.impl 背景实现类 com.google.code.kaptcha.impl.DefaultBackground kaptcha.background.clear.from […]
View Details
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/// <summary> /// 替换SQL注入的危险字符 /// </summary> /// <param name="param"></param> /// <returns></returns> public static string ReplaceInjectString(string param) { if (string.IsNullOrEmpty(param)) return string.Empty; var result = new StringBuilder(param); return result .Replace("'", "'") .Replace(",", ",") .Replace(";", ";") .Replace("(", "(") .Replace("=", "=") .Replace("*", "*") .Replace("&", "&") .ToString(); } |
View Details
问题描述 在使用SpringBoot 热部署插件 devtools ,同时启动多个Application时,控制台会报这个警告: 问题分析 经查询,发现DevToolsProperties中配置了一个端口,默认是35729。
1 2 3 4 5 6 7 8 9 10 |
public static class Livereload { private boolean enabled = true; private int port = 35729; ... } |
原因:多个端口冲突了,导致热部署插件不生效。 解决方案 在application.properties文件中加上以下配置
1 2 3 4 |
#指定端口,具体视自己情况而定,只要不重复就可以 spring.devtools.livereload.port=35730 |
参考文章 https://blog.csdn.net/xudc0521/article/details/85560221 https://blog.csdn.net/weixin_43852529/article/details/90369869 from:https://www.freesion.com/article/3170268716/
View Detailsdocker部署springboot(默认已经安装好docker) 第一步:构建镜像 创建Dockerfile文件,文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 |
FROM frolvlad/alpine-oraclejdk8:slim VOLUME /tmp ADD index-1.5.10.RELEASE.jar app.jar RUN sh -c 'touch /app.jar' ENV JAVA_OPTS="" ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] |
其中 index-1.5.10.RELEASE.jar是你要发布的jar包。 然后把Dockerfile和index-1.5.10.RELEASE.jar建个文件夹,放到服务器上面。 cd进入你的文件夹,运行以下命令向docker中添加镜像:
1 |
docker build -t jingxiangming . |
执行命令后,你的docker中就添加了名为jingxiangming的镜像。 查看镜像命令:
1 |
docker images //运行命令后,你就可以看到刚刚添加的镜像了 |
第二步:启动容器
1 |
docker run -d -p 8080:8080 jingxiangming |
关于上面的命令,我认为有必要具体讲解一下: -d: 后台运行容器,并返回容器ID; -p: 端口映射,格式为:主机(宿主)端口:容器端口;//意思是第一个访问服务器的端口,第二个8080是服务器本地占用访问的端口 jingxiangming:docker里面的镜像名称 当然除了上面基本的参数外,还有额外的参数,这个就需要大家自己去查阅资料了,我这里只列举比较重要的。 启动成功后,会返回一个容器id,然后就可以测试访问了! 日志查看 查看运行的容器日志:
1 |
sudo docker logs -f -t --tail 行数 容器名 |
1 2 |
//查看容器名 docker ps |
from:https://blog.csdn.net/qq_29611427/article/details/81534037
View Details本文小秋熊介绍在Linux中使用命令启动SpringBoot生成的jar包,并且查看日志的方法。 1.首先将SpringBoot项目打包成JAR包,通过xFTP或者其他工具将JAR包上传到Linux上,然后执行如下命令启动项目: java -jar xxx.jar 该命令启动jar,一旦Xshell窗口关闭,JAR就停止运行了. 如果想让项目在后台一直运行,通过如下命令启动JAR: nohup java -jar xxx.jar > consoleMsg.log 2>&1 & 上面的2 和 1 的意思如下: 0 标准输入(一般是键盘) 1 标准输出(一般是显示屏,是用户终端控制台) 2 标准错误(错误信息输出) 注意:consoleMsg.log文件要先创建,执行命令: touch consoleMsg.log 查看项目运行日志: 1、tailf consoleMsg.log | grep --line-buffered findUserList 实时跟踪日志,这里是只要findUserList 这个方法被运行,就会将它的日志打印出来,用于跟踪特定的日志运行。 --line-buffered 是一行的缓冲区,只要这一行的缓冲区满了就会打印出来,所以可以用于实时监控日志。 2、 tailf -n 500 consoleMsg.log 打印最后500行日志,并且持续跟踪日志。 tail -n 2000 consoleMsg.log | less 分页查看最后2000行日志,并可以使用pageUp,pageDn滚动 3、tail -f consoleMsg.log (常用)直接查看日志末尾,有新日志会实时滚动更新。ctrl + c 退出 其它举例: (1)nohup java -jar xxx.jar >/data/log.log 2>/data/err.log & 解释:标准日志输出到/data/log.log文件,错误日志输出到/data/err.log文件。 (2)nohup java -jar xxx.jar >/data/log.log 2>&1 & 解释:标准日志输出到/data/log.log文件,错误日志重定向也输出到/data/log.log文件。 (3)nohup java -jar xxx.jar >/dev/null 2>/data/err.log & 解释:标准日志输出到/dev/null,也就是不输出标准日志,错误日志输出到/data/err.log文件。 一般采用上面(3)只输出错误日志就可以了,有需要的按照(1)、(2)进行输出。 命令后面加的 & ,可让命令在后台执行,否则关闭会话会停止程序。 […]
View DetailsJava NIO中的Files类(java.nio.file.Files)提供了多种操作文件系统中文件的方法。 Files.exists() Files.exits()方法用来检查给定的Path在文件系统中是否存在。 在文件系统中创建一个原本不存在的Payh是可行的。例如,你想新建一个目录,那么闲创建对应的Path实例,然后创建目录。 由于Path实例可能指向文件系统中的不存在的路径,所以需要用Files.exists()来确认。 下面是一个使用Files.exists()的示例:
1 2 3 4 5 |
Path path = Paths.get("data/logging.properties"); boolean pathExists = Files.exists(path, new LinkOption[]{ LinkOption.NOFOLLOW_LINKS}); |
这个示例中,我们首先创建了一个Path对象,然后利用Files.exists()来检查这个路径是否真实存在。 注意Files.exists()的的第二个参数。他是一个数组,这个参数直接影响到Files.exists()如何确定一个路径是否存在。在本例中,这个数组内包含了LinkOptions.NOFOLLOW_LINKS,表示检测时不包含符号链接文件。 Files.createDirectory() Files.createDirectory()会创建Path表示的路径,下面是一个示例:
1 2 3 4 5 6 7 8 9 10 |
Path path = Paths.get("data/subdir"); try { Path newDir = Files.createDirectory(path); } catch(FileAlreadyExistsException e){ // the directory already exists. } catch (IOException e) { //something else went wrong e.printStackTrace(); } |
第一行创建了一个Path实例,表示需要创建的目录。接着用try-catch把Files.createDirectory()的调用捕获住。如果创建成功,那么返回值就是新创建的路径。 如果目录已经存在了,那么会抛出java.nio.file.FileAlreadyExistException异常。如果出现其他问题,会抛出一个IOException。比如说,要创建的目录的父目录不存在,那么就会抛出IOException。父目录指的是你要创建的目录所在的位置。也就是新创建的目录的上一级父目录。 Files.copy() Files.copy()方法可以吧一个文件从一个地址复制到另一个位置。例如:
1 2 3 4 5 6 7 8 9 10 11 |
Path sourcePath = Paths.get("data/logging.properties"); Path destinationPath = Paths.get("data/logging-copy.properties"); try { Files.copy(sourcePath, destinationPath); } catch(FileAlreadyExistsException e) { //destination file already exists } catch (IOException e) { //something else went wrong e.printStackTrace(); } |
这个例子当中,首先创建了原文件和目标文件的Path实例。然后把它们作为参数,传递给Files.copy(),接着就会进行文件拷贝。 如果目标文件已经存在,就会抛出java.nio.file.FileAlreadyExistsException异常。类似的吐过中间出错了,也会抛出IOException。 覆盖已经存在的文件(Overwriting Existing Files) copy操作可以强制覆盖已经存在的目标文件。下面是具体的示例:
1 2 3 4 5 6 7 8 9 10 11 12 |
Path sourcePath = Paths.get("data/logging.properties"); Path destinationPath = Paths.get("data/logging-copy.properties"); try { Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); } catch(FileAlreadyExistsException e) { //destination file already exists } catch (IOException e) { //something else went wrong e.printStackTrace(); } |
注意copy方法的第三个参数,这个参数决定了是否可以覆盖文件。 Files.move() Java NIO的Files类也包含了移动的文件的接口。移动文件和重命名是一样的,但是还会改变文件的目录位置。java.io.File类中的renameTo()方法与之功能是一样的。
1 2 3 4 5 6 7 8 9 10 |
Path sourcePath = Paths.get("data/logging-copy.properties"); Path destinationPath = Paths.get("data/subdir/logging-moved.properties"); try { Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { //moving file failed. e.printStackTrace(); } |
首先创建源路径和目标路径的,原路径指的是需要移动的文件的初始路径,目标路径是指需要移动到的位置。 这里move的第三个参数也允许我们覆盖已有的文件。 Files.delete() Files.delete()方法可以删除一个文件或目录:
1 2 3 4 5 6 7 8 |
Path path = Paths.get("data/subdir/logging-moved.properties"); try { Files.delete(path); } catch (IOException e) { //deleting file failed e.printStackTrace(); } |
首先创建需要删除的文件的path对象。接着就可以调用delete了。 Files.walkFileTree() Files.walkFileTree()方法具有递归遍历目录的功能。walkFileTree接受一个Path和FileVisitor作为参数。Path对象是需要遍历的目录,FileVistor则会在每次遍历中被调用。 下面先来看一下FileVisitor这个接口的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public interface FileVisitor { public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attrs) throws IOException; public FileVisitResult visitFile( Path file, BasicFileAttributes attrs) throws IOException; public FileVisitResult visitFileFailed( Path file, IOException exc) throws IOException; public FileVisitResult postVisitDirectory( Path dir, IOException exc) throws IOException { } |
FileVisitor需要调用方自行实现,然后作为参数传入walkFileTree().FileVisitor的每个方法会在遍历过程中被调用多次。如果不需要处理每个方法,那么可以继承他的默认实现类SimpleFileVisitor,它将所有的接口做了空实现。 下面看一个walkFileTree()的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Files.walkFileTree(path, new FileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { System.out.println("pre visit dir:" + dir); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { System.out.println("visit file: " + file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { System.out.println("visit file failed: " + file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { System.out.println("post visit directory: " + dir); return FileVisitResult.CONTINUE; } }); |
FileVisitor的方法会在不同时机被调用: preVisitDirectory()在访问目录前被调用。postVisitDirectory()在访问后调用。 visitFile()会在整个遍历过程中的每次访问文件都被调用。他不是针对目录的,而是针对文件的。visitFileFailed()调用则是在文件访问失败的时候。例如,当缺少合适的权限或者其他错误。 上述四个方法都返回一个FileVisitResult枚举对象。具体的可选枚举项包括: CONTINUE TERMINATE SKIP_SIBLINGS SKIP_SUBTREE 返回这个枚举值可以让调用方决定文件遍历是否需要继续。 CONTINE表示文件遍历和正常情况下一样继续。 TERMINATE表示文件访问需要终止。 SKIP_SIBLINGS表示文件访问继续,但是不需要访问其他同级文件或目录。 SKIP_SUBTREE表示继续访问,但是不需要访问该目录下的子目录。这个枚举值仅在preVisitDirectory()中返回才有效。如果在另外几个方法中返回,那么会被理解为CONTINE。 Searching For Files 下面看一个例子,我们通过walkFileTree()来寻找一个README.txt文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Path rootPath = Paths.get("data"); String fileToFind = File.separator + "README.txt"; try { Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { String fileString = file.toAbsolutePath().toString(); //System.out.println("pathString = " + fileString); if(fileString.endsWith(fileToFind)){ System.out.println("file found at path: " + file.toAbsolutePath()); return FileVisitResult.TERMINATE; } return FileVisitResult.CONTINUE; } }); } catch(IOException e){ e.printStackTrace(); } |
Deleting Directies Recursively Files.walkFileTree()也可以用来删除一个目录以及内部的所有文件和子目。Files.delete()只用用于删除一个空目录。我们通过遍历目录,然后在visitFile()接口中三次所有文件,最后在postVisitDirectory()内删除目录本身。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Path rootPath = Paths.get("data/to-delete"); try { Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { System.out.println("delete file: " + file.toString()); Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Files.delete(dir); System.out.println("delete dir: " + dir.toString()); return FileVisitResult.CONTINUE; } }); } catch(IOException e){ e.printStackTrace(); } |
from:https://www.cnblogs.com/liangblog/p/8920579.html
View Details原文链接 译者:章筱虎 Path接口是java NIO2的一部分。首次在java 7中引入。Path接口在java.nio.file包下,所以全称是java.nio.file.Path。 java中的Path表示文件系统的路径。可以指向文件或文件夹。也有相对路径和绝对路径之分。绝对路径表示从文件系统的根路径到文件或是文件夹的路径。相对路径表示从特定路径下访问指定文件或文件夹的路径。相对路径的概念可能有点迷糊。不用担心,我将在本文的后面详细介绍相关细节。 不要将文件系统的path和操作系统的环境变量path搞混淆。java.nio.file.Path接口和操作系统的path环境变量没有任何关系。 在很多方面,java.nio.file.Path接口和java.io.File有相似性,但也有一些细微的差别。在很多情况下,可以用Path来代替File类。 创建Path实例 为了使用java.nio.file.Path实例,必须首先创建它。可以使用Paths 类的静态方法Paths.get()来产生一个实例。以下是示例:
1 2 3 4 5 6 7 8 9 10 11 |
import java.nio.file.Path; import java.nio.file.Paths; public class PathExample { public static void main(String[] args) { Path path = Paths.get("c:\\data\\myfile.txt"); } } |
请注意例子开头的两个import语句。想要使用Paths类和Path接口,必须首先引入相应包。其次,注意Paths.get(“c:\\data\\myfile.txt”)的用法。其使用了Paths.get方法创建了Path的实例。它是一个工厂方法。 创建绝对路径Path 调用传入绝对路径当做参数的Paths.get()工厂方法,就可以生成绝对路径Path。示例如下:
1 |
Path path = Paths.get("c:\\data\\myfile.txt"); |
示例中的绝对路径是c:\data\myfile.txt。有两个\字符的原因是第一个\是转义字符,表示紧跟着它的字符需要被转义。\\表示需要向字符串中写入一个\字符。 上文示例的path是windows下的路径。在Unix系统(Linux,MacOS,FreeBSD等)中,上文中的path是这样的:
1 |
Path path = Paths.get("/home/jakobjenkov/myfile.txt"); |
/home/jakobjenkov/myfile.txt就称作绝对路径。 如果把以/开头path的格式运行在windows系统中,系统会将其解析为相对路径。例如:
1 |
/home/jakobjenkov/myfile.txt |
将会被解析为路径是在C盘。对应的绝对路径是: C:/home/jakobjenkov/myfile.txt 创建相对路径Path 相对路径指从一个已确定的路径开始到某一文件或文件夹的路径。将确定路径和相对路径拼接起来就是相对路径对应的绝对路径地址。 java NIO Path类也能使用相对路径。可以通过Paths.get(basePath, relativePath)创建一个相对路径Path。示例如下:
1 2 3 |
Path projects = Paths.get("d:\\data", "projects"); Path file = Paths.get("d:\\data", "projects\\a-project\\myfile.txt"); |
第一个例子创建了一个指向d:\data\projects文件夹的实例。第二个例子创建了一个指向 d:\data\projects\a-project\myfile.txt 文件的实例。 当使用相对路径的时候,可以使用如下两种特别的符号。它们是: . .. .表示当前路径。例如,如果以如下方式创建一个相对路径:
1 2 |
Path currentDir = Paths.get("."); System.out.println(currentDir.toAbsolutePath()); |
创建的Path实例对应的路径就是运行这段代码的项目工程目录。 如果.用在路径中,则其表示的就是当前路径下。示例: Path currentDir = Paths.get(“d:\\data\\projects\.\a-project”); 对应的就是如下路径 d:\data\projects\a-project ..表示父类目录。示例: Path parentDir = Paths.get(“..”); Path对应的路径是当前运行程序目录的上级目录。 如果在path中使用..,表示上级目录的含义。例如:
1 2 |
String path = "d:\\data\\projects\\a-project\\..\\another-project"; Path parentDir2 = Paths.get(path); |
对应的绝对路径地址为: d:\data\projects\another-project 在a-project目录后面的..符号,将指向的目录修改为projects目录,因此,最终path指向another-project目录。 .和..都可以在Paths.get()的双形参方法中使用。示例:
1 2 3 4 |
Path path1 = Paths.get("d:\\data\\projects", ".\\a-project"); Path path2 = Paths.get("d:\\data\\projects\\a-project", "..\\another-project"); |
下面介绍NIO 的Path类有关相对路径的其他使用方法。 Path.normalize() Path 的normalize()方法可以标准化路径。标准化的含义是路径中的.和..都被去掉,指向真正的路径目录地址。下面是Path.normalize()示例:
1 2 3 4 5 6 7 8 |
String originalPath = "d:\\data\\projects\\a-project\\..\\another-project"; Path path1 = Paths.get(originalPath); System.out.println("path1 = " + path1); Path path2 = path1.normalize(); System.out.println("path2 = " + path2); |
上文示例,首先创建了一个包含..字符的路径地址。之后输出此路径。 之后,调用normalize方法,返回一个新的path对象。输出新对象的路径。 输出结果如下:
1 2 |
path1 = d:\data\projects\a-project\..\another-project path2 = d:\data\projects\another-project |
如你所见,标准化后的路径不再包含 a-project\..部分,因为它是多余的。 from:https://ifeve.com/java-nio-path-2/
View Details一、环境搭建 安装好JDK环境 到groovy官网下载groovySDK,解压到合适位置 groovy官网:http://www.groovy-lang.org/ 安装后的文件如上图所示,我们需要关注的是bin和doc文件夹下的内容,其它文件夹下是一些配置和groovy自带的一些jar包 配置groovy环境变量 二、与Java的不同之处 1、默认 imports 所有这些包和类都是默认导入的,您不必使用显式import语句来使用它们:
1 2 3 4 5 6 7 8 |
java.io.* java.lang.* java.math.BigDecimal java.math.BigInteger java.net.* java.util.* groovy.lang.* groovy.util.* |
2、运行时分派 在Groovy中,将在运行时选择将被调用的方法。 这称为运行时分派或Multi-methods。 这意味着将基于运行时参数的类型来选择方法。 在Java中,则是根据声明的类型,在编译时选择方法。 下面的代码,以Java代码编写,可以在Java和Groovy中编译,但它的行为会有所不同:
1 2 3 4 5 6 7 8 |
int method(String arg) { return 1; } int method(Object arg) { return 2; } Object o = "Object"; int result = method(o); |
在Java中, 您将得到:2 而在Groovy中:1 这是因为Java将使用静态信息类型,即o被声明为Object,而Groovy将在运行时选择该方法被实际调用时。 因为它是用String调用的,所以调用String版本。 3、数组初始化 在Groovy中,{…}块是为闭包而保留的。 这意味着您不能使用以下语法创建数组:
1 |
int [] array = {1,2,3} |
你必须使用:
1 |
int [] array = [1,2,3] |
4、自动资源管理块 Groovy不支持Java 7中的ARM(自动资源管理)块。 相反,Groovy提供了依赖闭包的各种方法,它们具有相同的效果,同时更加方便。 例如:
1 2 3 4 5 6 7 8 9 10 11 |
Path file = Paths.get("/path/to/file"); Charset charset = Charset.forName("UTF-8"); try (BufferedReader reader = Files.newBufferedReader(file, charset)) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } |
可以这样写:
1 2 3 |
new File('/path/to/file').eachLine('UTF-8') { println it } |
或者,如果你想要一个更接近Java的版本:
1 2 3 4 5 |
new File('/path/to/file').withReader('UTF-8') { reader -> reader.eachLine { println it } } |
5、Lambdas Java 8支持lambdas和方法引用:
1 2 |
Runnable run = () -> System.out.println("Run"); list.forEach(System.out::println); |
Java 8 lambdas可以或多或少被认为是匿名内部类。 Groovy不支持该语法,但是可以使用闭包:
1 2 |
Runnable run = { println 'run' } list.each { println it } // or list.each(this.&println) |
6、GStrings 由于双引号字符串字面量被解释为GString,Groovy将在GString和String之间自动转换 Groovy中的单引号用于String,双引号结果是String或GString,取决于文字中是否有插值。
1 2 3 |
assert 'c'.getClass()==String assert "c".getClass()==String assert "c${1}".getClass() in GString |
只有在赋给char类型的变量时,Groovy会自动将单字符String转换为char。 当调用类型为char的参数的方法时,我们需要显式转换或确保该值已预先转换。
1 2 3 4 5 6 7 8 9 |
char a='a' assert Character.digit(a, 16)==10 : 'But Groovy does boxing' assert Character.digit((char) 'a', 16)==10 try { assert Character.digit('a', 16)==10 assert false: 'Need explicit cast' } catch(MissingMethodException e) { } |
Groovy支持两种类型的转换,在转换为char的情况下,在转换multi-char 时存在微妙的差别。 Groovy风格的转换是更宽松的,将采取第一个字符,而C风格的转换将失败,异常。
1 2 3 4 5 6 7 8 9 10 11 12 |
// for single char strings, both are the same assert ((char) "c").class==Character assert ("c" as char).class==Character // for multi char strings they are not try { ((char) 'cx') == 'c' assert false: 'will fail - not castable' } catch(GroovyCastException e) { } assert ('cx' as char) == 'c' assert 'cx'.asType(char) == 'c' |
7、原始和封装 因为Groovy使用Objects来做每一件事,它对原始的引用自动包装。 因此,它不遵循Java的扩展优先于装箱。 这里有一个使用int的例子
1 2 3 4 5 6 7 8 9 10 11 12 |
int i m(i) //这是Java将调用的方法,因为扩展优先于装箱。 void m(long l) { println "in m(long)" } //这是Groovy实际调用的方法,因为所有的基本引用都使用它们的包装类。 void m(Integer i) { println "in m(Integer)" } |
8、==的行为 在Java中==表示对象的原始类型或标识的相等性。 在Groovy ==翻译为a.compareTo(b)== 0,如果他们是可比较的,否则a.equals(b)。 如果要检查身份,有is方法,例如a.is(b) 三、基础语法 1、动态类型 Groovy定义变量时:可以用Groovy风格的def声明,不指定类型;也可以兼容Java风格,指定变量类型;甚至还可以省略def或类型。
1 2 3 |
def t1 = 't1' String t2 = 't2' t3 = 't3' |
[…]
View Details
1 2 3 4 5 6 |
//使用File获取resources里面资源文件的相对路径 若文件名称为中文可能会报文件不存在 File file = new File(this.getClass().getResource("/province-city.josn").getPath()); //使用inputStream InputStream inputStream = this.getClass().getResourceAsStream("/province-city.json"); |
from:https://www.cnblogs.com/yang-xiansen/p/13529568.html
View Details