SpringBoot EasyUI 图片上传 CRUD 分页

一、需求

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

二、分析准备

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

三、实现

先看效果图
SpringBoot EasyUI 图片上传 CRUD 分页_第1张图片

1、前端

(1)页面student.html


<html>
<head>
    <meta charset="UTF-8">
    <title>学生管理title>
    
    <link rel="stylesheet" type="text/css" href="ui/themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="ui/themes/icon.css">
    
    <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>

    
    <script type="text/javascript" src="ui/ajaxfileupload.js">script>
    
    <script type="text/javascript" src="ui/jquery.serializejson.js">script>
    
    <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 = '+ row.id + ')">修改';
                    oper += ' + row.id + ')">删除';
                    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 "";
    }
}

// 异步上传图片
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文件


<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.0modelVersion>

    <groupId>com.wdp.wwwgroupId>
    <artifactId>springboot-easyui-200606artifactId>
    <version>1.0.0-SNAPSHOTversion>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.0.6.RELEASEversion>
    parent>

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

    <dependencies>
        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-jdbcartifactId>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>

        
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>1.3.2version>
        dependency>
        <dependency>
            <groupId>tk.mybatisgroupId>
            <artifactId>mapper-spring-boot-starterartifactId>
            <version>2.0.2version>
        dependency>

        
        <dependency>
            <groupId>com.github.pagehelpergroupId>
            <artifactId>pagehelper-spring-boot-starterartifactId>
            <version>1.2.3version>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
    dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            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

你可能感兴趣的:(SpringBoot,spring,boot,easyui,java)