[SpringMVC] Jrebel プラグインはホット デプロイメントとファイル アップロードを実装します

目次

1.Jレベル

1.1 Jrebel の概要

1.2 Jrebelプラグインのダウンロード

1.3 Jrebel サービスをダウンロードして開始する

1.4 オンラインでの GUID の生成

1.5 JRebelのアクティベーション 

1.6 関連設定

注意してください❗

2. ファイルのアップロードとダウンロード

2.1 pom 依存関係をインポートする

2.2 設定ファイルアップロードパーサー

2.3 ファイルアップロードフォームの設定

2.4 ファイルアップロードの実装

2.5 ファイルダウンロードの実装

2.6 複数ファイルのアップロードとダウンロード

注意してください❗


1.Jレベル

1.1 Jrebel の概要

        JRebel は Java 開発ツールであり、リアルタイム コード リロード用のプラグインです。その主な機能は、アプリケーションを再起動せずに、変更した Java コードを実行中のアプリケーションにリアルタイムで適用することにより、開発サイクルを短縮し、開発効率を向上させることです。

  1. ライブ コード リロード: JRebel は、開発者による Java コードへの変更を監視し、アプリケーションを再起動することなく、これらの変更を実行中のアプリケーションにリアルタイムで適用できます。こうすることで、開発者はコード変更の影響をすぐに確認できるため、再コンパイルやデプロイにかかる時間を節約できます。

  2. 複数のフレームワークとサーバーをサポート: JRebel は、Spring、Hibernate、Java EE、Tomcat、Jetty など、複数の Java フレームワークとサーバーをサポートします。Web アプリケーションを開発しているか、エンタープライズ レベルのアプリケーションを開発しているかに関係なく、JRebel を一般的に使用される開発フレームワークおよびサーバーと統合して、リアルタイムのコード リロードを提供できます。

  3. 高い互換性: JRebel は、ほとんどの Java 開発ツールおよび統合開発環境 (IDE) (Eclipse、IntelliJ IDEA、NetBeans など) と互換性があります。開発者は、別のツールに切り替えることなく、お気に入りの IDE で JRebel プラグインを使用できます。

  4. 高速なデプロイメント: JRebel は、アプリケーション全体を再起動せずに、変更したコードを実行中のアプリケーションに適用するだけでよいため、アプリケーションのデプロイメントを高速化できます。これは、大規模なアプリケーションや複雑な展開環境に特に役立ちます。

  5. 複数の開発シナリオをサポート: JRebel は、ローカル開発、リモート開発、クラウド開発など、さまざまな開発シナリオに適用できます。スタンドアロン開発でも分散開発でも、JRebel はリアルタイムのコード リロードを提供できます。

        全体として、JRebel は強力な Java 開発ツールであり、開発者はリアルタイム コード リロード機能により、アプリケーションを再起動することなく、変更を Java コードに迅速に適用できます。これにより、開発効率が大幅に向上し、開発サイクルが短縮され、開発者はコードの作成とデバッグにさらに集中できるようになります。

1.2 Jrebelプラグインのダウンロード

IDEA を開き、[ファイル]、[設定]、[プラグイン] の順に選択し、検索ボックスに「jrebel」と入力します。

1.3 Jrebel サービスをダウンロードして開始する

まずサービスをダウンロードし、GitHub Web サイトにアクセスします。リリース v1.4 · ilanyu/ReverseProxy · GitHub

指定した場所にダウンロードした後、以下に示すようにダブルクリックして開始します。

開始後、アイデアを開いてアクティブ化できますが、サービスを開いていない場合は、次のエラーが表示されます。

1.4 オンラインでの GUID の生成

 オンラインで GUID URL を生成: 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 はホット デプロイメントを実現するためにクラス ファイルの変更をリアルタイムで監視するため、いつでも変更を加えて有効にするには、アイデア環境で自動ミューテーション機能をオンにする必要があります。

注意事項

        Jrebel を通じてプロジェクトを開始する前に Jrebel サービスを開く必要があります。そうしないとエラーが発生します。プロジェクトを正しく開始した後はサービスを閉じないでください。まずサーバー (tomcat) をオフにしてから、Jrebel サービスをオフにします。オフライン モードを使用する必要がある場合、最初に jrebel サービスをオフにすることはできません。セットアップして Tomcat をオフにし、最後に Jrebel サービスをオフにすると、Jrebel サービスをオンにする必要がなくなり、プロジェクトを直接開始できます。ジュレベルを通じて。

2. ファイルのアップロードとダウンロード

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 ファイルアップロードの実装

ステップ 1:データテーブルを設計する

ステップ 2:テーブル情報を構成し、コードを生成する

ジェネレーターConfig.xml :  

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

ステップ 3:ビジネス ロジック レイヤーを作成し、インターフェイスを実装します...

ステップ 4:構成ファイルのパス情報

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);
    }
}

ステップ 5:プロジェクトとマッピングアドレスを構成する 

ステップ 6:コントローラーを作成する

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";
    }
}

ステップ 7:フロントエンド 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">
    <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>

 ステップ 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 キーを押しながら選択することは無効であり、選択できるファイルは 1 つだけです。

次に、複数のファイルのアップロードをローカルで表示できるかどうかをテストします。

注意事項

        複数の写真を選択する場合は、アップロードするファイルのサイズの設定と、データベースが写真を保存するフィールドの型の長さを超えているかどうかに注意する必要があります。これは、ファイルが正常にアップロードできるかどうかに影響します。複数のピクチャの累積スペースにはさらに多くのスペースが必要となるため、長すぎるピクチャ名を避けて、保存するフィールドの長さに対応できるかどうかを確認してください。

おすすめ

転載: blog.csdn.net/Justw320/article/details/132777189