目录
一、JRebel
1.1 Jrebel介绍
1.2 Jrebel插件下载
1.3 Jrebel服务下载并启动
1.4 在线生成GUID
1.5 JRebel激活
1.6 相关设置
注意❗
二、文件上传、下载
2.1 导入pom依赖
2.2 配置文件上传解析器
2.3 文件上传表单设置
2.4 文件上传实现
2.5 文件下载实现
2.6 多文件上传、下载
注意❗
JRebel是一个Java开发工具,它是一款用于实时代码重载的插件。它的主要功能是在不重新启动应用程序的情况下,将修改后的Java代码实时应用到正在运行的应用程序中,从而加快开发周期,提高开发效率。
实时代码重载:JRebel可以监测开发人员对Java代码的修改,并将这些修改实时应用到正在运行的应用程序中,无需重新启动应用程序。这样,开发人员可以立即看到他们的代码更改的效果,节省了重新编译和部署的时间。
支持多种框架和服务器:JRebel支持多种Java框架和服务器,包括Spring、Hibernate、Java EE、Tomcat、Jetty等。无论是开发Web应用程序还是企业级应用程序,JRebel都可以与常用的开发框架和服务器集成,提供实时代码重载的功能。
高度兼容性:JRebel与大多数Java开发工具和集成开发环境(IDE)兼容,如Eclipse、IntelliJ IDEA、NetBeans等。开发人员可以在他们喜欢的IDE中使用JRebel插件,无需切换到其他工具。
快速部署:JRebel可以加快应用程序的部署速度,因为它只需要将修改后的代码应用到运行中的应用程序,而不需要重新启动整个应用程序。这对于大型应用程序和复杂的部署环境特别有用。
支持多种开发场景:JRebel可以应用于各种开发场景,包括本地开发、远程开发、云开发等。无论是单机开发还是分布式开发,JRebel都可以提供实时代码重载的功能。
总的来说,JRebel是一个强大的Java开发工具,它通过实时代码重载的功能,使开发人员能够在不重新启动应用程序的情况下,快速应用他们对Java代码的修改。这大大提高了开发效率,减少了开发周期,使开发人员能够更专注于代码的编写和调试。
打开IDEA,选择File—>Settings—>Plugins—>在搜索框输入jrebel
首先下载服务,进入GitHub网址Release v1.4 · ilanyu/ReverseProxy · GitHub
下载到指定位置后双击启动即可,如下图:
启动后,就可以打开idea进行激活,如不打开服务则会出现如下错误:
在线生成GUID网址:GUID online erstellen
如果失效刷新GUID替换就可以!
服务器地址:https://127.0.0.1:8888/{GUID}
输入服务器地址,将{GUID}替换成上面的字符串,注意要除去{},然后再输入邮箱,只需正确的邮箱格式即可。
最后成功的界面:
安装成功之后就可以通过JRebel启动项目。这样修改完Java代码后,就可以不再需要重启服务器这样浪费时间的操作了。
1. 设置成离线工作模式
设置成离线模式后就不需要启动 ReverseProxy_windows_amd64 服务了
点击设置成离线模式后,如下图:
2. 设置自动编译
要想实现热部署,首先需要对Intellij按如下进行设置:
由于JRebel是实时监控class文件的变化来实现热部署的,所以在idea环境下需要打开自动变异功能才能实现随时修改,随时生效。
通过Jrebel启动项目之前需要打开Jrebel服务,不然就会出错,正确启动项目后不要把服务关闭,先关服务器(tomcat)再关掉Jrebel服务。如需使用离线模式,也不能先关jrebel服务,设置好、关掉tomcat最后才关Jrebel服务,之后就再也不需要开启Jrebel服务就可以直接通过Jrebel启动项目了。
1.3.3 commons-fileupload commons-fileupload${commons-fileupload.version}
在spring-mvc.xml文件中添加文件上传解析器。
这段代码配置了一个名为"multipartResolver"的Bean,用于处理文件上传。通过设置"defaultEncoding"属性、"maxUploadSize"属性和"resolveLazily"属性,可以指定文件上传时的字符编码、最大上传大小和延迟文件解析的行为。这样,Spring框架在处理文件上传时会根据这些配置进行相应的解析和限制。
定义一个简单的文件上传表单页面,设置enctype属性指定了表单数据的编码类型为"multipart/form-data",这是用于支持文件上传的编码类型。然后设置上传的文件将会被命名为"imgFile"用于被后台接受,最后将文件上传到指定的URL。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>文件上传
步骤一:设计数据表
步骤二:配置表信息,并生成代码
generatorConfig.xml :
步骤三:创建业务逻辑层并实现接口...
步骤四:配置文件路径信息
resource.properties:
#本地路径 dir=D:/upload/ #服务器路径 server=/upload/
编写配置文件读取工具类
package com.ycxw.utils; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * 配置文件读取工具类 * @author 云村小威 * @site blog.csdn.net/Justw320 * @create 2023-09-10 16:57 */ public class PropertiesUtil { public static String getValue(String key) throws IOException { Properties p = new Properties(); InputStream in = PropertiesUtil.class.getResourceAsStream("/resource.properties"); p.load(in); return p.getProperty(key); } }
步骤五:配置项目与映射地址
步骤六:编写控制器
package com.ycxw.web; import com.ycxw.biz.UploadImgBiz; import com.ycxw.model.UploadImg; import com.ycxw.utils.PageBean; import com.ycxw.utils.PropertiesUtil; import org.apache.commons.io.FileUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.util.List; /** * @author 云村小威 * @site blog.csdn.net/Justw320 * @create 2023-09-10 16:50 */ @Controller @RequestMapping("/file") public class UploadImgController { @Autowired private UploadImgBiz uploadImgBiz; /*新增方法*/ @RequestMapping("/add") public String save(UploadImg uploadImg, HttpServletRequest request) { uploadImgBiz.insertSelective(uploadImg); return "redirect:list"; } /*删除方法*/ @RequestMapping("/del/{id}") public String del(@PathVariable("id") Integer id) { uploadImgBiz.deleteByPrimaryKey(id); return "redirect:/file/list"; } /*修改方法*/ @RequestMapping("/edit") public String edit(UploadImg uploadImg, HttpServletRequest request) { uploadImgBiz.updateByPrimaryKeySelective(uploadImg); return "redirect:list"; } /*查询方法*/ @RequestMapping("/list") public String list(UploadImg uploadImg, HttpServletRequest request) { PageBean pageBean = new PageBean(); pageBean.setRequest(request); ListuploadImgs = uploadImgBiz.listPager(uploadImg, pageBean); // ModelAndView modelAndView = new ModelAndView(); // modelAndView.addObject("UploadImgs", UploadImgs); // modelAndView.addObject("pageBean", pageBean); // modelAndView.setViewName("UploadImg/list"); request.setAttribute("uploadImgs", uploadImgs); request.setAttribute("pageBean", pageBean); return "file/list"; } /*数据回显*/ @RequestMapping("/preSave") public String preSave(UploadImg uploadImg, HttpServletRequest request) { if (uploadImg != null && uploadImg.getId() != null && uploadImg.getId() != 0) { UploadImg img = uploadImgBiz.selectByPrimaryKey(uploadImg.getId()); request.setAttribute("img", img); } return "file/edit"; } /*图片上传*/ @RequestMapping("upload") public String upload(UploadImg img,MultipartFile imgFile) throws IOException { //读取配置文夹本地路径和服务器路径 String dir = PropertiesUtil.getValue("dir"); String server = PropertiesUtil.getValue("server"); //利用MultipartFile类接受前端传递到后台的文件 System.out.println("文件名:"+imgFile.getOriginalFilename()); System.out.println("文件类型:"+imgFile.getContentType()); //将文件转成流写入到服务器 FileUtils.copyInputStreamToFile(imgFile.getInputStream(),new File(dir+imgFile.getOriginalFilename())); //通过对象将图片保存到数据库 img.setImg(server+imgFile.getOriginalFilename()); uploadImgBiz.updateByPrimaryKeySelective(img); return "redirect:list"; } }
步骤七:编写前端jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="w" uri="http://jsp.veryedu.cn" %>博客列表
ID | 用户 | 图片 | |
---|---|---|---|
${i.id } | ${i.name } | 修改 删除 图片上传 图片下载 |
步骤8:运行测试
根据传入的文件id查询对应的文件信息,然后根据文件路径读取文件内容,并将文件内容和设置好的HTTP头信息封装成一个ResponseEntity对象,最后返回给客户端进行文件下载。
@RequestMapping("/download") public ResponseEntitydownload(UploadImg uploadImg, HttpServletRequest req){ try { //先根据文件id查询对应图片信息 UploadImg img = this.uploadImgBiz.selectByPrimaryKey(uploadImg.getId()); String diskPath = PropertiesUtil.getValue("dir"); String reqPath = PropertiesUtil.getValue("server"); //上面获取的数据库地址,需要转换才能下载成本地路径 String realPath = img.getImg().replace(reqPath,diskPath); String fileName = realPath.substring(realPath.lastIndexOf("/")+1); //下载关键代码 File file=new File(realPath); HttpHeaders headers = new HttpHeaders();//http头信息 String downloadFileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");//设置编码 headers.setContentDispositionFormData("attachment", downloadFileName); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); //MediaType:互联网媒介类型 contentType:具体请求中的媒体类型信息 return new ResponseEntity (FileUtils.readFileToByteArray(file),headers, HttpStatus.OK); }catch (Exception e){ e.printStackTrace(); } return null; }
示例:
1. 编写方法:
@RequestMapping("/download") public ResponseEntitydownload(UploadImg uploadImg, HttpServletRequest req) { try { //先根据文件id查询对应图片信息 UploadImg img = this.uploadImgBiz.selectByPrimaryKey(uploadImg.getId()); String diskPath = PropertiesUtil.getValue("dir"); String reqPath = PropertiesUtil.getValue("server"); //上面获取的数据库地址,需要转换才能下载成本地路径 String realPath = img.getImg().replace(reqPath, diskPath); String fileName = realPath.substring(realPath.lastIndexOf("/") + 1); //下载关键代码 File file = new File(realPath); HttpHeaders headers = new HttpHeaders();//http头信息 String downloadFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");//设置编码 headers.setContentDispositionFormData("attachment", downloadFileName); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); //MediaType:互联网媒介类型 contentType:具体请求中的媒体类型信息 return new ResponseEntity (FileUtils.readFileToByteArray(file), headers, HttpStatus.OK); } catch (Exception e) { e.printStackTrace(); } return null; }
2. 编写前端页面做对比:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>文件上传 单文件上传
3. 运行测试
如下图,多文件上传选择了10个文件,而单文件上传功能使用ctrl+选择是无效的,只能选择当个文件。
接下测试多文件上传是否能在本地查看
选择多张图片的时候需要注意设置文件上传的大小,还有数据库存储图片的字段的类型长度是否超过,这都会影响文件是否能上传成功。因为多张图片的空间累计需要更多的空间,通过避免图片名称过长,查看存储该字段的长度是否能装的下。