珂泽小站 - SpringBoot
type: channel
link: https://www.kezez.com/tag/SpringBoot/
items: Springboot为方法创建单独的线程并后台执行
items: jar包部署运行与停止运行命令
items: SpringBoot项目Cookie登录实践
items: SpringBoot使用Base64Utils对字符串进行Base64编码和解码
items: 「转载」SpringBoot解决CORS问题
items: uni-app 对接 SpringBoot 实现图片上传
items: SpringBoot实战之使用Fastjson解析外链JSON
items: SpringBoot实战之整合EasyExcel处理Excel表格
items: SpringBoot安全优化之整合AntiSamy过滤XSS攻击
items: SpringBoot处理图片或文件上传

Springboot为方法创建单独的线程并后台执行
type: item
date: 2022-04-20T10:30:37+00:00
description: 一般在调用方法操作时，访问后方法会在前台执行，执行结束后才会返回结果，但如果是在web的情况下，如果需要执行的方法耗时较长，必然会影响前台的使用体验，我们可以通过为这个方法创建一个后台线程，让这个线程自己单独执行，执行结束后写入结果，前台需要查询结果时刷新即可，不会影响前台操作。Springboot 内置了 @Async 注解，用于为方法创建一个线程，让这个方法异步执行。要使用这个注解，我们需要在启动类上添加@EnableAsync注解，才可以继续使用。在需要进行异步执行的方法添加@Async注解即可。不过我在普通方法使用@Async注解时并没有正确的执行，在具有@Service注解的类中的方法使用此注解，也就是业务层，可以被正确执行。

jar包部署运行与停止运行命令
type: item
date: 2022-03-26T10:06:00+00:00
description: 运行jar包直接通过java-jar的方式可直接在终端前台运行jar包，也会直接动态显示日志，这个方式可以测试jar包能不能正常的运行。java -jar hgnuman-1.3.0-RELEASE.jar 如果测试莫得问题，那么就可以ctrl+c退出程序，就让这个jar包后台运行了sudo -u www nohup java -jar hgnuman-1.3.0-RELEASE.jar >hgnuman.log 2>&1 &这个命令中，我切换到了www用户来执行，nohup让程序在后台执行，后面的log就是让这个程序的日志输出到当前目录下，当然名称可以随意更改。运行这个命令后会返回程序的PID，等待一会程序就正常运行了。停止jar包运行如果是前台的话，直接ctrl+c即可停止，如果是在后台运行，那就可通过下方的命令来找到当前正在运行jar包的pid，然后通过kill命令干掉这个程序。ps aux|grep hgnuman-1.3.0-RELEASE.jar这里可以看到PID是30268，我们kill掉他kill 30268执行之后如果没有任何输出，那就说明已经kill掉了，因为没有结果就是最好的结果。

SpringBoot项目Cookie登录实践
type: item
date: 2022-03-20T08:16:00+00:00
description: Cookie生成与处理首先写一个cookie加密的方法，目前的思路是根据用户名和密码生成加密后的cookie token,加密规则 Base64(username) + "|" + md5(username+password) 生成一段结果字符串public static String encryUserCookieMd5(String username,String password){ String str = username+password; String md5_username_password = DigestUtils.md5DigestAsHex(str.getBytes()); String base64_username = Base64Utils.encodeToString(username.getBytes(StandardCharsets.UTF_8)); return base64_username + "|" + md5_username_password; }然后写一个解密的方法，读取request中的cookie,传入的cokie字符串的值 通过 “|”将cookie字符串分割为两个部分 将第一部分加密的username进行解密，并返回这个username值public static String decryUserCookieMd5(String cookie){ String[] cookies = cookie.split("\\|"); byte[] username = Base64Utils.decode(cookies[0].getBytes(StandardCharsets.UTF_8)); return new String(username); }登录请求拦截注册一个登录拦截器 LoginIntercepter ，对登录请求进行拦截处理，首先判断session中是否以及存在登录了此用户，如果登录则直接返回true，代表登录成功，如果没有的话就获取cookie，根据上方的cookie编码解码规则，得到cookie中的用户名，然后根据用户名从数据库中查找用户，根据查找的这个用户的用户名和密码再次进行编码加密，与cookie原始值进行比对，如果完全想等则认为此用户可以使用cookie登录成功。public class LoginIntercepter implements HandlerInterceptor { @Autowired UserRepository userRepository; public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 登录检查逻辑 HttpSession session = request.getSession(); Object loginuser = session.getAttribute("LoginUser"); if (loginuser != null) { return true; } else { // 获得cookie Cookie[] cookies = request.getCookies(); Integer hase_cookie_user = 1; // 没有cookie信息，则重定向到登录界面 if (null != cookies) { // 获取cookie里面的一些用户信息 for (Cookie item : cookies) { // 根据获取的cookie值,将值进行解密获取username // 然后从数据库中获取用户名和密码并进行加密操作 // 如果加密后的字符串和当前传入的字符串相同，则代表此用户可通过cookie登录 if ("cookie_username".equals(item.getName())) { String cookie_username = item.getValue(); String uname = SecMd5.decryUserCookieMd5(cookie_username); log.info("uname:" + uname); User user = userRepository.findByUsernameEquals(uname); if (user != null) { String user_name = user.getUsername(); String user_password = user.getPassword(); if (SecMd5.encry…

SpringBoot使用Base64Utils对字符串进行Base64编码和解码
type: item
date: 2022-03-20T07:51:16+00:00
description: 使用Base64UtilsSpring框架提供了可以进行base64编码解码的工具包，我们可以直接导入使用import org.springframework.util.Base64Utils;base64编码并返回字符串public static String encryStringBase64(String str){ return Base64Utils.encodeToString(str.getBytes(StandardCharsets.UTF_8)); }base64解码并生成字符串public static String decryStringBase64(String base64_str){ byte[] str = Base64Utils.decode(base64_str.getBytes(StandardCharsets.UTF_8)); return new String(str); }这里解码后会返回一个byte类型的数组，需要将它转换成字符串，需要使用new来创建字符串，而不可用直接使用toString()方法，如果使用了toString方法则会返回数组的内存地址字符串Base64Utils源码解析通过查看Base64Utils的源码可以发现Base64Utils也是通过java自带的Base64工具包来实现的方法作用encode(byte[] src)对给定的字节数组进行base64编码。 参数原始字节数组 返回编码后的字节数组decode(byte[] src)对给定的字节数组进行base64解码。 参数编码的字节数组 返回原始字节数组encodeUrlSafe(byte[] src)使用RFC 4648“URL和文件名安全字母表”对给定的字节数组进行base64编码。 参数: SRC -原始字节数组 返回: 编码后的字节数组decodeUrlSafe(byte[] src)base64解码给定的字节数组使用RFC 4648“URL和文件名安全字母表”。 参数: SRC -编码的字节数组 返回: 原始字节数组encodeToString(byte[] src)将给定的字节数组进行base64编码为String。 参数: SRC -原始字节数组 返回: 编码后的字节数组作为UTF-8字符串decodeFromString(String src)从给定的UTF-8字符串字节数组解码。 参数: src -编码的UTF-8字符串 返回: 原始字节数组encodeToUrlSafeString(byte[] src)使用RFC 4648“URL和文件名安全字母表”将给定的字节数组编码为字符串。 参数: SRC -原始字节数组 返回: 编码后的字节数组作为UTF-8字符串decodeFromUrlSafeString(String src)使用RFC 4648“URL和文件名安全字母表”从UTF-8字符串解码给定的字节数组。 参数: src -编码的UTF-8字符串 返回: 原始字节数组源代码/* * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.util; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import …

「转载」SpringBoot解决CORS问题
type: item
date: 2022-01-20T10:19:00+00:00
description: 本文转载来源：SpringBoot解决CORS问题在做前后端分离的开发或者前端调用第三方平台的接口时经常会遇到跨域的问题，前端总是希望能够通过各种方法解决跨域的问题。但事实上跨域问题是安全问题。这篇文章将会讲解一些为什么会有跨域问题，并提供一个方便的解决方法。为了阅读的流畅，相关的参考链接均会在文章末尾给出。本文使用的springboot版本为2.1.6.RELEASE，相应的spring版本为5.1.8.RELEASE。跨域问题的产生跨域问题的产生是因为浏览器的同源策略。同源策略将协议+域名+端口构成的三元作为一个整体，只有三者均相同的情况下才属于一个源。跨域问题也就是不同源之间访问导致的问题。同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。浏览器的同源策略 @developer.mozilla.org下表给出了相对http://store.company.com/dir/page.html同源检测的示例:URL结果原因http://store.company.com/dir2/other.html成功只有路径不同http://store.company.com/dir/inner/another.html成功只有路径不同https://store.company.com/secure.html失败不同协议 ( https和http )http://store.company.com:81/dir/etc.html失败不同端口 ( http:// 80是默认的)http://news.company.com/dir/other.html失败不同域名 ( news和store )对于跨域的请求，服务器可以接受到请求，但浏览器不会出来请求的返回结果。在浏览器中打开本地的一个html文件，在客户端中输入一下的内容可以模拟跨域的请求。（为了防止因为https的限制而无法发送请求，可以自己启动一个前端服务，然后再进行试验。）var xhttp = new XMLHttpRequest(); xhttp.open("GET", "http://192.168.20.185:8080/users/12345678", true); xhttp.send();跨域资源共享 CORSCORS是一个W3C标准，全称是"跨域资源共享"（Cross-origin resource sharing）。它允许浏览器向跨源服务器，发出XMLHttpRequest请求，从而克服了AJAX只能同源使用的限制。-- 前端的辅助配置Header值示例描述Access-Control-Allow-Credentialstrue是否允许发送Cookie，默认falseAccess-Control-Allow-HeadersAuthorization,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers后端接受的请求头。除了Accept，Accept-Language，Content-Language，Last-Event-ID和Content-Type外的附加请求头Access-Control-Allow-MethodsGET,POST,HEAD,OPTIONS,PUT,DELETE,PATCH后端接受的请求方法。除了HEAD，GET，POST外的请求方法Access-Control-Allow-Originhttp://localhost:4000请求的来源，一般为当前页面所在的源。要么为准确值，要么为*.Access-Control-Expose-HeadersAccess-Control-Allow-Origin,Access-Control-Allow-Credentials暴露给客户端的请求头。除了Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma之外的附加响应头Access-Control-Max-Age86400预检请求有效时长，单位为秒当Access-Control-Allow-Credentials为true时，不可以设置Access-Control-Allow-Origin为*减少预检请求（Option） 通过延长预检请求的有效期，可以减少对同一个源的Option请求的数量。如设置为86400，则24小时内无需在对同一个源发送Option请求。Spring Web解决方法通过过滤器处理请求，对origin进行判断，并添加必要的Hea…

uni-app 对接 SpringBoot 实现图片上传
type: item
date: 2022-01-20T09:53:00+00:00
description: 实现uniapp点击按钮从相册选择图片上传，上传成功后返回图片的路径及URL参数前端使用uni自带的图片选择以及上传组件 <view> 上传图片 </view> 后端创建一个实体类，用来返回上传完成后的文件结果package cn.vwmwv.hgnuman.entity; import lombok.Data; @Data public class UpFile { String pathString; String fileUrl; String msg; } 封装一个上传文件的方法/* * Copyright (c) 2022. Kaygb * All rights reserved. * Site: https://www.vwmwv.cn/ * Github: https://github.com/kaygb/ */ package cn.vwmwv.hgnuman.utils; import cn.vwmwv.hgnuman.entity.UpFile; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.system.ApplicationHome; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Objects; import java.util.Random; @Slf4j public class UploadFile { public UpFile upFile( MultipartFile file){ String basePath = new ApplicationHome(this.getClass()).getSource().getParentFile().getPath() + "/upload-files/"; log.info(basePath); String pathString; String fileNameString; String file_url; UpFile upFile = new UpFile(); // 检查文件是否为null以及文件类型后缀是否符合要求 if (file != null && CheckFileType.CheckImgType(file.getContentType())) { // 图片后缀 String file_suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."), file.getOriginalFilename().length()); Random rand = new Random(); // 图片名称 fileNameString = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + (rand.nextInt(1000) + 1) + file_suffix; // 存储路径 pathString = basePath + new SimpleDateFormat("yyyy").format(new Date()) + "/" + new SimpleDateFormat("MMdd").format(new Date()) + "/" + fileNameString; // 图片url file_url = "/upload-files/" + new SimpleDateFormat("yyyy").format(new Date()) + "/" + new SimpleDateFormat("MMdd").format(new Date()) + "/" + fileNameString; try { File files = new File(pathString); // 创建新文件 boolean dir = files.getParentFile().exists(); //检查文件路径是否存在 if (!files.getParentFile().exists()) { // 如果不存在则创…

SpringBoot实战之使用Fastjson解析外链JSON
type: item
date: 2021-08-21T09:01:00+00:00
description: 在最近上线的小圈子Springboot项目中，使用了阿里巴巴开源fastjson对api中的数据进行解析。引入依赖<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>RELEASE</version> </dependency>后端代码创建Service创建HttpClient Service，用来处理对外部url的http请求@Service public class HttpClient { public String client(String url, HttpMethod method, MultiValueMap<String,String> param) throws Exception{ RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String > responseEntity = restTemplate.getForEntity(url,String.class); return responseEntity.getBody(); } }处理url的json数据并转换成字符串String url = "https://circleapi.url.cn/xxx/xxx/"+page; HttpMethod httpMethod = HttpMethod.GET; MultiValueMap<String,String> param = new LinkedMultiValueMap<>(); String jsonData = httpClient.client(url,httpMethod,param);提取数据节点注：代码块中的三个点...是忽略未展示的代码通过观察可以发现，我们只需要获取data节点下的数据即可，所以我们将data节点下的数据转换为数组JSONObject jsonObject = JSONObject.parseObject(jsonData); JSONArray jsonArray = jsonObject.getJSONArray("data");对JsonArray数组进行遍历，分割出单条数据for (int i = 0;i<jsonArray.size();i++){ String itemData = jsonArray.getString(i); JSONObject itemJsonObject = JSONObject.parseObject(itemData); String title = itemJsonObject.getString("title"); String text = itemJsonObject.getString("text"); String link = itemJsonObject.getString("link"); ··· }我们发现，在单条数据下的Author节点下还存在数据，所已我们也要对节点下的数据进行处理，将此节点转换为一个JSONObject对象，通过这个对象我们可以获取数据String itemAuthorItem = itemJsonObject.getString("author"); JSONObject itemAuthor = JSONObject.parseObject(itemAuthorItem); String name = itemAuthor.getString("name"); String hash = itemAuthor.getString("hash"); String site = itemAuthor.getString("site");创建一个时间转换工具类，顺便格式化一下时间戳public class DateTimeUtils { public static String convertTimestamp2Date(Long timestamp, String pattern) …

SpringBoot实战之整合EasyExcel处理Excel表格
type: item
date: 2021-07-22T11:42:00+00:00
description: 如果我们需要把数据库中的数据导出，那么大家可能会使用POI，POI是非常强大的，但是却有它的缺点，比如比较消耗内存，所以阿里巴巴团队便开源了JAVA解析Excel工具EasyExcel。easyexcel重写了poi对07版Excel的解析，能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M，并且再大的excel不会出现内存溢出，03版依赖POI的sax模式。在上层做了模型转换的封装，让使用者更加简单方便。什么是EasyExcel?EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。 Github地址:https://github.com/alibaba/easyexcel使用引入POM依赖由于是对POI进行的优化，所以我们可以在引入EasyExcel的时候先将之前的POI依赖删除或注释掉，然后填入以下依赖： <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.10</version> </dependency>然后Reload maven等待引入EasyExcel。创建实体类/* * Copyright (c) 2021. Kaygb * All rights reserved. * Site: https://www.vwmwv.cn/ * Github: https://github.com/kaygb/ */ package cn.vwmwv.hgnuman.entity; import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import org.springframework.data.annotation.CreatedDate; import javax.persistence.*; import java.util.Date; // 报修任务 @Data @Entity @Table(name = "mana_task") @ColumnWidth(30) public class Task { @ExcelIgnore @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; @ExcelProperty(value = "创建时间", index = 0) @CreatedDate @JsonFormat(pattern="yyyy-MM-dd hh:mm:ss") @Column Date createtime;// 创建时间 @ExcelIgnore @Column Date updatetime;// 接单时间 @ExcelIgnore @Column Date verfytime;// 审核时间 @ExcelProperty(value = "报修内容描述", index = 1) @Column String description;// 报修内容描述 @ExcelProperty(value = "图片链接", index = 2) @Column String imgsrc; // 图片地址 @ExcelIgnore @Column Integer categoryid; // 所属分类id @ExcelProperty(value = "分类", index = 3) @Column String categoryname; // 此处省略部分代码 }在实体类上使用注解，表示该字段是否是需要导出的字段，并通过index设设置列顺序@ExcelProperty(value = "表头字段" index = 1)@ExcelIgnore // 忽略此字段，即导出的时候不输出@ColumnWidth(30) // 指定列宽为30取出数据写入Excel项目中使用的Spring-data-jpa，所以我们通过方法对数据库进行时间区间查询并返回一个List（数据库和数据记得配置好）List<Task> taskList = taskRepository.findAllByCreatetimeGr…

SpringBoot安全优化之整合AntiSamy过滤XSS攻击
type: item
date: 2021-07-06T15:08:00+00:00
description: 什么是XSS？XSS攻击全称跨站脚本攻击，是一种在web应用中的计算机安全漏洞，它允许恶意web用户将代码植入到提供给其它用户使用的页面中。也就是说，在日常所常用的表单中，我们内嵌一段js代码提交，用户通过访问再从数据库中取出这段代码，就会跟随页面进行执行，甚至可以发送cookie，跳转网站等等。我们可以使用以下代码填入表单中验证系统是否存在XSS问题。 使用Antisamy进行XSS过滤AntiSamy是OWASP的一个开源项目，通过对用户输入的 HTML / CSS / JavaScript 等内容进行检验和清理，确保输入符合应用规范。AntiSamy被广泛应用于Web服务对存储型和反射型XSS的防御中。如何使用？引入依赖和配置文件首先我们引入maven依赖。<dependency> <groupId>org.owasp.antisamy</groupId> <artifactId>antisamy</artifactId> <version>RELEASE</version> </dependency>引入之后，我们可以通过查看jar包可以发现，AntiSamy自带了多个配置文件：其中，这些常用的配置文件介绍如下：antisamy-anythinggoes.xml允许所有有效的HTML和CSS元素输入（但能拒绝JavaScript或跟CSS相关的网络钓鱼攻击），因为它包含了对于每个元素的基本规则，所以你在裁剪其它策略文件的时候可以把它作为一个知识库，一般不建议使用。antisamy-ebay.xmleBay 是当下最流行的在线拍卖网站之一。它是一个面向公众的站点，因此它允许任何人发布一系列富HTML的内容，允许输入的内容列表包含了比 Slashdot 更多的富文本内容，所以它的受攻击面也要大得多。该策略相对安全，适用于电子商务网站。antisamy-myspace.xmlMySpace 是最流行的一个社交网站之一。用户允许提交除了JavaScript之外的几乎所有他们想用的HTML和CSS。MySpace现在用一个黑名单来验证用户输入的HTML，相对较危险，不建议使用。antisamy-slashdot.xmlSlashdot 是一个提供技术新闻的网站，其安全策略非常严格。用户只能提交下列的HTML标签：< b>、< u>、< i>、< a>、< blockquote>，并且还不支持CSS。该策略文件来实现了类似的功能，允许所有文本格式的标签来直接修饰字体、颜色或者强调作用，适用于新闻网站的评论过滤。antisamy-tinymce.xml只允许文本格式通过，相对较安全antisamy.xml默认规则，允许大部分HTML通过这里，我们使用slashdot配置文件，将此文件复制到resource目录中即可开始使用。创建XSSFilter过滤器通过doFilter方法来对传入的request过滤package cn.vwmwv.hgnuman.congfig; import cn.vwmwv.hgnuman.filter.XssFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AntiSamyConfiguration { // 过滤器配置文件 @Bean public FilterRegistrationBean filterRegistrationBean(){ // XSS过滤器 FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new XssFilter()); filterRegistrationBean.addUrlPatterns("/*"); filterRegistrationBean.setOrder(1); return filterRegistrationBean; } }创建XssRequestWrapper package cn.vwmwv.hgnuman.filter; import org.owasp.validator.html.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWr…

SpringBoot处理图片或文件上传
type: item
date: 2021-06-15T14:29:00+00:00
description: 现在，我们需要使用springboot和layui来上传图片或者文件，springboot已经集成了文件上传功能，我们可以直接开始使用。本次的需求是：在表单中，点击按钮上传图片，上传成功则在按钮旁边把上传的图片显示出来。视图层上传文件之后，需要将上传后获取的文件url路径放到一个隐藏的input中，在提交的时候提交给数据库存起来，所以，我们先在表单中放一个按钮和一个隐藏的img标签 问题描述 上传照片 上传图片 立即提交 其中的重点在下方，可以看到，我们放入了一个按钮，一个img标签，并且为img标签设置了默认不显示。 上传照片 上传图片 接下来，使用js来请求接口并且上传文件，上传成功后res为服务器返回的值，包括了url和实际路径，然后接着把上面的img标签填充src并且让他显示即可。//执行实例 var uploadInst = upload.render({ elem: '#uploadimg' //绑定元素 ,url: '/fileUpload' //上传接口 ,accept: 'file' ,method: 'POST' ,done: function(res){ //上传完毕回调 $("#show_up_img").attr("src","/upload-files/"+res.data.url).css("display",""); layer.alert(res.data.url + " " + res.data.path); } ,error: function(){ layer.alert("上传失败！图片限制10MB内"); //请求异常回调 } });视图的显示以及提交逻辑已经写好了，接下来，我们需要在后端处理上传的文件。控制层我们先设置一个上传的目录，也就是一个上传到服务器的路径，这里我先设置为D盘的一个文件夹。（当然，服务器大都是运行linux的，而linux和win的文件系统稍有不同，这部分后面再说）D://upload-files//在处理文件之前，我们要先配置一下路径映射，将请求的/upload-files映射到我们刚刚设置的文件夹@Configuration public class AdminWebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 映射资源url与本地资源路径 registry.addResourceHandler("/upload-files/**").addResourceLocations("file:D:/upload-files/"); } }接着，我们写一个post方法，来处理上传的文件，其中，为了避免中文文件名称的编码问题，将上传的文件名称截取到最后一个小数点，然后通过时间戳加上随机数的方式来避免文件名重复。String file_suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."),file.getOriginalFilename().length()); Random rand = new Random(); fileNameString = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_"+ (rand.nextInt(1000)+1) + file_suffix; pathString = "D://upload-files//" + fileNameString;然后使用一个Map来返回layui所需要的json的数据Map<String,Object> map = new HashMap<>(); Map<String,String> datas = new HashMap<>(); datas.put("path", pathString); datas.put("url",fileNameString); //状态码如果成功返回0 map.put("code", "0"); //错误代码 map.put("msg", ""); //返回路径 map.put("data", datas);完整代码如下：@PostMapping("/fileUpload") public Map<String,Object> fileUpload(@RequestParam(value = "file") MultipartFi…