-
缓冲流概述 缓冲流介绍: 缓冲流也称为高效流、或者高级流。之前学习的字节流和字符流可以称为原始流。 作用:缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能 缓冲流分为: 字节缓存输入流、字节缓冲输出流、字符缓冲输入流、字符缓冲输出流 字节缓冲流 字节缓冲输入流:BufferedInputStream,提高字节输入流读取数据的性能,读写功能上与原始流相比并无变化。 字节缓冲输出流:BufferedOutputStream,提高字节输出流读取数据的性能,读写功能上与原始流相比并无变化。 字节缓冲流性能优化原理: 字节缓冲输入流自带了8KB缓冲池,以后我们直接从缓冲池读取数据,所以性能较好。 字节缓冲输出流自带了8KB缓冲池,数据就直接写入到缓冲池中去,写数据性能极高了。 将原始流包装为缓冲流的构造器如下: 构造器 说明 BufferedInputStream(InputStream is) 可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能 BufferedOutputStream(OutputStream os) 可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能 public static void main(String[] args) throws Exception { // 创建原始字节输入流 InputStream is = new FileInputStream("/Users/chenyq/Documents/test.txt"); // 创建原始字节输出流 OutputStream os = new FileOutputStream("/Users/chenyq/Documents/test1.txt"); // 将低级的字节输入流包装为高级的缓存输入流 InputStream bis = new BufferedInputStream(is); // 将低级的字节输出流包装为高级的缓存输出流 OutputStream bos = new BufferedOutputStream(os); } 读写功能和之前原始流的读写并无区别: public static void main(String[] args) { try ( // 创建原始字节输入流 InputStream is = new FileInputStream("/Users/chenyq/Documents/test.txt"); // 创建原始字节输出流 OutputStream os = new FileOutputStream("/Users/chenyq/Documents/test1.txt"); // 将低级的字节输入流包装为高级的缓存输入流 InputStream bis = new BufferedInputStream(is); // 将低级的字节输出流包装为高级的缓存输出流 OutputStream bos = new BufferedOutputStream(os); ) { // 文件拷贝: 读写操作 byte[] arr = new byte[1024]; int len; while ((len = bis.read(arr)) != -1) { bos.write(arr, 0, len); } } catch(Exception e) { e.printStackTrace(); } } 字符缓存流 字符缓存输入流 字符缓冲输入流:实现类BufferedReader。 作用:提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能。 字符缓存输入流构造器如下: 构造器 说明 BufferedReader(Reader r) 可以把低级的字符输入流包装成一个高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能 public static void main(String[] args) throws Exception { // 创建原始字符输入流 Reader r = new FileReader("/Users/chenyq/Documents/test.txt"); // 将原始字符输入流包装为字符缓存输入流 Reader br = new BufferedReader(r); } 字符原始输入流的方法字符缓存输入流同样适用: public static void main(String[] args) { try ( // 创建原始字符输入流 Reader r = new FileReader("/Users/chenyq/Documents/test.txt"); // 将原始字符输入流包装为字符缓存输入流 Reader br = new BufferedReader(r); ){ // 读取文件 char[] arr = new char[1024]; int len; while ((len = br.read(arr)) != -1) { String res = new String(arr, 0, len); System.out.println(res); } } catch (Exception e) { e.printStackTrace(); } } 字符缓存输入流在原有的方法上新增了方法: 方法 说明 readLine() 读取一行数据, 并返回该行内容的字符串,无行可读返回null 按行读取: 普通方法 public static void main(String[] args) { try ( Reader r = new FileReader("/Users/chenyq/Documents/test.txt"); BufferedReader br = new BufferedReader(r); ){ // 读取第一行 System.out.println(br.readLine()); } catch (Exception e) { e.printStackTrace(); } } 按行读取: 循环方法 public static void main(String[] args) { try ( Reader r = new FileReader("/Users/chenyq/Documents/test.txt"); BufferedReader br = new BufferedReader(r); ){ String res; while ((res = br.readLine()) != null) { System.out.println(res); } } catch (Exception e) { e.printStackTrace(); } } 字符缓存输出流: 字符缓冲输出流:实现类BufferedWriter。 作用:提高字符输出流写取数据的性能,除此之外多了换行功能 字符缓存输出流构造器如下: 构造器 说明 BufferedWriter(Writer w) 可以把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能 public static void main(String[] args) throws Exception { Writer w = new FileWriter("/Users/chenyq/Documents/test.txt"); // 将原始字符输出流包装为缓冲输出流 Writer bw = new BufferedWriter(w); } 字符缓存输出流新增功能: 当然原生输输出流的功能同样可以使用 方法 说明 newLine() 换行操作 public static void main(String[] args) { try ( Writer w = new FileWriter("/Users/chenyq/Documents/test.txt", true); BufferedWriter bw = new BufferedWriter(w); ){ // 定义一个字符数组 char[] arr = {'我', '爱', 'C', 'h', 'i', 'n', 'a'}; // 定义一个字符串 String str = "我爱学习Java"; // 写入一个字符 bw.write('我'); bw.write(98); // 换行 bw.newLine(); // 写入一个字符数组 bw.write(arr); // 换行 bw.newLine(); // 写入字符数组的一部分 bw.write(arr, 1, 3); // 换行 bw.newLine(); // 写入一个字符串 bw.write(str); // 换行 bw.newLine(); // 写入一个字符串的一部分 bw.write(str, 0, 4); // 换行 bw.newLine(); } catch (IOException e) { throw new RuntimeException(e); } } ———————————————— 版权声明:本文为CSDN博主「学全栈的灌汤包」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/m0_71485750/article/details/127601905
-
一、前言介绍: 随着社会的发展和科学技术的进步,互联网技术越来越受欢迎。网络传播的生活方式逐渐受到广大人民群众的喜爱。越来越多的互联网爱好者开始在互联网上满足他们的基本需求,同时逐渐进入各个用户的生活起居。互联网具有许多优点,例如便利性,速度,高效率和低成本。因此,类似于驾校管理,满足用户工作繁忙的需求,不仅是方便用户随时查看信息的途径,而且还能提高管理效率。本文首先以驾校管理过程的基本问题作为研究对象。在开发系统之前,我们对现有状况进行了详细的调查和分析。最后,我们利用计算机技术开发了一套完整合适的驾校管理。该系统的实现主要优势是:该系统主要采用计算机技术开发,它方便快捷;系统可以通过管理员界面查看系统所涉及的驾校管理所有信息管理。 驾校管理软件是一款方便、快捷、实用的信息服务查询软件。随着智能网络在全球市场的不断普及以及各种智能平台的使用,作为中国主流智能的技术开发系统,自然需要这样的软件来满足更多用户的需求和体验。系统的开发与人们的日常需求相关,如通过管理系统获取到个人中心、学员管理、驾校教练管理、预约教练管理、预约教练管理、评价教练管理、考试成绩管理、考试通知管理、报考信息管理、练车通知管理、预约练车管理、驾考套餐管理、报名信息管理、车辆信息管理等信息详细情况,了解最新资讯信息等。 二、主要技术: 2.1 Spring Boot框架介绍: Spring框架是Java平台上的一种开源应用框架,提供具有控制反转特性的容器。尽管Spring框架自身对编程模型没有限制,但其在Java应用中的频繁使用让它备受青睐,以至于后来让它作为EJB(EnterpriseJavaBeans)模型的补充,甚至是替补。Spring框架为开发提供了一系列的解决方案,比如利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等等。Spring框架具有控制反转(IOC)特性,IOC旨在方便项目维护和测试,它提供了一种通过Java的反射机制对Java对象进行统一的配置和管理的方法。Spring框架利用容器管理对象的生命周期,容器可以通过扫描XML文件或类上特定Java注解来配置对象,开发者可以通过依赖查找或依赖注入来获得对象。Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。Spring框架的AOP框架仅提供基本的AOP特性,虽无法与AspectJ框架相比,但通过与AspectJ的集成,也可以满足基本需求。Spring框架下的事务管理、远程访问等功能均可以通过使用SpringAOP技术实现。Spring的事务管理框架为Java平台带来了一种抽象机制,使本地和全局事务以及嵌套事务能够与保存点一起工作,并且几乎可以在Java平台的任何环境中工作。 2.2 MYSQL数据库: 数据库是系统开发过程中不可或缺的一部分。 在WEB应用方面,MySQL AB开发了一个具有很大优势的MySQL关系数据库管理系统。 MySQL可以将数据存储在不同的表中,这非常灵活,并且还可以提高系统在实际应用中的速度。 数据库访问最常用于标准SQL语言,MySQL用于SQL语言,因此它具有高度兼容性。数据库的操作是必不可少的,包括对数据库表的增加、删除、修改、查询等功能。现如今,数据库可以分为关系型数据库和非关系型数据库,Mysql属于关系性数据库,Mysql数据库是一款小型的关系型数据库,它以其自身特点:体积小、速度快、成本低等,Mysql数据库是目前最受欢迎的开源数据库。 在WEB应用技术中, Mysql数据库支持不同的操作系统平台,虽然在不同平台下的安装和配置都不相同,但是差别也不是很大,Mysql在Windows平台下两种安装方式,二进制版和免安装版。安装完Mysql数据库之后,需要启动服务进程,相应的客户端就可以连接数据库,客户端可通过命令行或者图形界面工具登录数据库。 三、系统设计: 3.1 系统架构设计: 3.2 登录时序图设计: 四、功能截图: 4.1 登录注册: 4.2 前端页面: 4.2.1 系统首页: 4.2.2 教练模块: 4.2.3 考试须知: 4.2.4 预约练车: 4.2.5 车辆信息: 4.2.6 系统公告信息: 4.2.7 个人中心模块: 4.2.8 用户后台模块: 4.3 后端管理: 4.3.1 教练管理: 4.3.2 考试通知: 4.3.3 报名管理: 4.3.4 车辆信息: 4.3.5 系统公告等 五、代码实现: /** * 登录相关 */ @RequestMapping("users") @RestController public class UserController{ @Autowired private UserService userService; @Autowired private TokenService tokenService; /** * 登录 */ @IgnoreAuth @PostMapping(value = "/login") public R login(String username, String password, String captcha, HttpServletRequest request) { UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username)); if(user==null || !user.getPassword().equals(password)) { return R.error("账号或密码不正确"); } String token = tokenService.generateToken(user.getId(),username, "users", user.getRole()); return R.ok().put("token", token); } /** * 注册 */ @IgnoreAuth @PostMapping(value = "/register") public R register(@RequestBody UserEntity user){ // ValidatorUtils.validateEntity(user); if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) { return R.error("用户已存在"); } userService.insert(user); return R.ok(); } /** * 退出 */ @GetMapping(value = "logout") public R logout(HttpServletRequest request) { request.getSession().invalidate(); return R.ok("退出成功"); } /** * 密码重置 */ @IgnoreAuth @RequestMapping(value = "/resetPass") public R resetPass(String username, HttpServletRequest request){ UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username)); if(user==null) { return R.error("账号不存在"); } user.setPassword("123456"); userService.update(user,null); return R.ok("密码已重置为:123456"); } /** * 列表 */ @RequestMapping("/page") public R page(@RequestParam Map<String, Object> params,UserEntity user){ EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>(); PageUtils page = userService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params)); return R.ok().put("data", page); } /** * 列表 */ @RequestMapping("/list") public R list( UserEntity user){ EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>(); ew.allEq(MPUtil.allEQMapPre( user, "user")); return R.ok().put("data", userService.selectListView(ew)); } /** * 信息 */ @RequestMapping("/info/{id}") public R info(@PathVariable("id") String id){ UserEntity user = userService.selectById(id); return R.ok().put("data", user); } /** * 获取用户的session用户信息 */ @RequestMapping("/session") public R getCurrUser(HttpServletRequest request){ Long id = (Long)request.getSession().getAttribute("userId"); UserEntity user = userService.selectById(id); return R.ok().put("data", user); } /** * 保存 */ @PostMapping("/save") public R save(@RequestBody UserEntity user){ // ValidatorUtils.validateEntity(user); if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) { return R.error("用户已存在"); } userService.insert(user); return R.ok(); } /** * 修改 */ @RequestMapping("/update") public R update(@RequestBody UserEntity user){ // ValidatorUtils.validateEntity(user); UserEntity u = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())); if(u!=null && u.getId()!=user.getId() && u.getUsername().equals(user.getUsername())) { return R.error("用户名已存在。"); } userService.updateById(user);//全部更新 return R.ok(); } /** * 删除 */ @RequestMapping("/delete") public R delete(@RequestBody Long[] ids){ userService.deleteBatchIds(Arrays.asList(ids)); return R.ok(); } } @Configuration public class InterceptorConfig extends WebMvcConfigurationSupport{ @Bean public AuthorizationInterceptor getAuthorizationInterceptor() { return new AuthorizationInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(getAuthorizationInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**"); super.addInterceptors(registry); } /** * springboot 2.0配置WebMvcConfigurationSupport之后,会导致默认配置被覆盖,要访问静态资源需要重写addResourceHandlers方法 */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**") .addResourceLocations("classpath:/resources/") .addResourceLocations("classpath:/static/") .addResourceLocations("classpath:/admin/") .addResourceLocations("classpath:/front/") .addResourceLocations("classpath:/public/"); registry.addResourceHandler("/upload/**").addResourceLocations("file:D:/work/"); super.addResourceHandlers(registry); } } ———————————————— 版权声明:本文为CSDN博主「java李杨勇」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_39709134/article/details/128781905
-
大佬们,这么多数据,按照我目前的方式很慢啊,有没有其他好的快速的方法 。
-
1 jetson 查看方法 官方新推出 jtop 工具,专门用来查看 jetson 的 CPU、GPU 等信息,使用方法也很简单 安装方法 sudo -H pip install jetson-stats 使用方法,直接在命令行输入 jtop 就会有显示输出 对于 Xavier NX 和 AGX 设备,还有 DLA 硬件可以调用,实现加速功能,但目前还没有一个比较好的方式来查看其占用情况,只能看到其是否被调用,如下 cat /sys/devices/platform/host1x/15880000.nvdla0/power/runtime_status #DLA0 cat /sys/devices/platform/host1x/158c0000.nvdla1/power/runtime_status #DLA1 如果想要持续观察,可以结合 watch 指令,比如 1s 输出一次 watch -n 1 "cat /sys/devices/platform/host1x/15880000.nvdla0/power/runtime_status" #DLA0 watch -n 1 "cat /sys/devices/platform/host1x/158c0000.nvdla1/power/runtime_status" #DLA1 -----------------------以下为旧版本内容,可以不再使用------------------- 内存 free -m 系统内核 uname -a CPU信息 lscpu USB设备 lsusb CPU占用情况 sudo apt-get install htop htop CPU 百分比中有不同的颜色,颜色含义如下 蓝色:显示低优先级进程使用的CPU的百分比。 绿色:显示普通用户拥有的进程使用的CPU的百分比。 红色:显示系统进程使用的CPU的百分比。 青色:显示Steal时间使用的CPU的百分比。 GPU 使用情况 sudo tegrastats 会输出如下所示的内容,注意一定要加sudo,否则输出的信息不完整 RAM 1920/7851MB (lfb 1131x4MB) cpu [9%@345,off,off,9%@345,13%@345,13%@345] EMC 6%@1600 APE 150 NVDEC 1164 GR3D 7%@114 具体含义为 RAM 就是内存占用 cpu 当然就是CPU占用率了,TX2一共6个核,显示每核的占用情况 EMC – external memory controller, 就是外存控制器 单位 bus%@MHz AVP – audio/video processor, TX2 自带的音频视频ASIC处理器 单位 processor%@MHz NVDEC – NVIDIA video decoder engine, TX2 带有视频编解码hevc的加速器 %MHz GR3D – GPU, processor, GPU的主频 %@MHz 2 dGPU 查看方法 对于dGPU 设备,如 2080,TITAN V,T4 等大卡,NVIDIA自带了一个nvidia-smi的命令行工具,会显示显存使用情况: $ nvidia-smi 显示结果如下 但是只能输出一次结果,我们在训练数据的时候,想实时观察 GPU 的利用情况,因此需要添加一个定时输出的功能。这时候就需要用到 watch 命令,来周期性地执行 nvidia-smi 命令了。 watch 的基本用法是: $ watch [options] command 最常用的参数是 -n, 后面指定是每多少秒来执行一次命令。 我们设置每 1s 显示 GPU 使用情况: $ watch -n 1 nvidia-smi 显示结果如下 实现了周期性显示 GPU 利用情况的功能,CPU 显示仍可以用 htop 指令实现
-
1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。 Java.io是大多数面向数据流的输入/输出类的主要软件包。此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO。 流IO的好处是简单易用,缺点是效率较低。块IO效率很高,但编程比较复杂。 JavaIO模型 : Java的IO模型设计非常优秀,它使用Decorator模式,按功能划分Stream,您可以动态装配这些Stream,以便获得您需要的功能。例如,您需要一个具有缓冲的文件输入流,则应当组合使用FileInputStream和BufferedInputStream。 2.数据流的基本概念 数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。对数据读取程序来说,看不到数据流在写入时的分段情况,每次可以读取其中的任意长度的数据,但只能先读取前面的数据后,再读取后面的数据。不管写入时是将数据分多次写入,还是作为一个整体一次写入,读取时的效果都是完全一样的。 “流是磁盘或其它外围设备中存储的数据的源点或终点。” 在电脑上的数据有三种存储方式,一种是外存,一种是内存,一种是缓存。比如电脑上的硬盘,磁盘,U盘等都是外存,在电脑上有内存条,缓存是在CPU里面的。外存的存储量最大,其次是内存,最后是缓存,但是外存的数据的读取最慢,其次是内存,缓存最快。这里总结从外存读取数据到内存以及将数据从内存写到外存中。对于内存和外存的理解,我们可以简单的理解为容器,即外存是一个容器,内存又是另外一个容器。那又怎样把放在外存这个容器内的数据读取到内存这个容器以及怎么把内存这个容器里的数据存到外存中呢? 在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛: 标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流等等,java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。将数据冲外存中读取到内存中的称为输入流,将数据从内存写入外存中的称为输出流。 流是个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。 总结的基本概念如下: 1) 数据流: 一组有序,有起点和终点的字节的数据序列。包括输入流和输出流。【从内存数据的流向进行划分】2) 输入流(Input Stream): 程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道 3) 输出流: 程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道。 采用数据流的目的就是使得输出输入独立于设备。 Input Stream不关心数据源来自何种设备(键盘,文件,网络) Output Stream不关心数据的目的是何种设备(键盘,文件,网络 3 数据流分类: 流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种: 1) 字节流:数据流中最小的数据单元是字节 2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。 Java I/O主要包括如下几个层次,包含三个部分: 1.流式部分:IO的主体部分; 2.非流式部分:主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor等类; 3.其他类:文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。 主要的类如下: 1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。 2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。 3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。 Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。 4. Reader(文件格式操作):抽象类,基于字符的输入操作。 5. Writer(文件格式操作):抽象类,基于字符的输出操作。 6. RandomAccessFile(随机文件操作):它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。 5. 非流式文件类--File类 在Java语言的java.io包中,由File类提供了描述文件和目录的操作与管理方法。但File类不是InputStream、OutputStream或Reader、Writer的子类,因为它不负责数据的输入输出,而专门用来管理磁盘文件与目录。 作用:File类主要用于命名文件、查询文件属性和处理文件目录。 public class File extends Object implements Serializable,Comparable {} File类共提供了三个不同的构造函数,以不同的参数形式灵活地接收文件和目录名信息。构造函数: 1)File (String pathname) 例:File f1=new File("FileTest1.txt"); //创建文件对象f1,f1所指的文件是在当前目录下创建的FileTest1.txt 2)File (String parent , String child) 例:File f2=new File(“D:\\dir1","FileTest2.txt") ;// 注意:D:\\dir1目录事先必须存在,否则异常 3)File (File parent , String child) 例:File f4=new File("\\dir3"); File f5=new File(f4,"FileTest5.txt"); //在如果 \\dir3目录不存在使用f4.mkdir()先创建 一个对应于某磁盘文件或目录的File对象一经创建, 就可以通过调用它的方法来获得文件或目录的属性。 1)public boolean exists( ) 判断文件或目录是否存在 2)public boolean isFile( ) 判断是文件还是目录 3)public boolean isDirectory( ) 判断是文件还是目录 4)public String getName( ) 返回文件名或目录名 5)public String getPath( ) 返回文件或目录的路径。 6)public long length( ) 获取文件的长度 7)public String[ ] list ( ) 将目录中所有文件名保存在字符串数组中返回。 File类中还定义了一些对文件或目录进行管理、操作的方法,常用的方法有: 1) public boolean renameTo( File newFile ); 重命名文件 2) public void delete( ); 删除文件 3) public boolean mkdir( ); 创建目录 例子: import java.io.File; 02. import java.io.IOException; 03. public class TestFile { 04. public static void main(String args[]) throws IOException { 05. File dir = new File("\\root"); 06. File f1 = new File(dir, "fileOne.txt"); 07. File f2 = new File(dir, "fileTwo.java"); 08. // 文件对象创建后,指定的文件或目录不一定物理上存在 09 if (!dir.exists()) 10. dir.mkdir(); 11. if (!f1.exists()) 12. f1.createNewFile(); 13. if (!f2.exists()) 14. f2.createNewFile(); 15. System.out.println("f1's AbsolutePath= " + f1.getAbsolutePath()); 16. System.out.println("f1 Canread=" + f1.canRead()); 17. System.out.println("f1's len= " + f1.length()); 18. String[] FL; 19. int count = 0; 20. FL = dir.list(); 21. for (int i = 0; i 22. count++; 23. System.out.println(FL[i] + "is in \\root"); 24. } 25. System.out.println("there are" + count + "file in //root"); 26. } 27. 28. } 说明:File类的方法: (1) exists()测试磁盘中指定的文件或目录是否存在 (2) mkdir()创建文件对象指定的目录(单层目录) (3) createNewFile()创建文件对象指定的文件 (4) list()返回目录中所有文件名字符串 6. Java.IO流类库 1. io流的四个基本类 java.io包中包含了流式I/O所需要的所有类。在java.io包中有四个基本类:InputStream、OutputStream及Reader、Writer类,它们分别处理字节流和字符流: 基本数据流的I/O 输入/输出 字节流 字符流 输入流 Inputstream Reader 输出流 OutputStream Writer Java中其他多种多样变化的流均是由它们派生出来的: JDK1.4版本开始引入了新I/O类库,它位于java.nio包中,新I/O类库利用通道和缓冲区等来提高I/O操作的效率。 在java.io包中, java.io.InputStream 表示字节输入流, java.io.OutputStream表示字节输出流,处于java.io包最顶层。这两个类均为抽象类,也就是说它们不能被实例化,必须生成子类之后才能实现一定功能 7. io流的具体分类 一、按I/O类型来总体分类 1. Memory 1)从/向内存数组读写数据: CharArrayReader、 CharArrayWriter、ByteArrayInputStream、ByteArrayOutputStream 2)从/向内存字符串读写数据 StringReader、StringWriter、StringBufferInputStream 2.Pipe管道:实现管道的输入和输出(进程间通信): PipedReader、PipedWriter、PipedInputStream、PipedOutputStream 3.File 文件流。对文件进行读、写操作 :FileReader、FileWriter、FileInputStream、FileOutputStream 4.ObjectSerialization 对象输入、输出 :ObjectInputStream、ObjectOutputStream 5.DataConversion数据流 按基本数据类型读、写(处理的数据是Java的基本类型(如布尔型,字节,整数和浮点数)):DataInputStream、DataOutputStream 6.Printing 包含方便的打印方法 :PrintWriter、PrintStream 7.Buffering缓冲 在读入或写出时,对数据进行缓存,以减少I/O的次数:BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream 8.Filtering 滤流,在数据进行读或写时进行过滤:FilterReader、FilterWriter、FilterInputStream、FilterOutputStream 9.Concatenation合并输入 把多个输入流连接成一个输入流 :SequenceInputStream 10.Counting计数 在读入数据时对行记数 :LineNumberReader、LineNumberInputStream 11.Peeking Ahead 通过缓存机制,进行预读 :PushbackReader、PushbackInputStream 12.Converting between Bytes and Characters 按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换(Stream到Reader,Writer的转换类):InputStreamReader、OutputStreamWriter 二、按数据来源(去向)分类: 1、File(文件): FileInputStream, FileOutputStream, FileReader, FileWriter 2、byte[]:ByteArrayInputStream, ByteArrayOutputStream 3、Char[]: CharArrayReader, CharArrayWriter 4、String: StringBufferInputStream, StringReader, StringWriter 5、网络数据流:InputStream, OutputStream, Reader, Writer ———————————————— 原文链接:https://blog.csdn.net/weixin_36377930/article/details/114186351
-
MySql中json类型的使用 MySQL从5.7.8起开始支持JSON字段,这极大的丰富了MySQL的数据类型。也方便了广大开发人员。但MySQL并没有提供对JSON对象中的字段进行索引的功能,至少没有直接对其字段进行索引的方法。本文将介绍利用MySQL 5.7中的虚拟字段的功能来对JSON对象中的字段进行索引。 一、使用json的目的 1、可以直接过滤记录 2、可以直接update,而无须先读取 3、可以在一条SQL中完成多条纪录的修改! 4、通过json类型,完美的实现了表结构的动态变化 5、通过计算生成列且在该列上建立索引。提高查询效率 二、开始使用 1.建表 建表语句如下: CREATE TABLE `msg_info` ( `id` int(10) unsigned NOT NULL, `message` json NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 2.插入数据 insert into msg_info values (1,'{"name":"zhangsan","phone":"13752763211"}'); insert into msg_info values (2,'{"name":"lisi","phone":"13752763222"}'); 3.查询更新操作 1、过滤记录 select * from msg_info where message->'$.phone'='13752763211'; 2、查询json内指定字段 select message->'$.name' from msg_info; # 这样查询出来的字段是带双引号的,使用如下语句可去除双引号,也可以使用关键字JSON_UNQUOTE select message->>'$.name' from msg_info; 3、直接更新json串内的字段内容 UPDATE msg_info set message = JSON_SET(message, '$.name', 'lili') WHERE id = 1; # 为json串添加字段 update msg_info set message = JSON_INSERT(message, '$.age', 30) WHERE id = 1; 3.动态扩展字段 1、为json添加虚拟字段 ALTER TABLE msg_info ADD v_phone varchar (12) GENERATED ALWAYS AS (JSON_UNQUOTE(message->'$.phone' )); 2、为虚拟字段创建索引,提高查询效率 # 通过执行计划可以查看创建索引前后的变化 ALTER TABLE msg_info ADD INDEX idx_phone(v_phone); mybatis存取mysql中的json mysql 5.7后新增了一个json类型字段,以往json入库都是转字符串,取到前端造成了不少困扰。今天就做了个小例子把这个整合到ssm例子中。 这边也顺便说下如果idea在启动tomcat客户端控制台出现乱码处理办法 这边也顺便说下如果idea在启动tomcat客户端控制台出现乱码处理办法 打开idea安装目录-bin 用记事本打开idea.exe.vmoptions和idea64.exe.vmoptions文件 在文件后面添加一行:-Dfile.encoding=UTF-8 好了进入正题 第一步先配置一个typehandler,代码如下 import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig.Feature; import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; /** * mapper里json型字段到类的映射。 * 用法一: * 入库:#{jsonDataField, typeHandler=com.adu.spring_test.mybatis.typehandler.JsonTypeHandler} * 出库: * <resultMap> * <result property="jsonDataField" column="json_data_field" javaType="com.xxx.MyClass" typeHandler="com.adu.spring_test.mybatis.typehandler.JsonTypeHandler"/> * </resultMap> * * 用法二: * 1)在mybatis-config.xml中指定handler: * <typeHandlers> * <typeHandler handler="com.adu.spring_test.mybatis.typehandler.JsonTypeHandler" javaType="com.xxx.MyClass"/> * </typeHandlers> * 2)在MyClassMapper.xml里直接select/update/insert。 * */ public class JsonTypeHandler<T extends Object> extends BaseTypeHandler<T> { private static final ObjectMapper mapper = new ObjectMapper(); private Class<T> clazz; public JsonTypeHandler(Class<T> clazz) { if (clazz == null) throw new IllegalArgumentException("Type argument cannot be null"); this.clazz = clazz; } @Override public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, this.toJson(parameter)); } @Override public T getNullableResult(ResultSet rs, String columnName) throws SQLException { return this.toObject(rs.getString(columnName), clazz); } @Override public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return this.toObject(rs.getString(columnIndex), clazz); } @Override public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return this.toObject(cs.getString(columnIndex), clazz); } private String toJson(T object) { try { return mapper.writeValueAsString(object); } catch (Exception e) { throw new RuntimeException(e); } } private T toObject(String content, Class<?> clazz) { if (content != null && !content.isEmpty()) { try { return (T) mapper.readValue(content, clazz); } catch (Exception e) { throw new RuntimeException(e); } } else { return null; } } static { mapper.configure(Feature.WRITE_NULL_MAP_VALUES, false); mapper.setSerializationInclusion(Inclusion.NON_NULL); } mapper代码 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cm.dao.UserDao"> <resultMap id="user" type="com.cm.model.UserModel"> <id column="id" jdbcType="NUMERIC" property="id"/> <result column="name" jdbcType="VARCHAR" property="name"/> <result column="age" jdbcType="NUMERIC" property="age"/> <result column="hobby" jdbcType="NUMERIC" property="hobby" typeHandler="com.cm.mybaits.JsonTypeHandler"/> </resultMap> <select id="getAllUsers" resultMap="user"> select * from user </select> <insert id="addUser"> <!--ignore忽略自动增长的主键id--> insert ignore into user (name, age, hobby) values (#{id}, #{name} ,#{hobby, typeHandler=com.cm.mybaits.JsonTypeHandler}) </insert> 这边有个坑是mysql 驱动一定要5.1.40,不然取出来的json中文是乱码。虽然说是低于5.1.36会乱码,但是我试了5.1.6还是乱码。 <update id="updateUser"> update user set name=#{name} where id=#{id} </update> <delete id="deleteUser" parameterType="String"> delete from user where id=#{id} </delete> <select id="getUser" resultType="UserModel"> select * from user where id = #{id} </select> </mapper> mysql表结构 插入的测试代码 效果预览 入库 取数据 这边有个坑是mysql 驱动一定要5.1.40,不然取出来的json中文是乱码。虽然说是低于5.1.36会乱码,但是我试了5.1.6还是乱码。 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency> 文章知识点与官方知识档案匹配,可进一步学习相关知识 ———————————————— 原文链接:https://blog.csdn.net/qq_43842093/article/details/122612071
-
最近用到了el-tree控件,主要是数据的格式,按照官网的数据格式来就可以显示节点的树形结构了。 代码参考很多 这里给出一个比较好的链接:https://blog.csdn.net/qq_36956154/article/details/79893876 代码说明在注释里写的很详细了已经,这里不再叙述说明。至于为什么抽取成这种格式的数据,那是因为ElementUI-tree规定的数据格式,你想要用这个控件,就必须按照他们规定的这个格式 来。 数据格式如下: Controller代码 @RequestMapping("/cateList") @ResponseBody public List<TbCategory> cateList() { // 整体思路: // 1、取得所有数据、放入集合List1 (tbCategories) // 2、将List1所有数据都放入到map(treeMap)中:元素id为键,元素本身对象为值 // 3、取得顶层节点放入集合List2中(resultList) // 4、遍历List1中的所有数据,通过数据的parentId为键在map中取值 // 1)如果能取到,则说明该元素有父节点 // 1、判断该父节点下的childList中是否有已经子节点 // 1、若无:则创建一个集合,将子节点放入 // 2、若有:则直接将子节点放入即可 // 5、把放好的数据放回到map中 // 6、返回List2(resultList) // 注意:整个过程将所有数据取出放入list2(resultList),返回的也是 //list2 List<TbCategory> tbCategories = categoryService.cateList(); List<TbCategory> resultList = new ArrayList<TbCategory>(); // 存贮顶层的数据 Map<Object ,Object> treeMap = new HashMap(); Object itemTree; for(int i = 0;i<tbCategories.size() && !tbCategories.isEmpty();i++){ itemTree = tbCategories.get(i); treeMap.put(tbCategories.get(i).getNodeId(),tbCategories.get(i));// 把所有的数据都放到map中 } // 这里也可以用另一种方法,就是拿到集合里的每个元素的父id去数据库中查询,但是,这样与数据库的交互次数就太多了 // 遍历map得到顶层节点(游离节点也算作顶层节点) for(int i =0;i<tbCategories.size();i++){ // 优点1:整个方法,只查询了一次数据库 // 优点2:不用知道顶层节点的id if(!treeMap.containsKey(tbCategories.get(i).getParentId())){ // 我们在存储的时候就是将元素的id为键,元素本身为值存入的 // 以元素的父id为键,在map里取值,若取不到则,对应的元素不存在,即没有父节点,为顶层节点或游离节点 // 将顶层节点放入list集合 resultList.add(tbCategories.get(i)); } } // 循环数据,将数据放到该节点的父节点的children属性中 for(int i =0 ;i<tbCategories.size()&& !tbCategories.isEmpty();i++){ // 数据库中,若一个元素有子节点,那么,该元素的id为子节点的父id //treeMap.get(tbCategories.get(i).getParentId()); // 从map集合中找到父节点 TbCategory category = (TbCategory)treeMap.get(tbCategories.get(i).getParentId()); if(category!=null ){ // 不等于null,也就意味着有父节点 // 有了父节点,要判断父节点下存贮字节点的集合是否存在,然后将子节点放入 if(category.getChildList() == null){ // 判断一个集合是否被创建用null:表示结合还没有被分配内存空间(即还没有被创建),内存大小自然为null // 用集合的size判断集合中是否有元素,为0,没有元素(集合已经被创建), category.setChildList(new ArrayList<TbCategory>()); } category.getChildList().add(tbCategories.get(i)); // 添加到父节点的ChildList集合下 // 这一步其实可以不要,因为我们修改了数据(添加了子节点,然后在将元素放入到map中, // 若键相同,map会自动覆盖掉相同的键值对,达到更新map集合中的数据的目的),但是我们 // 这里只是从map中取值,而并不关心值的子节点(子节点是对象本身自己封装的。这里我们知道 // 元素从查询后放入map,父节点放入list,然后通过键来在map中取得对象,之后再将修改过的对象重新放入map当中 // ,我们并没有直接操作list,但是在list中对象的值却是已经修改过了,这就是对象的引用传递,同一个引用对象是通过 // 地址值来操作对象的,即有不同的引用,但是对象中的属性是已经通过引用的操作而改变的,所以这里一旦修改过后,无论是map中还是list中,再次取值时都已经是更改过后的值了) treeMap.put(tbCategories.get(i).getParentId(),category); // 把放好的数据放回到map中 } } return resultList; } 实体类: private Long nodeId; private String categoryName; private Long parentId; private Long childId; private List<T> childList; 以上数据都在后台封装好了,前台直接获取数据显示即可 <el-tree :data="treeList" :props="defaultProps" @node-click="handleNodeClick" node-key="nodeId" show-checkbox=true> </el-tree> js: defaultProps:{ children: 'childList', label: 'categoryName' // 这里的名字要和你封装的数据中的节点的名字一样 } // 点击事件 handleNodeClick: function (data) { console.log("没做处理"); } 方法抽取 /// 上面的方法虽然也能用,但是想把这个方法抽取成一个通用的方法,以后再写的时候就可以直接调取该方法了。抽取的过程中还是遇到了很多的问题的。 例如实体类A是对应数据库中存储节点的表的实体类,但是,实体类中是不存在setChildList、getChildList集合这些方法的。我就把这些存贮信息的字段写在了一个工具类里面,然后方法也在该工具类里。这样返回的时候就要返回一个装有该工具类的一个集合了。还有一个问题就是该工具类中都需要那些字段?因为是一棵树,所以我们需要节点id,几点的父id,节点的名称,以及存储子节点的集合,如果想要更多的数据,可以添加一个 T data泛型,该泛型直接将原本存储节点的实体类对象存储进来。这样所有的数据就都整齐了,数据结构也就完整了。 contrell代码: 因为我们想抽取一个公用的方法,那么参数的类型就是不确定的,即传入的list中元素的类型是不固定的,所以要用到泛型。上面说过了,我们要拿到节点id,父id,以及节点的名称赋值给工具类中对应的字段。但是既然是用泛型,所以就不知道对象类型,所以我们在工具类中是点不出相应的方法来取到值的,我们就要用到反射,反射的知道类中具体的字段或者方法的名字来取值,所以我们在controller来调用工具类的时候就要,将节点id、父id和节点名称传入。当然了还要传入从后台查询到了装有数据的list集合。 contreller代码如下所示: @RequestMapping("/cateList") @ResponseBody public List<TreeUtils> cateList() throws Exception{ List<TbCategory> tbCategories = categoryService.cateList(); List<TreeUtils> treeList = TreeUtils.getTreeList(tbCategories,"nodeId", "parentId", "categoryName"); return treeList; } 工具类: // 抽取方法的时候要考虑一个问题,即,返回一个集合,集合中有父节点和字节点,父节点和字节点的类型一定要统一, // 即这里返回的是一个装有TreeUtils类型的集合,那么集合里的父节点和子节点一定都得是TreeUtils类型的 public class TreeUtils<T> { private Integer id; // 节点id private Integer parentId; // 父节点 private String name; // 节点名称 ,返回给前台的是一个装有TreeUtils的集合的数据,所以在前台显示数据的时候,el-tree的lable的名字的和这个一样 private List<TreeUtils> childList; // 父节点中存放子节点的集合 private T data; // 节点数据 方法 /** * @param listData // 从数据库中查询的数据 * @return */ public static List<TreeUtils> getTreeList(List<?> listData ,String id,String parentId,String categoryName) throws Exception{ List<TreeUtils> resultList = new ArrayList<TreeUtils>(); // 最终返回的结果 Map<Integer ,Object> map = new HashMap<Integer,Object>(); for(int i =0;i<listData.size() && !listData.isEmpty();i++){ // 写一个与该方法差不多的方法,将得到TreeUtils的代码抽取出来 // 也可以将listData集合整个转换成装有TreeUtils的集合x,然后再循环x TreeUtils treeUtils = new TreeUtils(); treeUtils.setId(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),id).toString())); // id // 返回值为Object无法直接转换成Integer,先toString,再转换成Integer。这里的返回值写成Object是因为多种类型字段的值都可以用该方法 treeUtils.setParentId(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),parentId).toString())); // 父id treeUtils.setName(TreeUtils.getFileValue(listData.get(i),categoryName).toString()); // 节点名 //System.out.println("节点名为+"+TreeUtils.getFileValue(listData.get(i),categoryName).toString()); treeUtils.setData(listData.get(i)); // data:原对象中的所有属性,无children // 通过反射得到每条数据的id将数据封装的map集合中,id为键,元素本身为值 map.put(treeUtils.getId(),treeUtils); // 将所有顶层元素添加到resultList集合中 //if( 0 == treeUtils.getParentId()){ // resultList.add(treeUtils); // } } // 得到所有的顶层节点,游离节点也算作顶层节点 // 优点一,不用知道等级节点的id // 优点而,只查询了一次数据库 for(int i =0;i<listData.size();i++){ if(!map.containsKey(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),parentId).toString()))){ resultList.add((TreeUtils) map.get(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),id).toString()))); } } for(int i =0;i<listData.size() && !listData.isEmpty();i++){ TreeUtils obj = (TreeUtils)map.get(Integer.parseInt(TreeUtils.getFileValue(listData.get(i), parentId).toString())); if(obj != null){ if(obj.getChildList() == null){ obj.setChildList(new ArrayList()); } obj.getChildList().add(map.get(Integer.parseInt(TreeUtils.getFileValue(listData.get(i),id).toString()))); } } return resultList; } 反射的方法 /** * 通过反射得到的数据类型的也是不一定的,所以这里我们返回值为Object * Object是无法直接转为Integer,现将Object转为String,然后再将String转为Integer * @param item * @param fileName * @return */ public static Object getFileValue(Object item,String fileName) throws Exception { Class<?> aClass = item.getClass(); Field file = aClass.getDeclaredField(fileName); // 得到所有字段包括私有字段 file.setAccessible(true); // 取消访问限制 return file.get(item); // 这里就体现出反射的意思了,我们通常都是通过对象拿到字段,这里是通过字段,将类的字节码对象为参数传入,来得到值 } ps:抽取方法遇到了很多的问题,其中的T,?等泛型还只是会简单的用,并不熟练,以后要多加学习。 ———————————————— 原文链接:https://blog.csdn.net/java_xxxx/article/details/81099437
-
File.createNewFile和 File.createTempFile比较和区别 File 的 createNewFile() 方法: createNewFile();返回值为 boolean; File file = new File("D:\\test\\1.txt"); boolean res = file.createNewFile(); if(!res)System.out.println("创建失败!"); 如果D:/test 目录下没有 1.txt文件,则创建该文件; 如果没有test目录,直接抛出异常; 如果1.txt已经存在,那么文件创建失败。 可以得知,createNewFile() 方法,根据抽象路径创建一个新的空文件,当抽象路径指定的文件存在时,创建失败。 File 的 createTempFile() 方法 该方法有两种调用方式: 在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。 createTempFile(String prefix, String suffix); 方法默认的保存路径为:C:\Documents and Settings\Administrator\Local Settings\Temp 。 在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。 createTempFile(String prefix, String suffix, File directory); createTempFile() 方法,在指定的目录下创建一个temp文件,directory 类型为File ,如果路径不存在,则创建失败。 3.删除方法 //立即删除文件 file.delete(); //在JVM退出时删除文件 file.deleteOnExit(); 总结:临时文件能够使用默认路径,可以避免存在创建文件是因为路径错误导致创建文件失败的问题。 如果需求中需要创建一个临时文件,这个临时文件可能作为存储使用,但在程序运行结束后需要删除文件,可以使用deleteOnExit方法 ———————————————— 原文链接:https://blog.csdn.net/lp15203883326/article/details/83783433
-
单表的查询并根据时间分页 1、yml或者properties中配数据源,配自己的数据库就好。 mybatis-plus: mapper-locations: ../mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl //这个是为了在控制台打印SQL语句。 2、导入Mybatis-Plus的依赖,我这里使用的是3.4.0的版本,这里一定要注意依赖的版本号,3.4.0以后,分页插件的配置进行了更新。这里强调一下,如果自带分页插件失效,先检查版本和配置。 <!--MyBatis-plus配置--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> 3、新建一个config,这个config写Mybatis-Plus的插件配置,MP的插件配置有很多,这里单说一下分页的配置。 /** * 注意@MapperScan,使用springboot的话,启动类是要扫描数据层的,如果仅用的是MP对数据 * 库操作,启动类里面的@MapperScan是不用写的,只写这里就好。 * */ @Configuration @MapperScan("com.tiktang.dao") public class MybatisPlusConfig { /** * IPage的分页使用的是拦截器,属于物理分页,好处就是处理大量数据时,查询速度快。 * 有兴趣的同学可以看看什么是物理分页和逻辑分页。 * @return */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); //向Mybatis过滤器链中添加分页拦截器 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } @Bean public ConfigurationCustomizer configurationCustomizer() { return configuration -> configuration.setUseDeprecatedExecutor(false); } } 4、单表的实体类entity对象,自己数据库中的字段,此步进行了省略。 5、程序的步骤,我一般习惯先写Mapper.xml,Mapper,service,serviceImpl,controller。按这个步骤来说,首先要先写的是Mapper.xml,但是是单表操作,又是用MP框架,就不用再写Mapper.xml了。 6、Mapper //News为实体类 @Repository public interface NewsMapper extends BaseMapper<News> { } 7、service //News为实体,page为当前页,pageSize是一页多少个 public interface NewsService { IPage<News> queryNewsList(Integer page, Integer pageSize); } 8、serviceImpl @Service public class NewsServiceImpl implements NewsService { @Autowired private NewsMapper newsMapper; @Override public IPage<News> queryNewsList(Integer page, Integer pageSize) { // Page<News> page1 = new Page<>(page,pageSize); //这里进行了时间排序 QueryWrapper<News> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc("news_time"); //MP自带的selectPage方法,有兴趣的同学,可以看一下源码 IPage<News> iPage = newsMapper.selectPage(new Page<>(page, pageSize), queryWrapper); return iPage; } } 9、controller @GetMapping("/newsList") public Result<News> queryNewsList(@RequestParam Integer page, @RequestParam Integer pageSize){ IPage<News> iPage = newsService.queryNewsList(page, pageSize); return Result.ok().data("iPage",iPage); } Result是我自己封装的结果集,有时间会再写一下关于返回统一结果集的内容。 到此单表查询分页并根据时间排序就完成。 @GetMapping("/getCompanyInvest") public Result getCompanyInvest(@RequestParam String companyId, @RequestParam Integer currentPage, @RequestParam Integer pageNumber){ QueryWrapper<CompanyInvest> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("company_id",companyId); Page<CompanyInvest> page = new Page<>(currentPage,pageNumber); IPage<CompanyInvest> companyInvestIPage = companyInvestMapper.selectPage(page,queryWrapper); Map<String,Object> map = new HashMap<>(); map.put("公司投资信息的子页面",companyInvestIPage); return Result.ok().data(map); }———————————————— 原文链接:https://blog.csdn.net/qq_42405688/article/details/119967684
-
Mybatis-Plus(mbp) 提供 Wrapper 极大的减少大家的写SQL 的时间,Wrapper 类封装了大量的逻辑方法 eq , gt , lt等,使得操作数据库的代码进一步简洁。 在代码中有更新数据的需求,发现 mbp 提供了 UpdateWrapper 类简化更新的操作。 继承自 BaseMapper 的自定以mapper的 update() 有这两个参数 /** * 根据 whereEntity 条件,更新记录 * * @param entity 实体对象 (set 条件值,可以为 null) * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) */ int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); 实体对象可以为null且为set条件值,说明有两种方法可以实现更新。 第一种: 将需要更新的字段,设置到entity 中 UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("name","shimin"); User user = new User(); user.setAge(18); Integer rows = userMapper.update(user, updateWrapper); 第二种: 可以将entity设置为 null ,将需要更新的字段设置到 UpdateWrapper 中 UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); updateWrapper.set("id","123")eq("name","shimin"); Integer rows = userMapper.update(null, updateWrapper); ———————————————— 原文链接:https://blog.csdn.net/mikelv01/article/details/123920873
-
SpringBoot导出下载csv文件 说明 工具类代码 Controller代码 说明 今天看到需求里面有个需要将数据导成csv文件的格式,这里记录下自己的实现过程。直接上后端代码,这里用的springboot框架实现。 工具类代码 工具类代码下面最下面有一个main方法可直接执行导出功能,你可以用这个测试数据看看效果。 package com.etone.project.utils; import org.apache.commons.beanutils.BeanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.*; public class CsvUtils { public static final Logger logger = LoggerFactory.getLogger(CsvUtils.class); /** * 生成为CVS文件 * * @param exportData * 源数据List * @param map * csv文件的列表头map * @param outPutPath * 文件路径 * @param fileName * 文件名称 * @return */ @SuppressWarnings("rawtypes") public static File createCSVFile(List exportData, LinkedHashMap map, String outPutPath, String fileName) { File csvFile = null; BufferedWriter csvFileOutputStream = null; try { File file = new File(outPutPath); if (!file.exists()) { file.mkdir(); } // 定义文件名格式并创建 csvFile = File.createTempFile(fileName, ".csv", new File(outPutPath)); logger.debug("csvFile:" + csvFile); // UTF-8使正确读取分隔符"," csvFileOutputStream = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(csvFile), "GBK"), 1024); logger.debug("csvFileOutputStream:" + csvFileOutputStream); // 写入文件头部 for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator .hasNext();) { java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator .next(); csvFileOutputStream .write("" + (String) propertyEntry.getValue() != null ? (String) propertyEntry .getValue() : "" + ""); if (propertyIterator.hasNext()) { csvFileOutputStream.write(","); } } csvFileOutputStream.newLine(); // 写入文件内容 for (Iterator iterator = exportData.iterator(); iterator.hasNext();) { Object row = (Object) iterator.next(); for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator .hasNext();) { java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator .next(); csvFileOutputStream.write((String) BeanUtils.getProperty( row, (String) propertyEntry.getKey())); if (propertyIterator.hasNext()) { csvFileOutputStream.write(","); } } if (iterator.hasNext()) { csvFileOutputStream.newLine(); } } csvFileOutputStream.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { csvFileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return csvFile; } /** * 下载文件 * * @param response * @param csvFilePath * 文件路径 * @param fileName * 文件名称 * @throws IOException */ public static void exportFile(HttpServletResponse response, String csvFilePath, String fileName) throws IOException { // response.setHeader("Content-type", "application-download"); FileInputStream in = null; OutputStream out = response.getOutputStream(); byte[] buffer = new byte[1024]; int len = 0; response.setContentType("text/csv;charset=UTF-8"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); response.setCharacterEncoding("UTF-8"); try { in = new FileInputStream(csvFilePath); while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } out.flush(); } catch (FileNotFoundException e) { logger.error("获取文件错误!"); } finally { if (in != null) { try { in.close(); out.close(); } catch (Exception e) { throw new RuntimeException(e); } } } } /** * 导出 * * @param response * @param * @return * @throws IOException */ public static void downloadFile(HttpServletRequest request, HttpServletResponse response, String uri) throws IOException { // 获取服务其上的文件名称 File file = new File(uri); String name = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".zip"; StringBuffer sb = new StringBuffer(); sb.append("attachment; filename=").append(name); response.setHeader("Expires", "0"); response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0"); response.setHeader("Pragma", "public"); response.setContentType("application/x-msdownload;charset=UTF-8"); response.setHeader("Content-Disposition", new String(sb.toString() .getBytes(), "ISO8859-1")); // 将此文件流写入到response输出流中 FileInputStream inputStream = new FileInputStream(file); OutputStream outputStream = response.getOutputStream(); byte[] buffer = new byte[1024]; int i = -1; while ((i = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, i); } outputStream.flush(); outputStream.close(); inputStream.close(); } /** * 删除该目录filePath下的所有文件 * * @param filePath * 文件目录路径 */ public static void deleteFiles(String filePath) { File file = new File(filePath); if (file.exists()) { File[] files = file.listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].isFile()) { files[i].delete(); } } } } /** * 删除单个文件 * * @param filePath * 文件目录路径 * @param fileName * 文件名称 */ public static void deleteFile(String filePath, String fileName) { File file = new File(filePath); if (file.exists()) { File[] files = file.listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].isFile()) { if (files[i].getName().equals(fileName)) { files[i].delete(); return; } } } } } /** * 下载csv文件 * @param path * @param response */ public static void download(String path, HttpServletResponse response) { try { // path是指欲下载的文件的路径。 File file = new File(path); // 取得文件名。 String filename = file.getName(); // 以流的形式下载文件。 InputStream fis = new BufferedInputStream(new FileInputStream(path)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); // 清空response response.reset(); // 设置response的Header,给文件名进行utf-8编码,不然下载的时候文件名乱码不对 response.addHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode (filename, "UTF-8" )); response.addHeader("Content-Length", "" + file.length()); OutputStream toClient = new BufferedOutputStream( response.getOutputStream()); response.setContentType("application/vnd.ms-excel;charset=gb2312"); toClient.write(buffer); toClient.flush(); toClient.close(); } catch (IOException ex) { ex.printStackTrace(); } } /** * 测试数据 * * @param args */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static void main(String[] args) { List exportData = new ArrayList<Map>(); Map row1 = new LinkedHashMap<String, String>(); row1 = new LinkedHashMap<String, String>(); row1.put("1", "11"); row1.put("2", "12"); row1.put("3", "13"); row1.put("4", "14"); exportData.add(row1); row1.put("1", "11"); row1.put("2", "12"); row1.put("3", "13"); row1.put("4", "14"); exportData.add(row1); LinkedHashMap map = new LinkedHashMap(); map.put("1", "第一列"); map.put("2", "第二列"); map.put("3", "第三列"); map.put("4", "第四列"); String path = "E:/export/"; String fileName = "文件导出"; File file = CsvUtils.createCSVFile(exportData, map, path, fileName); String fileName2 = file.getName(); logger.debug("文件名称:" + fileName2); } } main方式执行后,数据样式如下,我这里用的wps打开的: Controller代码 @RestController @RequestMapping("/dtracejobinfo") public class DtraceJobInfoController { public static final Logger logger = LoggerFactory.getLogger(DtraceJobInfoController.class); @Autowired public IDtraceJobInfoManager iDtraceJobInfoManager; //导出图层为csv文件 @RequestMapping(value = "/exportDtraceJob", method = RequestMethod.POST) public Object exportDtraceJob(@RequestParam(value = "jobName", required = false) String jobName, HttpServletResponse response) { Map<String, Object> result = new HashMap<String, Object>(); result.put("status", "000"); result.put("message", "操作成功!"); try { if(StringUtils.isBlank(jobName)){ result.put("status", "999"); result.put("message", "操作失败,jobName值不能为空!"); return result; } QueryCriteria criteria = new QueryCriteria(); criteria.put("jobName", jobName); //根据任务名称查询出对应的file_md5的值,然后根据file_md5值去dtrace_job_file_info表里面查询出对应的值 Map<String, Object> dtraceJob = iDtraceJobInfoManager.getByDtraceJobName(criteria); System.out.println("=============="+dtraceJob.get("dtrace_file_id")); if(dtraceJob.get("dtrace_file_id")==null){ result.put("status", "999"); result.put("message", "操作失败,当前任务dtrace_file_id值为空,无法下载!"); return result; } criteria.put("fileMd5", dtraceJob.get("dtrace_file_id").toString()); //因架构差异这里返回的一般是一个对象 List<Map<String, Object>> list =iDtraceJobInfoManager.exportDtraceJob(criteria); //下面代码是重点,参考下面代码 //设置第一列列名 LinkedHashMap map = new LinkedHashMap(); map.put("1", "st_astext"); List exportData = new ArrayList<Map>(); Map row1 = new LinkedHashMap<String, String>(); for (Map<String, Object> mapList : list) { // 执行导出操作 //System.out.println("经纬度值="+mapList.get("st_astext").toString()); row1 = new LinkedHashMap<String, String>(); row1.put("1", mapList.get("st_astext").toString()); exportData.add(row1); } //设置导出路径,本地测试用这个地址 String path = "E:/export/"; //线上放到linux服务器的时候用下面地址 //String path = "/data/export/"; //设置导出文件名 String fileName = jobName; File file = CsvUtils.createCSVFile(exportData, map, path, fileName); String fileName2 = file.getName(); logger.debug("文件名称:" + fileName2); //下载到本地 CsvUtils.download(path+fileName2,response); } catch (Exception e) { logger.error("操作失败:", e); result.put("status", "999"); result.put("message", "操作失败!"); } return result; } } 代码执行完后结果如下展示: 这里将代码里面的post请求方式改成get方便你直接用浏览器测试 下载逻辑是先将文件导出后,然后对该文件进行下载。好了,代码实现就到这里面了。 ———————————————— 原文链接:https://blog.csdn.net/weixin_48040732/article/details/120222910
-
业务场景:用户发送下单请求,格式为xml格式,服务器接收数据完成下单,并返回结果给客户。请求格式:<request><head><sign></sign><time></time><msg></msg></head><body><productId></productId><count></count><price></price><user><userId></userId><name></name><mobil></mobil><email></email></user><extendInfos><extendInfo><city></city><province></province><district></district><address></address></extendInfo></extendInfos></body></request>这段请求报文是xml格式的,在后台我们可以使用 javax.xml.bind.annotation 这个包格式化数据。我们可以在做数据对应的dto是用@XmlElement注释标注对应节点比如:import java.io.Serializable;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlRootElement;import org.apache.commons.lang.builder.ToStringBuilder;import org.apache.commons.lang.builder.ToStringStyle;import com.juqitech.adapter.dto.ChannelDTO;@XmlRootElement(name = "request")@XmlAccessorType(XmlAccessType.NONE)public class RequestDTO implements Serializable {private static final long serialVersionUID = -1;@XmlElementprivate RequestHeaderDTO head;@XmlElementprivate RequestBodyDTO body;public RequestHeaderDTO getHead() {return head;}public void setHead(RequestHeaderDTO head) {this.head = head;}public RequestBodyDTO getBody() {return body;}public void setBody(RequestBodyDTO body) {this.body = body;}}@XmlRootElement(name = "request")可以定义在类上,代表根节点@XmlAccessorType(XmlAccessType.FIELD)表示使用这个类中的 private 非静态字段作为 XML 的序列化的属性或者元素。这里还可以选择属性,也就是使用 set/get 方法来序列化属性或者元素。关键在于在请求中有个extendInfos的array数组,一般我们都会用list来表示,所以在RequestBodyDTO中可以这么写:import java.io.Serializable;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlRootElement;import org.apache.commons.lang.builder.ToStringBuilder;import org.apache.commons.lang.builder.ToStringStyle;import com.juqitech.adapter.dto.ChannelDTO;@XmlRootElement(name = "body")@XmlAccessorType(XmlAccessType.NONE)public class RequestBodyDTO implements Serializable {private static final long serialVersionUID = -1;//....前面的属性省略@XmlElementWrapper(name="extendInfos")@XmlElement(name="extendInfo")private List<extendInfo> extendInfos;//。。其他的省略}@XmlRootElement(name = "extendInfo")@XmlAccessorType(XmlAccessType.NONE)public class extendInfo{@XmlElementprivate String city;@XmlElementprivate String province;@XmlElementprivate String district;//省略}@XmlElementWrapper 这个注释用来在外面在包一层,用于处理list集合原文链接:https://www.shuzhiduo.com/A/kvJ30bPA5g/
-
@Scope注解 @Scope注解的目的是用来调节作用域 @Scope("prototype")//多实例,IOC容器启动创建的时候,并不会创建对象放在容器在容器当中,当你需要的时候,需要从容器当中取该对象的时候,就会创建。 @Scope("singleton")//单实例 IOC容器启动的时候就会调用方法创建对象,以后每次获取都是从容器当中拿同一个对象(map当中)。 @Scope("request")//同一个请求创建一个实例 @Scope("session")//同一个session创建一个实例 ———————————————— 原文链接:https://blog.csdn.net/weixin_43732955/article/details/88931003
-
spring给我们提供了jdbc的统一封装,和其它的orm不同,它是对jdbc api的封装,相当于我们自己写的java bean,而没有对对象模型进行封装(比如将po封装为pojo)。它保持了jdbc数据对象的原始性,具有极大程度的灵活性,其性能也极高。 我们知道在进行增量操作的时候最好是使用PreparedStatement,这样会节省数据库服务器编译sql语句的成本。而Spring也提供了对增量操作的支持,而BatchPreparedStatementSetter接口则是其核心。 先看看BatchPreparedStatementSetter接口里都定义了些操作。 public interface BatchPreparedStatementSetter{ public int getBatchSize(); public void setValues(PreparedStatement ps,int i);} 该接口是被JdbcTemplate类使用的CallBack接口。批操作中的每个操作都使用相同的sql语句,而该接口则sql语句中的占位符设置具体的值。 public int getBatchSize();用来返回批次的大小 public void setValues(PreparedStatement ps,int i); 用来为PreparedStatement设值。 参数说明: ps:我们将要设值的PreparedStatement i:在这个批次中,正在执行操作的索引,从0算起。 以批量更新为例,我们要做的是先实现BatchPreparedStatementSetter接口,然后再调用JdbcTemplate的batchUpdate(sql,setter)操作,参数sql是预编译语句 ,setter是BatchPreparedStatementSetter的一个实例。下面是我写的一段代码: public void batchInsertRows(String sql,final List<Object[]> dataSet) throws Exception{ BatchPreparedStatementSetter setter=new BatchPreparedStatementSetter(){ public int getBatchSize(){ return dataSet.size(); } public void setValues(PreparedStatement ps,int i){ Object[] obj = dataSet.get(i); int nextId = getNextId(); try{ ps.setLong(1,nextId); ps.setLong(2,Integer.parseInt(obj[0].toString())); ps.setLong(3,Integer.parseInt(obj[1].toString())); ps.setString(4,(String)obj[2]);} catch(Exception e){ e.printStackTrace(); } } }; jdbcTemplate.batchUpdate(sql,setter); }原文链接:https://www.cnblogs.com/love-you-girl/p/4032679.html
-
常见的Slf4j日志打印有两种方式,分别为传统方式(LoggerFactory)和注解方式(@Slf4j)。一 :传统方式package com.tr.demo.controller;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.GetMapping;@RestController@RequestMapping("/Test")public class Test { private final static Logger logger = LoggerFactory.getLogger(Test.class); @GetMapping("/helloWorld") public void String sayHello(){ logger.info("hello Sfl4j + logback......"); }}二:注解方式(@Slf4j)pom中引入依赖 <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> </dependency>IDEA安装lombok插件使用package com.tr.demo.controller;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.GetMapping;@Slf4j@RestController@RequestMapping("/Test")public class Test { @GetMapping("/helloWorld") public void String sayHello(){ logger.info("hello Sfl4j + logback......"); }}
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签