本篇文章重点分享一下怎么通过easyui的filebox实现文件上传的功能,从前端代码到后端接口都会展示给大家。
1、form表单同步上传
传统的文件上传会把<input type="file" />放到一个<form></form>里,设置form表单的提交方式为post,而且数据传输格式为multipart/form-data
<form method="post" action="/upload" enctype="multipart/form-data">请选择文件:<input type="file" name="file" /><input type="submit" value="提交" /></form>
2、异步文件上传
以上是表单的同步提交,如果要实现异步文件上传的话,又该怎么做呢?
首先,说一下异步文件上传的基本思路:
文件上传框可以不放在<form>里,而是在<form>标签里面设置一个隐藏域,保存我们文件上传之后后端返回来的url,同时可以通过url回显图片。
本篇文章中,文件上传输入框放在了form表单里,方便通过easyui表单的validate方法验证必填项。
接下来开始步入正题,贴上前端页面的代码:
<!DOCTYPE html><html><head><meta charset="utf-8" /><link rel="stylesheet" href="/css/themes/icon.css"/><link rel="stylesheet" href="/css/themes/default/easyui.css" /><title>法宝管理>>法宝类型列表</title><script src="/js/public/jquery.min.js"></script><script src="/js/easyui/jquery.easyui.min.js"></script><script src="/js/easyui/easyui-lang-zh_CN.js"></script><script src="/js/public/util.js"></script><script src="/js/public/public.js"></script><script src="/js/fabao/fabao_category_list.js"></script></head><body><form id="search_form"><table style="border-spacing:5px;"><tr><td><input id="_type" /></td><td><input id="_name" /></td><td><a id="search">搜索</a></td><td><a id="clear">清空</a></td></tr></table></form><!-- 法宝类型对话框 --><div id="fabao_category_dialog" style="display:none;"><form id="fabao_category_form"><input type="hidden" id="id" name="id" /><table style="border-spacing:5px;"><tr><td>法宝名称</td><td><input id="name" name="name" /></td><td>法宝类型</td><td><input id="type" name="type" /></td></tr><tr><td>法宝信息</td><td colspan="3"><input id="note" name="note" /></td></tr></table></form></div><!-- 修改法宝图片对话框 --><div id="upload_dialog" style="display:none;"><form id="upload_form"><input type="hidden" id="categoryId" name="id" /><input type="hidden" id="image" name="image" /><table style="border-spacing:5px;"><tr><td>上传图片</td><td><input id="upload" /></td></tr><tr><td>图片预览</td><td><img id="img" height="80" /></td></tr></table></form></div><table id="fabao_category_list"></table></body></html>
以上是一个完整页面的HTML代码,我们只需要关注以下代码片段,其中设置了一个隐藏域<input type="hidden" />用于保存文件上传的回显图片URL,当我们提交表单时,会把这个url一起提交到后台,这时候只需要完成通过ID修改图片的操作。
<div id="upload_dialog" style="display:none;"><form id="upload_form"><input type="hidden" id="categoryId" name="id" /><input type="hidden" id="image" name="image" /><table style="border-spacing:5px;"><tr><td>上传图片</td><td><input id="upload" /></td></tr><tr><td>图片预览</td><td><img id="img" height="80" /></td></tr></table></form></div>
页面的js代码如下:(注意:这里的datagrid的ajax请求方式默认是get,博主修改了easyui.min.js,并把默认方式改成了post)
let requestUrl;let types = ["主动法宝", "被动法宝"];function addHandler() {requestUrl = "/fabao_category/insert";$("#fabao_category_dialog").dialog("open");}function editHandler() {let rowData = $("#fabao_category_list").datagrid("getSelected");if (rowData) {requestUrl = "/fabao_category/updateById";$("#id").val(rowData.id);$("#name").textbox("setValue", rowData.name);$("#type").combobox("setValue", rowData.type);$("#note").textbox("setValue", rowData.note);$("#fabao_category_dialog").dialog("open");} else {alertMsg("请选择要修改的记录!", "warning");}}function imageHandler() {let rowData = $("#fabao_category_list").datagrid("getSelected");if (rowData) {requestUrl = "/fabao_category/updateById";$("#categoryId").val(rowData.id);$("#image").val(rowData.image);$("#img").attr("src", rowData.image);$("#upload_dialog").dialog("open");} else {alertMsg("请选择要修改的记录!", "warning");}}$(document).ready(function() {$("#_type").combobox({width: 150,prompt: "法宝类型",panelHeight: "auto",data: getJsonData(types)});$("#_name").textbox({prompt: "请输入法宝名称"});// 搜索按钮$("#search").linkbutton({iconCls: "icon-search"}).click(function() {let type = $("#_type").combobox("getValue");let name = $("#_name").textbox("getValue");$("#fabao_category_list").datagrid("load", {type: type,name: name});});$("#clear").linkbutton({iconCls: "icon-delete"}).click(function() {$("#search_form").form("clear");});$("#name").textbox({width: 120,required: true});$("#type").combobox({width: 120,required: true,panelHeight: "auto",data: getJsonData(types)});$("#note").textbox({width: 314,height: 80,required: true,multiline: true});$("#fabao_category_dialog").dialog({title: "法宝信息",modal: true,closed: true,closable: false,draggable: false,buttons: [{iconCls: "icon-save",text: "保存",handler: function() {let selector = "#fabao_category_form";checkForm(selector, function () {let data = $(selector).serialize();post(requestUrl, data, function(response) {showMsg(response.message);$(selector).form("clear");$("#fabao_category_dialog").dialog("close");$("#fabao_category_list").datagrid("reload");}, error);});}}, {iconCls: "icon-cancel",text: "取消",handler: function() {$("#fabao_category_dialog").dialog("close");$("#fabao_category_form").form("clear");}}]});// 文件上传框$("#upload").filebox({buttonText: "选择文件",width: 200,required: true,onChange: function() {fileUpload(this, "/fabao_category/upload");}});// 上传图片对话框$("#upload_dialog").dialog({title: "法宝图片",modal: true,closed: true,closable: false,draggable: false,buttons: [{iconCls: "icon-save",text: "保存",handler: function() {let selector = "#upload_form";checkForm(selector, function () {let data = $(selector).serialize();post(requestUrl, data, function(response) {showMsg(response.message);resetValue("#upload");$(selector).form("clear");$("#upload_dialog").dialog("close");$("#fabao_category_list").datagrid("reload");}, error);});}}, {iconCls: "icon-cancel",text: "取消",handler: function() {resetValue("#upload");$("#upload_form").form("clear");$("#upload_dialog").dialog("close");}}]});// 法宝类型数据列表$("#fabao_category_list").datagrid({url: "/fabao_category/selectByPage",striped: true,fitColumns: true,singleSelect: true,height: table_height,pagination: true,pageList: pageList,pageSize: pageList[0],loadFilter: function(result){if (result.code === 200){return result.data;} else {return null;}},toolbar: [{iconCls: "icon-add",text: "添加",handler: function() {addHandler()}}, "-", {iconCls: "icon-edit",text: "修改",handler: function() {editHandler();}}, "-", {iconCls: "icon-image",text: "图片",handler: function() {imageHandler();}}],columns: [[{field: "id", title: "编号", align: "center"},{field: "name", title: "法宝名称", align: "center", width: 100},{field: "type", title: "类型", align: "center", width: 100,formatter: function(value) {return "<div>" + types[value] + "</div>";}},{field: "image", title: "图片", align: "center", width: 40, formatter: function(value) {return "<img height='" + size + "' src='" + value + "' />";}},{field: "note", title: "法宝信息", align: "center", width: 400,formatter: function(value) {return "<div class='ell'>" + value + "</div>";}}]]});});
重点看以下代码片段
let requestUrl;function imageHandler() {let rowData = $("#fabao_category_list").datagrid("getSelected");if (rowData) {requestUrl = "/fabao_category/updateById";$("#categoryId").val(rowData.id);$("#image").val(rowData.image);$("#img").attr("src", rowData.image);$("#upload_dialog").dialog("open");} else {alertMsg("请选择要修改的记录!", "warning");}}$(document).ready(function() {$("#upload").filebox({buttonText: "选择文件",width: 200,required: true,onChange: function() {fileUpload(this, "/fabao_category/upload");}});$("#upload_dialog").dialog({title: "法宝图片",modal: true,closed: true,closable: false,draggable: false,buttons: [{iconCls: "icon-save",text: "保存",handler: function() {let selector = "#upload_form";checkForm(selector, function () {let data = $(selector).serialize();post(requestUrl, data, function(response) {showMsg(response.message);resetValue("#upload");$(selector).form("clear");$("#upload_dialog").dialog("close");$("#fabao_category_list").datagrid("reload");}, error);});}}, {iconCls: "icon-cancel",text: "取消",handler: function() {$("#upload_form").form("clear");$("#upload_dialog").dialog("close");}}]});});
当我们选中某行数据时,点击【图片】按钮,就会打开我们的文件上传的对话框,同时如果这行记录本来的图片不为空,也会显示出来。效果图大概是这样
当我们点击上传文件后面的选择框并选择图片上传时,会提交post请求到接口"/fabao_category/upload",完成文件的上传,上传成功后会返回文件的相对路径,然后重新设置图片预览后面的图片的src属性为返回的URL。
当我们点击保存按钮时,会通过ajax的post请求的方式提交表单数据到我们的"/fabao_category/updateById"接口,就是修改法宝类型信息的接口。数据修改成功之后会刷新表格数据。
$("#fabao_category_list").datagrid("reload");
js文件里的多个方法来自于util.js
let wkf = "该功能暂未开放,敬请期待~";let base = "http://localhost:9091/api/mhxysy";base = "";/*** 封装的ajax get请求* @param url 请求url* @param params 请求参数* @param success 成功回调函数* @param error 失败回调函数* @param async 是否异步*/function get(url, params, success, error, async = true) {$.ajax({type: "GET",url: base + url,data: params,cache: false,async: async,dataType: "json",processData: true,success: success,error: error});}/*** 封装的ajax post请求* @param url 请求url* @param params 请求参数* @param success 成功回调函数* @param error 失败回调函数* @param async 是否异步*/function post(url, params, success, error, async = true) {$.ajax({type: "POST",url: base + url,data: params,async: async,cache: false,dataType: "json",processData: true,success: success,error: error});}/*** Ajax POST请求* @param url 请求路径* @param data 请求参数* @param success 成功回调* @param error 失败回调*/function ajaxPost(url, data, success, error) {$.ajax({url: base + url,data: data,cache: false,async: true,type: "POST",dataType: "json",processData: false,contentType: false,success: success,error: error});}let error = (res) => {console.log(res);if (res && res.responseJSON) {let response = res.responseJSON;if (res.status && res.status === 404) {let message;if(response.path) {message = "路径" + response.path + "不存在。";} else {message = response.message;}alertMsg(message, "error");} else {alertMsg(response.message, "error");}}}/*** 右下角弹出消息提示* @param message 提示消息* @param type 消息类型*/function showMsg(message, type = "slide") {$.messager.show({title: "消息",msg: message,timeout: 3000,showType: type});}/** 弹出提示* @param message 提示消息* @param type 提示类型:warning/error/info/question*/function alertMsg(message, type = "info") {$.messager.alert("提示", message, type);}/*** 重置文件上传组件的值* @param selector 组件的选择器*/function resetValue(selector) {$(selector).filebox("initValue", null);}/*** 功能未开放*/function unopen() {alertMsg(wkf);}function unselected() {alertMsg("请选择一条记录!", "warning");}function fileUpload(_obj, url) {let file = $(_obj).context.ownerDocument.activeElement.files[0];let form = new FormData();form.append("file", file);ajaxPost(url, form, function (result) {let image = result.data;$("#image").val(image);$("#img").attr("src", image);}, error);}/*** 验证表单* @param selector 选择器* @param func 表单验证通过后执行的操作*/function checkForm(selector, func) {let $form = $(selector);let bool = $form.form("validate");if (bool) {func();} else {alertMsg("请填写正确的表单项", "warning");}}/*** 根据数组获取json格式的数据* @param arr*/function getJsonData(arr) {let jsonData = [];for (let i = 0; i < arr.length; i++) {let elem = {"value": i + "", "text": arr[i]};jsonData.push(elem);}return jsonData;}/*** 初始化easyui数据列表datagrid* @param selector 选择器* @param url 加载数据的URL* @param toolbar 头部工具栏* @param columns 表格的列* @param height 表格高度* @param pageList 分页参数* @param rownumbers 是否显示行号*/function asDatalist(selector, url, toolbar, columns, height = 432, pageList = [10, 20, 50, 100], rownumbers = false) {$(selector).datagrid({url: url,striped: true,height: height,fitColumns: true,singleSelect: true,rownumbers: rownumbers,pagination: true,pageList: pageList,pageSize: pageList[0],loadFilter: function(result){if (result.code === 200){return result.data;} else {return null;}},toolbar: toolbar,columns: columns});}
接下来看一下后端的接口怎么写的:
FabaoCategoryController.java
package cn.edu.sgu.www.mhxysy.controller.fabao;import cn.edu.sgu.www.mhxysy.restful.JsonResult;import cn.edu.sgu.www.mhxysy.restful.PageResult;import cn.edu.sgu.www.mhxysy.entity.fabao.FabaoCategory;import cn.edu.sgu.www.mhxysy.pager.fabao.FabaoCategoryPager;import cn.edu.sgu.www.mhxysy.service.fabao.FabaoCategoryService;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.multipart.MultipartFile;import java.io.IOException;import java.util.List;@RestController@Api(tags = "法宝类型控制器类")@RequestMapping(path = "/fabao_category", produces="application/json; charset=utf-8")public class FabaoCategoryController {private final FabaoCategoryService service;@Autowiredpublic FabaoCategoryController(FabaoCategoryService service) {this.service = service;}@ApiOperation("添加法宝类型")@RequestMapping(value = "/insert", method = RequestMethod.POST)public JsonResult<Void> insert(FabaoCategory category) {service.insert(category);return JsonResult.success("添加成功");}@ApiOperation("通过id修改法宝类型信息")@RequestMapping(value = "/updateById", method = RequestMethod.POST)public JsonResult<Void> updateById(FabaoCategory category) {service.updateById(category);return JsonResult.success("修改成功");}@ApiOperation("查询全部法宝类型")@RequestMapping(value = "/selectAll", method = RequestMethod.GET)public List<FabaoCategory> selectAll() {return service.selectAll();}@ApiOperation("通过id查询法宝类型信息")@RequestMapping(value = "/selectById", method = RequestMethod.GET)public FabaoCategory selectById(@RequestParam Integer id) {return service.selectById(id);}@ApiOperation("分页查询法宝类型列表")@RequestMapping(value = "/selectByPage", method = RequestMethod.POST)public JsonResult<PageResult<FabaoCategory>> selectByPage(FabaoCategoryPager pager) {Page<FabaoCategory> result = service.selectByPage(pager);return JsonResult.restPage(result);}@ApiOperation("上传图片")@RequestMapping(value = "/upload", method = RequestMethod.POST)public JsonResult<String> upload(MultipartFile file) throws IOException {String url = service.upload(file);return JsonResult.success(null, url);}}
FabaoCategoryServiceImpl.java
package cn.edu.sgu.www.mhxysy.service.fabao.impl;import cn.edu.sgu.www.mhxysy.util.StringUtils;import cn.edu.sgu.www.mhxysy.base.Pager;import cn.edu.sgu.www.mhxysy.consts.DirectoryConsts;import cn.edu.sgu.www.mhxysy.entity.fabao.FabaoCategory;import cn.edu.sgu.www.mhxysy.mapper.fabao.FabaoCategoryMapper;import cn.edu.sgu.www.mhxysy.pager.fabao.FabaoCategoryPager;import cn.edu.sgu.www.mhxysy.service.fabao.FabaoCategoryService;import cn.edu.sgu.www.mhxysy.util.UploadUtils;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.multipart.MultipartFile;import java.io.IOException;import java.util.List;/*** @author heyunlin* @version 1.0*/@Servicepublic class FabaoCategoryServiceImpl implements FabaoCategoryService {private final UploadUtils uploadUtils;private final FabaoCategoryMapper mapper;@Autowiredpublic FabaoCategoryServiceImpl(UploadUtils uploadUtils, FabaoCategoryMapper mapper) {this.uploadUtils = uploadUtils;this.mapper = mapper;}@Overridepublic void insert(FabaoCategory category) {mapper.insert(category);}@Overridepublic void updateById(FabaoCategory category) {mapper.updateById(category);}@Overridepublic List<FabaoCategory> selectAll() {return mapper.selectList(null);}@Overridepublic FabaoCategory selectById(Integer id) {return mapper.selectById(id);}@Overridepublic Page<FabaoCategory> selectByPage(FabaoCategoryPager pager) {QueryWrapper<FabaoCategory> wrapper = new QueryWrapper<>();Page<FabaoCategory> page = Pager.ofPage(pager);wrapper.eq(pager.getType() != null,"type", pager.getType());wrapper.like(StringUtils.isNotEmpty(pager.getName()),"name", pager.getName());return mapper.selectPage(page, wrapper);}@Overridepublic String upload(MultipartFile file) throws IOException {String directory = DirectoryConsts.DIRECTORY_FABAO;return uploadUtils.upload(file, directory);}}
DirectoryConsts.java
DirectoryConsts就是一个存放常量的接口,保存项目用到的文件上传的相对路径
package cn.edu.sgu.www.mhxysy.consts;/*** 常量工具类* 定义了项目用到的文件上传路径相对根路径root的文件夹*/public interface DirectoryConsts {/*** 角色图片上传文件夹*/String DIRECTORY_ROLE = "/role/head";/*** 烹饪图片上传文件夹*/String DIRECTORY_CUISINE = "/cuisine";/*** 药品图片上传文件夹*/String DIRECTORY_MEDICINE = "/medicine";/*** 角色日常记录图片上传文件夹*/String DIRECTORY_DAILY_RECORD = "/daily_record";/*** 角色时装图片上传文件夹*/String DIRECTORY_ROLE_SHIZHUANG = "/role_shizhuang";/*** 特技图片上传文件夹*/String DIRECTORY_TETJ = "/teji";/*** 法宝图片上传文件夹*/String DIRECTORY_FABAO = "/fabao";/*** 坐骑图片上传文件夹*/String DIRECTORY_ZUOQI = "/zuoqi";/*** 门派图片上传文件夹*/String DIRECTORY_SCHOOL = "/school";/*** 门派法宝图片上传文件夹*/String DIRECTORY_SCHOOL_FABAO = "/school_fabao";/*** 器灵图片上传文件夹*/String DIRECTORY_QILING = "/qiling";/*** 宠物图片上传文件夹*/String DIRECTORY_CHONGWU = "/chongwu";/*** 助战图片上传文件夹*/String DIRECTORY_PARTNER = "/partner";/*** 助战图片上传文件夹*/String DIRECTORY_PARTNER_SKILL = "/partner_skill";/*** 装备图片上传文件夹*/String DIRECTORY_EQUIPMENT = "/equipment";/*** 修炼技能图片上传文件夹*/String DIRECTORY_XIULIAN = "/xiulian";/*** 变身卡图片上传文件夹*/String DIRECTORY_BIANSHENKA = "/bianshenka";/*** 坐骑技能图片上传文件夹*/String DIRECTORY_ZUOQI_SKILL = "/zuoqi_skill";/*** 门派技能图片上传文件夹*/String DIRECTORY_SCHOOL_SKILL = "/school_skill";/*** 宠物技能图片上传文件夹*/String DIRECTORY_CHONGWU_SKILL = "/chongwu_skill";/*** 宠物内丹图片上传文件夹*/String DIRECTORY_CHONGWU_NEIDAN = "/chongwu_neidan";/*** 宠物套装技能图片上传文件夹*/String DIRECTORY_CHONGWU_TAOZHUANG = "/chongwu_taozhuang";/*** 宠物专属内丹图片上传文件夹*/String DIRECTORY_ZHUANSHUNEIDAN = "/zhuanshu_neidan";/*** 器灵套装图片上传文件夹*/String DIRECTORY_QILING_TAOZHUANG = "/qiling_taozhuang";/*** 宠物装备图片上传文件夹*/String DIRECTORY_CHONGWU_EQUIPMENT = "/chongwu_equipment";/*** 器灵套装图片上传文件夹*/String DIRECTORY_QILING_TAOZHUANG_IMAGE = "/qiling_taozhuang_image";/*** 星印图片上传文件夹*/String DIRECTORY_XINGYIN = "/xingyin";/*** 星印图片上传文件夹*/String DIRECTORY_XINGYIN_SKILL = "/xingyin_skill";/*** 星印特效图片上传文件夹*/String DIRECTORY_XINGYIN_TEXIAO = "/xingyin_texiao";/*** 装备制造书图片上传文件夹*/String DIRECTORY_FORGE_BOOK = "/forge_book";}
UploadUtils.java
UploadUtils是文件上传工具类,定义为组件,因为要读取配置文件
package cn.edu.sgu.www.mhxysy.util;import cn.edu.sgu.www.mhxysy.restful.ResponseCode;import cn.edu.sgu.www.mhxysy.exception.GlobalException;import org.springframework.beans.factory.annotation.Value;import org.ponent;import org.springframework.web.multipart.MultipartFile;import java.io.File;import java.io.IOException;/*** 文件上传工具类* @author heyunlin* @version 1.0*/@Componentpublic class UploadUtils {/*** 文件上传根路径*/@Value("${uploads.path}")private String root;public String getRoot() {return root;}/*** 图片上传* @param file MultipartFile对象* @param directory 文件上传目录* @return JsonResult<String>*/public String upload(MultipartFile file, String directory) throws IOException {boolean result = check(file);if (result) {// 获取文件名String fileName = StringUtils.getFileName(file);// 创建目标对象File targetFile = new File(root + directory, fileName);// 保存文件file.transferTo(targetFile);return directory + "/" + fileName;}return null;}/*** 检查文件格式* @param file MultipartFile*/private boolean check(MultipartFile file) {if (file == null) {throw new GlobalException(ResponseCode.BAD_REQUEST, "您未上传任何图片!");}String filename = file.getOriginalFilename();if (StringUtils.isNotEmpty(filename)) {String fileType = StringUtils.getFileType(filename).toLowerCase();// 图片文件名后缀String picPrefix = ".webp,.jpeg,.jpg,.png";if (!picPrefix.contains(fileType)) {throw new GlobalException(ResponseCode.BAD_REQUEST, "只允许上传格式为" + picPrefix + "的图片");}return true;} else {throw new GlobalException(ResponseCode.BAD_REQUEST, "获取上传的文件名失败~");}}}
StringUtils.java
这是字符串工具类,封装常用的字符串相关方法
package cn.edu.sgu.www.mhxysy.util;import org.springframework.web.multipart.MultipartFile;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;/*** String工具类* @author heyunlin* @version 1.0*/public class StringUtils {/*** 判断字符串是否为null或""* 字符串为""或null返回true,否则返回false* @param str 要判断的字符串* @return boolean*/public static boolean isEmpty(String str) {return str == null || str.isEmpty() || isBlank(str);}/*** 判断字符串是否为""或null* 字符串为""或null返回false,否则返回true* @param str 要判断的字符串* @return boolean*/public static boolean isNotEmpty(String str) {return !isEmpty(str);}/*** 判断字符串是否为空白字符* 字符串为空白字符返回true,否则返回false* @param str 要判断的字符串* @return boolean*/public static boolean isBlank(String str) {return str.trim().length() == 0;}/*** 判断字符串是否不是空白字符* 字符串不是空白字符返回true,否则返回false* @param str 要判断的字符串* @return boolean*/public static boolean isNotBlank(String str) {return !isBlank(str);}/*** 判断字符串是否为null或""* 字符串为""或null返回true,否则返回false* @param str 要判断的字符串* @return boolean*/public static boolean isNullOrEmpty(String str) {return str == null || str.isEmpty();}/*** 检查字符串是否包含空白字符* 如果不包含空格返回true,否则返回false* @param str 需要比较的字符串* @return boolean*/public static boolean check(String str) {// 去除空白字符后字符串的长度int realLength = str.replaceAll("\\s", "").length();// 字符串原来的长度int originalLength = str.length();return realLength == originalLength;}/*** 根据当前时间生成UUID* @return String*/public static String uuid() {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");LocalDateTime localDate = LocalDateTime.now();return localDate.format(formatter);}/*** 通过文件名获取文件类型* @param fileName 文件名*/public static String getFileType(String fileName) {// 得到文件名中最后一次出现"."的位置int index = fileName.lastIndexOf('.');// 文件类型统一转换为小写return fileName.substring(index).toLowerCase();}/*** 获取文件名* @param filename String* @return String 由当前时间生成的新文件名*/public static String getFileName(String filename) {// 返回uuid.文件类型,如:0618131456.jpgreturn uuid() + getFileType(filename);}/*** 获取文件名* @param file MultipartFile对象* @return String 由当前时间生成的新文件名*/public static String getFileName(MultipartFile file) {// 得到上传文件的原始文件名String filename = file.getOriginalFilename();// 判断文件名是否为空if (isNullOrEmpty(filename)) {throw new RuntimeException("获取文件名失败!");}// 返回uuid.文件类型,如:0618131456.jpgreturn uuid() + getFileType(filename);}/*** 驼峰命名转下划线命名* @param str 待转换的字符串* @return String*/public static String toLowerCase(String str) {// 小写和大写紧挨一起的地方加上分隔符_,然后全部转为小写str = str.replaceAll("([a-z])([A-Z])", "$1_$2");return str.toLowerCase();}/*** 下划线命名转驼峰命名* @param str 待转换的字符串* @return String*/private static String toUpperCase(String str) {// 将下划线替换为空格StringBuilder under= new StringBuilder();str = str.toLowerCase().replace("_", " ");// 将字符串根据空格分割成数组String[] array = str.split(" ");// 将每个单词首字母大写for (String s : array) {String letter = s.substring(0, 1).toUpperCase() + s.substring(1);under.append(letter);}return under.toString();}}
最后是统一自定义异常GlobalException
package cn.edu.sgu.www.mhxysy.exception;import cn.edu.sgu.www.mhxysy.restful.ResponseCode;import lombok.Data;import lombok.EqualsAndHashCode;/*** 自定义异常* @author heyunlin* @version 1.0*/@Data@EqualsAndHashCode(callSuper = true)public class GlobalException extends RuntimeException {private ResponseCode responseCode;public GlobalException(ResponseCode responseCode, String message) {super(message);setResponseCode(responseCode);}}
配合全局异常处理类,就可以在项目运行过程时发生异常主动捕获,并调用对应的异常处理方法返回响应对象
package cn.edu.sgu.www.mhxysy.exception.handler;import cn.edu.sgu.www.mhxysy.restful.JsonResult;import cn.edu.sgu.www.mhxysy.restful.ResponseCode;import cn.edu.sgu.www.mhxysy.exception.GlobalException;import org.springframework.http.HttpStatus;import org.springframework.validation.BindException;import org.springframework.validation.BindingResult;import org.springframework.validation.FieldError;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseStatus;import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.servlet.http.HttpServletResponse;/*** 全局异常处理类* @author heyunlin* @version 1.0*/@RestControllerAdvicepublic class GlobalExceptionHandler {/*** 处理GlobalException* @param e GlobalException* @return JsonResult<Void>*/@ExceptionHandler(GlobalException.class)public JsonResult<Void> handlerGlobalException(HttpServletResponse response, GlobalException e) {System.err.println(e.getMessage());e.printStackTrace();response.setStatus(e.getResponseCode().getValue());return JsonResult.error(e.getResponseCode(), e);}/*** 处理BindException* @param e BindException* @return JsonResult<Void>*/@ExceptionHandler(BindException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public JsonResult<Void> handlerBindException(BindException e) {e.printStackTrace();BindingResult bindingResult = e.getBindingResult();FieldError fieldError = bindingResult.getFieldError();assert fieldError != null;String defaultMessage = fieldError.getDefaultMessage();return JsonResult.error(ResponseCode.BAD_REQUEST, defaultMessage);}/*** 处理Exception* @param e Exception* @return JsonResult<Void>*/@ExceptionHandler(Exception.class)@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)public JsonResult<Void> handlerException(Exception e) {e.printStackTrace();return JsonResult.error(ResponseCode.ERROR, e);}}
整个项目的结构如下
好了,这篇文章就分享到这里了,如果文章对你有所帮助,不要忘了点赞+收藏哦~