Day429.订单服务 -谷粒商城
Posted 阿昌喜欢吃黄桃
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day429.订单服务 -谷粒商城相关的知识,希望对你有一定的参考价值。
订单服务
一、环境搭建
- 因为我们做的是
动静分离
,将静态资源上传到nginx上
- 配置本地域名:
C:\\Windows\\System32\\drivers\\etc\\hosts
- 配置服务网关:
achangmall-gateway/src/main/resources/application.yml
- id: order_route
uri: lb://achangmall-order
predicates:
- Host=order.achangmall.com
- 修改静态页面的地址,例如:↓
- 引入thymeleaf依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 写一个测试的页面跳转的controller
com.achang.achangmall.order.web.HelloController
@Controller
public class HelloController {
@GetMapping("/{page}.html")
public String listPage(@PathVariable("page")String page){
return page;
}
}
- 关闭thymeleaf缓存
spring:
thymeleaf:
cache: false
- 启动订单服务、nginx、网关服务、nacos服务测试
依次
访问order.achangmall.com/confirm/detail/list/pay
.html,例如:↓
http://order.achangmall.com/confirm.html
二、整合SpringSession
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
- 配置文件
spring:
session:
store-type: redis
redis:
host: 192.168.109.101
port: 6379
achangmall:
thread:
core-size: 20
max-size: 200
keep-alive-time: 20
- 配置类
com.achang.achangmall.order.conf.AchangmallSessionConfig
@Configuration
public class AchangmallSessionConfig {
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
//放大作用域
cookieSerializer.setDomainName("achangmall.com");
cookieSerializer.setCookieName("ACHANGSESSION");
return cookieSerializer;
}
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
//使用json存储redis,而不是默认的序列化存储
return new GenericJackson2JsonRedisSerializer();
}
}
com.achang.achangmall.order.conf.ThreadPoolConfig
@Configuration
public class ThreadPoolConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
pool.getCoreSize(),
pool.getMaxSize(),
pool.getKeepAliveTime(),
TimeUnit.SECONDS, new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
return threadPoolExecutor;
}
}
com.achang.achangmall.order.conf.ThreadPoolConfigProperties
@Component
@ConfigurationProperties(prefix = "achangmall.thread")
@Data
public class ThreadPoolConfigProperties {
private Integer coreSize;
private Integer MaxSize;
private Integer keepAliveTime;
}
- 启动类
@EnableRedisHttpSession
、@EnableFeignClients
三、订单基本介绍
1、简介
电商系统涉及到 3 流,分别是信息流
、资金流
、物流
,而订单系统作为中枢将三者有机的集合起来。
订单模块是电商系统的枢纽,在订单这个环节上需求获取多个模块的数据和信息,同时对这些信息进行加工处理后流向下个环节,这一系列就构成了订单的信息流通。
2、订单构成
3、订单状态
- 待付款
- 已付款/ 待发货
- 待收货/ 已发货
- 已完成
- 已取消
- 售后中
4、订单流程
四、编码
1、订单登录拦截
- com.achang.achangmall.order.conf.OrderWebConfig
@Configuration
public class OrderWebConfig implements WebMvcConfigurer {
@Autowired
private LoginUserInterceptor loginUserInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginUserInterceptor).addPathPatterns("/**");
}
}
- com.achang.achangmall.order.interceptor.LoginUserInterceptor
//用户登录拦截器
@Component
public class LoginUserInterceptor implements HandlerInterceptor {
public static ThreadLocal<MemberResponseVo> loginUser = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
MemberResponseVo user = (MemberResponseVo) session.getAttribute(AuthServerConstant.LOGIN_USER);
if (user!=null){
//登录了
loginUser.set(user);
return true;
}else {
//没登录
session.setAttribute("msg","请先登录");
response.sendRedirect("http://auth.achangmall.com/login.html");
return false;
}
}
}
2、订单确认页
- com.achang.achangmall.order.vo.OrderConfirmVo
订单确认页vo
//订单确认页vo
public class OrderConfirmVo {
@Getter @Setter
/** 会员收获地址列表 **/
List<MemberAddressVo> memberAddressVos;
@Getter @Setter
/** 所有选中的购物项 **/
List<OrderItemVo> items;
/** 发票记录 **/
@Getter @Setter
/** 优惠券(会员积分) **/
private Integer integration;
/** 防止重复提交的令牌 **/
@Getter @Setter
private String orderToken;
@Getter @Setter
Map<Long,Boolean> stocks;
public Integer getCount() {
Integer count = 0;
if (items != null && items.size() > 0) {
for (OrderItemVo item : items) {
count += item.getCount();
}
}
return count;
}
/** 订单总额 **/
//BigDecimal total;
//计算订单总额
public BigDecimal getTotal() {
BigDecimal totalNum = BigDecimal.ZERO;
if (items != null && items.size() > 0) {
for (OrderItemVo item : items) {
//计算当前商品的总价格
BigDecimal itemPrice = item.getPrice().multiply(new BigDecimal(item.getCount().toString()));
//再计算全部商品的总价格
totalNum = totalNum.add(itemPrice);
}
}
return totalNum;
}
/** 应付价格 **/
//BigDecimal payPrice;
public BigDecimal getPayPrice() {
return getTotal();
}
}
- com.achang.achangmall.order.vo.MemberAddressVo
@Data
public class MemberAddressVo {
private Long id;
/**
* member_id
*/
private Long memberId;
/**
* 收货人姓名
*/
private String name;
/**
* 电话
*/
private String phone;
/**
* 邮政编码
*/
private String postCode;
/**
* 省份/直辖市
*/
private String province;
/**
* 城市
*/
private String city;
/**
* 区
*/
private String region;
/**
* 详细地址(街道)
*/
private String detailAddress;
/**
* 省市区代码
*/
private String areacode;
/**
* 是否默认
*/
private Integer defaultStatus;
}
- com.achang.achangmall.order.vo.OrderItemVo
@Data
public class OrderItemVo {
private Long skuId;
private Boolean check;
private String title;
private String image;
/**
* 商品套餐属性
*/
private List<String> skuAttrValues;
private BigDecimal price;
private Integer count;
private BigDecimal totalPrice;
/** 商品重量 **/
private BigDecimal weight = new BigDecimal("0.085");
}
- com.achang.achangmall.order.web.OrderWebController
@Controller
public class OrderWebController {
@Autowired
private OrderService orderService;
@GetMapping("/toTrade.html")
public String toTrade(Model model){
OrderConfirmVo vo = orderService.confirmOrder();
model.addAttribute("orderConfirmData",vo);
return "confirm";
}
}
- com.achang.achangmall.order.feign.MemberFeignService
远程调用用户模块获取数据
@FeignClient("achangmall-member")
public interface MemberFeignService {
/**
* 查询当前用户的全部收货地址
*/
@GetMapping(value = "/member/memberreceiveaddress/{memberId}/address")
List<MemberAddressVo> getAddress(@PathVariable("memberId") Long memberId);
}
- com.achang.achangmall.member.controller.MemberReceiveAddressController
@RestController
@RequestMapping("member/memberreceiveaddress")
public class MemberReceiveAddressController {
@Autowired
private MemberReceiveAddressService memberReceiveAddressService;
@GetMapping("/{memberId}/address")
public List<MemberReceiveAddressEntity> getAddress(@PathVariable("memberId") Long memberId){
List<MemberReceiveAddressEntity> list = memberReceiveAddressService.getAddress(memberId);
return list;
}
}
- com.achang.achangmall.member.service.impl.MemberReceiveAddressServiceImpl
@Service("memberReceiveAddressService")
public class MemberReceiveAddressServiceImpl extends ServiceImpl<MemberReceiveAddressDao, MemberReceiveAddressEntity> implements MemberReceiveAddressService {
@Override
public List<MemberReceiveAddressEntity> getAddress(Long memberId) {
List<MemberReceiveAddressEntity> list = this.list(new QueryWrapper<MemberReceiveAddressEntity>().eq("member_id", memberId));
return list;
}
}
- com.achang.achangmall.order.feign.CartFeignService
@FeignClient("achangmall-cart")
public interface CartFeignService {
/**
* 查询当前用户购物车选中的商品项
* @return
*/
@GetMapping(value = "/currentUserCartItems")
List<OrderItemVo> getCurrentCartItems();
}
@Controller
public class CartController {
@Resource
private CartService cartService;
/**
* 获取当前用户的购物车商品项
*/
@GetMapping(value = "/currentUserCartItems")
@ResponseBody
public List<CartItemVo> getCurrentCartItems() {
List<CartItemVo> cartItemVoList = cartService.getUserCartItems();
return cartItemVoList;
}
}
- com.achang.achangmall.cart.service.impl.CartServiceImpl
@Override
public List<CartItemVo> getUserCartItems() {
List<CartItemVo> cartItemVoList = new ArrayList<>();
//获取当前用户登录的信息
UserInfoTo userInfoTo = CartIntercept.toThreadLocal.get();
//如果用户未登录直接返回null
if (userInfoTo.getUserId() == null) {
return null;
} else {
//获取购物车项
String cartKey = CART_PREFIX + userInfoTo.getUserId();
//获取所有的
List<CartItemVo> cartItems = getCartItems(cartKey);
if (cartItems == null) {
throw new CartExceptionHandler();
}
//筛选出选中的
cartItemVoList = cartItems.stream()
.filter(items -> items.getCheck())
.map(item -> {
//更新为最新的价格(查询数据库)
BigDecimal price = productFeignService.getPrice(item.getSkuId());
item.setPrice(price);
return item;
})
.collect(Collectors.toList());
}
return cartItemVoList;
}
- com.achang.achangmall.cart.feign.ProductFeignService
@FeignClient("achangmall-product")
public interface ProductFeignService {
/**
* 根据skuId查询当前商品的最新价格
* @param skuId
* @return
*/
@GetMapping(value = "/product/skuinfo/{skuId}/price")
BigDecimal getPrice(@PathVariable("skuId") Long skuId);
}
- com.achang.achangmall.product.app.SpuInfoController
@RestController
@RequestMapping("product/spuinfo")
public class SpuInfoController {
@Autowired
private SkuInfoService skuInfoService;
/**
* 根据skuId查询当前商品的价格
*/
@GetMapping(value = "/{skuId}/price")
public BigDecimal getPrice(@PathVariable("skuId") Long skuId) {
//获取当前商品的信息
SkuInfoEntity skuInfo = skuInfoService.getById(skuId);
//获取商品的价格
BigDecimal price = skuInfo.getPrice();
return price;
}
}
- com.achang.achangmall.order.service.impl.OrderServiceImpl
@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
@Autowired
private MemberFeignService memberFeignService;
@Autowired
private CartFeignService cartFeignService;
@Override
public OrderConfirmVo confirmOrder() {
OrderConfirmVo vo = new OrderConfirmVo();
MemberResponseVo user = LoginUserInterceptor.loginUser.get();
//远程获取 对应用户收货地址
List<MemberAddressVo> address = memberFeignServi以上是关于Day429.订单服务 -谷粒商城的主要内容,如果未能解决你的问题,请参考以下文章
Java SSM 项目实战 day03 功能介绍,订单的操作,订单的增删改查
Java SSM 项目实战 day04 功能介绍,订单的操作,订单的增删改查,实现登录功能