谷粒商城项目(学习笔记十五)

第十二章:订单服务

一、RabbitMQ环境的搭建

1)、安装RabbitMQ

docker run -d --name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 rabbitmq:management

2)、访问15672端口登录后台管理界面

默认的用户名和密码都是guest

3)、为order订单访问引入RabbitMQ服务

1.引入依赖

        
            org.springframework.boot
            spring-boot-starter-amqp
        

2.配置环境

spring:
  rabbitmq:
    host: 自己的地址
    port: 5672
    virtual-host: /
    publisher-confirm-type: correlated
    publisher-returns: true
    template:
      mandatory: true
    listener:
      simple:
        acknowledge-mode: manual

3.添加@EnableRabbit注解

二、订单模块的前端整合

和前面一样,这里省略

三、整合spring session

使登录信息同步

1)、引入session的依赖

        
        
            org.springframework.boot
            spring-boot-starter-data-redis
            
                
                    io.lettuce
                    lettuce-core
                
            
        
        
            redis.clients
            jedis
        
        
            org.springframework.session
            spring-session-data-redis
        

2)、引入session配置和线程池配置

谷粒商城项目(学习笔记十五)_第1张图片

spring.session.store-type=redis
gulimall.thread.core-size=20
gulimall.thread.max-size=200
gulimall.thread.keep-alive-time=10

spring.redis.host=101.43.79.94

 3)、开启注解

@EnableRedisHttpSession

四、配置拦截器

1)、拦截order项目所有请求

@Configuration
public class OrderWebConfiguration implements WebMvcConfigurer {


    @Autowired
    LoginUserInterceptor interceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(interceptor).addPathPatterns("/**");
    }
}

2)、设置拦截没登录的请求

@Component
public class LoginUserInterceptor implements HandlerInterceptor {


    public static ThreadLocal loginUser = new ThreadLocal<>();
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //  /order/order/status/2948294820984028420
        String uri = request.getRequestURI();
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        boolean match = antPathMatcher.match("/order/order/status/**", uri);
        boolean match1 = antPathMatcher.match("/payed/notify", uri);
        if(match || match1){
            return true;
        }


        MemberRespVo attribute = (MemberRespVo) request.getSession().getAttribute(AuthServerConstant.LOGIN_USER);
        if(attribute!=null){
            loginUser.set(attribute);
            return true;
        }else {
            //没登录就去登录
            request.getSession().setAttribute("msg","请先进行登录");
            response.sendRedirect("http://auth.gulimall.com/login.html");
            return false;
        }

    }
}

五、确认订单业务

1)、封装vo

//订单确认页需要用的数据
public class OrderConfirmVo {

     收货地址,ums_member_receive_address表
    @Setter @Getter
    List address;


    //所有选中的购物项
    @Setter @Getter
    List items;

    //发票记录....

    //优惠券信息...
    @Setter @Getter
    Integer integration;

    @Setter @Getter
    Map stocks;


    //防重令牌
    @Setter @Getter
    String orderToken;

    public Integer getCount(){
        Integer i = 0 ;
        if(items!=null){
            for (OrderItemVo item : items) {
                i+=item.getCount();
            }
        }
        return i;
    }

//    BigDecimal total;//订单总额

    public BigDecimal getTotal() {
        BigDecimal sum = new BigDecimal("0");
        if(items!=null){
            for (OrderItemVo item : items) {
                BigDecimal multiply = item.getPrice().multiply(new BigDecimal(item.getCount().toString()));
                sum = sum.add(multiply);
            }
        }

        return sum;
    }

//    BigDecimal payPrice;

    public BigDecimal getPayPrice() {
       return  getTotal();
    }

    //应付价格

}

2)、获取member的收货地址

    @GetMapping("/{memeberId}/addresses")
    public List getAddress(@PathVariable("memeberId") Long memberId){
        return memberReceiveAddressService.getAddress(memberId);
    }

3)、获取购物项

    @GetMapping("/currentUserCartItems")
    @ResponseBody
    public List getCurrentUserCartItems(){

        return cartService.getUserCartItems();
    }

4)、查询用户积分

        //3、查询用户积分
        Integer integration = memberRespVo.getIntegration();
        confirmVo.setIntegration(integration);

5)、请求头问题

feign远程调用丢失请求头问题:

远程调用新创建的请求会丢失cookie等请求头,需要为其添加请求头

@Configuration
public class GuliFeignConfig {

    @Bean("requestInterceptor")
    public RequestInterceptor requestInterceptor(){
        return new RequestInterceptor(){
            @Override
            public void apply(RequestTemplate template) {
                //1、RequestContextHolder拿到刚进来的这个请求
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                if(attributes!=null){
                    System.out.println("RequestInterceptor线程...."+Thread.currentThread().getId());
                    HttpServletRequest request = attributes.getRequest(); //老请求
                    if(request != null){
                        //同步请求头数据,Cookie
                        String cookie = request.getHeader("Cookie");
                        //给新请求同步了老请求的cookie
                        template.header("Cookie",cookie);
                    }
                }
            }
        };
    }
}

6)、异步编排

CompletableFuture getAddressFuture = CompletableFuture.runAsync(() -> {
            //1、远程查询所有的收货地址列表
            System.out.println("member线程...." + Thread.currentThread().getId());
            //每一个线程都来共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List address = memberFeignService.getAddress(memberRespVo.getId());
            confirmVo.setAddress(address);
        }, executor);

7)、查询库存

        CompletableFuture cartFuture = CompletableFuture.runAsync(() -> {
            //2、远程查询购物车所有选中的购物项
            System.out.println("cart线程...." + Thread.currentThread().getId());
            //每一个线程都来共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List items = cartFeignService.getCurrentUserCartItems();
            confirmVo.setItems(items);
            //feign在远程调用之前要构造请求,调用很多的拦截器
            //RequestInterceptor interceptor : requestInterceptors
        }, executor).thenRunAsync(() -> {
            List items = confirmVo.getItems();
            List collect = items.stream().map(item -> item.getSkuId()).collect(Collectors.toList());

            //TODO 一定要启动库存服务,否则库存查不出。
            R hasStock = wmsFeignService.getSkusHasStock(collect);
            List

你可能感兴趣的:(谷粒商城项目,rabbitmq,分布式,中间件)