这一节虽然简单,但是很繁琐,可以先了解 @RequestMapping 的使用,不是很明白也没有关系,先继续往下学习,等你回头再看一遍的时候,你会发现 @RequestMapping 竟然是如此的简单! @RequestMapping可以在控制器类上或者控制器方法上使用。 在类的级别上的注解会将一个特定请求或者请求模式映射到一个控制器之上。之后你还可以另外添加方法级别的注解来进一步指定到处理方法的映射关系。 基础用法: 下面的 @RequestMapping("/index") 等同于 @RequestMapping(value = "/index")
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.pudding.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("/index") public class HelloWorldController { @RequestMapping(value = "/hello", method = RequestMethod.GET) public String hello() { return "/WEB-INF/views/success.jsp"; } @RequestMapping(value = "/world", method = RequestMethod.POST) public String world() { return "/WEB-INF/views/success.jsp"; } } |
method 参数支持:GET, PUT, POST, DELETE 以及 PATCH。使用 method 可以限制接受的请求类型。 hello() 方法将只接受请求方式为 GET 方式,请求地址为:/index/hello 的请求。 world() 方法将只接受请求方式为 POST 方式,请求地址为:/index/world 的请求。 @GetMapping("/hello") 等同于 @RequestMapping(value="/hello", method=RequestMethod.GET) @PostMapping("/world") 等同于 @RequestMapping(value="/world", method=RequestMethod.POST) 映射多个地址: @RequestMapping 还可以将多个请求映射到一个方法上,只需要给 value 来指定一个包含多个路径的列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.pudding.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/index") public class HelloWorldController { @RequestMapping(value = {"/hello", "/world", "/helloworld"}) public String hello() { return "/WEB-INF/views/success.jsp"; } } |
URI模板: URI模板可以为快速访问 @RequestMapping 中指定的URL的一个特定的部分提供很大的便利。 使用 @PathVariable 可以获取到 {name} 的值,并在控制台进行输出。比如请求地址为:http://localhost:8080/SpringMVC/hello/jack 那么控制台上将会把 jack 进行输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.pudding.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorldController { @RequestMapping("/hello/{name}") public String hello(@PathVariable String name) { System.out.println(name); return "/WEB-INF/views/success.jsp"; } } |
如果路径中的URI变量和方法中的参数名不一样的话,那么需要在 @PathVariable 中显示的绑定参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.pudding.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorldController { @RequestMapping("/hello/{name}") public String hello(@PathVariable("name") String username) { System.out.println(username); return "/WEB-INF/views/success.jsp"; } } |
一个方法可以拥有任意数量的 @PathVariable 注解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.pudding.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorldController { @RequestMapping("/hello/{name}/age/{age}") public String hello(@PathVariable String name, @PathVariable int age) { System.out.println("name:" + name + ",age:" + age); return "/WEB-INF/views/success.jsp"; } } |
@PathVariable 可以被应用于所有 简单类型 的参数上,比如 int、long、Date 等类型。Spring会自动地帮你把参数转化成合适的类型,如果转换失败,就抛出一个 TypeMismatchException。如果你需要处理其他数据类型的转换,也可以注册自己的类。 带正则表达式的URI模板: 你可以使用正则表达式来准确的描述可以接受的请求路径:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.pudding.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorldController { @RequestMapping("/hello/{name:[a-z]+}/age/{age}") public String hello(@PathVariable String name, @PathVariable int age) { System.out.println("name:" + name + ",age:" + age); return "/WEB-INF/views/success.jsp"; } } |
Ant风格的路径模式: 除了URI模板外,@RequestMapping注解还支持Ant风格的路径模式(如/hello/*.do等)。不仅如此,还可以把URI模板变量和Ant风格的glob组合起来使用(比如/hello/*/user/{userId}这样的用法等)。其中*则表示任意字符串。但是遇到 / 那么就会认为是下一部分的URI,所以 * 中不能有 / 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.pudding.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorldController { // 匹配的地址:http://localhost:8080/SpringMVC/hello/jack/user/18 @RequestMapping("/hello/*/user/{userId}") public String hello(@PathVariable String userId) { System.out.println(userId); return "/WEB-INF/views/success.jsp"; } } |
那么想要匹配带 / 的路径那该怎么办?可以使用 ** 来进行匹配。例如 /hello/**/user/{userId} 则会匹配 /hello/ 和 /user/{userId} 之间的部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.pudding.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorldController { // 匹配的地址:http://localhost:8080/SpringMVC/hello/jack/tom/cat/user/18 @RequestMapping("/hello/**/user/{userId}") public String hello(@PathVariable String userId) { System.out.println(userId); return "/WEB-INF/views/success.jsp"; } } |
路径样式的匹配(Path Pattern Comparison): 当一个URL同时匹配多个模板(pattern)时,我们将需要一个算法来决定其中最匹配的一个。 URI模板变量的数目和通配符数量的总和最少的那个路径模板更准确。举个例子,/hotels/{hotel}/*这个路径拥有一个URI变量和一个通配符,而/hotels/{hotel}/**这个路径则拥有一个URI变量和两个通配符,因此,我们认为前者是更准确的路径模板。 如果两个模板的URI模板数量和通配符数量总和一致,则路径更长的那个模板更准确。举个例子,/foo/bar*就被认为比/foo/*更准确,因为前者的路径更长。 如果两个模板的数量和长度均一致,则那个具有更少通配符的模板是更加准确的。比如,/hotels/{hotel}就比/hotels/*更精确。 […]
View DetailsIntelliJ IDEA 简称 IDEA,被业界公认为最好的 Java 集成开发工具,尤其在智能代码助手、代码自动提示、代码重构、代码版本管理(Git、SVN、Maven)、单元测试、代码分析等方面有着亮眼的发挥。IDEA 产于捷克,开发人员以严谨著称的东欧程序员为主。IDEA 分为社区版和付费版两个版本。 idea2021免费激活教程: https://www.jb51.net/article/195962.htm https://www.jb51.net/article/196349.htm 下面开始今天的正文介绍: 很多文章介绍IntelliJ IDEA开启热部署功能都会写到在IntelliJ IDEA中的注册表中开启compiler.automake.allow.when.app.running选项,此选项在IntelliJ IDEA 2021.2之后的版本迁移到高级设置中。如下图所示: 如果你安装了中文语言包,那么它在这里 到此这篇关于解决IDEA2021版compiler.automake.allow.when.app.running不存在的问题的文章就介绍到这了,更多相关idea2021compiler.automake.allow.when.app.running不存在内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! from:https://www.jb51.net/article/223927.htm
View Details1.SLF4J(Simple logging Facade for Java) 意思为简单日志门面,它是把不同的日志系统的实现进行了具体的抽象化,只提供了统一的日志使用接口,使用时只需要按照其提供的接口方法进行调用即可,由于它只是一个接口,并不是一个具体的可以直接单独使用的日志框架,所以最终日志的格式、记录级别、输出方式等都要通过接口绑定的具体的日志系统来实现,这些具体的日志系统就有log4j,logback,java.util.logging等,它们才实现了具体的日志系统的功能。 如何使用SLF4J? 既然SLF4J只是一个接口,那么实际使用时必须要结合具体的日志系统来使用,我们首先来看SLF4J和各个具体的日志系统进行绑定时的框架原理图: 其实slf4j原理很简单,他只提供一个核心slf4j api(就是slf4j-api.jar包),这个包只有日志的接口,并没有实现,所以如果要使用就得再给它提供一个实现了些接口的日志包,比 如:log4j,common logging,jdk log日志实现包等,但是这些日志实现又不能通过接口直接调用,实现上他们根本就和slf4j-api不一致,因此slf4j又增加了一层来转换各日志实现包的使 用,当然slf4j-simple除外。其结构如下: slf4j-api(接口层) | 各日志实现包的连接层( slf4j-jdk14, slf4j-log4j) | 各日志实现包 所以,结合各日志实现包使用时提供的jar包情况为: SLF4J和logback结合使用时需要提供的jar:slf4j-api.jar,logback-classic.jar,logback-core.jar SLF4J和log4j结合使用时需要提供的jar:slf4j-api.jar,slf4j-log412.jar,log4j.jar SLF4J和JDK中java.util.logging结合使用时需要提供的jar:slf4j-api.jar,slf4j-jdk14.jar SLF4J和simple(SLF4J本身提供的一个接口的简单实现)结合使用时需要提供的jar:slf4j-api.jar,slf4j-simple.jar 当然还有其他的日志实现包,以上是经常会使用到的一些。 注意,以上slf4j和各日志实现包结合使用时最好只使用一种结合,不然的话会提示重复绑定日志,并且会导致日志无法输出。 slf4j-api.jar:对外提供统一的日志调用接口,该接口具体提供的调用方式和方法举例说明: public class Test { private static final Logger logger = LoggerFactory.getLogger(Tester.class); //通过LoggerFactory获取Logger实例 public static void main(String[] args) { //接口里的统一的调用方法,各具体的日志系统都有实现这些方法 logger.info("testlog: {}", "test"); logger.debug("testlog: {}", "test"); logger.error("testlog: {}", "test"); logger.trace("testlog: {}", "test"); logger.warn("testlog: {}", "test"); } } 如果系统中之前已经使用了log4j做日志输出,想使用slf4j作为统一的日志输出,该怎么办呢? 如果之前系统中是单独使用log4j做为日志输出的,这时再想使用slf4j做为日志输出时,如果系统中日志比较多,此时更改日志输出方法肯定是不太现实的,这个时候就可以使用log4j-over-slf4j.jar将使用log4j日志框架输出的日志路由到slf4j上来统一采用slf4j来输出日志。 为什么要使用SLF4J? slf4j是一个日志接口,自己没有具体实现日志系统,只提供了一组标准的调用api,这样将调用和具体的日志实现分离,使用slf4j后有利于根据自己实际的需求更换具体的日志系统,比如,之前使用的具体的日志系统为log4j,想更换为logback时,只需要删除log4j相关的jar,然后加入logback相关的jar和日志配置文件即可,而不需要改动具体的日志输出方法,试想如果没有采用这种方式,当你的系统中日志输出有成千上万条时,你要更换日志系统将是多么庞大的一项工程。如果你开发的是一个面向公众使用的组件或公共服务模块,那么一定要使用slf4的这种形式,这有利于别人在调用你的模块时保持和他系统中使用统一的日志输出。 slf4j日志输出时可以使用{}占位符,如,logger.info("testlog: {}", "test"),而如果只使用log4j做日志输出时,只能以logger.info("testlog:"+"test")这种形式,前者要比后者在性能上更好,后者采用+连接字符串时就是new 一个String 字符串,在性能上就不如前者。 2.log4j(log for java) Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。 如何使用? 引入jar,使用log4j时需要的jar为:log4j.jar。 定义配置文件log4j.properties或log4j.xml 在具体的类中进行使用: 在需要日志输出的类中加入:private static final Logger logger = Logger.getLogger(Tester.class); //通过Logger获取Logger实例 在需要输出日志的地方调用相应方法即可:logger.debug(“System […]
View Details摘要
想要把一个复杂的微服务项目部署到K8S上去,首先我们得学会把单个SpringBoot应用部署上去。今天我们来讲下如何把SpringBoot应用部署到K8S上去,和使用Docker Compose部署非常类似,希望对大家有所帮助!
学前准备
学习本文需要有一些K8S基础,对K8S还不了解的朋友可以参考如下的文章。
《K8S太火了!花10分钟玩转它不香么?》
《自从上了K8S,项目更新都不带停机的!》
java -Dfile.encoding=utf-8 -jar demo.jar 添加编码即可 from:https://www.cnblogs.com/provence666/p/10743551.html
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问题描述 在使用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