[SpringMVC] El complemento Jrebel implementa la implementación en caliente y la carga de archivos

Tabla de contenido

1. JRebel

1.1 Introducción a Jrebel

1.2 Descarga del complemento Jrebel

1.3 Descargue e inicie el servicio Jrebel

1.4 Generar GUID en línea

1.5 Activación de JRebel 

1.6 Configuraciones relacionadas

Nota❗

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

Nota❗


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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

Supongo que te gusta

Origin blog.csdn.net/Justw320/article/details/132777189
Recomendado
Clasificación