【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依赖

 <commons-fileupload.version>1.3.3</commons-fileupload.version><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>${commons-fileupload.version}</version></dependency>

2.2 配置文件上传解析器

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

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 必须和用户JSP 的pageEncoding属性一致,以便正确解析表单的内容 --><property name="defaultEncoding" value="UTF-8"></property><!-- 文件最大大小(字节) 1024*1024*50=50M--><property name="maxUploadSize" value="52428800"></property><!--resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常--><property name="resolveLazily" value="true"/>
</bean>

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

2.3 文件上传表单设置

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

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><base href="${pageContext.request.contextPath }"><title>文件上传</title>
</head>
<body>
<form action="/file/upload" method="post" enctype="multipart/form-data"><label>编号:</label><input type="text" name="id" readonly="readonly" value="${param.id}"/><br/><label>图片:</label><input type="file" name="imgFile"/><br/><input type="submit" value="上传图片"/>
</form>
</body>
</html>

2.4 文件上传实现

步骤一:设计数据表

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

generatorConfig.xml :  

        <table schema="" tableName="img_upload" domainObjectName="UploadImg"enableCountByExample="false" enableDeleteByExample="false"enableSelectByExample="false" enableUpdateByExample="false"></table>

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

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

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 {@Autowiredprivate 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);List<UploadImg> uploadImgs = 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" %>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><linkhref="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css"rel="stylesheet"><scriptsrc="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script><base href="${pageContext.request.contextPath }"><title>博客列表</title><style type="text/css">.page-item input {padding: 0;width: 40px;height: 100%;text-align: center;margin: 0 6px;}.page-item input, .page-item b {line-height: 38px;float: left;font-weight: 400;}.page-item.go-input {margin: 0 10px;}</style>
</head>
<body>
<form class="form-inline"action="/file/list" method="post"><div class="form-group mb-2"><input type="text" class="form-control-plaintext" name="name"placeholder="请输入用户名称"></div><button type="submit" class="btn btn-primary mb-2">查询</button><a class="btn btn-primary mb-2" href="/file/preSave">新增</a>
</form><table class="table table-striped"><thead><tr><th scope="col">ID</th><th scope="col">用户</th><th scope="col">图片</th></tr></thead><tbody><c:forEach var="i" items="${uploadImgs }"><tr><td>${i.id }</td><td>${i.name }</td><td><img src="${i.img }" style="width: 200px;height: 100px;"></td><td><a href="/file/preSave?id=${i.id}">修改</a><a href="/file/del/${i.id}">删除</a><a href="/page/file/upload?id=${i.id}">图片上传</a><a href="/file/download?id=${i.id}">图片下载</a></td></tr></c:forEach></tbody>
</table>
<!-- 这一行代码就相当于前面分页需求前端的几十行了 -->
<w:page pageBean="${pageBean }"></w:page></body>
</html>

 步骤8:运行测试

2.5 文件下载实现

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

   @RequestMapping("/download")public ResponseEntity<byte[]> download(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<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);}catch (Exception e){e.printStackTrace();}return null;}

 示例:

2.6 多文件上传、下载

1. 编写方法:

 @RequestMapping("/download")public ResponseEntity<byte[]> download(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<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);} catch (Exception e) {e.printStackTrace();}return null;}

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

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><base href="${pageContext.request.contextPath }"><title>文件上传</title>
</head>
<body>
<h3>单文件上传</h3>
<form action="/file/upload" method="post" enctype="multipart/form-data"><label>编号:</label><input type="text" name="id" readonly="readonly" value="${param.id}"/><br/><label>图片:</label><input type="file" name="imgFile"/><br/><input type="submit" value="上传图片"/>
</form>
<br>
<h3>多文件上传</h3>
<form method="post" action="/file/uploads" enctype="multipart/form-data"><input type="file" name="files" multiple><button type="submit">上传</button>
</form>
</body>
</html>

3. 运行测试 

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

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

注意事项

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/74850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第十八天|513. 找树左下角的值|112. 路径总和|106. 从中序与后序遍历序列构造二叉树

513. 找树左下角的值 题目&#xff1a;给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1 思路一&#xff1a;层序遍历&#xff0c;最后一层的第一个元素&#xff0c;即…

基于51单片机DS18B20温度及电流检测-proteus仿真-源程序

一、系统方案 本设计采用52单片机作为主控器&#xff0c;液晶1602显示&#xff0c;DS18B20检测温度&#xff0c;电流检测。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 void lcd_init() //lcd 初始化设置子函数&#xff0c;不带参数 ,0x…

持安科技入选数说安全《2023中国网络安全市场年度报告》

近日&#xff0c;网络安全产业研究平台数说安全发布《2023中国网络安全市场年度报告》&#xff0c;报告共分为158页核心报告&#xff0c;及番外篇《网安融资新星及融资过亿企业介绍》&#xff0c;作为以甲方身份创业的零信任办公安全明星企业&#xff0c;持安科技以网安融资新星…

MATLAB R2023a完美激活版(附激活补丁)

MATLAB R2023a是一款面向科学和工程领域的高级数学计算和数据分析软件&#xff0c;它为Mac用户提供了强大的工具和功能&#xff0c;用于解决各种复杂的数学和科学问题。以下是MATLAB R2023a Mac的一些主要特点和功能&#xff1a; 软件下载&#xff1a;MATLAB R2023a完美激活版 …

select多选回显问题 (取巧~)

要实现的效果&#xff1a; 实际上select选择框&#xff0c;我想要的是数组对象&#xff0c;但是后端返回来的是个字符串。 以下是解决方法&#xff1a; 以上是一种简单的解决方法~ 也可以自己处理数据或者让后端直接改成想要的格式。

Kafka3.0.0版本——消费者(手动提交offset)

目录 一、消费者&#xff08;手动提交 offset&#xff09;的概述1.1、手动提交offset的两种方式1.2、手动提交offset两种方式的区别1.3、手动提交offset的图解 二、消费者&#xff08;手动提交 offset&#xff09;的代码示例2.1、手动提交 offset&#xff08;采用同步提交的方式…

Python爬虫 教程:IP池的使用

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 一、简介 爬虫中为什么需要使用代理 一些网站会有相应的反爬虫措施&#xff0c;例如很多网站会检测某一段时间某个IP的访问次数&#xff0c;如果访问频率…

[SICTF 2023 #Round2] Crypto,PWN,Reverse

似乎很久没写了。 周五到周日&#xff0c;两天的这个比赛&#xff0c;有些东西还真是头回用&#xff0c;值得纪录一下。 Crypto 密码这块这届还是比较简单的&#xff0c;没有复杂的题&#xff0c;但量大分多。 【签到】古典大杂烩 给了一堆emoji的图 &#x1f429;&#x…

GCP Architect之VPN+Network

VPN 搜索结果共计:11 [单选]As part of implementing their disaster recovery plan, your company is trying to replicate their production MySQL database from their private data center to their GCP project using a Google Cloud VPN connection. They are experien…

OpenCV(三十四):轮廓外接最大、最小矩形和多边形拟合

目录 1.轮廓外接最大矩形boundingRect() 2.轮廓外接最小矩形minAreaRect() 3.轮廓外接多边形approxPolyDP() 1.轮廓外接最大矩形boundingRect() Rect cv::boundingRect ( InputArray array ) array:输入的灰度图像或者2D点集&#xff0c;数据类型为vector<Point>或者M…

Go语言的[GPM模型]

在go中,线程是运行Groutine的实体,调度器的功能是把可以运行的Groutine分配到工作线程上 GPM模型 M与P的数量没有绝对的数量关系,当一个M阻塞时,P就会创建一个或者切换到另一个M,所以即使设置了runtime.GOMAXPROCS(1) 也可能创建多个M出来; 当M发现给自己输送G协程的那个P队列为…

《AI一键生成抖音商品种草文案》让你秒变带货王!

在这个数字化的时代&#xff0c;我们的生活被各种应用所包围&#xff0c;其中&#xff0c;抖音作为一款短视频分享平台&#xff0c;已经成为了我们生活中不可或缺的一部分。然而&#xff0c;作为一名抖音创作者&#xff0c;你是否曾经遇到过这样的困扰&#xff1a;在创作商品种…

C#程序到底从哪里开始看,从Main函数开始,那么Main函数是什么?

视觉人机器视觉粉丝问我,拿到自己公司得架构,问我,C#程序到底从哪里看,从Main函数开始,那么Main函数是什么? Main()函数 Main()是C#应用程序的入口点,执行这个函数就是执行应用程序。也就是说,在执行过程开始时,会执行Main()函数,在Main()函数执行完毕时,执行过…

【JavaSpring】spring接口-beanfactory和applicationcontext与事件解耦

beanfactory 1.applicationcontext的父接口 2.是Spring的核心容器 功能 表面只有getBean&#xff0c;但实现类默默发挥了巨大作用 1.管理所有bean 2.控制反转 3.基本的依赖注入 applicationcontext 功能 1.继承了MessageSource&#xff0c;有了处理国际化资源的能力 …

[H5动画制作系列] Sprite及Text Demo

参考代码: sprite.js: var canvas, stage, container; canvas document.getElementById("mainView"); function init() {stage new createjs.Stage(canvas);createjs.Touch.enable(stage);var loader new createjs.LoadQueue(false);loader.addEventListener(&q…

云计算与虚拟化

一、概念 什么是云计算&#xff1f; 云计算&#xff08;cloud computing&#xff09;是分布式计算的一种&#xff0c;指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序&#xff0c;然后&#xff0c;通过多部服务器组成的系统进行处理和分析这些小程序得到结果…

SLAM论文详解(5) — Bundle_Adjustment_LM(BALM)论文详解

目录 1 摘要 2 相关工作 3 BA公式和导数 A. 直接BA公式 B. 导数 C. 二阶近似 4 自适应体素化 5. 将BALM结合进LOAM 6. 实验 7. 算法应用场景解析 1 摘要 Bundle Adjustment是一种用于同时估计三维结构和传感器运动运动的优化算法。在视觉SLAM&#xff0c;三维重建等…

爬虫逆向实战(30)-某查查股东关联公司(HmacSHA512)

一、数据接口分析 主页地址&#xff1a;某查查 1、抓包 通过抓包可以发现数据接口是api/people/getRelatCompany 2、判断是否有加密参数 请求参数是否加密&#xff1f; 无 请求头是否加密&#xff1f; 通过查看“标头”可以发现&#xff0c;请求头中有一个key和value都是…

基于Sentinel的微服务保护

前言 Sentinel是Alibaba开源的一款微服务流控组件&#xff0c;用于解决分布式应用场景下服务的稳定性问题。Sentinel具有丰富的应用场景&#xff0c;它基于流量提供一系列的服务保护措施&#xff0c;例如多线程秒杀情况下的系统承载&#xff0c;并发访问下的流量控制&#xff…

9.8day59

503. 下一个更大元素 II - 力扣&#xff08;LeetCode&#xff09; 知识点&#xff1a;单调栈 42. 接雨水 - 力扣&#xff08;LeetCode&#xff09;