jwt+springcloud+springboot+thymeleaf(购物车业务)

在这里插入图片描述
1 添加购物车接口开发
1.1Feign接口声明

在这里插入图片描述
1). 定义Feign远程 调用的接口
@FeignClient(name = “goods”)
public interface SkuFeign {
@GetMapping("/sku/spu/{spuId}")
public List findSkuListBySpuId(@PathVariable(“spuId”) String spuId);

@GetMapping("/sku/{id}")
public Result<Sku> findById(@PathVariable("id") String id);

}

2). 订单微服务中开启Feign调用开关
@EnableFeignClients(basePackages = {“com.changgou.goods.feign”})

1.2 Service层逻辑
1). Redis数据结构
数据结构: Hash
cart_Tom 100001 OrderItem
100002 OrderItem

2). 加入购物车逻辑
A. 查询redis中的购物车数据
B. 判定redis中是否包含当前添加的sku信息 , 如果已经存在, 更新数量, 计算总金额
C. 如果不存在, 将当前商品组装成购物车对象 , 加入Redis

3). 代码实现
public void addCart(String skuId, Integer num, String username) {
//1.查询redis中相对应的商品信息
OrderItem orderItem = (OrderItem) redisTemplate.boundHashOps(CART+username).get(skuId);
if (orderItem != null){
//2.如果当前商品在redis中的存在,则更新商品的数量与价钱
orderItem.setNum(orderItem.getNum()+num);

    orderItem.setMoney(orderItem.getNum()*orderItem.getPrice());
    orderItem.setPayMoney(orderItem.getNum()*orderItem.getPrice());
}else {
    //3.如果当前商品在redis中不存在,将商品添加到redis中
    Sku sku = skuFeign.findById(skuId).getData();
    Spu spu = spuFeign.findSpuById(sku.getSpuId()).getData();

    //封装orderItem
   orderItem = this.sku2OrderItem(sku,spu,num);
}

//3.将orderitem添加到redis中
redisTemplate.boundHashOps(CART+username).put(skuId,orderItem);

}

1.3 Controller 层逻辑
@GetMapping("/addCart")
public Result addCart(@RequestParam(“skuId”) String skuId, @RequestParam(“num”) Integer num){
//动态获取当前人信息,暂时静态
String username = “itcast”;
cartService.addCart(skuId,num,username);
return new Result(true, StatusCode.OK,“加入购物车成功”);
}

2 购物车列表查询接口
1). Service
A. 查询当前用户对应的redis中购物车列表数据 ;
B. 计算购物车中商品总数量, 总金额 ;

@Override
public Map list(String username) {
Map map = new HashMap();
/*
A. 查询当前用户对应的redis中购物车列表数据 ;
B. 计算购物车中商品总数量, 总金额 ;
*/
// 根据用户名查询所对应的value
List orderItemList = redisTemplate.boundHashOps(CART + username).values();
// 1.使用map封装redis中的购物车列表数据
map.put(“orderItemList”,orderItemList);
// 2.定义变量接受商品的总数量。以及总金额
Integer totalMoney = 0;
Integer totalNum = 0;
if (orderItemList != null){
for (OrderItem orderItem : orderItemList) {
totalMoney += orderItem.getMoney();
totalNum += orderItem.getNum();
}
map.put(“totalMoney”,totalMoney);
map.put(“totalNum”,totalNum);
}
return map;
}

2). Controller
@GetMapping("/list")
public Map list(){
//动态获取当前人信息,暂时静态
String username = “itcast”;
Map map = cartService.list(username);
return map;
}

  1. 购物车渲染
    3.1 实现思路

在这里插入图片描述
3.2 购物车渲染服务搭建
1). pom.xml


com.changgou
changgou_service_order_api
1.0-SNAPSHOT


com.changgou
changgou_common
1.0-SNAPSHOT


org.springframework.boot
spring-boot-starter-thymeleaf

2). application.yml
server:
port: 9011
spring:
application:
name: order-web
main:
allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
thymeleaf:
cache: false
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:6868/eureka
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
client:
config:
default: #配置全局的feign的调用超时时间 如果 有指定的服务配置 默认的配置不会生效
connectTimeout: 60000 # 指定的是 消费者 连接服务提供者的连接超时时间 是否能连接 单位是毫秒
readTimeout: 80000 # 指定的是调用服务提供者的 服务 的超时时间() 单位是毫秒
#hystrix 配置
hystrix:
command:
default:
execution:
timeout:
#如果enabled设置为false,则请求超时交给ribbon控制
enabled: true
isolation:
strategy: SEMAPHORE
thread:
# 熔断器超时时间,默认:1000/毫秒
timeoutInMilliseconds: 80000
#请求处理的超时时间
ribbon:
ReadTimeout: 4000
#请求连接的超时时间
ConnectTimeout: 3000

3). 引导类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {“com.changgou.order.feign”})
public class WebOrderApplication {

public static void main(String[] args) {
    SpringApplication.run(WebOrderApplication.class,args);
}

}

3.3 Feign接口定义
@FeignClient(name = “order”)
public interface CartFeign {

@GetMapping("/cart/addCart")
public Result addCart(@RequestParam("skuId") String skuId, @RequestParam("num") Integer num);

@GetMapping("/cart/list")
public Map list();

}

3.4 Controller层
@Controller
@RequestMapping("/wcart")
public class CartController {

@Autowired
private CartFeign cartFeign;

//查询
@GetMapping("/list")
public String list(Model model){
    Map map = cartFeign.list();
    model.addAttribute("items",map);
    return "cart";
}

//添加
@GetMapping("/add")
@ResponseBody
public Result<Map> add(String id,Integer num){
    cartFeign.addCart(id,num);
    Map map = cartFeign.list();
    return new Result<>(true, StatusCode.OK,"添加购物车成功",map);
}

}

3.5 购物车列表页面渲染
1). 需要在服务网关中增加路由配置
#购物车订单渲染微服务
- id: changgou_order_web_route
uri: lb://order-web
predicates:
- Path=/api/wcart/,/api/worder/
filters:
- StripPrefix=1

2). 遍历展示数据

TIP :
th:inline —> 内联JavaScript , 如果需要在js中获取Thymeleaf数据模型中的数据, 需要加该属性 ;
3). 页面遍历展示数据

  • {{item.name}}
  • {{item.price}}

4). + - 事件绑定
在这里插入图片描述

  • 5). 后台处理
    在这里插入图片描述
    4.购物车渲染
    4.1 订单微服务接入认证
    1). pom.xml

    org.springframework.cloud
    spring-cloud-starter-oauth2

    2). 引入公钥 public.key
    3). 引入配置 ResourceServerConfig
    4.2 微服务之间的认证
    1). 当前问题

    在这里插入图片描述
    2). 解决方案
    通过Feign拦截器, 在通过Feign进行远程调用时, 对请求增加头信息, 让头信息 Authorization 继续往下传递 ;
    3). 代码实现
    A. 在Common中定义FeignInterceptor
    @Component
    public class FeignInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
    // 传递令牌
    // 1.获取request请求
    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    if (requestAttributes != null){
    HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
    // 2.获取所有的请求头
    if (request != null){
    Enumeration headerNames = request.getHeaderNames();
    // 3.遍历所有的请求头名称
    while (headerNames.hasMoreElements()){
    String headerName = headerNames.nextElement();
    // 4.判断如果有Authorization 的请求头,则传递令牌
    if (“authorization”.equals(headerName)){
    String headerValue = request.getHeader(headerName);
    requestTemplate.header(headerName,headerValue);
    }
    }
    }
    }
    }
    }

    B. 在Feign远程调用发起微服务中声明该Bean
    @Bean
    public FeignInterceptor feignInterceptor(){
    return new FeignInterceptor();
    }

    4.3 动态获取当前登录用户
    1). common引入依赖

    io.jsonwebtoken
    jjwt
    0.9.0
    provided

    2). common依赖工具类
    public class TokenDecode {
    //公钥
    private static final String PUBLIC_KEY = “public.key”;

    private static String publickey="";
    
    /***
     * 获取用户信息
     * @return
     */
    public Map<String,String> getUserInfo(){
        //获取授权信息
        OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails();
        //令牌解码
        return dcodeToken(details.getTokenValue());
    }
    
    /***
     * 读取令牌数据
     */
    public Map<String,String> dcodeToken(String token){
        //校验Jwt
        Jwt jwt = JwtHelper.decodeAndVerify(token, new RsaVerifier(getPubKey()));
    
        //获取Jwt原始内容
        String claims = jwt.getClaims();
        return JSON.parseObject(claims,Map.class);
    }
    
    
    /**
     * 获取非对称加密公钥 Key
     * @return 公钥 Key
     */
    public String getPubKey() {
        if(!StringUtils.isEmpty(publickey)){
            return publickey;
        }
        Resource resource = new ClassPathResource(PUBLIC_KEY);
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
            BufferedReader br = new BufferedReader(inputStreamReader);
            publickey = br.lines().collect(Collectors.joining("\n"));
            return publickey;
        } catch (IOException ioe) {
            return null;
        }
    }
    

    }

    核心 : 读写公钥内容, 解析jwt令牌 ;
    3). 需要获取当前登录用户微服务中配置
    @Bean
    public TokenDecode tokenDecode(){
    return new TokenDecode();
    }

    4). 获取登录用户
    String username = tokenDecode.getUserInfo().get(“username”);

    4.4 页面跳转设置
    1). 需求
    A. 如果用户没有登录, 访问业务系统, 直接跳转登录页面 ;
    B. 从哪儿来到哪儿去 ;

    2). 流程
    在这里插入图片描述

    3). 代码实现
    A. 服务网关中进行改造
    在这里插入图片描述
    在这里插入图片描述

    B. 认证微服务 /oauth/toLogin改造
    在这里插入图片描述

    C. login.html登录成功的回调函数中改造

    在这里插入图片描述

    发布了120 篇原创文章 · 获赞 9 · 访问量 7349

    猜你喜欢

    转载自blog.csdn.net/weixin_44993313/article/details/104584130
    今日推荐