bug:Oss endpoint can‘t be empty
问题原因【两种】:
1.springboot和springcloud没有改为对应版本
解决:SpringBoot版本改为2.1.8.RELEASE;SpringCloud版本改为Greenwich.SR3
2.yml缩进格式问题
解决:现在yml文件上写一遍再拷贝到nacos中
阿里云对象存储-服务端签名后直传【本次项目选择这种方式】
应用服务器核心代码如下:
@RestController
public class OssController {
@Autowired
OSS ossClient;
@Value("${spring.cloud.alicloud.oss.endpoint}")
private String endpoint;
@Value("${spring.cloud.alicloud.oss.bucket}")
private String bucket;
@Value("${spring.cloud.alicloud.access-key}")
private String accessId;
// @DateTimeFormat(pattern = "yyyy-MM-dd")
// private String format;
@RequestMapping("/oss/policy")
public R policy() {
//https://gulimall-hello.oss-cn-beijing.aliyuncs.com/hahaha.jpg
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
// String callbackUrl = "http://88.88.88.88:8888";
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = format + "/"; // 用户上传文件时指定的前缀。
Map<String, String> respMap = null;
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
respMap = new LinkedHashMap<String, String>();
respMap.put("accessid", accessId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
// respMap.put("expire", formatISO8601Date(expiration));
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
}
return R.ok().put("data",respMap);
}
}
请求应用服务器后返回的签名信息如下图:
{
"msg": "success",
"code": 0,
"data": {
"accessid": "LTAI5tMLLaHcLLv4xt2jtRMd",
"policy": //策略,加密后的结果
"eyJleHBpcmF0aW9uIjoiMjAyNC0wNS0yOFQwMTo0MDoxNC4wMTdaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIyMDI0LTA1LTI4LyJdXX0=",
"signature": "rfCvvWPz/eJXXasHpci0eS6Ijsk=", //签名
"dir": "2024-05-28/",//要给哪个文件上传
"host": "https://liyumall-yyds.oss-cn-beijing.aliyuncs.com",//上传后的主机地址
"expire": "1716860414"//过期时间
}
}
最终用户会把从服务器返回的签名信息跟要上传的文件一起打包到OSS当中。
最后,再在网关服务中,断言重写路径
- id: third_party_route
uri: lb://liyumall-third-party
predicates:
- Path=/api/thirdparty/**
filters:
- RewritePath=/api/thirdparty/(?<segment>.*),/$\{segment}
阿里云oss-前后端联调
出现bug【跨域问题】
Access to XMLHttpRequest at ‘http://localhost:8001 springBoot + vue请求显示跨域问题
解决办法【阿里云oss设置跨域规则】并且前端代码里请求的域名需要填写正确
点击上传成功
上传业务的跨域流程:
向服务器发起预检请求-向服务器发送真实请求-向发起oss预检请求-向服务器发送oss真实请求
表单校验【前端】:
firstLetter: [
{validator:(rule,value,callback)=>{
//前端校验检索首字母
if(value==''){
callback(new Error('首字母必须填写'));
}else if(!/^[a-zA-Z]$/.test(value)){
callback(new Error('首字母必须a-z或者A-Z之间'));
}else{
callback();
}
},trigger:'blur'}
],
sort: [
{ validator:(rule,value,callback)=>{
//前端校验检索排序字段
if(value==''){
callback(new Error('排序字段必须填写'));
}else if(!Number.isInteger(value)||value<0){
callback(new Error('排序必须是一个大于等于0的整数'));
}else{
callback();
}
}, trigger: 'blur' }
]
JSR303 数据校验
使用步骤
1.标注校验
2.开启校验功能
3.提取校验错误信息
4.分组校验
5.自定义校验
* 后端校验JSR303
* 1.给Bean属性添加校验注解,还可定义自己的message提示
* 2.在controller中添加开启校验主键@Valid/@Validated
* 3.给校验的bean后紧跟一个BindingResult result,就可以获取到校验的结果【可以使用全局异常处理替代】
* 4.分组校验【同一属性在不同业务中,有不同的校验要求】
* 1.@NotBlank()
* 2.校验@Validated({AddGroup.class})
* 5.自定义校验
* 1)编写一个自定义的校验注解 public @interface ListValue[可以指定多个自定义的校验器]
* 2)编写一个自定义的校验器 public class ListValueConstraintValidator
* 3)关联自定义的校验器和自定义的校验注解 @Constraint(validatedBy = {ListValueConstraintValidator.class})
自定义校验核心代码:
/**
* @author 鲤鱼军
* @version 1.0
* @description 自定义的校验注解
* @date 2024-05-28 - 下午 8:08
*/
@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class})//注解所使用的校验器
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})//注解可以标识的地方
@Retention(RUNTIME)//注解可在运行时获取
public @interface ListValue {
/**
* 校验出错以后错误信息去哪取
* @return
*/
String message() default "{com.lnut.common.valid.ListValue.message}";
/**
* 支持分组校验规则
* @return
*/
Class<?>[] groups() default {};
/**
* 自定义负载信息
* @return
*/
Class<? extends Payload>[] payload() default {};
/**
* 默认值
* @return
*/
int[] vals() default {};
}
/**
* @author 鲤鱼军
* @version 1.0
* @description 自定义的校验器
* @date 2024-05-28 - 下午 8:33
*/
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {//<校验注解,什么类型的注解>
private Set<Integer> set = new HashSet<>();
/**
* @param constraintAnnotation 注解详细信息
*/
@Override
public void initialize(ListValue constraintAnnotation) {
int[] vals = constraintAnnotation.vals();
for (int val : vals) {
set.add(val);
}
}
/**
* 判断是否校验成功
* @param value 需要校验的值
* @param context 上下文环境信息
* @return 判断value是否在set当中
*/
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
return set.contains(value);
}
}
全局异常处理
使用步骤
@RestControllerAdvice【类启用】+@ExceptionHandler【方法启用】
@Slf4j
@RestControllerAdvice(basePackages = "com.lnut.liyumall.product.controller")//扫描路径
public class liyumallExceptionControllerAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleVaildException(MethodArgumentNotValidException e){
log.error("数据校验出现问题{},异常类型:{}",e.getMessage(),e.getClass());
BindingResult bindingResult = e.getBindingResult();
Map<String, String> errorMap = new HashMap<>();
bindingResult.getFieldErrors().forEach(fieldError -> {
errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());
});
return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",errorMap);
}
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable throwable){
log.error("程序抛出异常{}",throwable.getMessage());
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(), BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
}
}