项目随笔-【大事件(文章类)】
自定义参数校验注解
需要写一个自定义注解Xxx+校验规则的类XxxValidation【需要继承ConstraintValidator】
自定义注解
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {StateValidation.class})//使用 `StateValidation` 类来验证该字段的值是否满足特定的约束条件
public @interface State {
String message() default "state参数的值只能是已发布或者草稿";//验证失败的错误提示信息
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
注解校验规则
public class StateValidation implements ConstraintValidator<State,String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
//校验规则
if (value == null){
return false;
}
if (value.equals("已发布") || value.equals("草稿")){
return true;
}
return false;
}
}
<State>
是ConstraintValidator
接口的第一个泛型参数,它指定了验证器将要验证的约束注解的类型。在这个例子中,State
可能是一个自定义的注解,用于标记需要验证的字段。<String>
是ConstraintValidator
接口的第二个泛型参数,它指定了验证器将要验证的属性值的类型。在这个例子中,String
表示StateValidation
类将验证String
类型的属性值。
阿里云Oss存储
工具类
public class AliOssUtil {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
private static final String ENDPOINT = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。【这里没使用】
// EnvironmentVariableCredentialsProvider credentialsProvider =
// CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
private static final String ACCESS_KEY_ID = "LTAI5tJKk5H98ZmQQ9CgeG8y";
private static final String ACCESS_KEY_SECRET = "90xHhXxKig6LNnbb4ubpRBeIdw7RAT";
// 填写Bucket名称,例如examplebucket。
private static final String BUCKET_NAME = "zy-bigevent";
public static String uploadFile(String objectName, InputStream in) throws Exception {
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
// 创建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_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;
}
}
Controller
@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("C:\\Users\\23117\\Desktop\\files\\"+originalFilename));
String url = AliOssUtil.uploadFile(fileName, file.getInputStream());
return Result.success(url);
}
}
Redis主动失效令牌
令牌主动失效机制
● 登录成功后,给浏览器响应令牌的同时,把该令牌存储到redis中。
● LoginInterceptor拦截器中,需要验证浏览器携带的令牌,并同时需要获取到redis中存储的与之相同的令牌。
● 当用户修改密码成功后,删除redis中存储的旧令牌。
登录
@PostMapping("/login")
public Result<String> login(String username,String password) {
//业务逻辑...
String token = JwtUtil.genToken(claims);
//把 token 存储到 redis 中
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
//redis存储令牌 key 和 value 都是 token
operations.set(token,token,1, TimeUnit.HOURS);//TimeUnit.HOURS 是 redis key 的过期时间单位
return Result.success(token);
//业务逻辑...
}
更换密码【此时需要主动删除redis中的token】
@PatchMapping("/updatePwd")
public Result updatePwd(@RequestBody Map<String, String> parms,@RequestHeader("Authorization") String token) {
//业务逻辑...
userService.updatePwd(newPwd);//更新新密码
//删除redis对应的token
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
operations.getOperations().delete(token);
return Result.success();
}
拦截器
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//令牌验证
String token = request.getHeader("Authorization");
try {
//获取redid key
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
String redisToken = operations.get(token);
if (redisToken == null){
//token 已经失效
throw new RuntimeException();
}
Map<String, Object> claims = JwtUtil.parseToken(token);
ThreadLocalUtil.set(claims);
//放行
return true;
} catch (Exception e) {
response.setStatus(401);
//不放行
return false;
}
}
SpringBoot项目部署
需要pom.xml文件加入打包插件
<build>
<plugins>
<!-- 打包插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.3.0</version>
</plugin>
</plugins>
</build>
在maven生命周期中点击 package生成jar
在对应环境部署 java -jar 【 jar的名字 】
SpringBoot配置方式
SpringBoot多环境开发
- SpringBoot多环境开发需要分开发环境、测试环境、生产环境
SpringBoot多环境开发单文件配置
#通用信息,指定生效的环境
spring:
profiles:
active: dev
server:
servlet:
context-path: /aaa
---
#开发环境
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/big_event
username: root
password: zy
servlet:
multipart:
max-file-size: 5MB
data:
redis:
host: localhost
port: 6379
config:
activate:
on-profile: dev
mybatis:
configuration:
map-underscore-to-camel-case: true #开启驼峰命名/下划线命名转换
server:
port: 8081
---
#测试环境
spring:
config:
activate:
on-profile: test
server:
port: 8082
---
#生产环境
spring:
config:
activate:
on-profile: pro
server:
port: 8084
SpringBoot多环境开发多文件配置
application.yml
#通用信息,指定生效的环境
spring:
profiles:
active: test
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/big_event
username: root
password: zy
server:
servlet:
context-path: /aaa
application-dev.yml
#开发环境
config:
activate:
on-profile: dev
server:
port: 8081
application-pro.yml
#生产环境
spring:
config:
activate:
on-profile: pro
server:
port: 8084
application-test.yml
#测试环境
spring:
config:
activate:
on-profile: test
server:
port: 8082
SpringBoot多环境开发多文件配置-分组
application.yml
#通用信息,指定生效的环境
spring:
profiles:
group:
"dev": devService,devDB,devSelf
active: dev
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/big_event
username: root
password: zy
server:
servlet:
context-path: /aaa
application-devService
#开发环境
server:
port: 8085
application-devDb
#数据库相关配置
application-devSelf
#自定义相关配置
项目参考:
B站:BV14z4y1N7pg