-
密码加密:
学习了使用 MD5 加密密码,避免明文存储,但了解到 MD5 不够安全,后续可以尝试更安全的算法,比如 bcrypt。 -
配置文件:
掌握了在 Spring Boot 的 yml 文件中使用占位符${}
来配置不同环境的变量。 -
日志记录:
学会了使用 SLF4J 的占位符{}
来高效记录日志,避免字符串拼接。 -
异常处理:
使用@ExceptionHandler
处理特定异常(如重复条目异常),提取关键信息返回给前端,但意识到直接暴露异常信息可能不安全,需要更全面的异常处理策略。 -
文件上传:
学习了通过MultipartFile
处理文件上传,使用 UUID 生成唯一文件名,改进了文件扩展名的处理方式,但需要注意文件名为空或格式异常的情况。 -
MyBatis 动态 SQL:
掌握了useGeneratedKeys
和keyProperty
获取自增主键,以及使用foreach
实现批量插入,但要注意性能和 SQL 长度问题。 -
代码简化:
使用 Lombok 的@Data
或@Builder
注解简化了 setter 和 getter,减少了样板代码。 -
占位符使用:
理解了 SLF4J 的{}
和 MyBatis 的${}
、#{}
的区别,避免 SQL 注入问题。
对密码进行md5加密
password = DigestUtils.md5DigestAsHex(password.getBytes());
使用了DigestUtils工具类
学会了如何分文件写yml文件,占位符¥{}
slf4j的占位符{}
mybatis的占位符号#{}
全局错误处理
@ExceptionHandler //标记方法为异常处理器,指定该方法可以处理特定类型的异常。 public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){ String message = ex.getMessage(); if(message.contains("Duplicate entry")){ String[] split = message.split(" "); String username = split[2]; String msg = username + MessageConstant.ALREADY_EXISTS; return Result.error(msg); }else{ return Result.error("未知错误"); } } }
@RestController 和 @RequestMapping 注解的作用
在 Spring 框架中,@RestController 和 @RequestMapping 是两个常用的注解,用于定义和配置 RESTful Web 服务的控制器。下面是这两个注解的详细解释及其在你的代码中的作用。
1. @RestController
定义 @RestController 是 Spring 提供的一个组合注解,用于简化控制器类的定义。
作用
@Controller:标记一个类为 Spring MVC 控制器。******
@ResponseBody:默认将方法的返回值直接写入 HTTP 响应体中,而不是解析为视图。
2. @RequestMapping
定义 @RequestMapping 是 Spring 提供的一个注解,用于映射 HTTP 请求到特定的处理方法或控制器类。
作用
类级别:定义控制器类处理的请求的基本路径。*************
方法级别:定义具体方法处理的请求路径、请求方法(如 GET、POST 等)、请求参数等。
如何格式化日期
在系统当中如何上传图片
public Result<String> upload(MultipartFile file){ log.info("文件上传:{}",file); try { String originalFilename = file.getOriginalFilename(); String extension = originalFilename.substring(originalFilename.lastIndexOf(".")); String objectName = UUID.randomUUID().toString() + extension; String filePath = aliOssUtil.upload(file.getBytes(), objectName); return Result.success(filePath); } catch (IOException e) { log.error("文件上传失败:{}",e); } return null; }
MultipartFile (是 Spring 框架提供的一个接口,位于 org.springframework.web.multipart.MultipartFile 包中。
它用于处理 HTTP 请求中的文件上传功能)常用方法
String getOriginalFilename():获取文件的原始名称(包括扩展名)。 String getName():获取表单字段的名称。 String getContentType():获取文件的内容类型(如 image/jpeg)。 long getSize():获取文件的大小(以字节为单位)。 byte[] getBytes():将文件内容读取为字节数组。 InputStream getInputStream():获取文件的输入流。 void transferTo(File dest):将文件保存到指定的目标路径
在上述代码当中就使用了getOriginalFilename(),方法来获取原始名称然后通过substring(originalFilename.lastIndexOf("."))获取到了文件的extension(文件拓展名)
定义 substring(int beginIndex) 是 Java 中 String 类的一个方法,用于从指定的起始索引位置提取子字符串。
返回值 返回从 beginIndex 开始到字符串末尾的子字符串定义 lastIndexOf(String str) 是 Java 中 String 类的一个方法,用于查找指定字符或子字符串在字符串中最后一次出现的位置。
返回值 返回指定字符或子字符串最后一次出现的索引位置(从 0 开始)。如果未找到,则返回 -1。<思考>
可以使用String方法当中的split()方法来获得文件的后缀名字但是极其不方便
public Result<String> upload(MultipartFile file) { log.info("文件上传:{}", file); try { String originalFilename = file.getOriginalFilename(); String[] parts = originalFilename.split("\\."); String extension = parts.length > 1 ? "." + parts[parts.length - 1] : ""; String objectName = UUID.randomUUID().toString() + extension; String filePath = aliOssUtil.upload(file.getBytes(), objectName); return Result.success(filePath); } catch (IOException e) { log.error("文件上传失败:{}", e); } return null; }
aliOssUtil是一个自定义工具类里面封装的使用阿里OSS的基本配置
UUID (用于生成唯一标识符)
UUID.randomUUID() 返回的是一个 java.util.UUID 类型的对象
<思考>
try-catch 中是否需要 throw
写了 log.error 并不意味着不需要 throw。
是否需要 throw 取决于业务需求:
如果希望将异常继续向上抛出,让调用方处理,则需要使用 throw。
如果异常已经被处理(例如返回了友好的错误响应),则可以不抛出异常总结
log.error 仅用于记录错误信息,不会影响异常的传播。
是否需要 throw 取决于业务逻辑:如果需要调用方感知异常,则应抛出;否则可以通过返回值明确告知结果。
1. 定义
类:BeanUtils 是 Spring 框架中的一个工具类,位于 org.springframework.beans 包中。
方法:copyProperties(Object source, Object target) 是 BeanUtils 类中的一个静态方法。
2. 作用
复制属性:将源对象(source)中的属性值复制到目标对象(target)中。
自动匹配:根据属性名称和类型自动匹配并复制属性。
<大量简化了 setter和getter的调用,和Builder有异曲同工之妙>
下面是关于useGeneratedKeys和keyProperty的代码以及相关介绍
useGeneratedKeys 属性: 指定是否使用数据库自动生成的主键。
keyProperty 属性: 指定将生成的主键值赋给 Java 对象的哪个属性。如下代码就是赋值给类中的id属性
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into dish(name,category_id,price,image,description,create_time,update_time,create_user,update_user,status)
values
(#{name},#{categoryId},#{price},#{image},#{description},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})
</insert>
MYBATIS中的动态SQL<foreach>
直接传入list集合而不用大量重复传入集合当中的元素
void insertBatch(List<DishFlavor> flavors);
xml映射文件的写法
<insert id="insertBatch">
insert into dish_flavor (dish_id, name, value) values
<foreach collection="flavors" item="df" separator=",">
(#{df.dishId},#{df.name},#{df.value})
</foreach>
</insert>
//separator=",
"separator: 指定每个元素之间的分隔符,这里使用逗号 , 来分隔不同的 VALUES 子句。
//SQL
INSERT INTO dish_flavor (dish_id, name, value) VALUES
(1, 'Flavor1', 'Value1'),
(2, 'Flavor2', 'Value2'),
(3, 'Flavor3', 'Value3');