SpringBoot EasyUI 图片上传 CRUD 分页

一、需求

使用SpringBoot+EasyUI实现带图片字段的表的CRUD,包括分页和模糊查询。

二、分析准备

1、前端jQuery EasyUI可去中文官网下载最新的http://www.jeasyui.net/download/jquery.html
2、后端SpringBoot+MyBatis本篇只展示其配置文件、配置类和controller层。

三、实现

先看效果图
信息展示

1、前端

(1)页面student.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>学生管理</title>
    <!--EasyUI的CSS-->
    <link rel="stylesheet" type="text/css" href="ui/themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="ui/themes/icon.css">
    <!--EasyUI的JS-->
    <script type="text/javascript" src="ui/jquery.min.js"></script>
    <script type="text/javascript" src="ui/jquery.easyui.min.js"></script>
    <script type="text/javascript" src="ui/locale/easyui-lang-zh_CN.js"></script>

    <!--异步上传图片使用的JS-->
    <script type="text/javascript" src="ui/ajaxfileupload.js"></script>
    <!--把表单数据转为JSON对象的JS-->
    <script type="text/javascript" src="ui/jquery.serializejson.js"></script>
    <!--CRUD通用JS-->
    <script type="text/javascript" src="./js/crud.js"></script>

    <script type="text/javascript">
        var name = "student";
        var width = 350;
        var height = 220;
        var columns = [[
            {field: 'id', title: '学生编号', width: 100},
            {field: 'image', title: '学生照片', formatter:showImage},
            {field: 'name', title: '学生姓名', width: 100},
            {
                field: '-', title: '操作', width: 80,
                formatter: function (value, row, index) {
                    var oper = '<a href="javascript:void(0)" οnclick="edit(' + row.id + ')">修改</a>';
                    oper += ' <a href="javascript:void(0)" οnclick="del(' + row.id + ')">删除</a>';
                    return oper;
                }
            }
        ]];
    </script>
</head>
<body>
<div class="easyui-panel" style="padding-left:4px;border-bottom:0px;">
    <div style="height:4px;"></div>
    <form id="searchForm">
        <table>
            <tr>
                <td>学生姓名</td>
                <td><input name="name"/></td>
                <td>
                    <button id="searchBtn" type="button">查询</button>
                </td>
            </tr>
        </table>
    </form>
    <div style="height:4px;"></div>
</div>

<table id="grid"></table>

<div id="editDlg">
    <form id="editForm">
        <input type="hidden" name="id"/>
        <table>
            <tr>
                <td width="25%">学生图片</td>
                <td>
                    <input type="hidden" value="" name="image" id="pic">
                    <image id="img" src="" style='width:96px;height:96px'/>
                    <input class="easyui-filebox" id="fileId" name="file"
                           data-options="onChange:changeImg" buttonText="请选择一张图片"
                    />
                </td>
            </tr>
            <tr>
                <td>学生姓名</td>
                <td><input name="name"></td>
            </tr>
        </table>
        <button id="saveBtn" type="button">保存</button>
    </form>
</div>
</body>
</html>
(2)三个JS

ajaxfileupload.js和jquery.serializejson.js可自取
链接:https://pan.baidu.com/s/1SJz0f_zwo8zqs5VSBNBD6w 提取码:mt62
crud.js

var method = ""; // 确定提交的方法是新增还是保存

$(function () {
    $('#grid').datagrid({
        url: name + '/findPage',  // 从远程站点请求数据的URL
        columns: columns, // 数据网格(datagrid)的列(column)的配置对象,更多细节请参见列(column)属性
        height: $(window).height() - 60, // 设置整体网格高度
        width: $(window).width() - 30, // 设置整体网格宽度
        singleSelect: true, //设置为 true,则只允许选中一行。
        pagination: true, //设置为 true,则在数据网格(datagrid)底部显示分页工具栏
        toolbar: [
            {
                text: '新增',
                iconCls: 'icon-add',
                handler: function () {
                    // 指定保存事件提交的方法
                    method = "/add";
                    $('#editForm').form('clear'); // 清空表格
                    $('#img').attr("src", ""); // 清空图片
                    // 弹出窗口
                    $('#editDlg').dialog('open');
                }
            }
        ]
    });

    // 启动分页工具栏中的刷新按钮
    $('#grid').pagination({
        showRefresh: true
    });

    // 查询
    $('#searchBtn').bind('click', function () {
        // 把表单数据转换成JSON对象
        var formData = $('#searchForm').serializeJSON();
        $('#grid').datagrid('load', formData);
    });

    var h = 200;
    var w = 300;
    if (typeof (height) != "undefined") {
        h = height;
    }
    if (typeof (width) != "undefined") {
        w = width;
    }
    // 编辑窗口
    $('#editDlg').dialog({
        title: '编辑窗口',	//对话框的标题文本。
        width: w,	//设置面板(panel)的宽度。
        height: h,	//设置面板(panel)的高度。
        closed: true, // 刚开始窗口是否为关闭状态,true表示关闭
        modal: true // 模式窗口,背景窗口变灰色,不可选
    });

    // 保存动作
    $('#saveBtn').bind('click', function () {
        var formData = $('#editForm').serializeJSON();
        $.ajax({
            url: name + method,
            data: formData,
            dataType: 'json',
            type: 'post',
            success: function (rtn) {
                $.messager.alert('提示', rtn.msg, 'info', function () {
                    if (rtn.success) {
                        // 成功的话,关闭窗口
                        $('#editDlg').dialog('close');
                        // 刷新表格数据
                        $('#grid').datagrid('reload'); //重新加载行,就像 load 方法一样,但是保持在当前页。
                    }
                });
            }
        });
    });
});

// 删除
function del(id) {
    $.messager.confirm('确认', '确认要删除吗?', function (yes) {
        if (yes) {
            // 删除动作
            $.ajax({
                url: name + '/delete?id=' + id,
                dataType: 'json',
                type: 'post',
                success: function (rtn) {
                    $.messager.alert('提示', rtn.msg, 'info', function () {
                        if (rtn.success) {
                            // 刷新表格数据
                            $('#grid').datagrid('reload');
                        }
                    });
                }
            });
        }
    });
}

// 修改
function edit(id) {
    // 弹出窗口
    $('#editDlg').dialog('open');
    // 清空表单内容
    $('#editForm').form('clear');
    // 加载数据,用于修改前读取记录信息
    $.ajax({
        url: name + '/findOne?id=' + id,
        dataType: 'json',
        type: 'post',
        success: function (rtn) {
            $('#editForm').form('load', rtn);

            if (name == "student") {
                $('#img').attr("src", rtn.image);
            }
        }
    });
    method = "/update";
}


// 图片展示
function showImage(value, row, index) {
    if (value) {
        return "<img style='width:72px;height:72px;' border='1' src='" + value + "'/>";
    }
}

// 异步上传图片
function changeImg() {
    // 清空时再次触发此方法,直接返回
    if ($('#fileId').filebox('getValue') == "") {
        return;
    }
    // 异步上传
    $.ajaxFileUpload({
        url: 'upload/uploadFile',
        dataType: 'json',
        type: 'post',
        secureuri: false,
        fileElementId: 'filebox_file_id_1', // 单张图片,固定写法
        success: function (data) {
            $('#img').attr("src", data.msg); // 图片回显赋值
            $('#pic').attr("value", data.msg); // 提交的数据赋值
        }
    });

    //上传成功后清空里面的值
    $('#fileId').filebox('clear');
}

2、后端

(1)pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wdp.www</groupId>
    <artifactId>springboot-easyui-200606</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--实体类相关-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--MySQL相关-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--MyBatis相关-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.2</version>
        </dependency>

        <!--业务相关工具-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>

        <!--web相关-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
(2)配置文件application.properties
# 映射端口
server.port=8001
# 上传图片存放地址
file-save-path=D:/ref/pic/images/

# 设置上传文件大小 如果是想要不限制文件上传的大小,那么就把两个值都设置为-1
# 设置单个文件的大小
spring.servlet.multipart.max-file-size=1MB
# 设置单次请求的文件的总大小
spring.servlet.multipart.max-request-size=5MB

#打印sql,方便调试
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

# 设置数据源 驱动SpringBoot自己可以推测
spring.datasource.url=jdbc:mysql:///db1
spring.datasource.username=root
spring.datasource.password=root

# 别名扫描
mybatis.type-aliases-package=com.wdp.www.pojo
# mapper.xml配置文件扫描,如果有可放开下面的注释
# mybatis.mapper-locations=classpath:mybatis/mappers/*.xml
(3)两个实体工具类

Result.java

package com.wdp.www.util;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;

/**
 * 返回信息实体
 *
 * @author Dongpo
 */
@Getter
@Setter
@AllArgsConstructor
public class Result implements Serializable {
	/**
	 * 是否成功
	 */
	private boolean success;

	/**
	 * 提示信息
	 */
	private String msg;
}

PageResult.java

package com.wdp.www.util;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.List;

/**
 * 分页结果
 *
 * @author Dongpo
 */
@Getter
@Setter
@AllArgsConstructor
public class PageResult implements Serializable {
	/**
	 * 总记录数
	 */
	private Long total;

	/**
	 * 当前页结果
	 */
	private List rows;
}
(4)两个Controller

StudentController.java

package com.wdp.www.controller;

import com.wdp.www.pojo.Student;
import com.wdp.www.service.StudentService;
import com.wdp.www.util.PageResult;
import com.wdp.www.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description 学生
 * @Author DongPo
 */
@RestController
@RequestMapping("student")
public class StudentController {
	@Autowired
	private StudentService studentService;

	@RequestMapping("findPage")
	public PageResult findPage(Student student, Integer page, Integer rows) {
		PageResult pageResult = studentService.findPage(student, page, rows);
		return pageResult;
	}

	@RequestMapping("findOne")
	public Student findOne(Long id) {
		Student student = studentService.findOne(id);
		return student;
	}

	@RequestMapping("add")
	public Result add(Student student) {
		try {
			studentService.add(student);
			return new Result(true, "添加成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "添加失败");
		}
	}

	@RequestMapping("update")
	public Result update(Student student) {
		try {
			studentService.update(student);
			return new Result(true, "修改成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "修改失败");
		}
	}

	@RequestMapping("delete")
	public Result delete(Long id) {
		try {
			studentService.delete(id);
			return new Result(true, "删除成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "删除失败");
		}
	}
}

UploadController.java

package com.wdp.www.controller;

import com.wdp.www.util.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @Description 上传图片
 * @Author DongPo
 */
@Controller
@RequestMapping("upload")
public class UploadController {
	/**
	 * 时间格式化,用来创建文件夹
	 */
	private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy/MM/dd/");

	/**
	 * 设置最大文件限制 单位bit
	 */
	private static final int FILE_MAX_SIZE = 1 * 1024 * 1024;

	/**
	 * 文件类型限制
	 */
	private static final List<String> FILE_CONTENT_TYPES = new ArrayList<>();

	static {
		FILE_CONTENT_TYPES.add("image/jpeg");
		FILE_CONTENT_TYPES.add("image/jpg");
		FILE_CONTENT_TYPES.add("image/png");
	}

	/**
	 * 图片保存路径,自动从properties文件中获取数据
	 * 示例:D:/ref/pic/images/
	 */
	@Value("${file-save-path}")
	private String fileSavePath;

	@RequestMapping("uploadFile")
	@ResponseBody
	public Result uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
		// 0.文件检查
			// 检查大小
		long size = file.getSize();
		if (size > FILE_MAX_SIZE) {
			return new Result(false, "文件大小不能超过" + (FILE_MAX_SIZE / 1024) + "KB");
		}
			// 检查类型
		String contentType = file.getContentType();
		if (!FILE_CONTENT_TYPES.contains(contentType)) {
			return new Result(false, "只支持以下类型的文件格式:" + FILE_CONTENT_TYPES);
		}

		// 1.后半段目录:2020/06/07/
		String directory = SDF.format(new Date());

		/**
		 *  2.文件保存目录  D:/ref/pic/images/2020/06/17/
		 *  如果目录不存在,则创建
		 */
		File dir = new File(fileSavePath + directory);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		System.out.println("图片上传,保存位置:" + fileSavePath + directory);

		// 3.给文件重新设置一个名字
			// 截取后缀
		String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
		String newFileName = UUID.randomUUID().toString().replaceAll("-", "") + suffix;

		// 4.创建这个新文件
		File newFile = new File(fileSavePath + directory + newFileName);

		// 5.复制操作
		try {
			file.transferTo(newFile);
			//	协议 :// ip地址 :端口号 / 文件目录(/images/2020/06/07/xxx.jpg)
			String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/images/" + directory + newFileName;
			System.out.println("图片上传,访问URL:" + url);

			return new Result(true, url);
		} catch (IOException e) {
			return new Result(false, "上传异常");
		}
	}
}
(5)一个资源映射配置类

FileConfig.java

package com.wdp.www.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Description 映射路径配置
 * @Author DongPo
 */
@Configuration
public class FileConfig implements WebMvcConfigurer {
	/**
	 * 图片保存路径,自动从properties文件中获取数据
	 * 示例:D:/ref/pic/images/
	 */
	@Value("${file-save-path}")
	private String fileSavePath;

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		/**
		 * 配置资源映射
		 * 意思是:如果访问的资源路径是以“/images/”开头的,
		 * 就给我映射到本机的“D:/ref/pic/images/”这个文件夹内,去找你要的资源
		 * 注意:D:/ref/pic/images/ 后面的 “/”一定要带上
		 */
		registry.addResourceHandler("/images/**")
			.addResourceLocations("file:" + fileSavePath);
	}
}

四、总结

创造工具的人是伟大的,所以对他们最好的感谢就是合理的使用这些工具。
前端为jQuery EasyUI的简单使用,实体类使用了lombok插件,Mapper接口使用了通用Mapper,业务中使用了分页工具,web层为SpringBoot的简单使用。
总体来说,这是一种简便的、易于上手的从前端到后端的全栈解决方案。

五、附录

牛顿说过,如果说我能够看的远一些,那是因为我站在巨人的肩膀上。
参考1:https://blog.csdn.net/sd6275832ght
参考2:https://blog.csdn.net/RuanBigShuai

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值