一、lombok的使用:
lombok是一个可以减少代码量的小工具,使用非常简单,只需要添加如下依赖:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
如果开发工具为idea,那么再安装一下lombok插件即可。安装方法:
setting ---> plugins ---> browse repositories,然后搜索lombok。
如果开发工具是eclipse,安装lombok插件就麻烦一些,百度上有很多教程,此处就不再搬运了。
添加了依赖,安装好了插件,就可以使用了。下面主要介绍它的两个注解。
1、@Data:
我们在写实体类时,每个实体类都要写set、get方法以及toString方法等,虽然编辑器可以自动生成,但还是有些麻烦,而且大量的set、get方法使代码看起来不清爽。那么可以使用@Data
来搞定。在实体类上加上此注解,就相当于写了set、get、toString、equals等方法。
@Entity @Data public class OrderDetail { @Id private String detailId; private String orderId; private String productId; private String productName; private BigDecimal productPrice; private Integer productQuantity; private String productIcon; }
这样的代码看起来就干净清爽多了。
2、@Slf4j:
这也是一个常用的注解。一般我们需要用日志都会像下面这样写:
Logger log = (Logger) LoggerFactory.getLogger(当前类.class); log.error("【查询商品】商品不存在,productId={}",productId);
而加了这个注解,就不用自己创建log对象了,要用时直接用log
调用对应方法就行了。
log.error("【查询商品】商品不存在,productId={}",productId);
关于lombok还有好多注解,暂且先介绍这两个常用的。
二、createTime和updateTime问题:
一般的表中,我们都会加上createTime和updateTime两个字段。然后有记录存入数据库时,要实体.setCreateTime(new Date())
来赋值,更新时就要实体.setUpdateTime(new Date())
。每次有新增记录或有更新时都要这样set一下,有些麻烦。其实这两个时间字段可以交给数据库管理。建表时createTime和updateTime字段这样写:
create table 'product_category'( ...... `create_time` timestamp not null default current_timestamp comment '创建时间', `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间', ...... )
然后在对应的实体类上加@DynamicUpdate
注解即可实现这两个字段的自动更新。创建时不用setCreateTime,更新时也不用setUpdateTime了。
@Entity @DynamicUpdate // 动态更新 @Data public class ProductCategory { ...... private Date createTime; private Date updateTime; }
三、枚举类的使用:
关于枚举类,我之前只是在学Java基础的时候了解过,后来老师教的一些demo中都没用到过,最近看的一个项目用到了,在此记录其用法。先看下面的代码:
@Entity @Data public class ProductInfo { ...... private Integer productStatus;//商品状态(0正常,1下架) }
有一个商品类,productStatus是其状态,0是上架,1是下架。如果现在要查询所有上架商品,那么做法如下:
List<ProductInfo> productInfoList = productInfoRepository.findByProductStatus(0);
这里可能看得还挺清楚,0表示上架,查询上架的,那么就是productStatus = 0 的,所以传入0即可。但是在项目中,实体类一多,用0和1表示的东西一多,就很容易搞错,到时候自己都要看半天才知道0代表什么1代表什么。这种情况就可以用枚举类来处理。新建一个ProductStatusEnum枚举类:
@Getter public enum ProductStatusEnum { UP(0,"上架"), DOWN(1,"下架") ; private Integer code; private String message; ProductStatusEnum(Integer code,String message) { this.code = code; this.message = message; } }
那么查询方法就可以这样写了:
List<ProductInfo> productInfoList = productInfoRepository.findByProductStatus(ProductStatusEnum.UP.getCode());
ProductStatusEnum.UP.getCode()
就是0,这样一看就知道是查上架的商品。
四、VO的使用:
VO是view object的简称,中文意思是视图对象,也就是我们在controller中返回给前端的内容。一般开发时,我们要按照前端给的文档给前端返回相应的内容,比如现有api如下:
路由:GET /sell/buyer/product/list
参数:无
返回:
{ "code": 0, "msg": "成功", "data": [ { "name": "类目名1", "type": 1, "foods": [ { "id": "123456", "name": "商品名1", "price": 4.5, "description": "xxxxx", "icon": "http://xxx.com", } ] }, { "name": "类目名2", "type": 2, "foods": [ { "id": "123457", "name": "商品名2", "price": 10.9, "description": "xxxxx", "icon": "http://xxx.com", }, { "id": "123457", "name": "商品名3", "price": 10.9, "description": "xxxxx", "icon": "http://xxx.com", } ] } ] }
咋一看很复杂,其实不然。一个中括号就表示里面的是list。那么可以知道,最外层是由code、msg和类目的list组成;第二层就是由类目名name、type和商品的list组成;商品的list就包含了商品的信息。那么要如何构造这样的返回对象呢?先从最外层开始写。根据最外层的三个字段,可以写出ResultVo类:
/** * 返回给前端的最外层对象 * Create by zhu on 2018/10/7 */ @Data public class ResultVo<T> { private Integer code;//错误码 private String msg;//提示信息 private T data;//返回的内容 }
这里data定义为泛型,这样就可以通用。
现在将ResultVo对象返回给前端:
@GetMapping("/test") public ResultVo test(){ ResultVo resultVo = new ResultVo(); resultVo.setCode(0); resultVo.setMsg("test"); resultVo.setData("这是内容"); return resultVo; }
就会得到如下效果:
说明最外层是没有错的,根据api提供的信息又可以写出如下vo:
@Data public class ProductVo { //这里写的字段名与前端api需要的不一致没关系,加上如下注解,直接里面写api需要的字段名 @JsonProperty("name") private String categoryName; @JsonProperty("type") private Integer categoryType; @JsonProperty("foods")//这个foods是一个商品的list private List<ProductInfoVo> productInfoVoList; }
//这个就是最里层的商品对象 @Data public class ProductInfoVo { @JsonProperty("id") private String productId; @JsonProperty("name") private String productName; @JsonProperty("price") private BigDecimal productPrice; @JsonProperty("description") private String productDescription; @JsonProperty("icon") private String productIcon; }
注意,前端需要的name其实是类目名,如果这个vo也直接定义变量name,到时候会搞不清楚到底是商品的name还是类目的name。解决方案是:这里应该是什么就写什么,然后通过@JsonProperty("xxx")来指定返回给前端时的名字。
写好后再去controller中:
@GetMapping("/test") public ResultVo test() { ResultVo resultVo = new ResultVo(); ProductVo productVo = new ProductVo(); ProductInfoVo productInfoVo = new ProductInfoVo(); productInfoVo.setProductName("商品1"); productVo.setProductInfoVoList(Arrays.asList(productInfoVo)); productVo.setCategoryName("类目1"); resultVo.setData(Arrays.asList(productVo)); resultVo.setMsg("成功"); resultVo.setCode(0); return resultVo; }
把最里层的赋好值设置给中间层,中间层赋好值设置给最外层,再把最外层返回给前端,效果如下:
这样返回的格式就对了,和api一致。接下来要做的事就是从数据库查出相应的记录,然后赋给这三个对象就行了。
从上面的controller中可以发现,我们每次都要new一个最外层的ResultVo对象,然后setCode、setMsg、setData。每个方法中都new一个还是很麻烦的,所以可以封装一下:
public class ResultVoUtil { /** 成功时使用 */ public static ResultVo success(Object object){ ResultVo resultVo = new ResultVo(); resultVo.setData(object); resultVo.setCode(0); resultVo.setMsg("成功"); return resultVo; } /** 成功时且不需要返回值时使用 */ public static ResultVo success(){ return success(null); } /** 请求错误时使用 */ public static ResultVo error(Integer code,String msg){ ResultVo resultVo = new ResultVo(); resultVo.setCode(code); resultVo.setMsg(msg); return resultVo; } }
那么上面的controller就可以改成:
@GetMapping("/test") public ResultVo test() { ProductVo productVo = new ProductVo(); ProductInfoVo productInfoVo = new ProductInfoVo(); productInfoVo.setProductName("商品1"); productVo.setProductInfoVoList(Arrays.asList(productInfoVo)); productVo.setCategoryName("类目1"); return ResultVoUtil.success(Arrays.asList(productVo)); }
这样代码看起来就简洁多了,而且这个ResultVoUtil也是通用的,传入相应的Object对象即可。