电商秒杀基础构建项目笔记2(优化效验准则和商品模型创建)
第16步
优化效验规则,
先增加依赖,hibernate-validator,封装了一些效验规则,创建一个validator包,在里面创建一个ValitationResult,编写效验信息返回的类,创建ValidatorImpl,添加@Component,注入Bean实例化,定义效验,判断结果是否有错,在UserModel定义用户数据的约束,在service层调用新增的validator效验方法,注掉之前的校验方法。
引入validator的效验规则依赖
<!--效验规则-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.14.Final</version>
</dependency>
编写ValidationResult,
public class ValidationResult {
//检查结果是否有错
private boolean hasError = false;
//存放错误信息的map
private Map<String,String> errorMsgMap=new HashMap<>();
public boolean isHasError() {
return hasError;
}
public void setHasError(boolean hasError) {
this.hasError = hasError;
}
public Map<String, String> getErrorMsgMap() {
return errorMsgMap;
}
public void setErrorMsgMap(Map<String, String> errorMsgMap) {
this.errorMsgMap = errorMsgMap;
}
//实现通用的通过格式化字符串信息获取错误结果的msg方法
public String getErrorMsg(){
return StringUtils.join(errorMsgMap.values().toArray(),",");
}
编写ValidatorImpl
@Component
public class ValidatorImpl implements InitializingBean {
//效验结果是否有错
private Validator validator;
//实现效验方法并返回结果
public ValidationResult validate(Object bean){
ValidationResult result = new ValidationResult();
Set<ConstraintViolation<Object>> constraintViolationSet = validator.validate(bean);
if (constraintViolationSet.size() >0){
//有错误
result.setHasError(true);
constraintViolationSet.forEach(constraintViolation->{
String errMsg = constraintViolation.getMessage();
String propertyName = constraintViolation.getPropertyPath().toString();
result.getErrorMsgMap().put(propertyName,errMsg);
});
}
return result;
}
@Override
public void afterPropertiesSet() throws Exception {
//将hibernate validator通过工厂化的方式实例化
this.validator= Validation.buildDefaultValidatorFactory().getValidator();
}
第17步
商品模型创建
首先创建编写ItemModel,描述商品的信息,之后再创建数据库,如果pom文件里面之前的逆向生成文件设置为打开时,要注意关闭,在Mybatis逆向生成里面增加数据库配置,将自增的id插入到mapper.xml文件中。
编写ItemModel
public class ItemModel {
private Integer id;
//商品的名称
private String title;
//商品的价格
private BigDecimal price;
//商品的库存
private Integer stock;
//商品的描述
private String description;
//商品的价格
private String sales;
// 商品描述图片的url
private String imgUrl;
}
第18步
编写商品service层,逻辑实现,编写controller层,业务实现返回给前端。
先编写商品模型的接口ItemService,接着实现类实现逻辑业务,在dao层增加效验约束条件,在实现类里面编写创建商品逻辑,之后在商品库存xml文明增加一个通过用户id查询的sql语句,顺便补上接口,接着编写把商品的数据返回给前端,下一步就可以编写controller层了,创建商品项目controller和ItemVO(返回给前端看的商品数据)
商品模型接口
public interface ItemService {
//创建商品
ItemModel createItem(ItemModel itemModel) throws BusinessException;
//商品列表浏览
List<ItemModel> listItem();
//商品详细浏览
ItemModel getItemById(Integer id);
}
实现类
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private ValidatorImpl validator;
@Autowired
private ItemDOMapper itemDOMapper;
@Autowired
private ItemStockDOMapper itemStockDOMapper;
private ItemDO convertItemDOFromItemModel(ItemModel itemModel){
if (itemModel == null){
return null;
}
ItemDO itemDO = new ItemDO();
BeanUtils.copyProperties(itemModel,itemDO);
itemDO.setPrice(itemModel.getPrice().doubleValue());
return itemDO;
}
private ItemStockDO convertItemStockDOFromItemModel(ItemModel itemModel){
if(itemModel == null) {
return null;
}
ItemStockDO itemStockDO = new ItemStockDO();
itemStockDO.setItemId(itemModel.getId());
itemStockDO.setStock(itemModel.getStock());
return itemStockDO;
}
@Override
@Transactional
public ItemModel createItem(ItemModel itemModel) throws BusinessException {
//效验入参
ValidationResult result = validator.validate(itemModel);
if (result.isHasError()){
throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,result.getErrorMsg());
}
//转化itemmodel->dataobject
ItemDO itemDO = this.convertItemDOFromItemModel(itemModel);
//写入数据库
itemDOMapper.insertSelective(itemDO);
itemModel.setId(itemDO.getId());
ItemStockDO itemStockDO = this.convertItemStockDOFromItemModel(itemModel);
itemStockDOMapper.insertSelective(itemStockDO);
return this.getItemById(itemModel.getId());
}
@Override
public List<ItemModel> listItem() {
return null;
}
@Override
public ItemModel getItemById(Integer id) {
ItemDO itemDO = itemDOMapper.selectByPrimaryKey(id);
if (itemDO == null){
return null;
}
//获取操作库存数量
ItemStockDO itemStockDO = itemStockDOMapper.selectByItemId(itemDO.getId());
//将dataobject转化为model
ItemModel itemModel = convertModelFromDataObject(itemDO, itemStockDO);
return itemModel;
}
private ItemModel convertModelFromDataObject(ItemDO itemDO,ItemStockDO itemStockDO){
ItemModel itemModel = new ItemModel();
BeanUtils.copyProperties(itemDO,itemModel);
itemModel.setPrice(new BigDecimal(itemDO.getPrice()));
itemModel.setStock(itemStockDO.getStock());
return itemModel;
}
@Override
public boolean decreaseStock(Integer itemId, Integer amount) {
return false;
}
@Override
public void increaseSales(Integer itemId, Integer amount) throws BusinessException {
}
}
在商品库存mapper.xml文件中增加一个查询sql
<select id="selectByItemId" parameterType="java.lang.Integer" resultMap="BaseResultMap">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
This element was generated on Thu Dec 03 20:49:59 CST 2020.
-->
select
<include refid="Base_Column_List" />
from item_stock
where item_id = #{itemId,jdbcType=INTEGER}
</select>
编写ItemVO
public class ItemVO {
private Integer id;
//商品的名称
private String title;
//商品的价格
private BigDecimal price;
//商品的库存
private Integer stock;
//商品的描述
private String description;
//商品的价格
private String sales;
// 商品描述图片的url
private String imgUrl;
}
编写ItemController
@Controller("/item")
@RequestMapping("/item")
@CrossOrigin(origins = {"*"}, allowCredentials = "true")
public class ItemController extends BaseController {
@Autowired
ItemService itemService;
//创建商品
@RequestMapping(value = "/create", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType createItem(@RequestParam(name = "title") String title,
@RequestParam(name = "price") BigDecimal price,
@RequestParam(name = "stock") Integer stock,
@RequestParam(name = "imgUrl") String imgUrl,
@RequestParam(name = "description") String description) throws BusinessException {
// 封装service请求用来创建商品
ItemModel itemModel = new ItemModel();
itemModel.setTitle(title);
itemModel.setPrice(price);
itemModel.setStock(stock);
itemModel.setImgUrl(imgUrl);
itemModel.setDescription(description);
ItemModel itemModelForReturn = itemService.createItem(itemModel);
ItemVO itemVO = this.convertVOFromModel(itemModelForReturn);
return CommonReturnType.create(itemVO);
}
private ItemVO convertVOFromModel(ItemModel itemModel) {
if(itemModel == null) {
return null;
}
ItemVO itemVO = new ItemVO();
BeanUtils.copyProperties(itemModel,itemVO);
return itemVO;
}
}
第19步
编写商品模型的前端界面
在controller层实现商品详情浏览
编写createItem.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="static/assets/global/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<link href="static/assets/global/css/components.css" rel="stylesheet" type="text/css"/>
<link href="static/assets/admin/pages/css/login.css" rel="stylesheet" type="text/css"/>
<script src="static/assets/global/plugins/jquery-1.11.0.min.js" type="text/javascript"></script>
</head>
<body class="login">
<div class="content">
<h3 class="form-title">创建商品</h3>
<div class="form-group">
<label class="control-label">商品名</label>
<div>
<input class="form-control" type="text" name="title" id="title">
</div>
</div>
<div class="form-group">
<label class="control-label">商品价格</label>
<div>
<input class="form-control" type="text" name="price" id="price">
</div>
</div>
<div class="form-group">
<label class="control-label">商品库存</label>
<div>
<input class="form-control" type="text" name="stock" id="stock">
</div>
</div>
<div class="form-group">
<label class="control-label">商品描述</label>
<div>
<input class="form-control" type="text" name="description" id="description">
</div>
</div>
<div class="form-group">
<label class="control-label">商品图片</label>
<div>
<input class="form-control" type="text" name="imgUrl" id="imgUrl">
</div>
</div>
<div class="form-actions">
<button class="btn blue" id="create" type="submit">
提交创建
</button>
</div>
</div>
</body>
<script>
$(document).ready(function() {
$("#create").on("click", function() {
var title = $("#title").val();
var price = $("#price").val();
var stock = $("#stock").val();
var description = $("#description").val();
var imgUrl = $("#imgUrl").val();
if (title == null || title == "") {
alert("商品名不能为空");
return false;
}
if (price == null || price == "") {
alert("商品价格不能为空");
return false;
}
if (stock == null || stock == "") {
alert("商品库存不能为空");
return false;
}
if (description == null || description == "") {
alert("商品描述不能为空");
return false;
}
if (imgUrl == null || imgUrl == "") {
alert("商品图片不能为空");
return false;
}
$.ajax({
type: "POST",
contentType: "application/x-www-form-urlencoded",
url: "http://localhost:8090/item/create",
data: {
"title": title,
"price": price,
"stock": stock,
"description": description,
"imgUrl": imgUrl
},
xhrFields:{
withCredentials:true
},
success: function(data) {
if (data.status == "success") {
alert("创建成功");
} else {
alert("创建失败,原因为" + data.data.errMsg);
}
},
error: function(data) {
alert("创建失败,原因为" + data.responseText);
}
});
return false;
});
});
</script>
</html>
在controller添加实现商品详情浏览
//商品详情页浏览
@RequestMapping(value = "/get", method = {RequestMethod.GET})
@ResponseBody
public CommonReturnType getItem(@RequestParam(name = "id")Integer id){
ItemModel itemModel = itemService.getItemById(id);
ItemVO itemVO = this.convertVOFromModel(itemModel);
return CommonReturnType.create(itemVO);
}
private ItemVO convertVOFromModel(ItemModel itemModel) {
if(itemModel == null) {
return null;
}
ItemVO itemVO = new ItemVO();
BeanUtils.copyProperties(itemModel,itemVO);
return itemVO;
}