jsp使用七牛云API和webuploader上传多组图片

jsp使用七牛云API和webuploader上传多组图片

介绍

前作:JavaWeb servlet jsp 使用七牛云API上传图片

使用mysql保存图片七牛云路径,在上传图片的时候直接上传到七牛云

前端使用了layui,图片多组上传使用了百度的WebUploader,本来想用swfupload的,但是10年前的东西实在不太行,我连跑都跑不起来…

另外我加入了log4j用来打日志

下面是简单演示

qiniu

目录树

大致上是这样

├─sql
├─src
│  └─main
│      ├─java
│      │  └─top
│      │      └─sehnsucht
│      │          ├─dao
│      │          │  └─impl
│      │          ├─service
│      │          │  └─impl
│      │          ├─util
│      │          └─vo
│      └─webapp
│          ├─js
│          ├─layui
│          │  ├─css
│          │  │  └─modules
│          │  │      ├─laydate
│          │  │      │  └─default
│          │  │      └─layer
│          │  │          └─default
│          │  └─font
│          ├─WEB-INF
│          └─webuploader
│              ├─dist

webuploader里面只有dist用到

遇到的问题

上传组件的选择问题

swfupload实在是用不了,报错全部解决也不行,搜来搜去选择了WebUploader,至少是国人写的,好歹文档是中文,不至于看不懂

进度条

看着官网的示例有进度条,但是我这里没有,发现是css的问题,然后去百度加进去就好了

image-20211114130805121

多线程

用这个组件后台会自动往你写的那个地址传东西,这个是并发的,如果不加锁结果老是不对,所以我在UploadServlet那里加了锁

前端界面

使用了layui来构建前端,包括日期组件也是layui自带的,挺好用的,用那个表单组件的时候差点卡住了,不过问题不大,看文档看懂就好了

数据库

从浏览器选择的日期传到后端再进行数据库的查询

关键代码

我将完整代码放到了
https://gitee.com/hex-cxm/jspQiNiu

有兴趣的可以打个star

我这里只放关键代码,不然太多了

UserPhotoDaoImpl

package top.sehnsucht.dao.impl;

import org.apache.log4j.Logger;
import top.sehnsucht.dao.UserPhotoDao;
import top.sehnsucht.util.DBUtil;
import top.sehnsucht.vo.Photo;
import top.sehnsucht.vo.UserInfo;
import top.sehnsucht.vo.UserPhoto;

import java.io.FileInputStream;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description:
 * @Author: Cai
 * @CreateTime: 2021/11/12
 */

public class UserPhotoDaoImpl implements UserPhotoDao {
    
    
    private Logger logger = Logger.getLogger(this.getClass());

    /**
     * 返回ArrayList<ArrayList<String>>,方便转成json传到前端
     * 只有用户信息
     *
     * @return
     */
    @Override
    public ArrayList<Map<String, String>> getAllUser() {
    
    
        Connection conn = null;
        PreparedStatement ps = null;
        FileInputStream in = null;
        ResultSet rs = null;
        ArrayList<Map<String, String>> arrs = new ArrayList<>();
        try {
    
    
            conn = DBUtil.getConn();
            String sql = "select id,username,birthday from userinfo order by id";
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery(sql);
            while (rs.next()) {
    
    
                Map<String, String> map = new HashMap();
                Integer id = rs.getInt(1);
                String username = rs.getString(2);
                java.util.Date birthday = rs.getDate(3);
                map.put("id", id.toString());
                map.put("username", username);
                map.put("birthday",birthday.toString());
                arrs.add(map);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            DBUtil.closeConn(conn);
            if (null != ps) {
    
    
                try {
    
    
                    ps.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
        return arrs;
    }

    /**
     * 添加photo到数据库中
     *
     * @param userPhotos
     */
    @Override
    public void addUserAndPhoto(ArrayList<UserPhoto> userPhotos) {
    
    
        Connection conn = null;
        PreparedStatement ps = null;
        try {
    
    
            conn = DBUtil.getConn();
            for (int i = 0; i < userPhotos.size(); i++) {
    
    
                String sql = "insert into userphoto (userid, photoname, photourl) values (?,?,?)";
                ps = conn.prepareStatement(sql);
                ps.setInt(1, userPhotos.get(i).getUserid());
                ps.setString(2, userPhotos.get(i).getPhotoName());
                ps.setString(3, userPhotos.get(i).getPhotoUrl());
                int count = ps.executeUpdate();
                if (count > 0) {
    
    
                    System.out.println("插入成功!");
                } else {
    
    
                    System.out.println("插入失败!");
                }
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            DBUtil.closeConn(conn);
            if (null != ps) {
    
    
                try {
    
    
                    ps.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 根据id查找图片集合
     *
     * @param id
     * @return
     */
    @Override
    public ArrayList<UserPhoto> getPhotoByUserId(Integer id) {
    
    
        Connection conn = null;
        PreparedStatement ps = null;
        FileInputStream in = null;
        ResultSet rs = null;
        ArrayList<UserPhoto> userPhotos = new ArrayList<UserPhoto>();
        try {
    
    
            conn = DBUtil.getConn();
//            String sql = "select * from photo where id = " + id;
            String sql = "select userid, photoname, photourl from userphoto where userid = " + id;
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery(sql);
            while (rs.next()) {
    
    
                UserPhoto userPhoto = new UserPhoto(rs.getInt(1),rs.getString(2),rs.getString(3));
                userPhotos.add(userPhoto);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            DBUtil.closeConn(conn);
            if (null != ps) {
    
    
                try {
    
    
                    ps.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
        return userPhotos;
    }

    /**
     * 插入用户,返回用户id(主键)
     *
     * @param userInfo
     * @return
     */
    @Override
    public Integer addUser(UserInfo userInfo) {
    
    
        Connection conn = null;
        PreparedStatement ps = null;
        Integer ansId = null;
        try {
    
    
            conn = DBUtil.getConn();
            String sql = "insert into userinfo (username,birthday) values(?,?)";
            ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            ps.setString(1, userInfo.getUsername());
            ps.setObject(2, userInfo.getBirthday());
            int count = ps.executeUpdate();
            if (count > 0) {
    
    
                System.out.println("插入成功!");
                ResultSet rs = ps.getGeneratedKeys();
                if (rs.next()) {
    
    
                    //获取主键,设置了主键自增
                    ansId = rs.getInt(1);
                }
            } else {
    
    
                System.out.println("插入失败!");
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            DBUtil.closeConn(conn);
            if (null != ps) {
    
    
                try {
    
    
                    ps.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
        return ansId;
    }

    /**
     * 根据要求查看用户
     * @param name
     * @param startDate
     * @param endDate
     * @return
     */
    @Override
    public ArrayList<Map<String, String>> getSomeUser(String name, String startDate, String endDate) {
    
    
        Connection conn = null;
        PreparedStatement ps = null;
        FileInputStream in = null;
        ResultSet rs = null;
        ArrayList<Map<String, String>> arrs = new ArrayList<>();
        logger.debug("正常进入");
        try {
    
    
            conn = DBUtil.getConn();
            String sql = "select id,username,birthday from userinfo where ";
            if (name != null && !name.equals("")) {
    
    
                sql += " username like '%" + name + "%' ";
            } else {
    
    
                sql += " username like '%' ";
            }
            if (startDate!= null) {
    
    
                sql += " and birthday >= '" + java.sql.Date.valueOf(startDate) + "'";
            }
            if (endDate!= null) {
    
    
                sql += " and birthday <= '" + java.sql.Date.valueOf(endDate) + "'";
            }
            sql += " order by id ";
            logger.info("sql: " + sql);
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery(sql);
            while (rs.next()) {
    
    
                Map<String, String> map = new HashMap();
                Integer id = rs.getInt(1);
                String username = rs.getString(2);
                java.util.Date birthday = rs.getDate(3);
                map.put("id", id.toString());
                map.put("username", username);
                map.put("birthday",birthday.toString());
                arrs.add(map);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            DBUtil.closeConn(conn);
            if (null != ps) {
    
    
                try {
    
    
                    ps.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
        return arrs;
    }
}

UploadServlet

package top.sehnsucht;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import top.sehnsucht.util.Qiniu;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.log4j.Logger;

/**
 * @Description:
 * @Author: Cai
 * @CreateTime: 2021/10/29
 */

public class UploadServlet extends HttpServlet {
    
    
    private Logger logger=Logger.getLogger(this.getClass());
    private Lock lock = new ReentrantLock();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        lock.lock();
        try {
    
    
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/html; charset=UTF-8");
            logger.info("单次请求" + req);

            //判断文件是否可以上传
            boolean isMultipart = ServletFileUpload.isMultipartContent(req);
            //可以上传,有问题就报异常
            if (isMultipart) {
    
    
                //创建一个FileItem工厂,通过工厂创建文件上传核心组件ServletFileUpload对象
                ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
                try {
    
    
                    //通过核心上传组件解析request请求,获取表单的所有表单项,表单的每一个表单项对应一个FileItem
                    List<FileItem> items = upload.parseRequest(req);
                    Iterator<FileItem> it = items.iterator();
                    for (FileItem item : items) {
    
    
                        if (item.isFormField()) {
    
    
                            logger.error("其他类型");
                        } else {
    
    
                            String filename = item.getName();
                            String path = req.getSession().getServletContext().getRealPath("/") + "\\1";
                            File file = new File(path);
                            if (!file.exists()) {
    
    
                                file.mkdirs();
                            }
                            file = new File(path, filename);
                            item.write(file);
                            logger.debug(filename + "上传成功");
                            Qiniu.uploadPic(filename,path + "\\" + filename);
                            logger.debug("图片地址为:" + Qiniu.picUrl());
                            logger.info(filename + "七牛云上传成功");

                            //把文件名和url存到session中
                            String allFilename = (String) req.getSession().getServletContext().getAttribute("allFilename");
                            if (allFilename == null) {
    
    
                                allFilename = "";
                            }
                            logger.debug("allFilename" + allFilename);
                            allFilename = (allFilename + "," + filename);
                            req.getSession().getServletContext().setAttribute("allFilename", allFilename);
                            String allPicUrls = (String) req.getSession().getServletContext().getAttribute("allPicUrls");
                            if (allPicUrls == null) {
    
    
                                allPicUrls = "";
                            }
                            logger.debug("allPicUrls" + allPicUrls);
                            allPicUrls = (allPicUrls + "," + Qiniu.picUrl());
                            req.getSession().getServletContext().setAttribute("allPicUrls", allPicUrls);

                        }
                    }
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            lock.unlock();
            logger.debug("解锁");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        doGet(req, resp);
    }
}

JDBCServlet

package top.sehnsucht;

import org.apache.log4j.Logger;
import top.sehnsucht.dao.UserPhotoDao;
import top.sehnsucht.dao.impl.UserPhotoDaoImpl;
import top.sehnsucht.service.UserPhotoService;
import top.sehnsucht.service.impl.UserPhotoServiceImpl;
import top.sehnsucht.util.DateFormatUtil;
import top.sehnsucht.vo.UserInfo;
import top.sehnsucht.vo.UserPhoto;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.ArrayList;


public class JDBCServlet extends HttpServlet {
    
    
    private Logger logger = Logger.getLogger(this.getClass());

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        logger.debug(req.getSession().getServletContext().getAttribute("allFilename"));
        logger.debug(req.getSession().getServletContext().getAttribute("allPicUrls"));
        logger.debug(req.getParameter("username"));
        logger.debug(req.getParameter("birthday"));


        String allFilename = req.getSession().getServletContext().getAttribute("allFilename").toString();
        String[] splitFilename = allFilename.split(",");
        String allPicUrls = req.getSession().getServletContext().getAttribute("allPicUrls").toString();
        String[] splitPicUrls = allPicUrls.split(",");

        UserPhotoDao userPhotoDao = new UserPhotoDaoImpl();
        UserPhotoService userPhotoService = new UserPhotoServiceImpl(userPhotoDao);


        UserInfo userInfo = new UserInfo(req.getParameter("username"), DateFormatUtil.tran(req.getParameter("birthday")));

        Integer id = userPhotoService.addUser(userInfo);


        ArrayList<UserPhoto> userPhotos = new ArrayList<>();
        for (int i = 1; i < splitFilename.length; i++) {
    
    
            UserPhoto userPhoto = new UserPhoto(id, splitFilename[i], splitPicUrls[i]);
            userPhotos.add(userPhoto);
        }

        userPhotoService.addUserAndPhoto(userPhotos);


        String strBackUrl = "http://" + req.getServerName() + ":" + req.getServerPort() + "/list.jsp";
        resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
        resp.setHeader("Location", strBackUrl);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        doGet(req, resp);
    }
}

list.jsp

<%--
  Created by IntelliJ IDEA.
  User: windows
  Date: 2021/10/29
  Time: 10:08
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>列表</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/layui/css/layui.css">
    <script src="${pageContext.request.contextPath}/layui/layui.js"></script>
    <script src="${pageContext.request.contextPath}/js/jquery-3.6.0.js"></script>
</head>
<body>

<div style="border-radius: 5px;margin-top: 100px;margin-left: 200px;margin-right: 200px">
    <form class="layui-form layui-form-pane" action="" id="form-search">
        <fieldset class="table-search-fieldset">
            <legend>搜索条件</legend>
            <div class="layui-form-item">
                <div class="layui-inline">
                    <label class="layui-form-label">姓名:</label>
                    <div class="layui-input-inline" style="width: 150px;">
                        <input type="text" name="name" placeholder="请输入姓名" autocomplete="off" class="layui-input">
                    </div>

                    <label class="layui-form-label">日期:</label>
                    <div class="layui-input-inline" style="width: 200px;">
                        <input id="startDate" type="text" name="startDate" placeholder="起始日期" autocomplete="off" class="layui-input date">
                    </div>
                    <div class="layui-form-mid">-</div>
                    <div class="layui-input-inline" style="width: 200px;">
                        <input id="endDate" type="text" name="endDate" placeholder="终止日期" autocomplete="off"
                               class="layui-input date">
                    </div>

                </div>
                <button  id="btn-search" lay-submit lay-filter="btn-search-filter" type="button" class="layui-btn layui-btn-radius layui-btn-normal">
                    <i class="layui-icon layui-icon-search"></i>
                    查询
                </button>
                <button  id="btn-reset" type="reset" class="layui-btn layui-btn-radius layui-btn-primary">
                    <i class="layui-icon layui-icon-fonts-clear"></i>
                    清空条件
                </button>
            </div>
        </fieldset>
    </form>
    <table id="demo" lay-filter="table-pic-filter"></table>
</div>

<script type="text/html" id="col-pic-toolbar">
    <a class="layui-btn layui-btn-xs" lay-event="look">查看</a>
</script>
<script>

    layui.use(['laydate', 'table', 'form'], function () {
    
    
        var laydate = layui.laydate;
        var table = layui.table;
        var form = layui.form;

        //表格头部工具栏事件监听
        form.on('submit(btn-search-filter)', function(data){
    
    
            console.log(data.elem) //被执行事件的元素DOM对象,一般为button对象
            console.log(data.form) //被执行提交的form对象,一般在存在form标签时才会返回
            console.log(data.field) //当前容器的全部表单字段,名值对形式:{name: value}

            table.reload('demo', {
    
    
                where: {
    
     //设定异步数据接口的额外参数,任意设
                    name: data.field.name,
                    startDate: data.field.startDate,
                    endDate: data.field.endDate
                }
                ,page: {
    
    
                    curr: 1 //重新从第 1 页开始
                }
            });
            return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。
        });

        laydate.render({
    
    
            elem: '.date' //指定元素
        });

        table.render({
    
    
            elem: '#demo'
            , height: 312
            , url: '/data.jsp' //数据接口
            , page: false //关闭分页
            , cols: [[ //表头
                {
    
    field: 'id', title: 'id', width: 100, sort: true, fixed: 'left'}
                , {
    
    field: 'username', title: 'username', width: 200}
                , {
    
    field: 'birthday', title: 'birthday', width: 200}
                , {
    
    title: '操作', align: 'center', toolbar: '#col-pic-toolbar'}
            ]]
        });

        table.on('tool(table-pic-filter)', function (obj) {
    
    
            let data = obj.data;
            let layEvent = obj.event;
            if (layEvent === 'look') {
    
    
                console.log(data.name)
                console.log("list id: " + data.id);
                sessionStorage.setItem("id", data.id)
                let url = '/transfer.jsp'
                layer.open({
    
    
                    type: 2,
                    title: "查看图片",
                    area: ['60%', '60%'],
                    shadeClose: true,
                    content: url
                });
            }
        });
    });
</script>
</body>
</html>

add.jsp

<%--
  Created by IntelliJ IDEA.
  User: windows
  Date: 2021/10/29
  Time: 10:08
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>上传</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/layui/css/layui.css">
    <script src="${pageContext.request.contextPath}/layui/layui.js"></script>
    <script src="${pageContext.request.contextPath}/js/jquery-3.6.0.js"></script>
    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/webuploader/dist/webuploader.css">
    <script src="${pageContext.request.contextPath}/webuploader/dist/webuploader.js"></script>


    <style>
        body {
    
    
            text-align: center;
            padding: 20px;
        }

        form {
    
    
            width: 500px;
            margin: auto;
        }
    </style>
</head>
<body>
<form method="get" action="${pageContext.request.contextPath}/jdbc" enctype="multipart/form-data" class="layui-form">
    <div class="layui-form-item">
        <label class="layui-form-label">姓名</label>
        <div class="layui-input-block">
            <input id="name" type="text" name="username" required placeholder="请输入姓名" autocomplete="off"
                   class="layui-input">
        </div>
    </div>
    <div class="layui-form-item">
        <label class="layui-form-label">生日</label>
        <div class="layui-input-block">
            <input id="birthday" type="text" name="birthday" required placeholder="请输入生日" autocomplete="off"
                   class="layui-input">
        </div>
    </div>

    <div class="layui-form-item wu-example" id="uploader">
        <label class="layui-form-label"></label>
        <div class="layui-input-block" >
            <div id="fileList" class="uploader-list"></div>
            <div id="filePicker" style="float: left">选择图片</div>
            <button id="btn-submit" class="layui-btn" lay-submit lay-filter="*" style="float: right">上传</button>
        </div>
    </div>
</form>

<script>
    layui.use(['laydate'], function () {
    
    
        let laydate = layui.laydate;
        laydate.render({
    
    
            elem: '[name="birthday"]'
        });
    });

    $(document).ready(function () {
    
    
        var uploader = WebUploader.create({
    
    
            // swf文件路径
            swf: '/webuploader/dist/Uploader.swf',

            // 文件接收服务端。
            server: '/upload',

            // 选择文件的按钮。可选。
            // 内部根据当前运行是创建,可能是input元素,也可能是flash.
            pick: '#filePicker',
            // 最大上传并发数
            thread: 1,


            // 只允许选择图片文件。
            accept: {
    
    
                title: 'Images',
                extensions: 'gif,jpg,jpeg,bmp,png',
                mimeTypes: 'image/*'
            },

            // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
            // resize: false,
            auto :true
        });

        // 当有文件添加进来的时候
        uploader.on( 'fileQueued', function( file ) {
    
    
            var $li = $(
                    '<div id="' + file.id + '" class="file-item thumbnail">' +
                    '<img>' +
                    '<div class="info">' + file.name + '</div>' +
                    '</div>'
                ),
                $img = $li.find('img');

            $list = $('#fileList');
            // $list为容器jQuery实例
            $list.append( $li );

            // 创建缩略图
            // 如果为非图片文件,可以不用调用此方法。
            // thumbnailWidth x thumbnailHeight 为 100 x 100
            uploader.makeThumb( file, function( error, src ) {
    
    
                if ( error ) {
    
    
                    $img.replaceWith('<span>不能预览</span>');
                    return;
                }

                $img.attr( 'src', src );
            }, 200, 200 );
        });

        // 文件上传过程中创建进度条实时显示。
        uploader.on( 'uploadProgress', function( file, percentage ) {
    
    
            var $li = $( '#'+file.id ),
                $percent = $li.find('.progress span');

            // 避免重复创建
            if ( !$percent.length ) {
    
    
                $percent = $('<p class="progress"><span></span></p>')
                    .appendTo( $li )
                    .find('span');
            }

            $percent.css( 'width', percentage * 100 + '%' );
        });

        // 文件上传成功,给item添加成功class, 用样式标记上传成功。
        uploader.on( 'uploadSuccess', function( file ) {
    
    
            $( '#'+file.id ).addClass('upload-state-done');
        });

        // 文件上传失败,显示上传出错。
        uploader.on( 'uploadError', function( file ) {
    
    
            var $li = $( '#'+file.id ),
                $error = $li.find('div.error');

            // 避免重复创建
            if ( !$error.length ) {
    
    
                $error = $('<div class="error"></div>').appendTo( $li );
            }

            $error.text('上传失败');
        });

        // 完成上传完了,成功或者失败,先删除进度条。
        uploader.on( 'uploadComplete', function( file ) {
    
    
            $( '#'+file.id ).find('.progress').remove();
        });

    })


</script>
</body>
</html>

pom.xml

有些用到了有些没用到

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.18</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.13</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.12.RELEASE</version>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.2.1</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
<dependency>
    <groupId>com.qiniu</groupId>
    <artifactId>qiniu-java-sdk</artifactId>
    <version>7.7.0</version>
</dependency>
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-nop</artifactId>
    <version>1.7.2</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.14</version>
</dependency>

参考

模糊查询日期时间的方法

Java并发编程:Lock

Web Uploader官网

layui镜像文档

等…

猜你喜欢

转载自blog.csdn.net/Dueser/article/details/121322693
今日推荐