# 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();