分布式项目 16 购物车系统,dubbo框架(重点是拦截器),优化userId,配合拦截器

news2024/11/19 15:55:09

01.创建jt-cart项目
第一步:在这里插入图片描述
第二步:
在这里插入图片描述
第三步:在这里插入图片描述
第四步:
在pom.xml文件中添加jt-common的依赖,如图所示:
在这里插入图片描述
第五步:
添加插件

<build>
<plugins>
<!--跳过测试类打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

第六步:创建pojo实体类对象
说明:在jt-common项目下的com.jt.pojo创建Cart实体类

@Data
@Accessors(chain = true)
@TableName("tb_cart")
public class Cart extends BasePojo{
@TableId(type = IdType.AUTO)
private Long id;//购物车数据主键
private Long userId;
private Long itemId;
private String itemTitle;//商品的标题
private String itemImage;//商品图片
private Long itemPrice;//商品价格
private Integer num;//商品数量
}

第七步:创建Dubbo接口
说明:在jt-common项目com.jt.service包下创建DubboCartService接口

package com.jt.service;
public interface DubboCartService {
}

第八步:
资源整合
说明:由于jt-cart中的需求和jt-sso的差不多,所以在搭建jt-cart项目时可以将jt-sso项目的src复制一份,然后进行少量的修改,如图所示:
在这里插入图片描述
接下来开始修改:
第一步:将Controller包都删掉,因为后期的跨域实现使用dubbo,后台服务不需要声明controller,所有将com.jt.controller包以及资源都删掉。
第二步:将com.jt.mapper包下的资源都删掉,然后创建一个CartMapper接口,代码如下:

package com.jt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.Cart;
public interface CartMapper extends BaseMapper<Cart>{
}

第三步:将com.jt.service包下的资源都删掉,然后新创建一个DubboCartServiceImpl实现类,代码如下:

package com.jt.service;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.CartMapper;
@Service
public class DubboCartServiceImpl implements DubboCartService {
@Autowired
private CartMapper cartMapper;
}

第四步:修改src/main/resource目录下的配置文件:将UserMapper改为CartMapper,如图所示:
在这里插入图片描述
第五步:修改application.yml文件,配置如下:

server:
port: 8094
servlet:
context-path: /
spring:
datasource:
#引入druid数据源
#type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?
serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true
&allowMultiQueries=true
username: root
password: root
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.jt.mapper: debug
dubbo:
scan:
basePackages: com.jt #指定dubbo的包路径 后期扫描的是dubbo下的一些注解例如
@Service
application:
name: provider-cart #指定服务的名称(必须指定)
registry: #配置注册中心的信息
address: zookeeper://192.168.126.129:2181?
backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #RPC调用的规范
name: dubbo #使用dubbo的协议 就可以实现前台直接调用后台
port: 20881 #服务的连接时的端口号

第六步:启动项目
在这里插入图片描述
02.购物车列表展现
第一步:页面url分析
在这里插入图片描述
第二步:页面JS分析
分析:cart.jsp页面
在这里插入图片描述
第三步:jt-web的CartController
说明:打开jt-web项目,然后创建一个进行资源调度的CartController类,然后完成业务实现:

@Controller
@RequestMapping("/cart")
public class CartController {
/**
* 需求:当用户点击“购物车”按钮时,需要跳转到用户的购物车页面cart.jsp
* url:http://www.jt.com/cart/show.html
* 方法返回值:页面的名称cart
*/
@RequestMapping("/show")
public String show() {
return "cart";
}
}

第四步:在cart.jsp页面中完成页面数据动态展示,修改controller类

@Controller
@RequestMapping("/cart")
public class CartController {
@Reference(check=false)
private DubboCartService cartService;
/**
* 需求:当用户点击“购物车”按钮时,需要跳转到用户的购物车页面cart.jsp
* url:http://www.jt.com/cart/show.html
* 方法返回值:页面的名称cart
* 页面数据显示:应该根据userId动态的查询购物车记录。之后实现页面的展示
* 页面数据取值:${cartList} 表示利用el表达式动态的获取购物车列表信息
*/
@RequestMapping("/show")
public String show(Model model) {
Long userId=7L;//先从数据库中查询一下cart表,然后将userId写死
List<Cart> cartList=cartService.findCartListByUserId(userId);
model.addAttribute("cartList", cartList);
return "cart";
}
}

第五步:编辑DubboCartService接口

public interface DubboCartService {
List<Cart> findCartListByUserId(Long userId);
}

第六步:编辑DubboCartServiceImpl实现类

@Service
public class DubboCartServiceImpl implements DubboCartService {
@Autowired
private CartMapper cartMapper;
@Override
public List<Cart> findCartListByUserId(Long userId) {
QueryWrapper<Cart> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("user_id", userId);
return cartMapper.selectList(queryWrapper);
}
}

这里的service注解是dubbo框架下的注解,不是spring的service注解。
03.购物车数量修改业务
说明:对于加入购物车的列表数据,可以进行购物车商品数量的修改。
第一步:页面url分析
在这里插入图片描述
第二步:页面JS分析

itemNumChange : function(){
$(".increment").click(function(){//+
var _thisInput = $(this).siblings("input");
_thisInput.val(eval(_thisInput.val()) + 1);
$.post("/cart/update/num/"+_thisInput.attr("itemId")+"/"+_thisInput.val(),functi
on(data){
//加载完成数据之后,刷新页面总价
TTCart.refreshTotalPrice();
});
});
$(".decrement").click(function(){//-
var _thisInput = $(this).siblings("input");
if(eval(_thisInput.val()) == 1){
return ;
}
_thisInput.val(eval(_thisInput.val()) - 1);
$.post("/cart/update/num/"+_thisInput.attr("itemId")+"/"+_thisInput.val(),functi
on(data){
TTCart.refreshTotalPrice();
});
});

第三步:编辑CartController,修改controller类
说明:编辑jt-web中的CartController实现业务调用.

/**
* 需求:当用户修改商品数量时,需要发起ajax请求,实现商品数量修改
* 如何修改?
* url:http://www.jt.com/cart/update/num/562379/11
* 基于商品的itemId修改商品的数量
* 参数:itemId,num
* 返回值:SysResult对象
* 如何准确修改某一个用户的某一条商品的数量?通过userId和ItemId共同确定要修改的购物车数量
*/
@RequestMapping("/cart/update/num/{itemId}/{num}")
@ResponseBody
public SysResult updateCartNum(Cart cart) {
Long userId=7L;
cart.setUserId(userId);
cartService.updateNum(cart);
return SysResult.success();
}

第四步:编辑中立接口DubboCartService
说明:在jt-common中创建DubboCartService独立接口

public interface DubboCartService {
List<Cart> findCartListByUserId(Long userId);
void updateNum(Cart cart);
}

第五步:编辑DubboCartServiceImpl
说明:编辑jt-cart项目,实现cart中数量的修改。

/*
* 业务分析:
* 根据itemId和userId修改购物车的数量
*/
@Override
public void updateNum(Cart cart) {
Cart cartTemp=new Cart();
cartTemp.setNum(cart.getNum()).setUpdated(new Date());
UpdateWrapper<Cart> updateWrapper=new UpdateWrapper<>();
updateWrapper.eq("user_id", cart.getUserId())
.eq("item_id", cart.getItemId());
cartMapper.update(cartTemp, updateWrapper);
}

04.购物车数据新增
说明:当查看某一个商品信息时,可以通过“加入购物车”进行购物车数据的新增。
在这里插入图片描述

第一步:页面url分析
在这里插入图片描述
在这里插入图片描述

第二步:页面JS分析

function addCart(){
var url = "http://www.jt.com/cart/add/${item.id}.html";
document.forms[0].action = url; //js设置提交链接
document.forms[0].submit(); //js表单提交
}

第三步:业务分析
说明:需求是将商品添加到购物车
1.如果用户之前之前添加过该到购物车,则需求更新购物的商品的数量。
2.如果用户第一次添加该商品到购物车,则需要做购物车的新增。
第四步:修改编辑jt-web的CartController

/**
* 需求:当用户将某一个商品点击“加入购物车”,需要将该商品添加到购物车中
* (1)如果用户对于该商品进行第一次新增,则需要新增购物车数据
* (2)如果用户不是第一次新增,则只需要做购物车数量修改
* url:http://www.jt.com/cart/add/562379.html
* 参数:Cart cart
* 返回值:重定向购物的列表页面
*/
@RequestMapping("/cart/add/{itemId}")
public String saveCart(Cart cart) {
//业务的实现
Long userId=7L;
cart.setUserId(userId);
cartService.saveCart(cart);
return "redirect:/cart/show.html";
}

第四步:编辑DubboCartService
说明:编辑jt-common中的DubboCartService接口

public interface DubboCartService {
void saveCart(Cart cart);
}

第五步:编辑DubboCartServiceImpl
说明:在jt-cart项目中编辑DubboCartServiceImpl进行业务实现。

/**
* 业务分析:
* 查询购物车列表中是否已经存在当前添加的商品数据,根据user_id和item_id查询
* 如果不存在,则入库新增
* 如果存在,则需要更新购物车的数量
*/
@Override
public void saveCart(Cart cart) {
//1.先根据userId和itemId到购物车中进行数据的查询
QueryWrapper<Cart> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("user_id", cart.getUserId()).eq("item_id", cart.getItemId());
Cart cartDB = cartMapper.selectOne(queryWrapper);
//2.判断cartDB是否为null
if(cartDB==null) {
//cartDB为空,说明没有查到对应的购物车数据,做购物车数据新增
cart.setCreated(new Date()).setUpdated(cart.getCreated());
cartMapper.insert(cart);
}else {
//说明cartDB不为null,证明用户之前已经新增过了,只需要修改购物车数量即可
int num=cart.getNum()+cartDB.getNum();
Cart cartTemp=new Cart();
cartTemp.setId(cartDB.getId()).setNum(num).setUpdated(new Date());
cartMapper.updateById(cartTemp);
}
}

第五步:业务测试
说明:启动jt-cart,jt-mange以及jt-web项目(注意启动顺序),然后访问jt首页,选中商品加入购物
车。
在这里插入图片描述
在这里插入图片描述
05.购物车列表删除业务
第一步:页面url分析
在这里插入图片描述

第二步:页面JS分析

<a id="remove-11345721-1" data-more="removed-87.20-1"
clstag="clickcart|keycount|xincart|btndel318558" class="cart-remove"
href="/cart/delete/${cart.itemId}.html">删除</a>

第三步:删除购物车列表业务实现
01.编辑CartController
说明:编辑jt-web中的CartController

/**
* 需求:删除购物车列表数据
* url:/cart/delete/${cart.itemId}.html
* 参数:itemId
* 返回值:重定向到购物车列表页面
*/
@RequestMapping("/cart/delete/{itemId}")
public String deleteCart(@PathVariable Long itemId) {
Long userId=7L;
//根据itemId和userId删除购物车数据
Cart cart=new Cart();
cart.setUserId(userId).setItemId(itemId);
cartService.deleteCart(cart);
return "redirect:/cart/show.html";
}

02.编辑DubboCartService接口
说明:编辑jt-common中的DubboCartService接口

public interface DubboCartService {
void deleteCart(Cart cart);
}

03.编辑DubboCartServiceImpl
说明:编辑jt-cart中的DubboCartServiceImpl。

@Override
public void deleteCart(Car cart) {
//根据cart不为null属性充当where条件
QueryWrapper<Cart> wrapper=new QueryWrapper<>(cart);
cartMapper.delete(wrapper);
}

第四步:业务测试
在这里插入图片描述
06.权限控制
第一步:需求分析
说明:
假设用户在做敏感操作时,如果用户不登陆则不允许访问,需要重定向到用户的登录页面。例如:当用户没有登录的情况下是不可以访问购物车的。
如何实现: 拦截器

第二步:自定义拦截器
SpringMVC对外提供了一个拦截器接口,叫做HandlerInterceptor
在此接口中,有三个方法,分别为preHandle, postHandle, afterCompletion
这三个方法在拦截器中的作用如图所示
在这里插入图片描述
第三步:创建编辑自定义拦截器UserInterceptor
说明:在jt-web项目下面创建一个com.jt.interceptor包,在包下面创建一个UserInterceptor类,代码如下

//HandlerInterceptor是SpringMVC对外提供的拦截器的接口
@Component//将对象交给Spring容器管理
public class UserInterceptor implements HandlerInterceptor{
/**
* 说明:如果用户没有登录,应该重定向到用户的登录页面
* 如果用户已经登录,则拦截器放行,去请求资源数据
*
* 如何确定用户已经登录?
* 1.确定浏览器中的cookie是否有JT_TICKET的值
* 2.根据用户的ticket信息去判断redis中是否有值
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler)
throws Exception {
//登录的url:http://www.jt.com/user/login.html
response.sendRedirect("/user/login.html");
return false;//表示拦截
}
}

然后将我们自定义的拦截器UserInterceptor去添加到SpringMvc的拦截配置中, 打开jt-web项目下的com.jt.config包下的MvcConfigurer类中,代码如下

@Configuration //类似于web.xml
public class MvcConfigurer implements WebMvcConfigurer{
@Autowired
private UserInterceptor userInterceptor;
//新增拦截器 拦截的是:如果不登陆,就不允许访问购物车/订单业务
@Override
public void addInterceptors(InterceptorRegistry registry) {
//将自己的拦截器添加到注册中心。
registry.addInterceptor(userInterceptor)
//拦截器需要设定拦截路径(访问购物车或者订单的路径)
.addPathPatterns("/cart/**","/order/**");// /cart/** 表示购物车的多级目录
/cart/* 表示购物车一级目录
}
}

第四步:测试拦截器是否配置成功
说明:启动jt-web项目,然后在保证退出登录的情况下去访问购物车,看是否会被拦截到登录页面。
在这里插入图片描述
第五步:完善自定义拦截器UserInterceptor的业务
说明:如果用户没有登录,应该重定向到用户的登录页面
如果用户已经登录,则拦截器放行,去请求资源数据
代码实现如下所示:

@Component//将对象交给Spring容器管理
public class UserInterceptor implements HandlerInterceptor{
@Autowired
private JedisCluster jedisCluster;
/**
* 说明:如果用户没有登录,应该重定向到用户的登录页面
* 如果用户已经登录,则拦截器放行,去请求资源数据
*
* 如何确定用户已经登录?
* 1.确定浏览器中的cookie是否有JT_TICKET的值
* 2.根据用户的ticket信息去判断redis中是否有值
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler)
throws Exception {
//1.判断浏览器中的cookies中是否有记录
Cookie[] cookies = request.getCookies();
String ticket=null;
//2.判断cookies对象是否为null ,以及数组的长度是否为0
if(cookies !=null && cookies.length>0) {
//遍历数组
for (Cookie cookie : cookies) {
//获取名称为JT_TICKET的cookie
if("JT_TICKET".equals(cookie.getName())) {
ticket=cookie.getValue();
break;
}
}
}
//3.校验ticket信息是否有效,并基于ticket去redis中查询数据是否有效
if(!StringUtils.isEmpty(ticket)) {
if(jedisCluster.exists(ticket)) {
//redis存在该数据,就直接放行请求
return true;//表示放行
}
}
//登录的url:http://www.jt.com/user/login.html
response.sendRedirect("/user/login.html");
return false;//表示拦截
}
}

第六步:测试
依次启动jt-sso,jt-cart和jt-web,然后开始访问
访问方式为:在不登录的情况下测试是否可以访问购物车。
在登录的情况下测试是否可以访问购物车。

优化user对象传递方式
说明:我们在jt-cart项目中关于购物车列表数据的新增,删除,查询以及修改的业务中,为了保证操作购
物车只操作某一个用户的购物数据,所以需要在业务中指定userId,但是之前我们是写死的,现在我们
需要动态获取当前登录的用户的id。
如何实现?
1.可以使用Request域实现user数据的传递(在当次请求有效)
2.可以使用Session域实现user数据的传递(在当前会话有效)

第一步:user对象传递方式一(request域)
01.编辑自定义拦截器UserInterceptor。代码实现如下:

@Component //将对象的创建权利和管理权利都交给Spring容器
public class UserInterceptor implements HandlerInterceptor{
@Autowired
private JedisCluster jedisCluster;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler)
throws Exception {
//1.从浏览器中获取cookie
Cookie[] cookies = request.getCookies();
//2.判断cookies对象是否为null,以及数组的长度是否为0
String ticket=null;
if(cookies!=null && cookies.length>0) {
//遍历cookies数组
for (Cookie cookie : cookies) {
//获取名称为JT_TICKET的cookie
if("JT_TICKET".equals(cookie.getName())) {
//获取对应cookie的值(uuid)ticket
ticket=cookie.getValue();//null
break;
}
}
}
//3.校验ticket信息是否存在,并且基于ticket到redis查询是否有效
if(!StringUtils.isEmpty(ticket)) {
//到redis中基于ticket去判断是否存在该数据
if(jedisCluster.exists(ticket)) {
//redis k=uuid(ticket):v(userJSON)
String userJSON = jedisCluster.get(ticket);
//将json转换成User对象
User user=ObjectMapperUtil.toObject(userJSON, User.class);
/*
* 现在需要将用户信息user传递给jt-web中的CartController,该如何传递?
* 解决方式:request域。在当次请求有效
*/
request.setAttribute("JT_USER", user);
//表示redis中存在该数据,直接放行
return true;
}
}
//登录的url:http://www.jt.com/user/login.html
response.sendRedirect("/user/login.html");
//true表示拦截放行
//false表示拦截
return false;
}
}

02.修改CartController类
说明:通过request域获取user数据,具体代码修改如下代码所示:

@Controller
public class CartController {
@Reference(timeout = 5000,check = false)
private DubboCartService cartService;
/**
* 需求:删除购物车列表数据
* url:/cart/delete/${cart.itemId}.html
* 参数:itemId
* 返回值:重定向到购物车列表页面
*/
@RequestMapping("/cart/delete/{itemId}")
public String deleteCart(@PathVariable Long itemId,HttpServletRequest
request) {
User user=(User)request.getAttribute("JT_USER");
Long userId=user.getId();
//根据itemId和userId删除购物车数据
Cart cart=new Cart();
cart.setUserId(userId).setItemId(itemId);
cartService.deleteCart(cart);
return "redirect:/cart/show.html";
}
/**
* 需求:当用户将某一个商品点击“加入购物车”,需要将该商品添加到购物车中
* (1)如果用户对于该商品进行第一次新增,则需要新增购物车数据
* (2)如果用户不是第一次新增,则只需要做购物车数量修改
* url:http://www.jt.com/cart/add/562379.html
* 参数:Cart cart
* 返回值:重定向购物的列表页面
*/
@RequestMapping("/cart/add/{itemId}")
public String saveCart(Cart cart,HttpServletRequest request) {
//业务的实现
User user=(User)request.getAttribute("JT_USER");
Long userId=user.getId();
cart.setUserId(userId);
cartService.saveCart(cart);
return "redirect:/cart/show.html";
}
/**
* 需求:当用户修改商品数量时,需要发起ajax请求,实现商品数量修改
* 如何修改?
* url:http://www.jt.com/cart/update/num/562379/11
* 基于商品的itemId修改商品的数量
* 参数:itemId,num
* 返回值:SysResult对象
* 如何准确修改某一个用户的某一条商品的数量?通过userId和ItemId共同确定要修改的购物车数量
*/
@RequestMapping("/cart/update/num/{itemId}/{num}")
@ResponseBody
public SysResult updateCartNum(Cart cart,HttpServletRequest request) {
User user=(User)request.getAttribute("JT_USER");
Long userId=user.getId();
cart.setUserId(userId);
cartService.updateNum(cart);
return SysResult.success();
}
/*
* 需求:当用户点击“去购物车结算”,实现购物车页面的跳转
* url:http://www.jt.com/cart/show.html
* 参数:没有
* 返回值:页面的名称 cart.jsp
* 购物车列表数据的展现:应该根据userId动态的查询购物车记录,然后实现购物列表数据的展示
* 页面数据取值:${cartList}利用的el表达式动态获取购物车列表信息的展示
*/
@RequestMapping("/cart/show")
public String showCart(Model model,HttpServletRequest request) {
User user=(User)request.getAttribute("JT_USER");
Long userId=user.getId();
List<Cart> cartList=cartService.findCartListByUserId(userId);
model.addAttribute("cartList", cartList);
return "cart";
}
}

第二步:user对象传递方式二(session域)
01.编辑自定义拦截器UserInterceptor。代码实现如下:

@Component //将对象的创建权利和管理权利都交给Spring容器
public class UserInterceptor implements HandlerInterceptor{
@Autowired
private JedisCluster jedisCluster;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler)
throws Exception {
//1.从浏览器中获取cookie
Cookie[] cookies = request.getCookies();
//2.判断cookies对象是否为null,以及数组的长度是否为0
String ticket=null;
if(cookies!=null && cookies.length>0) {
//遍历cookies数组
for (Cookie cookie : cookies) {
//获取名称为JT_TICKET的cookie
if("JT_TICKET".equals(cookie.getName())) {
//获取对应cookie的值(uuid)ticket
ticket=cookie.getValue();//null
break;
}
}
}
//3.校验ticket信息是否存在,并且基于ticket到redis查询是否有效
if(!StringUtils.isEmpty(ticket)) {
//到redis中基于ticket去判断是否存在该数据
if(jedisCluster.exists(ticket)) {
//redis k=uuid(ticket):v(userJSON)
String userJSON = jedisCluster.get(ticket);
//将json转换成User对象
User user=ObjectMapperUtil.toObject(userJSON, User.class);
/*
* 现在需要将用户信息user传递给jt-web中的CartController,该如何传递?
* 解决方式:session域。在当前会话有效
*/
request.getSession().setAttribute("JT_USER", user);
//表示redis中存在该数据,直接放行
return true;
}
}
//登录的url:http://www.jt.com/user/login.html
response.sendRedirect("/user/login.html");
//true表示拦截放行
//false表示拦截
return false;
}
}

02.修改CartController类
说明:通过session域获取user数据,具体代码修改如下代码所示:

@Controller
public class CartController {
@Reference(timeout = 5000,check = false)
private DubboCartService cartService;
/**
* 需求:删除购物车列表数据
* url:/cart/delete/${cart.itemId}.html
* 参数:itemId
* 返回值:重定向到购物车列表页面
*/
@RequestMapping("/cart/delete/{itemId}")
public String deleteCart(@PathVariable Long itemId,HttpServletRequest
request) {
HttpSession session = request.getSession();
User user = (User)session.getAttribute("JT_USER");
Long userId=user.getId();
//根据itemId和userId删除购物车数据
Cart cart=new Cart();
cart.setUserId(userId).setItemId(itemId);
cartService.deleteCart(cart);
return "redirect:/cart/show.html";
}
/**
* 需求:当用户将某一个商品点击“加入购物车”,需要将该商品添加到购物车中
* (1)如果用户对于该商品进行第一次新增,则需要新增购物车数据
* (2)如果用户不是第一次新增,则只需要做购物车数量修改
* url:http://www.jt.com/cart/add/562379.html
* 参数:Cart cart
* 返回值:重定向购物的列表页面
*/
@RequestMapping("/cart/add/{itemId}")
public String saveCart(Cart cart,HttpServletRequest request) {
//业务的实现
HttpSession session = request.getSession();
User user = (User)session.getAttribute("JT_USER");
Long userId=user.getId();
cart.setUserId(userId);
cartService.saveCart(cart);
return "redirect:/cart/show.html";
}
/**
* 需求:当用户修改商品数量时,需要发起ajax请求,实现商品数量修改
* 如何修改?
* url:http://www.jt.com/cart/update/num/562379/11
* 基于商品的itemId修改商品的数量
* 参数:itemId,num
* 返回值:SysResult对象
* 如何准确修改某一个用户的某一条商品的数量?通过userId和ItemId共同确定要修改的购物车数量
*/
@RequestMapping("/cart/update/num/{itemId}/{num}")
@ResponseBody
public SysResult updateCartNum(Cart cart,HttpServletRequest request) {
HttpSession session = request.getSession();
User user = (User)session.getAttribute("JT_USER");
Long userId=user.getId();
cart.setUserId(userId);
cartService.updateNum(cart);
return SysResult.success();
}
/*
* 需求:当用户点击“去购物车结算”,实现购物车页面的跳转
* url:http://www.jt.com/cart/show.html
* 参数:没有
* 返回值:页面的名称 cart.jsp
* 购物车列表数据的展现:应该根据userId动态的查询购物车记录,然后实现购物列表数据的展示
* 页面数据取值:${cartList}利用的el表达式动态获取购物车列表信息的展示
*/
@RequestMapping("/cart/show")
public String showCart(Model model,HttpServletRequest request) {
HttpSession session = request.getSession();
User user = (User)session.getAttribute("JT_USER");
Long userId=user.getId();
List<Cart> cartList=cartService.findCartListByUserId(userId);
model.addAttribute("cartList", cartList);
return "cart";
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/633365.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

支撑臂爬楼履带车实现爬楼梯功能

1. 功能说明 本文示例将实现R018a支撑臂爬楼履带车爬楼梯的功能。 2. 结构说明 支撑臂爬楼履带车主要是由 小型平行履带底盘 和2个 舵机关节模组 组成。 3. 电子硬件 在这个示例中&#xff0c;我们采用了以下硬件&#xff0c;请大家参考&#xff1a; 主控板 Basra主控板&#…

MIT 6.S081 (BOOK-RISCV-REV1)教材第二章内容

MIT 6.S081 第二章内容 引言操作系统架构抽象系统资源用户态&#xff0c;核心态&#xff0c;以及系统调用内核组织代码&#xff08;XV6架构篇&#xff09;进程概述代码&#xff08;启动XV6和第一个进程&#xff09;真实世界 引言 MIT 6.S081 2020 操作系统 本文为MIT 6.S081课…

用饭店来形象比喻线程池的工作原理

一、线程池解决的问题&#xff1f; 使用线程池主要解决在程序中频繁创建和销毁线程导致的资源浪费&#xff0c;线程池可以维护一定量的线程来执行所需要的任务&#xff0c;维护的线程也可以重复使用。 二、用形象的饭店来解释工作原理 线程池就相当于一家饭店&#xff0c; 任…

SpringBoot框架的学生宿舍管理系统

项目介绍 主要功能&#xff1a; 管理员登录权限&#xff1a; ①学生管理&#xff1a;根据编号姓名搜索、可以新增修改删除、导入导出 ②楼宇管理&#xff1a;根据楼宇搜索、可以新增修改删除、导入导出 ③宿舍管理&#xff1a;根据宿舍编号搜索、可以新增修改删除、导入导出 ④…

HCIA-RS实验-配置FTP 业务

FTP简单说明 FTP&#xff08;File Transfer Protocol&#xff09;是一种用于文件传输的协议&#xff0c;可以在计算机之间进行文件的上传和下载。FTP使用客户端-服务器模型&#xff0c;客户端通过FTP客户端软件连接到服务器端的FTP服务端口&#xff0c;进行文件传输和管理。 F…

在fpga上开发音视频是一种什么体验?

前言&#xff1a; 今天周末回公司解决了解码播放问题&#xff0c;最近周末也没啥事情&#xff0c;一般周六都会过去公司学习音视频开源项目(过去公司&#xff0c;主要是住的近&#xff0c;所以很方便&#xff01;)&#xff0c;待在家里也是无聊&#xff0c;所以就回去看开源项目…

硬件设计电源系列文章-LDO设计

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 本文主要分享LDO的相关设计&#xff0c;尤其是LDO的并联设计 整体架构流程 提示&#xff1a;这里可以添加技术整体架构 主要是讲述LDO的并联&#xff1b;并联以增加输出驱动能力&#xff0c;其具体框架如下&#x…

详解Ribbon

目录 1.概述 2.使用 2.1.引入 2.2.启用 2.3.切换负载均衡算法 3.负载均衡源码分析 3.1.接口 3.2.抽象类 3.3.选择服务器 3.4.原子性 4.自定义负载均衡算法 1.概述 Ribbon是Netflix开源的一个客户端负载均衡库&#xff0c;也是Spring Cloud Netflix项目的核心组件之…

常见网络服务器并发模型

近些年&#xff0c;随着互联网的大发展&#xff0c;高并发服务器技术也快速进步&#xff0c;从简单的循环服务器模型处理少量网络并发请求&#xff0c;演进到解决C10K&#xff0c;C10M问题的高并发服务器模型。本文主要以TCP为例&#xff0c;总结了几种常见的网络服务器模型的实…

巧用文件批量改名高手删除子文件夹一例

比如有很多商品文件夹&#xff0c;里面又分出主图、细节图等&#xff0c;现在因工作需要把主图、细节图这些子文件夹去掉&#xff0c;把子文件夹里面的文件放在商品名称的父文件夹中&#xff0c;如图&#xff1a; 打开主图文件夹&#xff0c;我们可以看到文件名结构为数字编号的…

Git学习 - 2023-06-08

2023暑期学习 Git基础Git Fetch VS Git Pullgit pull --rebase VS git pull几种merge的方法Fork VS Clone CS Branch如何把master的内容更新到分支上详尽介绍 git fetch VS git pull其他命令 Git基础 git branch branch-name # 创建一个新的分支git checkout branch-name # 切…

Golang | Web开发之Gin框架快速入门基础实践

欢迎关注「全栈工程师修炼指南」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; 专注 企业运维实践、网络安全、系统运维、应用开发、物联网实战、全栈文章 等知识分享 “ 花开堪折直须折&#xf…

Learning C++ No.30 【lambda表达式实战】

引言&#xff1a; 北京时间&#xff1a;2023/6/9/9:13&#xff0c;今天8:15起床&#xff0c;可能是最近课非常少&#xff0c;导致写博客没什么压力&#xff0c;什么时间都能写&#xff0c;导致7点起不来&#xff0c;哈哈哈&#xff0c;习惯睡懒觉了&#xff0c;但是问题不大&a…

【二十七】springboot之通过threadLocal+参数解析器实现同session一样保存当前登录信息的功能

springboot篇章整体栏目&#xff1a; 【一】springboot整合swagger&#xff08;超详细 【二】springboot整合swagger&#xff08;自定义&#xff09;&#xff08;超详细&#xff09; 【三】springboot整合token&#xff08;超详细&#xff09; 【四】springboot整合mybatis…

绿豆影视系统5.1.8反编译版源码:PC+WAP+APP端【附搭建教程+软件】

简介&#xff1a; 绿豆影视系统5.1.8反编译版源码&#xff1a;PCWAPAPP端【附搭建教程软件】 优化内容 1.专题类目&#xff0c;在后台进行设置 2.短视频类目 &#xff0c;需要有信天翁id 3.优化首页栏目不显示问题 4.去除我的页面 不常用功能 5.修复自定义密码只能输入数字的…

二阳竟然是这样的~

今天周六&#xff0c;家人都出去玩了&#xff0c;把我自己扔家里了&#xff0c;因为我2阳了&#xff0c;出门都不带我玩了。 正好趁这个时间简单写下2阳的症状&#xff0c;和1阳有什么不一样。 先说结论&#xff1a; 我的亲身感受是2阳比1阳轻的多&#xff0c;没有浑身关节疼&a…

MySQL-索引详解(三)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️树高千尺&#xff0c;落叶归根人生不易&…

第64篇:史上最严重的APT供应链攻击事件,借助Solarwinds攻击欧美的流程图梳理和分析(上篇)...

Part1 前言 大家好&#xff0c;我是ABC_123&#xff0c;公众号正式更名为”希潭实验室”&#xff0c;敬请关注。本期分享一个堪称史上影响最大、危害最大的供应链攻击APT案例——Solarwinds供应链攻击事件&#xff0c;SolarWinds的旗下有数万家客户公司&#xff0c;包括了”财…

h.264 h.265 协议基本概念记录

区分一些概念 MPEG-4 是一套用于音频、视频信息的压缩编码标准H.264&#xff0c;AVC&#xff0c;编码格式&#xff0c;是MPEG-4 的第10部分H.265&#xff0c;HEVC&#xff0c;编码格式&#xff0c;是MPEG-H的第2部分mp4&#xff0c;rmvb&#xff0c;mkv&#xff0c;avi是容器&…

【ChatGPT】数据科学 ChatGPT Cheat Sheet 书籍分享(阿里云盘下载)

封皮 以下为书中部分内容的机器翻译 我们的重要提示指南 1. 以 AI 角色的描述开始提示。 例如&#xff0c;“你是{x}”或“我希望你扮演{x}”。如果您不确定&#xff0c;请尝试“你是一个有帮助的助手”。 例如&#xff0c;您是 OpenAI 的数据科学家&#xff0c;您正在研究大型…