静态资源及sql文件分享
链接:https://pan.baidu.com/s/1X-yjmQcPD3PqS21x0HplNA?pwd=23gr
提取码:23gr
根据商品id显示商品详情的SQL语句
select * from t_product where id=?
在ProductMapper接口中添加抽象方法
//根据id查询
Product getById(Integer id);
在ProductMapper.xml文件中配置findById(Integer id)方法的映射
<select id="getById" resultMap="ProductEntityMap">
select *
from t_product where id=#{id};
</select>
如果商品数据不存在,应该抛出ProductNotFoundException,所以创建ProductNotFoundException异常类并使其继承ServiceException
/** 商品数据不存在的异常 */
public class ProductNotFoundException extends ServiceException {
/**重写ServiceException的所有构造方法*/
}
在业务层IProductService接口中添加getById(Integer id)抽象方法
Product getById(Integer id);
在ProductServiceImpl类中,实现接口中的getById(Integer id)抽象方法
@Override
public Product getById(Integer id) {
Product product = productMapper.getById(id);
if (product==null){
throw new ProductNotFoundException("商品不存在");
}
product.setPriority(null);
product.setCreatedUser(null);
product.setCreatedTime(null);
product.setModifiedUser(null);
product.setModifiedTime(null);
return product;
}
在BaseController类中的handleException()方法中添加处理ProductNotFoundException的异常
else if (e instanceof ProductNotFoundException) {
result.setState(4006);
result.setMessage("访问的商品数据不存在的异常");
}
请求路径:/products/{id}/details
请求参数:Integer id
请求方式:GET
响应结果:JsonResult< Product>
在ProductController类中添加处理请求的getById()方法
@GetMapping("{id}/details")
public JsonResult<Product> getById(@PathVariable("id") Integer id){
Product product = productService.getById(id);
return new JsonResult<>(ok,product);
}
1.首页将商品id发送给详情页后,详情页需要从url中裁取获得该id,实现方法在jquery-getUrlParam.js中(目前怎么实现裁取可以先不学),所以需要在product.html页面中导入该js文件,这里我在body标签内部的最后引入该js文件
<script type="text/javascript" src="../js/jquery-getUrlParam.js"></script>
2.在product.html页面中body标签内部的最后添加获取当前商品详情的代码
<script type="text/javascript">
//调用jquery-getUrlParam.js文件的getUrlParam方法获取商品id
var id = $.getUrlParam("id");
console.log("id=" + id);
$(document).ready(function() {
$.ajax({
url: "/products/" + id + "/details",
type: "GET",
dataType: "JSON",
success: function(json) {
if (json.state == 200) {
console.log("title=" + json.data.title);
//html()方法:
// 假设有个标签
//那么$("#a").html()就是给该div标签加p标签
//$("#a").html("我爱中国")就是给该div标签填充"我爱中国"内容
$("#product-title").html(json.data.title);
$("#product-sell-point").html(json.data.sellPoint);
$("#product-price").html(json.data.price);
for (var i = 1; i <= 5; i++) {
$("#product-image-" + i + "-big").attr("src", ".." + json.data.image + i + "_big.png");
$("#product-image-" + i).attr("src", ".." + json.data.image + i + ".jpg");
}
} else if (json.state == 4006) { // 商品数据不存在的异常
location.href = "index.html";
} else {
alert("获取商品信息失败!" + json.message);
}
}
});
});
</script>
在store数据库中创建t_cart用户数据表
CREATE TABLE t_cart (
cid INT AUTO_INCREMENT COMMENT '购物车数据id',
uid INT NOT NULL COMMENT '用户id',
pid INT NOT NULL COMMENT '商品id',
price BIGINT COMMENT '加入时商品单价',
num INT COMMENT '商品数量',
created_user VARCHAR(20) COMMENT '创建人',
created_time DATETIME COMMENT '创建时间',
modified_user VARCHAR(20) COMMENT '修改人',
modified_time DATETIME COMMENT '修改时间',
PRIMARY KEY (cid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在entity包下创建购物车的Cart实体类并使其继承BaseEntity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Cart extends baseEntity implements Serializable {
private Integer cid;
private Integer uid;
private Integer pid;
private Long price;
private Integer num;
}
1.向购物车表中插入商品数据的SQL语句
insert into t_cart (除了cid以外的所有字段) value (匹配的值列表);
2.如果当前商品已经在购物车存在,则直接更新商品即可
update t_cart set num=? where cid=?
3.在插入或者更新具体执行哪个语句,取决于数据库中是否有当前的这个购物车商品的数据,需要查询语句才能确定
select * from t_cart where uid=? and pid=?
在mapper包下创建CartMapper接口,并添加抽象方法
//插入数据
Integer insert(Cart cart);
//修改商品数量
Integer updateNumByCid(Integer cid,Integer num,String modifiedUser, Date modifiedTime);
//c查询购物车中的数据
Cart findByUidAndPid(Integer uid,Integer pid);
在resources.mapper文件夹下创建CartMapper.xml文件,并在文件中配置以上三个方法的映射
<mapper namespace="com.cy.store.mapper.CartMapper">
<resultMap id="CartEntityMap" type="com.cy.store.entity.Cart">
<id column="cid" property="cid"/>
<result column="created_user" property="createdUser"/>
<result column="created_time" property="createdTime"/>
<result column="modified_user" property="modifiedUser"/>
<result column="modified_time" property="modifiedTime"/>
</resultMap>
<insert id="insert" useGeneratedKeys="true" keyProperty="cid">
insert into t_cart (uid,pid,price,num,created_user, created_time, modified_user, modified_time)
values (#{uid}, #{pid}, #{price}, #{num}, #{createdUser}, #{createdTime}, #{modifiedUser}, #{modifiedTime})
</insert>
<update id="updateNumByCid">
update t_cart set num=#{num},modified_user=#{modifiedUser}
,modified_time=#{modifiedTime} where cid=#{cid}
</update>
<select id="findByUidAndPid" resultMap="CartEntityMap">
select * from t_cart where uid=#{uid} and pid=#{pid}
</select>
</mapper>
在插入数据时,可能抛出InsertException异常;在修改数据时,可能抛出UpdateException异常.这两个异常已开发
在com.cy.store.service包下创建ICartService接口,并添加抽象方法
findByUidAndPid:查询购物车数据,参数是uid,pid
insert:插入购物车数据,参数是cart对象(属性有cid,uid,pid,price,num)
updateNumByCid:修改购物车中商品数量,参数是cid,num,modifiedUser,modifiedTime
price可以通过业务层中调用ProductMapper接口的findById获取,modifiedTime在业务层实现类的内部创建,所以需要的参数是uid,pid,num,username
即使持久层的方法参数是实体类对象,业务层的方法参数也大多不是实体类对象,因为实体类的部分属性是可以在业务层进行拼接然后封装到实体类对象中,再传给持久层(比如这里的price),这样的话就降低了前端传递数据的压力,如果该对象的所有方法都必须由前端传递过来,那么业务层方法参数可以是实体类对象(如注册用户时业务层的方法参数就是User对象)
public interface ICartService {
//加入到购物车
void addCart(Integer uid,Integer pid,Integer amount,String username);
}
创建CartServiceImpl类,并实现ICartService接口.在类中声明CartMapper持久层对象和IProductService处理商品数据的业务对象,并实现业务层的抽象方法
@Service
public class CartServiceImpl implements ICartService {
@Resource
private CartMapper cartMapper;
@Resource
private ProductMapper productMapper;
@Override
public void addCart(Integer uid, Integer pid, Integer amount, String username) {
Cart findCart = cartMapper.findByUidAndPid(uid, pid);
if (findCart==null){
Cart cart=new Cart();
Product product = productMapper.getById(pid);
cart.setPid(pid);
cart.setUid(uid);
cart.setNum(amount);
cart.setPrice(product.getPrice());
cart.setCreatedUser(username);
cart.setCreatedTime(new Date());
cart.setModifiedUser(username);
cart.setModifiedTime(new Date());
Integer integer = cartMapper.insert(cart);
if (integer!=1){
throw new InsertException("加入购物车产生异常");
}
}
else {
int oldNum=findCart.getNum();
int newNum=oldNum+amount;
Integer integer1 = cartMapper.updateNumByCid(findCart.getCid(), newNum, username, new Date());
if (integer1!=1){
throw new UpdateException("修改数量时产生异常");
}
}
}
}
nsertException异常和UpdateException异常都已经设置到BaseController类中,无需重复开发
请求路径:/carts/add_to_cart
请求方式:post
请求参数:Integer pid, Integer amount, HttpSession session
响应结果:JsonResult< Void>
在controller包下创建CartController类并继承BaseController类,在类中添加处理请求的addToCart()方法
@RestController
@RequestMapping("carts")
public class CartController extends BaseController{
@Autowired
private ICartService cartService;
@PostMapping("add_to_cart")
public JsonResult<Void> addCart(Integer pid, Integer amount, HttpSession session){
Integer getuidfromsession = getuidfromsession(session);
String getusernamesession = getusernamesession(session);
cartService.addCart(getuidfromsession,pid,amount,getusernamesession);
return new JsonResult<>(ok);
}
}
在product.html页面中的body标签内的script标签里为“加入购物车”按钮添加点击事件
回顾一下在ajax函数中data参数的数据设置的方式
data:$ (“选择的form表单”).serialize()。当需要提交的参数过多并且在同一个表单中时使用
data:new FormData($(“选择的form表单”)[0])。只适用提交文件
data:“username=TOM”。手动拼接,适合参数值固定并且参数值列表有限.等同于
var user = "控件某属性值或控件文本内容或自己声明的值"
data: "username="+user
使用JSON格式提交数据
data: {
"username": "Tom",
"age": 18
}
这里表单里面有很多无用参数,所以不使用表单提交
$("#btn-add-to-cart").click(function() {
$.ajax({
url: "/carts/add_to_cart",
type: "POST",
data: {
"pid": id,
"amount": $("#num").val()
},
dataType: "JSON",
success: function(json) {
if (json.state == 200) {
alert("增加成功!");
} else {
alert("增加失败!" + json.message);
}
},
error: function(xhr) {
alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);
location.href = "login.html";
}
});
});
后记
美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!!