【SpringBoot】黑马大事件笔记-day3

目录

文章管理部分

自定义注解校验

注解的概念

元注解

规定约束的注解

分页查询

OSS文件上传

获取AccessKey


上期回顾:

【SpringBoot】 黑马大事件笔记-day1

【SpringBoot】 黑马大事件笔记-day2

文章管理部分


自定义注解校验

先来看一下接口文档了解需求:

发布文章

基本信息

请求路径:/article
请求方式:POST
接口描述:该接口用于新增文章(发布文章)

请求参数

请求参数格式:application/json
请求参数说明:

请求数据样例:

{
"title": "陕西旅游攻略",
"content": "兵马俑,华清池,法门寺,华山...爱去哪去哪...",
"coverImg": "https://big-event-gwd.oss-cn-beijing.aliyuncs.com/9bf1cf5b-1420-4c1b91ad-e0f4631cbed4.png",
"state": "草稿",
"categoryId": 2
}

         首先他是一个简单的增删查改的接口,但是我们需要进行参数的校验;其他的校验方法都提供了对应的注解,而 state 的校验没有提供注解。这里就需要我们自己去写满足规定的注解。

Controller

@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;@PostMappingpublic Result add(@RequestBody @Validated Article article) {articleService.add(article);return Result.success();}
}

Service

    @Overridepublic void add(Article article) {// 更新创建时间与修改时间article.setCreateTime(LocalDateTime.now());article.setUpdateTime(LocalDateTime.now());// 获取用户信息 idMap<String,Object> map = ThreadLocalUtil.get();Integer id = (Integer) map.get("id");article.setCreateUser(id);articleMapper.add(article);}

Mapper

    <insert id="add">INSERT INTO article(title, content, cover_img,state,category_id, create_user, create_time, update_time)VALUES (#{title},#{content},#{coverImg},#{state},#{categoryId},#{createUser},#{createTime},#{updateTime})</insert>

Pojo

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Article {private Integer id;//主键ID@NotEmpty@Pattern(regexp = "^\\S{1,10}$")private String title;//文章标题@NotEmptyprivate String content;//文章内容@NotEmpty@URLprivate String coverImg;//封面图像@Stateprivate String state;//发布状态 已发布|草稿@NotNullprivate Integer categoryId;//文章分类idprivate Integer createUser;//创建人IDprivate LocalDateTime createTime;//创建时间private LocalDateTime updateTime;//更新时间
}

        其他注解根据接口文档提供的需求在字段加上对应的注解即可,@State 则需要我们自己来修改:

注解定义

interface

@Documented // 元注解
@Target(FIELD) // 元注解 ,FIELD 表示用在属性上
@Retention(RUNTIME) //元注解 ,表示运行时阶段生效
@Constraint(validatedBy = {StateValidated.class}) //填写校验规则类public @interface State {// 提供校验失败的提示信息String message() default "State的值只能是已发布或者草稿";// 指定分组Class<?>[] groups() default {};// 负载// 获取到State注解的附加信息Class<? extends Payload>[] payload() default {};
}

注解的概念

元注解

        元注解是专门用来注解其他注解的注解,简单来说就是专门为自定义注解提供的注解。Java提供了五种元注解:

注解作用
@Documented注解是否将包含在JavaDoc中
@Retention什么时候使用该注解,用于描述注解的生命周期
@Target注解用于什么地方
@Inherited是否允许子类继承该注解
@Repeatable是否可重复注解

@Target 的注解运用范围:

  • 类或接口:ElementType.TYPE
  • 字段:ElementType.FIELD
  • 方法:ElementType.METHOD
  • 构造方法:ElementType.CONSTRUCTOR
  • 方法参数:ElementType.PARAMETER

@Retention 的注解定义的生命周期:

  • 仅编译期:RetentionPolicy.SOURCE
  • 仅class文件:RetentionPolicy.CLASS
  • 运行期:RetentionPolicy.RUNTIME

 以上的 ElementType、RetentionPolicy 是枚举。

规定约束的注解

        @Constraint 注解是 Validation 框架中的一个注解,用于自定义约束注解,即自定义校验规则。

        通过在自定义注解上添加 @Constraint 注解,可以将该注解标记为一个自定义约束注解。同时,需要指定一个实现了 Validator 接口的验证器类,用于验证该注解所标记的字段或参数是否符合自定义的校验规则。

Validator

// 泛型参数说明<给哪个注解提供校验规则,校验的数据类型>
public class StateValidated implements ConstraintValidator<State,String> {/** value 表示校验数据* 方法体需要提供校验规则* 校验成功返回true,否则返回false*/@Overridepublic boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {if(value==null) return true;return value.equals("已发布") || value.equals("草稿");}
}

        这样我们的自定义注解 state 就已经完成了,简单总结一下:

创建一个 interface 注解 state
给 state 注解 添加元注解,声明运行范围与生命周期
添加  @Constraint 约束注解,并实现 Validator  约束类

        如果是非草稿或者已发布状态,那么程序就会抛出异常,这就说明我们的自定义注解的实现没有问题。

分页查询

先来看一下接口文档了解需求:

基本信息

请求路径:/article
请求方式:GET
接口描述:该接口用于根据条件查询文章

请求参数

请求参数格式:queryString

请求参数说明:

请求数据样例:

 pageNum=1&pageSize=3&categoryId=2&state=草稿

        分页查询是在 web 开发中常用的一种技术,当某个页面查询返回的数据量较大时,为了提高性能和用户体验不能将所有数据一次性返回给过前端,这时候就需要用到分页查询了。

        pagehelper 是一款开源的 Mybatis 第三方物理分页插件,依赖如下

    <pagehelper.version>1.4.6</pagehelper.version><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>${pagehelper.version}</version></dependency>

        我们以前都查询都是将所有结果直接给用户,而分页查询则是将全部查询信息按每页多少展现量进行反馈的;于是我们就需要一个类来记录分页的具体信息:

PageBean 类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean <T>{private Long total;   //总条数private List<T> items;//当前页数据集合
}

Controller

    @GetMappingpublic Result<PageBean<Article>> list(Integer pageNum,Integer pageSize,@RequestParam(required = false) Integer categoryId,@RequestParam(required = false) String state) {PageBean<Article> pb =  articleService.list(pageNum,pageSize,categoryId,state);return Result.success(pb);}

因为展示的是文章详细,但是要按照分页的形式展示:

所以我们需要传的参数类型为 Result<PageBean<Article>> ,

@RequestParam(required = false) 表示被标注的参数不是必传项。

 Service

@Overridepublic PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId, String state) {// 创建 PageBean 对象PageBean<Article> pageBean = new PageBean<>();// 开启分页查询 PageHelperPageHelper.startPage(pageNum, pageSize);// 获取用户信息Map<String,Object> map = ThreadLocalUtil.get();Integer userId = (Integer) map.get("id");// 调用mapperList<Article> as = articleMapper.list(userId,categoryId,state);// Page中提供了方法,可以获取PageHelper分页查询后// 得到的总记录条数和当前页数据Page<Article> p = (Page<Article>) as;// 把数据填充到 PageBean 对象并返回pageBean.setTotal(p.getTotal());pageBean.setItems(p.getResult());return pageBean;}
  • total:总记录数,表示满足查询条件的总记录数。
  • ltems:当前查询页数的集合类。

        使用的时候,只需在查询 list 前,调用 startPage 设置分页信息,即可使用分页功能。

Mapper

   <select id="list" resultType="com.thz.pojo.Article">SELECT * FROM article<where>create_user=#{userId}<if test="categoryId!=null">category_id=#{categoryId}</if><if test="state!=null">and state=#{state}</if></where></select>

 

        以上是按一页两条文章作为规范的,当跳转到第二页时与数据库内容保持一致,则说明该文章分页的代码没有错误。

OSS文件上传


要是实现将文件上传到阿里云OSS,首先就要开通OSS服务:

        将鼠标移至产品,找到并单击对象存储OSS,打开OSS产品详情页面新用户可以免费试用三个月。

点这个创建Bucket:

        创建存储空间,给新建的Bucket命名,服务器可以默认选华北的,读写权限为公共读,点击完成创建就可以创建了

获取AccessKey

要获取AccessKey,点击头像,然后选择AccessKey管理。

 

点击创建即可 

创建完后会获得这两个键值对,需要保存备用 

 

阿里文档链接:JavaOSS文档

点击链接就可以看到官方对 OSS 提供的一些资料:

导入 OSS 依赖: 

    <aliyun.version>3.17.4</aliyun.version><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>${aliyun.version}</version></dependency>

         阿里提供的文件上传源码可以在刚才的文档中找到,我们可以拿过来修改一下,作为我们项目的上传接口:

package com.thz.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;import java.io.FileInputStream;
import java.io.InputStream;public class AliOssUtil {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。private static final String ENDPOINT = "https://oss-cn-beijing.aliyuncs.com";// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。//EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();private static final String ACCESS_KEY_ID="换成你的AccessKey lD";private static final String ACCESS_KEY_SECRET="换成你的AccessKey Secret";// 填写Bucket名称,例如examplebucket。private static final String BUCKET_NAME = "换成你的Bucket名称";public static String uploadFile(String objectName, InputStream in) throws Exception {// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(ENDPOINT,ACCESS_KEY_ID, ACCESS_KEY_SECRET);String url = "";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名称.区域节点/objectNameurl = "https://"+BUCKET_NAME+"."+ENDPOINT.substring(ENDPOINT.lastIndexOf("/")+1)+"/"+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;}
}

注意:以上的 BUCKET_NAME、ACCESS_KEY_SECRET、ACCESS_KEY_SECRET 都需要设置成你自己OSS的配置。

最后完成 Controller 的编写即可:

    @PostMapping("/upload")public Result<String> upload(MultipartFile file) throws Exception {// 把文件的内容存储到本地磁盘上String originalFilename = file.getOriginalFilename();// 保证文件的名字是唯一的,从而防止文件覆盖String filename = UUID.randomUUID().toString()+originalFilename.substring(originalFilename.lastIndexOf("."));String url = AliOssUtil.uploadFile(filename,file.getInputStream());return Result.success(url);}

        在文件列表这里就可以查找自己的图片了,不过需要注意的是在OSS中我们是 url 的格式存储的,所以上传的文件名与 OSS 存储的文件名不一样也是应该的。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

webpack loader全解析,从入门到精通(10)

webpack 的核心功能是分析出各种模块的依赖关系&#xff0c;然后形成资源列表&#xff0c;最终打包生成到指定的文件中。更多复杂的功能需要借助 webpack loaders 和 plugins 来完成。 1. 什么是 Loader Loader 本质上是一个函数&#xff0c;它的作用是将某个源码字符串转换成…

基于Vue的电子商城后台管理系统

摘 要 随着数字化时代的到来&#xff0c;人们对软件市场的需求不断加大&#xff0c;可视化管理系统代替人工管理的趋势持续上升&#xff0c;尤其电子商城类项目&#xff0c;针对后台管理的多样化需求尤为迫切。所以&#xff0c;为满足市场与日俱增的需求&#xff0c;开发电子…

Mysql数据类型面试题15连问

整数类型的 UNSIGNED 属性有什么用&#xff1f; MySQL 中的整数类型可以使用可选的 UNSIGNED 属性来表示不允许负值的无符号整数。使用 UNSIGNED 属性可以将正整数的上限提高一倍&#xff0c;因为它不需要存储负数值。 例如&#xff0c; TINYINT UNSIGNED 类型的取值范围是 0 ~…

优选算法合集————双指针(专题一)

题目一&#xff1a;移动零 题目描述&#xff1a; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输…

docker基础:搭建centos7(详见B站泷羽sec)

docker的简单学习&#xff1a; sudo apt-get update //这个命令让系统检查有没有新软件 sudo apt-get install docker.io //安装 Docker sudo docker version //查看是否安装成功&#xff0c;显示docker的版本信息 启用Docker 启…

ThreadLocal的熟悉与使用

目录 1.ThreadLocal介绍2.ThreadLocal源码解析2.1 常用方法2.2 结构设计2.3 类图2.4 源码分析2.4.1 set方法分析2.4.2 get方法分析2.4.3 remove方法分析 3.ThreadLocal内存泄漏分析3.1 相关概念3.1.1 内存溢出3.1.2 内存泄漏3.1.3 强引用3.1.4 弱引用 3.2 内存泄漏是否和key使用…

振弦式表面式应变计数据要怎么采集

振弦式表面应变计是一种专门用于测量结构表面应变的传感器&#xff0c;其数据采集过程通常涉及以下步骤&#xff1a; 一、设备准备与连接 设备检查&#xff1a;确保振弦式表面应变计及其相关设备(如MCU自动测量单元、数据传输线等)处于良好工作状态&#xff0c;无损坏或故障。 …

pitest.org使用简介

pitest.org PIT生成的报告是一种易于阅读的格式&#xff0c;结合线路覆盖和变异覆盖信息。 pitest.org官网提供了四种使用方式&#xff1a; Maven快速入门 命令行快速启动 蚂蚁快速启动 Gradle快速启动&#xff08;外部链接&#xff09; 我所使用的是Maven的方式进行构建项…

我们所有人际关系的痛苦根源,都源于缺乏边界感

在现实生活里&#xff0c;我们常会遇到这样的情况&#xff1a;对方总是越界&#xff0c;而你又不知如何拒绝&#xff0c;这种不快就会积压在心底。于是&#xff0c;我们可能会想要从其他方面突破对方的界限作为报复&#xff0c;这时关系就会变得紧张。 没有界限的关系容易让人…

JS之正则表达式

一、什么是正则表达式 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </…

泷羽sec学习打卡-Windows基础virus

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 关于windows virus的那些事儿 一、Windows-Virus资源耗尽之无限弹窗cmd-virus测试锁机virus测试无限重启…

【风力发电】基于虚拟惯性控制+一次调频+下垂控制的DFIG双馈风力发电机三机九节点仿真模型

摘要 随着风力发电在电力系统中的渗透率逐渐提高&#xff0c;如何增强风电系统的动态响应能力成为关键问题。本文针对双馈感应发电机(DFIG)&#xff0c;提出一种结合虚拟惯性控制、一次调频和下垂控制的综合控制策略&#xff0c;以改善其在电网扰动条件下的稳定性和频率响应性…

智慧社区可视化解决方案:科技引领社区服务与管理新篇章

随着社会的发展&#xff0c;智慧社区作为新型城镇化发展目标和社区服务体系建设的重要举措&#xff0c;正逐步改变着我们的生活方式。智慧社区通过综合运用现代科学技术&#xff0c;整合区域资源&#xff0c;提升社区治理和服务水平&#xff0c;为居民提供更为便捷、高效、安全…

消息队列高级

目录 消息可靠性 生产者消息确认 第一步&#xff1a;修改application.yml配置文件信息 第二步&#xff1a;定义发送者确认confirm回调方法 第三步&#xff1a;创建消息发送者回执return回调方法&#xff08;确保消息从交换机到消息队列&#xff09; 总结&#xff1a; 消息持…

乐鑫USB方案助力设备互联和数据传输,启明云端乐鑫一级代理商

USB USB 是一种通用的总线标准&#xff0c;用于连接主机和外部设备。 乐鑫 USB 方案为用户提供了方便快捷的设备互联和数据传输方式。乐鑫 SoC 通过将 USB 作为标配外设之一&#xff0c;提供 USB 2.0 OTG 或 USB-Serial-JTAG 接口&#xff0c;支持主机 (Host) 和设备 (Device…

linux详解,基本网络枚举

基本网络枚举 一、基本网络工具 ifconfig ifconfig是一个用于配置和显示网络接口信息的命令行工具。它可以显示网络接口的P地址、子网掩码、MC地址等信息&#xff0c;还可以用于启动、停止或配置网络接口。 ip ip也是用于查看和管理网络接口的命令。 它提供了比ifconfig更…

✬宁波TISAX:✬信息安全管理、✬风险评估与✬数据保护✬的集成宝典✬

&#x1f600;宁波TISAX&#xff1a;&#x1f575;️‍♀️信息安全管理、&#x1f469;‍&#x1f4bb;风险评估与&#x1f937;&#x1f3fb;‍♂️数据保护的集成宝典&#x1f468;&#x1f3fb;‍&#x1f393; &#x1f432;在当今数字化时代&#xff0c;&#x1f4bb;信息…

【软考】系统架构设计师-计算机系统基础(1):计算机硬件

知识点汇总 1、指令集 精简指令集RISC&#xff1a;寄存器&#xff0c;硬布线&#xff0c;效率高&#xff1b;复杂指令集CISC&#xff1a;微程序控制技术&#xff0c;效率低&#xff1b; 2、奇偶校验码&#xff1a;码距是2&#xff08;出错位校验位&#xff09;&#xff0c;只…

关于分治法左右区间单调遍历应该如何设计

阅读以下文章&#xff0c;首先至少要求通过一道分治法的题目或听过一道该类型的讲解。 对于分治的题目&#xff0c;想必你应该知道&#xff0c;通常我们是对于一个区间拆分两个部分&#xff0c;而最小子问题通常是只包含一个元素的区间数组。为了后续方便处理更大范围的区间&am…

Mybatis的分页插件的使用方式

插件介绍: 使用mabatis中一个名为PageHelper的插件,会把我们后面的一条SQL进行一个动态的拼接,通过拦截器对sql动态的添加limit,从而实现分页的效果 使用方式: 1.先导入相关的依赖 2.在项目中的Mapper层中对应的Mapper.xml中写动态SQL 3.在项目中的Serviceimpl层通过PageHel…