0. 参考视频
1. 前期准备+引入依赖
1. 引入需要的依赖
![在这里插入图片描述](https://img-blog.csdnimg.cn/a7ce6209ba044c2d919f4a2bb2cb55ab.png)
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>nexus-aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
2. 乱码解决
<exclude>
<fork>true</fork>
<!-- spring-boot:run 中文乱码解决 -->
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
</exclude>
3. 数据库配置
server:
port: 8091
spring:
datasource:
typr: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
username: 数据库账户
password: 数据库密码
#选择xml的路径
mybatis:
mapper-locations: classpath:mapper/ *.xml
logging:
level:
com:
example:
mapper:
debug
2. 测试
- 注意加上@Mapper和@Service
1. 网页查看user列表
@Autowired
private UserService userService;
@GetMapping("/list")
public List<User> list(){
return userService.list();
}
![](https://img-blog.csdnimg.cn/b0e6ef8100754a458f795e432e7ee1ef.png)
2. apifox测试接口
测试
- 前置URL末尾有斜杠 下面的URL就不用写
![](https://img-blog.csdnimg.cn/b6be7d4dd44b4909a63862ecb6f247c0.png)
![](https://img-blog.csdnimg.cn/644eb75ea3a840d48e2d1b1af532c358.png)
4. 代码逻辑
1. 其它代码
1. 需要在数据库中实现自动填充时间
- MyBatis-Plus设置自动填充时间及@TableField(fill = FieldFill.INSERT)
- 设置时间格式 @JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone=“GMT+8”)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createtime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime updatetime;
package com.example.demo.utils;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Slf4j
@Component
public class FieldMetaObjectHandler implements MetaObjectHandler {
private final String TIME_CREATE = "createtime";
private final String TIME_UPDATE = "updatetime";
@Override
public void insertFill(MetaObject metaObject) {
System.out.println(metaObject);
this.strictInsertFill(metaObject, TIME_CREATE, LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, TIME_UPDATE, LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, TIME_UPDATE, LocalDateTime.class, LocalDateTime.now());
}
}
CURRENT_TIMESTAMP
![在这里插入图片描述](https://img-blog.csdnimg.cn/27da24b6f7af496aa95376c5bc62d6bb.png)
5. springboot集成JWT
1. SpringBoot集成JWT实现token验证
SpringBoot集成JWT实现token验证
2. JWT依赖
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
package com.qingge.springboot.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.qingge.springboot.entity.User;
import com.qingge.springboot.service.IUserService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
@Component
public class TokenUtils {
private static IUserService staticUserService;
@Resource
private IUserService userService;
@PostConstruct
public void setUserService() {
staticUserService = userService;
}
public static String genToken(String userId, String sign) {
return JWT.create().withAudience(userId)
.withExpiresAt(DateUtil.offsetHour(new Date(), 2))
.sign(Algorithm.HMAC256(sign));
}
public static User getCurrentUser() {
try {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
if (StrUtil.isNotBlank(token)) {
String userId = JWT.decode(token).getAudience().get(0);
return staticUserService.getById(Integer.valueOf(userId));
}
} catch (Exception e) {
return null;
}
return null;
}
}
2. 设置token
- 将密码加密后设置为token
- 是在UserDTO中加的token
String token = TokenUtils.genToken(one.getId().toString(), one.getPassword());
userDTO.setToken(token);
3. token拦截器
![在这里插入图片描述](https://img-blog.csdnimg.cn/35d00b89d2f84dd58466416c899c0418.png)
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private IUserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("token");
if(!(handler instanceof HandlerMethod)){
return true;
} else {
HandlerMethod h = (HandlerMethod) handler;
AuthAccess authAccess = h.getMethodAnnotation(AuthAccess.class);
if (authAccess != null) {
return true;
}
}
if (StrUtil.isBlank(token)) {
throw new ServiceException(Constants.CODE_401, "无token,请重新登录");
}
String userId;
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
}
User user = userService.getById(userId);
if (user == null) {
throw new ServiceException(Constants.CODE_401, "用户不存在,请重新登录");
}
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
}
return true;
}
}
4. 注册拦截器
![在这里插入图片描述](https://img-blog.csdnimg.cn/5041d26c2da34e96a79d9408d7211682.png)
6. 文件上传
- 一些图片的上传
![在这里插入图片描述](https://img-blog.csdnimg.cn/4f242bcf207b43b18e0b5621af083cae.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/51a1994422bc4e02b79cfcd1f0d93486.png)
- 注意file后面还有一个反斜杠 不然图片会和file同一级
- FileController - 确保路径全英文,文件名不要有空格- 文件需要有一个后缀 不要用原始的文件名字
- 存储的url在前台显示就可以点击下载
- UUID是唯一的,所以相同的图片他的UUID也不一样
@Value("${files.upload.path}")
private String fileUploadPath;
@PostMapping("/upload")
public String upload(@RequestParam MultipartFile file) throws IOException {
String originalFilename = file.getOriginalFilename();
String type = FileUtil.extName(originalFilename);
long size = file.getSize();
String fileUUID = IdUtil.fastSimpleUUID() + StrUtil.DOT + type;
**File uploadFile = new File(fileUploadPath + fileUUID);**
File parentFile = uploadFile.getParentFile();
if(!parentFile.exists()) {
parentFile.mkdirs();
}
String url;
String md5 = SecureUtil.md5(file.getInputStream());
Files dbFiles = getFileByMd5(md5);
if (dbFiles != null) {
url = dbFiles.getUrl();
} else {
file.transferTo(uploadFile);
url = "http://" + serverIp + ":9090/file/" + fileUUID;
}
Files saveFile = new Files();
saveFile.setName(originalFilename);
saveFile.setType(type);
saveFile.setSize(size/1024);
saveFile.setUrl(url);
saveFile.setMd5(md5);
fileMapper.insert(saveFile);
flushRedis(Constants.FILES_KEY);
return url;
}
@GetMapping("/{fileUUID}")
public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
File uploadFile = new File(fileUploadPath + fileUUID);
ServletOutputStream os = response.getOutputStream();
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
response.setContentType("application/octet-stream");
os.write(FileUtil.readBytes(uploadFile));
os.flush();
os.close();
}
- 查询这个文件是否已经存在
- 如果已经存在就用同一个链接
private Files getFileByMd5(String md5) {
QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("md5", md5);
List<Files> filesList = fileMapper.selectList(queryWrapper);
return filesList.size() == 0 ? null : filesList.get(0);
}
1. 测试