# zymall
**Repository Path**: dopayumiko/zymall
## Basic Information
- **Project Name**: zymall
- **Description**: No description available
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-10-06
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
web
一、JSR303数据校验
1.给Bean添加校验注解:javax.validation.constraints
# javax.validation.constraints
# 涉及到分组校验,AddGroup、UpdateGroup都是空接口
@NotNull(message = "修改必须指定品牌id",groups = {UpdateGroup.class})
@Null(message = "新增不能指定品牌id",groups = {AddGroup.class})
@NotBlank(message = "品牌名不能为空")
@NotEmpty(message = "logo不能为空",groups = {AddGroup.class})
@URL(message = "logo必须是一个合法的url地址",groups = {AddGroup.class,UpdateGroup.class})
@Pattern(regexp = "/^[a-zA-Z]$/",message = "首字母必须是一个字母",groups = {AddGroup.class,UpdateGroup.class})
@Min(value = 0,message = "排序必须大于等于0",groups = {AddGroup.class,UpdateGroup.class})
2. 开启校验功能@Valid,获取默认的校验错误响应
/**
* 保存
* @Valid:开启校验
*/
@RequestMapping("/save")
public R save(/*@Valid*/ @Validated(AddGroup.class) @RequestBody BrandEntity brand/*,BindingResult bindingResult*/){
// if (bindingResult.hasErrors()){
// Map map = new HashMap<>();
// bindingResult.getFieldErrors().forEach((fieldError)->{
// String message = fieldError.getDefaultMessage();
// String field = fieldError.getField();
// map.put(field,message);
// });
// return R.error(400,"提交的数据不合法").put("data",map);
// }else{
// brandService.save(brand);
// }
brandService.save(brand);
return R.ok();
}
3.分组校验(多场景的复杂校验)
1. 校验注解添加 groups属性,值为自定义空接口类
2. @Validated
4. 自定义校验
1. 编写自定义校验注解可以模仿@NotEmpty类似注解类
2. 编写自定义校验器 实现ConstraintValidator<校验注解类,校验数据类型>
3. 关联自定义校验器和校验注解 (校验注解类上添加@Constraint(validateBy={校验器类}))
二、统一异常处理
@RestControllerAdvice(basePackages = "com.zhouyi.zymall.product.controller")
public class ZymallExceptionControllerAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleValidException(MethodArgumentNotValidException e){
log.error("数据校验异常{},异常类型:{}",e.getMessage(),e.getClass());
Map map = new HashMap<>();
BindingResult bindingResult = e.getBindingResult();
bindingResult.getFieldErrors().forEach((fieldError -> {
map.put(fieldError.getField(),fieldError.getDefaultMessage());
}));
return R.error(BizCodeEnum.VALID_EXCEPTION.getCode(),BizCodeEnum.VALID_EXCEPTION.getMsg()).put("data",map);
}
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable e){
return R.error(BizCodeEnum.UNKNOW_EXCEPTION.getCode(),BizCodeEnum.UNKNOW_EXCEPTION.getMsg());
}
}
三、接口统一返回
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package com.zhouyi.common.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;
/**
* 返回数据
*
* @author Mark sunlightcs@gmail.com
*/
public class R extends HashMap {
private static final long serialVersionUID = 1L;
// alibaba fastjson
public T getData(TypeReference typeReference) {
Object data = get("data");
String s = JSON.toJSONString(data);
T t = JSON.parseObject(s,typeReference);
return t;
}
public T getData(String key,TypeReference typeReference) {
Object data = get(key); //默认是map
String jsonString = JSON.toJSONString(data);
T t = JSON.parseObject(jsonString, typeReference);
return t;
}
public R setData(Object data) {
put("data",data);
return this;
}
public R() {
put("code", 0);
put("msg", "success");
}
public static R error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}
public static R error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
public Integer getCode() {
return (Integer) this.get("code");
}
}
四、异步编排
1.线程池配置类
@ConfigurationProperties(prefix = "zymall.thread")
@Component
@Data
public class ThreadPoolConfigProperties {
private Integer coreSize;
private Integer maxSize;
private Integer keepAliveTime;
}
@Configuration
public class ZymallThreadConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool){
return new ThreadPoolExecutor(pool.getCoreSize(),
pool.getMaxSize(),pool.getKeepAliveTime(), TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100000), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
}
}
2.异步编排优化大业务类
@Override
public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {
SkuItemVo skuItemVo = new SkuItemVo();
CompletableFuture infoFuture = CompletableFuture.supplyAsync(() -> {
SkuInfoEntity info = getById(skuId);
skuItemVo.setInfo(info);
return info;
}, executor);
//等infoFuture才能执行
CompletableFuture saleFuture = infoFuture.thenAcceptAsync((res) -> {
List saleAttrVos = skuSaleAttrValueService.getSaleAttrsBySpuId(res.getSpuId());
skuItemVo.setSaleAttr(saleAttrVos);
}, executor);
//等infoFuture才能执行
CompletableFuture descFuture = infoFuture.thenAcceptAsync((res) -> {
SpuInfoDescEntity spuInfoDesc = spuInfoDescService.getById(res.getSpuId());
skuItemVo.setDesp(spuInfoDesc);
}, executor);
//等infoFuture才能执行
CompletableFuture baseAttrFuture = infoFuture.thenAcceptAsync((res) -> {
List attrGroupVo = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
skuItemVo.setGroupAttr(attrGroupVo);
}, executor);
CompletableFuture imagesFuture = CompletableFuture.runAsync(() -> {
List images = skuImagesService.getImagesBySkuId(skuId);
skuItemVo.setImages(images);
}, executor);
// 等所有任务都完成
CompletableFuture.allOf(saleFuture, descFuture, baseAttrFuture, imagesFuture).get();
return skuItemVo;
}
五、事务
1.默认隔离级别
# 采用数据库默认隔离级别
isolation.DEFAULT
2.默认的传播行为
propagation.REQUIRED
3.本地事务失效
同一个对象内事务方法互相调用默认失效,原因:绕过了代理对象,事务使用代理对象来控制的。解决如下:
1)、引入spring-boot-starter-aop,也就是引入aspectj
2)、@EnableAspectJAutoProxy(exposeProxy=true),开启aspectj动态代理
3)、本类互调对象
XxServiceImpl xxService = (XxServiceImpl) AopContext.currentProxy();
xxService.b();
xxService.c();