• 【SpringMVC】Jrebel 插件实现热部署与文件上传


    目录

    一、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

    1.1 Jrebel介绍

            JRebel是一个Java开发工具,它是一款用于实时代码重载的插件。它的主要功能是在不重新启动应用程序的情况下,将修改后的Java代码实时应用到正在运行的应用程序中,从而加快开发周期,提高开发效率。

    1. 实时代码重载:JRebel可以监测开发人员对Java代码的修改,并将这些修改实时应用到正在运行的应用程序中,无需重新启动应用程序。这样,开发人员可以立即看到他们的代码更改的效果,节省了重新编译和部署的时间。

    2. 支持多种框架和服务器:JRebel支持多种Java框架和服务器,包括Spring、Hibernate、Java EE、Tomcat、Jetty等。无论是开发Web应用程序还是企业级应用程序,JRebel都可以与常用的开发框架和服务器集成,提供实时代码重载的功能。

    3. 高度兼容性:JRebel与大多数Java开发工具和集成开发环境(IDE)兼容,如Eclipse、IntelliJ IDEA、NetBeans等。开发人员可以在他们喜欢的IDE中使用JRebel插件,无需切换到其他工具。

    4. 快速部署:JRebel可以加快应用程序的部署速度,因为它只需要将修改后的代码应用到运行中的应用程序,而不需要重新启动整个应用程序。这对于大型应用程序和复杂的部署环境特别有用。

    5. 支持多种开发场景:JRebel可以应用于各种开发场景,包括本地开发、远程开发、云开发等。无论是单机开发还是分布式开发,JRebel都可以提供实时代码重载的功能。

            总的来说,JRebel是一个强大的Java开发工具,它通过实时代码重载的功能,使开发人员能够在不重新启动应用程序的情况下,快速应用他们对Java代码的修改。这大大提高了开发效率,减少了开发周期,使开发人员能够更专注于代码的编写和调试。

    1.2 Jrebel插件下载

    打开IDEA,选择File—>Settings—>Plugins—>在搜索框输入jrebel

    1.3 Jrebel服务下载并启动

    首先下载服务,进入GitHub网址Release v1.4 · ilanyu/ReverseProxy · GitHub

    下载到指定位置后双击启动即可,如下图:

    启动后,就可以打开idea进行激活,如不打开服务则会出现如下错误:

    1.4 在线生成GUID

     在线生成GUID网址:GUID online erstellen

    如果失效刷新GUID替换就可以! 

    1.5 JRebel激活 

    服务器地址:https://127.0.0.1:8888/{GUID}

    输入服务器地址,将{GUID}替换成上面的字符串,注意要除去{},然后再输入邮箱,只需正确的邮箱格式即可。

     最后成功的界面:

             安装成功之后就可以通过JRebel启动项目。这样修改完Java代码后,就可以不再需要重启服务器这样浪费时间的操作了。

    1.6 相关设置

    1. 设置成离线工作模式 

    设置成离线模式后就不需要启动 ReverseProxy_windows_amd64 服务了

     点击设置成离线模式后,如下图:

    2. 设置自动编译

    要想实现热部署,首先需要对Intellij按如下进行设置:

            由于JRebel是实时监控class文件的变化来实现热部署的,所以在idea环境下需要打开自动变异功能才能实现随时修改,随时生效。

    注意事项

            通过Jrebel启动项目之前需要打开Jrebel服务,不然就会出错,正确启动项目后不要把服务关闭,先关服务器(tomcat)再关掉Jrebel服务。如需使用离线模式,也不能先关jrebel服务,设置好、关掉tomcat最后才关Jrebel服务,之后就再也不需要开启Jrebel服务就可以直接通过Jrebel启动项目了。

    二、文件上传、下载

    2.1 导入pom依赖

    1. <commons-fileupload.version>1.3.3commons-fileupload.version>
    2. <dependency>
    3. <groupId>commons-fileuploadgroupId>
    4. <artifactId>commons-fileuploadartifactId>
    5. <version>${commons-fileupload.version}version>
    6. dependency>

    2.2 配置文件上传解析器

    在spring-mvc.xml文件中添加文件上传解析器。

    1. "multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    2. "defaultEncoding" value="UTF-8">
    3. "maxUploadSize" value="52428800">
    4. "resolveLazily" value="true"/>

            这段代码配置了一个名为"multipartResolver"的Bean,用于处理文件上传。通过设置"defaultEncoding"属性、"maxUploadSize"属性和"resolveLazily"属性,可以指定文件上传时的字符编码、最大上传大小和延迟文件解析的行为。这样,Spring框架在处理文件上传时会根据这些配置进行相应的解析和限制。 

    2.3 文件上传表单设置

            定义一个简单的文件上传表单页面,设置enctype属性指定了表单数据的编码类型为"multipart/form-data",这是用于支持文件上传的编码类型。然后设置上传的文件将会被命名为"imgFile"用于被后台接受,最后将文件上传到指定的URL。

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. "${pageContext.request.contextPath }">
    3. 文件上传
    4. "/file/upload" method="post" enctype="multipart/form-data">
    5. "text" name="id" readonly="readonly" value="${param.id}"/>
    6. "file" name="imgFile"/>
    7. "submit" value="上传图片"/>

    2.4 文件上传实现

    步骤一:设计数据表

    步骤二:配置表信息,并生成代码

    generatorConfig.xml :  

    1. "" tableName="img_upload" domainObjectName="UploadImg"
    2. enableCountByExample="false" enableDeleteByExample="false"
    3. enableSelectByExample="false" enableUpdateByExample="false">

    步骤三:创建业务逻辑层并实现接口...

    步骤四:配置文件路径信息

    resource.properties:

    1. #本地路径
    2. dir=D:/upload/
    3. #服务器路径
    4. server=/upload/

    编写配置文件读取工具类

    1. package com.ycxw.utils;
    2. import java.io.IOException;
    3. import java.io.InputStream;
    4. import java.util.Properties;
    5. /**
    6. * 配置文件读取工具类
    7. * @author 云村小威
    8. * @site blog.csdn.net/Justw320
    9. * @create 2023-09-10 16:57
    10. */
    11. public class PropertiesUtil {
    12. public static String getValue(String key) throws IOException {
    13. Properties p = new Properties();
    14. InputStream in = PropertiesUtil.class.getResourceAsStream("/resource.properties");
    15. p.load(in);
    16. return p.getProperty(key);
    17. }
    18. }

    步骤五:配置项目与映射地址 

    步骤六:编写控制器

    1. package com.ycxw.web;
    2. import com.ycxw.biz.UploadImgBiz;
    3. import com.ycxw.model.UploadImg;
    4. import com.ycxw.utils.PageBean;
    5. import com.ycxw.utils.PropertiesUtil;
    6. import org.apache.commons.io.FileUtils;
    7. import org.springframework.beans.factory.annotation.Autowired;
    8. import org.springframework.stereotype.Controller;
    9. import org.springframework.web.bind.annotation.PathVariable;
    10. import org.springframework.web.bind.annotation.RequestMapping;
    11. import org.springframework.web.multipart.MultipartFile;
    12. import javax.servlet.http.HttpServletRequest;
    13. import java.io.File;
    14. import java.io.IOException;
    15. import java.util.List;
    16. /**
    17. * @author 云村小威
    18. * @site blog.csdn.net/Justw320
    19. * @create 2023-09-10 16:50
    20. */
    21. @Controller
    22. @RequestMapping("/file")
    23. public class UploadImgController {
    24. @Autowired
    25. private UploadImgBiz uploadImgBiz;
    26. /*新增方法*/
    27. @RequestMapping("/add")
    28. public String save(UploadImg uploadImg, HttpServletRequest request) {
    29. uploadImgBiz.insertSelective(uploadImg);
    30. return "redirect:list";
    31. }
    32. /*删除方法*/
    33. @RequestMapping("/del/{id}")
    34. public String del(@PathVariable("id") Integer id) {
    35. uploadImgBiz.deleteByPrimaryKey(id);
    36. return "redirect:/file/list";
    37. }
    38. /*修改方法*/
    39. @RequestMapping("/edit")
    40. public String edit(UploadImg uploadImg, HttpServletRequest request) {
    41. uploadImgBiz.updateByPrimaryKeySelective(uploadImg);
    42. return "redirect:list";
    43. }
    44. /*查询方法*/
    45. @RequestMapping("/list")
    46. public String list(UploadImg uploadImg, HttpServletRequest request) {
    47. PageBean pageBean = new PageBean();
    48. pageBean.setRequest(request);
    49. List uploadImgs = uploadImgBiz.listPager(uploadImg, pageBean);
    50. // ModelAndView modelAndView = new ModelAndView();
    51. // modelAndView.addObject("UploadImgs", UploadImgs);
    52. // modelAndView.addObject("pageBean", pageBean);
    53. // modelAndView.setViewName("UploadImg/list");
    54. request.setAttribute("uploadImgs", uploadImgs);
    55. request.setAttribute("pageBean", pageBean);
    56. return "file/list";
    57. }
    58. /*数据回显*/
    59. @RequestMapping("/preSave")
    60. public String preSave(UploadImg uploadImg, HttpServletRequest request) {
    61. if (uploadImg != null && uploadImg.getId() != null && uploadImg.getId() != 0) {
    62. UploadImg img = uploadImgBiz.selectByPrimaryKey(uploadImg.getId());
    63. request.setAttribute("img", img);
    64. }
    65. return "file/edit";
    66. }
    67. /*图片上传*/
    68. @RequestMapping("upload")
    69. public String upload(UploadImg img,MultipartFile imgFile) throws IOException {
    70. //读取配置文夹本地路径和服务器路径
    71. String dir = PropertiesUtil.getValue("dir");
    72. String server = PropertiesUtil.getValue("server");
    73. //利用MultipartFile类接受前端传递到后台的文件
    74. System.out.println("文件名:"+imgFile.getOriginalFilename());
    75. System.out.println("文件类型:"+imgFile.getContentType());
    76. //将文件转成流写入到服务器
    77. FileUtils.copyInputStreamToFile(imgFile.getInputStream(),new File(dir+imgFile.getOriginalFilename()));
    78. //通过对象将图片保存到数据库
    79. img.setImg(server+imgFile.getOriginalFilename());
    80. uploadImgBiz.updateByPrimaryKeySelective(img);
    81. return "redirect:list";
    82. }
    83. }

    步骤七:编写前端jsp

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    3. <%@ taglib prefix="w" uri="http://jsp.veryedu.cn" %>
    4. "Content-Type" content="text/html; charset=UTF-8">
    5. href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css"
    6. rel="stylesheet">
    7. src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js">
    8. "${pageContext.request.contextPath }">
    9. 博客列表
    10. "form-inline"
    11. action="/file/list" method="post">
    12. "form-group mb-2">
    13. "text" class="form-control-plaintext" name="name"
    14. placeholder="请输入用户名称">
  • "table table-striped">
  • var="i" items="${uploadImgs }">
  • "col">ID"col">用户"col">图片
    ${i.id }${i.name }
  • "${i.img }" style="width: 200px;height: 100px;">
  • "${pageBean }">
  •  步骤8:运行测试

    2.5 文件下载实现

            根据传入的文件id查询对应的文件信息,然后根据文件路径读取文件内容,并将文件内容和设置好的HTTP头信息封装成一个ResponseEntity对象,最后返回给客户端进行文件下载。

    1. @RequestMapping("/download")
    2. public ResponseEntity<byte[]> download(UploadImg uploadImg, HttpServletRequest req){
    3. try {
    4. //先根据文件id查询对应图片信息
    5. UploadImg img = this.uploadImgBiz.selectByPrimaryKey(uploadImg.getId());
    6. String diskPath = PropertiesUtil.getValue("dir");
    7. String reqPath = PropertiesUtil.getValue("server");
    8. //上面获取的数据库地址,需要转换才能下载成本地路径
    9. String realPath = img.getImg().replace(reqPath,diskPath);
    10. String fileName = realPath.substring(realPath.lastIndexOf("/")+1);
    11. //下载关键代码
    12. File file=new File(realPath);
    13. HttpHeaders headers = new HttpHeaders();//http头信息
    14. String downloadFileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");//设置编码
    15. headers.setContentDispositionFormData("attachment", downloadFileName);
    16. headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    17. //MediaType:互联网媒介类型 contentType:具体请求中的媒体类型信息
    18. return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);
    19. }catch (Exception e){
    20. e.printStackTrace();
    21. }
    22. return null;
    23. }

     示例:

    2.6 多文件上传、下载

    1. 编写方法:

    1. @RequestMapping("/download")
    2. public ResponseEntity<byte[]> download(UploadImg uploadImg, HttpServletRequest req) {
    3. try {
    4. //先根据文件id查询对应图片信息
    5. UploadImg img = this.uploadImgBiz.selectByPrimaryKey(uploadImg.getId());
    6. String diskPath = PropertiesUtil.getValue("dir");
    7. String reqPath = PropertiesUtil.getValue("server");
    8. //上面获取的数据库地址,需要转换才能下载成本地路径
    9. String realPath = img.getImg().replace(reqPath, diskPath);
    10. String fileName = realPath.substring(realPath.lastIndexOf("/") + 1);
    11. //下载关键代码
    12. File file = new File(realPath);
    13. HttpHeaders headers = new HttpHeaders();//http头信息
    14. String downloadFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");//设置编码
    15. headers.setContentDispositionFormData("attachment", downloadFileName);
    16. headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    17. //MediaType:互联网媒介类型 contentType:具体请求中的媒体类型信息
    18. return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);
    19. } catch (Exception e) {
    20. e.printStackTrace();
    21. }
    22. return null;
    23. }

     2. 编写前端页面做对比:

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. "${pageContext.request.contextPath }">
    3. 文件上传
    4. 单文件上传

    5. "/file/upload" method="post" enctype="multipart/form-data">
    6. "text" name="id" readonly="readonly" value="${param.id}"/>
    7. "file" name="imgFile"/>
    8. "submit" value="上传图片"/>

    9. 多文件上传

    10. "post" action="/file/uploads" enctype="multipart/form-data">
    11. "file" name="files" multiple>

    3. 运行测试 

            如下图,多文件上传选择了10个文件,而单文件上传功能使用ctrl+选择是无效的,只能选择当个文件。

    接下测试多文件上传是否能在本地查看

    注意事项

            选择多张图片的时候需要注意设置文件上传的大小,还有数据库存储图片的字段的类型长度是否超过,这都会影响文件是否能上传成功。因为多张图片的空间累计需要更多的空间,通过避免图片名称过长,查看存储该字段的长度是否能装的下。

  • 相关阅读:
    Cy3.5 NHS ester/琥珀酰亚胺活化酯,Cyanine3.5 NHS ester/琥珀酰亚胺活化酯(Methyl)
    c/c++的include机制简述
    Golang 基础之基础语法梳理 (三)
    vim常用命令
    猴子也能学会的jQuery第三期——使用jQuery
    uni-app 之 去掉顶部导航
    kubernetes部署
    RabbitMQ-消息模型
    LaaS LLM as a service
    企业现在开始准备应对2024技术趋势了
  • 原文地址:https://blog.csdn.net/Justw320/article/details/132777189