Tabla de contenido
1.2 Descarga del complemento Jrebel
1.3 Descargue e inicie el servicio Jrebel
1.6 Configuraciones relacionadas
2. Carga y descarga de archivos
2.1 Importar dependencias de pom
2.2 Analizador de carga de archivos de configuración
2.3 Configuración del formulario de carga de archivos
2.4 Implementación de carga de archivos
2.5 Implementación de descarga de archivos
2.6 Carga y descarga de múltiples archivos
1. JRebel
1.1 Introducción a Jrebel
JRebel es una herramienta de desarrollo de Java y un complemento para recargar código en tiempo real. Su función principal es aplicar código Java modificado a aplicaciones en ejecución en tiempo real sin reiniciar la aplicación, acelerando así el ciclo de desarrollo y mejorando la eficiencia del desarrollo.
-
Recarga de código en vivo: JRebel puede monitorear las modificaciones de los desarrolladores al código Java y aplicar estas modificaciones a las aplicaciones en ejecución en tiempo real sin reiniciar la aplicación. De esta manera, los desarrolladores pueden ver inmediatamente los efectos de los cambios en su código, ahorrando tiempo en la recompilación y la implementación.
-
Admite múltiples marcos y servidores: JRebel admite múltiples marcos y servidores Java, incluidos Spring, Hibernate, Java EE, Tomcat, Jetty, etc. Ya sea que esté desarrollando aplicaciones web o aplicaciones de nivel empresarial, JRebel se puede integrar con servidores y marcos de desarrollo de uso común para proporcionar recarga de código en tiempo real.
-
Alta compatibilidad: JRebel es compatible con la mayoría de las herramientas de desarrollo Java y entornos de desarrollo integrados (IDE), como Eclipse, IntelliJ IDEA, NetBeans, etc. Los desarrolladores pueden utilizar el complemento JRebel en su IDE favorito sin cambiar a otra herramienta.
-
Implementación rápida: JRebel puede acelerar la implementación de aplicaciones porque solo necesita aplicar código modificado a la aplicación en ejecución sin reiniciar toda la aplicación. Esto es especialmente útil para aplicaciones grandes y entornos de implementación complejos.
-
Admite múltiples escenarios de desarrollo: JRebel se puede aplicar a varios escenarios de desarrollo, incluido el desarrollo local, el desarrollo remoto, el desarrollo en la nube, etc. Ya sea que se trate de desarrollo independiente o desarrollo distribuido, JRebel puede proporcionar recarga de código en tiempo real.
En general, JRebel es una potente herramienta de desarrollo de Java que permite a los desarrolladores aplicar rápidamente sus modificaciones al código Java sin reiniciar la aplicación mediante la función de recarga de código en tiempo real. Esto mejora enormemente la eficiencia del desarrollo, reduce el ciclo de desarrollo y permite a los desarrolladores centrarse más en escribir y depurar código.
1.2 Descarga del complemento Jrebel
Abra IDEA, seleccione Archivo—>Configuración—>Complementos—>ingrese jrebel en el cuadro de búsqueda
1.3 Descargue e inicie el servicio Jrebel
Primero descargue el servicio e ingrese al sitio web de GitHub. Versión v1.4 · ilanyu/ReverseProxy · GitHub
Después de descargar en la ubicación especificada, haga doble clic para comenzar, como se muestra a continuación:
Después de comenzar, puede abrir la idea para la activación, si no abre el servicio, aparecerá el siguiente error:
1.4 Generar GUID en línea
Generar URL GUID en línea: GUID en línea erstellen
Si falla, simplemente actualice el GUID y reemplácelo.
1.5 Activación de JRebel
Dirección del servidor: https://127.0.0.1:8888/
{GUID}
Ingrese la dirección del servidor, reemplace {GUID} con la cadena anterior, tenga cuidado de eliminar {} y luego ingrese la dirección de correo electrónico. Simplemente use el formato de correo electrónico correcto.
La interfaz final exitosa:
Después de una instalación exitosa, puede iniciar el proyecto a través de JRebel. Después de modificar el código Java de esta manera, ya no es necesaria la lenta operación de reiniciar el servidor.
1.6 Configuraciones relacionadas
1. Establecer el modo de trabajo fuera de línea
Después de configurar el modo fuera de línea, no es necesario iniciar el servicio ReverseProxy_windows_amd64.
Después de hacer clic para configurar el modo fuera de línea, como se muestra a continuación:
2. Configurar la compilación automática
Para implementar la implementación en caliente, primero debe configurar Intellij de la siguiente manera:
Dado que JRebel monitorea los cambios en los archivos de clase en tiempo real para lograr una implementación en caliente, la función de mutación automática debe activarse en el entorno de la idea para realizar modificaciones en cualquier momento y surtir efecto en cualquier momento.
Cosas a tener en cuenta ❗
Debe abrir el servicio Jrebel antes de iniciar el proyecto a través de Jrebel, de lo contrario se producirá un error. No cierre el servicio después de iniciar el proyecto correctamente. Primero apague el servidor (tomcat) y luego apague el servicio Jrebel. Si necesita usar el modo fuera de línea, no puede desactivar el servicio Jrebel primero. Después de configurar, desactivar Tomcat y finalmente desactivar el servicio Jrebel, ya no necesita activar el servicio Jrebel y puede iniciar el proyecto directamente. a través de Jrebel.
2. Carga y descarga de archivos
2.1 Importar dependencias de 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 Analizador de carga de archivos de configuración
Agregue un analizador de carga de archivos en el archivo 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>
Este código configura un bean llamado "multipartResolver" para manejar la carga de archivos. Al configurar el atributo "defaultEncoding", el atributo "maxUploadSize" y el atributo "resolveLazily", puede especificar la codificación de caracteres, el tamaño máximo de carga y el comportamiento de análisis retrasado de archivos al cargar archivos. De esta manera, el marco Spring realizará el análisis y las restricciones correspondientes en función de estas configuraciones al procesar la carga de archivos.
2.3 Configuración del formulario de carga de archivos
Defina una página de formulario de carga de archivos simple y establezca el atributo enctype para especificar el tipo de codificación de los datos del formulario como "multipart/form-data", que es el tipo de codificación utilizado para admitir la carga de archivos. Luego configure el archivo cargado para que se llame "imgFile" para que lo acepte el fondo y, finalmente, cargue el archivo en la URL especificada.
<%@ 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 Implementación de carga de archivos
Paso 1: diseñar la tabla de datos
Paso 2: configurar la información de la tabla y generar código
generadorConfig.xml:
<table schema="" tableName="img_upload" domainObjectName="UploadImg"
enableCountByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" enableUpdateByExample="false">
</table>
Paso 3: Crear la capa de lógica de negocios e implementar la interfaz...
Paso 4: información de ruta del archivo de configuración
propiedades.recursos:
#本地路径
dir=D:/upload/
#服务器路径
server=/upload/
Escribir clase de herramienta de lectura de archivos de configuración
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);
}
}
Paso 5: configurar proyectos y direcciones de mapeo
Paso 6: escribe el controlador
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);
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";
}
}
Paso 7: escribir jsp front-end
<%@ 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">
<link
href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css"
rel="stylesheet">
<script
src="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>
Paso 8: ejecuta la prueba
2.5 Implementación de descarga de archivos
Consulte la información del archivo correspondiente de acuerdo con la ID del archivo entrante, luego lea el contenido del archivo de acuerdo con la ruta del archivo, encapsule el contenido del archivo y la información del encabezado HTTP configurado en un objeto ResponseEntity y finalmente devuélvalo al cliente para descargar el archivo.
@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;
}
Ejemplo:
2.6 Carga y descarga de múltiples archivos
1. Método de escritura:
@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. Escriba una página de inicio para comparar:
<%@ 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. Ejecute la prueba
Como se muestra en la imagen a continuación, se seleccionan 10 archivos para la carga de varios archivos, pero usar Ctrl+selección para la función de carga de un solo archivo no es válido y solo se puede seleccionar un archivo.
A continuación, pruebe si se pueden ver localmente varias cargas de archivos.
Cosas a tener en cuenta ❗
Al seleccionar varias imágenes, debe prestar atención a configurar el tamaño del archivo a cargar y si la longitud del tipo del campo en el que la base de datos almacena las imágenes excede, lo que afectará si el archivo se puede cargar correctamente. Debido a que el espacio acumulativo de varias imágenes requiere más espacio, al evitar nombres de imágenes demasiado largos, verifique si se puede acomodar la longitud del campo que se va a almacenar.