SpringBoot实战第五天

最后在开发一个文件上传接口,结束后端部分开发

文件上传接口

先看接口文档

阅读接口文档,唯一问题就是项目暂时还没有传到服务器上,所以对文件的存储与读取暂时在项目本地进行 

Controller层

@RestController
public class FileUploadController {@PostMapping("/upload")public Result<String> upload(MultipartFile file) throws IOException {//获取文件名String originalFilename = file.getOriginalFilename();//保证文件的名字是唯一的,防止文件覆盖String filename = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));//把文件内容存储到本地磁盘file.transferTo(new File("H:\\Desktop\\chessmanfile\\"+filename));return Result.success("rul地址");}
}

 

云存储头像

初见阿里OSS

下面使用阿里云OSS服务来存储头像

有关OSS存储的获取,bucket创建等部分掠过

由于我们写的项目是一个maven项目,根据官网的SDK引导,我们需要导入如下坐标

<!--        阿里云OSS依赖坐标--><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.15.1</version></dependency>

官网提示我们,使用1.9版本以上的JDK还需导入JAXB相关坐标

<!--        JAXB相关依赖--><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version></dependency><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version></dependency><!-- no more than 2.3.3--><dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.3</version></dependency>

 坐标导入完成后,我们使用官方给的一个示例文件进行测试

如上图,是从阿里云OSS官方示例文件修改而来的测试程序,其中修改了的部分都用下划线标出,第一个要修改的是endpoint,在控制台中可以找到

接下来就是accesskey的id和secret,官方文档给出的方法是将这两个信息配置进系统环境变量中去,这里不采用,直接定义两个变量来 ,再创建OSSClient实例中也作出了相应的修改

接下来就是本身的实例给服务器传入的是content,由于我们要存储的就是头像,所以直接改成传入一个图片来测试

运行了测试程序后在后台可以查看到我们的测试图片已经上传成功,下一步就是将图片的上传集成到我们的程序中去

云存储头像文件集成入程序 

我们书写一个工具类来使用,实际上就是根据上述修改方法对工具类进行仿写

public class AliOSSUtil {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。private static final String ENDPOINT = "https://oss-cn-beijing.aliyuncs.com";private static final String ACCESS_KEY_ID = "马赛克";private static final String ACCESS_KEY_SECRET = "马赛克";// 填写Bucket名称,例如examplebucket。private static final String BUCKET_NAME = "chessman";public static String main(String objectName , InputStream in) throws Exception {//初始化URLString URL = "";// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(ENDPOINT,ACCESS_KEY_ID,ACCESS_KEY_SECRET );try {// 填写字符串。String content = "Hello OSS,你好世界";// 创建PutObjectRequest对象。PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, objectName, in);// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。// ObjectMetadata metadata = new ObjectMetadata();// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());// metadata.setObjectAcl(CannedAccessControlList.Private);// putObjectRequest.setMetadata(metadata);// 上传字符串。PutObjectResult result = ossClient.putObject(putObjectRequest);URL = "https://"+BUCKET_NAME+"."+ENDPOINT_INDEX+"/"+ObjectName;} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}return URL;}
}

在main方法的参数中我们传入了文件存储路径和一个字符输入流,对应的替换我们之前在测试时写死的两个地方

还有,我们之前在书写有关头像的接口时都是要获取其URL信息,所以我们要让该方法返回头像对应的URL信息

有关URL组成

https://chessman.oss-cn-beijing.aliyuncs.com/111.jpg

这是刚刚上传的111.jpg的URL,可以看出,URL的组成为

https://BucketName.Endpoint/ObjectName

这一格式

所以我们可以通过字符串的拼接来实现URL的返回

下面就是对刚刚写的文件上传接口进行修改

文件上传接口修改

@RestController
public class FileUploadController {@PostMapping("/upload")public Result<String> upload(MultipartFile file) throws Exception {//获取文件名String originalFilename = file.getOriginalFilename();//保证文件的名字是唯一的,防止文件覆盖String filename = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));//把文件内容存储到本地磁盘//file.transferTo(new File("H:\\Desktop\\chessmanfile\\"+filename));String url = AliOSSUtil.uploadFile(filename,file.getInputStream());return Result.success(url);}
}

至此,后端的所有接口全部构建完毕!!!!!!!!!

完结撒花!

redis登录接口优化

当然,接口书写完毕不代表程序的维护和健壮性增强也到此为止,下面就用redis对登录接口进行优化

问题提出:我们对于用户的身份验证是依靠令牌的识别,但是我们令牌只有一个24小时过期机制,当用户更新了他的密码之后,会生成一个新的令牌,但此时旧令牌没有被我们回收,仍然能使用,我们需要有令牌主动失效机制

令牌主动失效机制

登陆成功后,给浏览器相应令牌的同时,给浏览器相应令牌的同时,把该令牌存储到redis中

LoginInterceptor拦截器中,需要验证浏览器携带的令牌,并同时需要获取到redis中存储的与之相同的令牌

当用户修改密码成功后,删除redis中存储的旧令牌

SpirngBoot集成redis

导入spring-boot-starter-data-redis起步依赖

<!--        redis坐标--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

在yml配置文件中,配置redis连接信息

  data:redis:host: localhostport: 6379

调用API(StringRedisTemplate)完成字符串的存取操作

以两个测试方法为例

    @Testpublic void testSet(){//redis中存储键值对 StringRedisTemplateValueOperations<String, String> Operations = stringRedisTemplate.opsForValue();Operations.set("username","cacb");//设置键值对及其过期时间Operations.set("timetest","haha" ,15, TimeUnit.SECONDS);}@Testpublic void tsetGet(){//从redis中获取键值对ValueOperations<String, String> Operations = stringRedisTemplate.opsForValue();System.out.println(Operations.get("username"));}

令牌主动失效代码实现

第一步、修改登录接口代码

            //将token存入到redis中ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set(token,token,12, TimeUnit.HOURS);return Result.success(token);

可以看到,修改就是在成功登录后向页面返回token的同时将token存入到redis中去,这里我设置的键值对过期时间与token过期时间一致 

第二步、修改修改密码接口代码

        userService.updatePwd( newPwd);//删除redis中对应的tokenValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.getOperations().delete(token);return Result.success();

可以看到,在成功玩修改了密码之后,要删除掉redis中的旧token,这里token从请求头中获取 

 public Result updatePwd(@RequestBody @Valid Map<String,String> params,@RequestHeader("Authorization") String token)

所以要对修改密码接口的传参进行如上修改 

第三步、修该登录拦截器代码

            //从redis中获取相同的的tokenValueOperations<String, String> operations = stringRedisTemplate.opsForValue();String redis_token = operations.get(token);if(redis_token == null){//此时token已经失效throw new RuntimeException();}

可以看到,在拦截其中我们将浏览器中获取的token作为键来从redis中获取值,如果查询到的值为空,那么就证明浏览器给出的token已经失效了,所以这时候就要拦截浏览。

至此,redis完善登录相关接口工作就基本完毕了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/473960.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日OJ题_二叉树dfs①_力扣2331. 计算布尔二叉树的值

目录 力扣2331. 计算布尔二叉树的值 解析代码 力扣2331. 计算布尔二叉树的值 2331. 计算布尔二叉树的值 难度 简单 给你一棵 完整二叉树 的根&#xff0c;这棵树有以下特征&#xff1a; 叶子节点 要么值为 0 要么值为 1 &#xff0c;其中 0 表示 False &#xff0c;1 表示…

QKD安全攻击防御方案分析和分级评估研究报告

今天分享的是行业报告&#xff1a;《QKD安全攻击防御方案分析和分级评估研究报告》 &#xff08;内容出品方&#xff1a;量子信息网络产业联盟&#xff09; 报告共计&#xff1a;180页 来源&#xff1a;《见鹿报告》 前言 量子通信是量子信息科学的重要分支&#xff0c;它…

【LeetCode: 429. N 叉树的层序遍历 + BFS】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Vuex核心知识整理

目录 1 搭建vuex环境 2 求和案例 3 getters 配置项 4 mapState 和 mapGetters 5 mapMutations 和 mapActions 6 Vuex 模块化 1 搭建vuex环境 vuex工作原理图&#xff08;摘自官网&#xff09; 什么时候使用Vuex&#xff1a; 1.当多个组件依赖于统一状态 2.来自不同组件…

接口测试用例设计:常见问题和风险

一、接口测试 接口测试&#xff0c;即对API进行测试。 接口测试过程容易出现的典型问题&#xff1a; (1) 传入参数处理不当&#xff0c;导致程序奔溃 (2) 类型溢出&#xff0c;导致数据读出和写入不一致 (3) 因对象权限未进行校验&#xff0c;可以访问其他用户的敏感信息 …

英文论文(sci)解读复现【NO.18】基于DS-YOLOv8的目标检测方法用于遥感图像

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的 SCI论文&a…

Acwing---873. 欧拉函数

欧拉函数 1.题目2.基本思想3.代码实现 1.题目 给定 n 个正整数 ai&#xff0c;请你求出每个数的欧拉函数。 欧拉函数的定义 输入格式 第一行包含整数 n n n。 接下来 n n n 行&#xff0c;每行包含一个正整数 a i ai ai。 输出格式 输出共 n n n 行&#xff0c;每行输出…

乡政府|乡政府管理系统|基于Springboot的乡政府管理系统设计与实现(源码+数据库+文档)

乡政府管理系统目录 目录 基于Springboot的乡政府管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、活动信息管理 3、新闻类型管理 4、新闻动态管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推…

【IIS中绑定SSL证书】

下载SSL证书&#xff1a; 打开服务器IIS&#xff1a; 点击导入 在IIS中新增网站&#xff1a;

BeginCTF2024 RE WP 剩下的复现

12. goforfun&#xff08;寄&#xff09; 前面是一些无关紧要的初始化 下面看到疑似rc4 虽然函数支离破碎&#xff0c;但可以看到rc4的结构&#xff0c;异或的部分做了魔改 后面似乎是base64换表&#xff0c;但脚本跑不出来&#xff0c;这里的算法没搞懂&#xff0c;只能贴一下…

MATLAB通信系统仿真设计——直接序列扩频通信系统仿真

一、背景 扩频通信就是通过增加带宽来换取较低的信噪比&#xff0c;这就是扩频通信的基本思想和理论依据。当信噪比无法提高时&#xff0c;可以加大带宽&#xff0c;达到提高信道容量的目的。扩频是一种宽带技术&#xff0c;由于扩频占用更宽的频带&#xff0c;看起来是浪费有…

C++项目 -- 高并发内存池(四)Page Cache

C项目 – 高并发内存池&#xff08;四&#xff09;Page Cache 文章目录 C项目 -- 高并发内存池&#xff08;四&#xff09;Page Cache一、PageCache设计1.PageCache的整体结构2.Common.h的更新3.CentralCache中的GetOneSpan函数的实现4.PageCache类设计5.代码实现 二、申请内存…