一.订单系统介绍和搭建
订单系统负责确认订单, 订单生成, 订单管理(我的订单, 物流信息, …). 独立系统, war工程. 需要使用的技术Spring+SpringMVC+Dubbo, 订单系统要求必须先登录才能访问, 需要提供拦截器进行登录状态的校验. 可以使用HttpClient远程调用百战-sso系统进行登录状态的校验.
二.进入订单结算页面
1.页面分析
baizhan-cart系统中的cart.jsp
baizhan-order系统中的order-cart.jsp
2.修改js脚本
cart.jsp页面
<script type="text/javascript">
$(function() {
// 全选复选框绑定事件
$('.jdcheckbox').click(function() {
var flag = this.checked;
$(':checkbox').each(function(i, e) {
e.checked = flag;
});
// 刷新总价格
BZCart.refreshTotalPrice();
});
// 每个商品前的复选框绑定事件
$('.checkbox').click(function() {
var f = true;
$('.checkbox').each(function(i, e) {
if(!e.checked) {
f = false;
return false;
}
});
$('.jdcheckbox').each(function(i, e) {
e.checked = f;
});
// 刷新总价格
BZCart.refreshTotalPrice();
});
// 给去结算按钮绑定事件
$('#toSettlement').click(function() {
var f = false;
$('.checkbox').each(function(i, e) {
if(e.checked) {
f = true;
return false;
}
});
if(!f) {
alert('至少要选择一个商品进行结算!');
return;
}
// 提交表单
$('#fmOrderCart').submit();
});
});
</script>
cart.js的刷新总价格方法
refreshTotalPrice : function(){ //重新计算总价
var total = 0;
var totalNum = 0;
$(".quantity-form .quantity-text").each(function(i,e){
var _this = $(e);
// 获取当前遍历项的复选框
var ck = _this.parent().parent().parent().find("input[type=checkbox]");
// 如果选中, 则运算
if(ck.get(0).checked) {
total += (eval(_this.attr("itemPrice")) * 10000 * eval(_this.val())) / 10000;
totalNum += eval(_this.val());
}
});
$(".totalSkuPrice").html(new Number(total/100).toFixed(2)).priceFormat({ //价格格式化插件
prefix: '¥',
thousandsSeparator: ',',
centsLimit: 2
});
$('#selectedCount').html(totalNum);
}
3.控制器
@Controller
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
/**
* 进入订单结算页面
*
* @param checkItem
* @param model
* @param req
* @return
*/
@RequestMapping("/order-cart")
public String orderCart(String[] checkItem, Model model, HttpServletRequest req) {
Collection<Map<String, Object>> cartList = orderService.cartList(checkItem, req);
model.addAttribute("cartList", cartList);
return "order-cart";
}
}
4.服务代码
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private RedisDao redisDao;
@Value("${cart_cookie_name}")
private String cartCookieName;
@Value("${cart_redis_key_pre}")
private String pre;
@Value("${cart_redis_key_post}")
private String post;
@Override
public Collection<Map<String, Object>> cartList(String[] checkItem, HttpServletRequest req) {
// 从cookie获取购物车的key
String cartKey = CookieUtil.getCookieValue(req, cartCookieName);
// 校验
if(StringUtils.isBlank(cartKey) || !cartKey.startsWith(pre) || !cartKey.endsWith(post)) {
return new ArrayList<>();
}
// 查询redis获取购物车
String jsonStr = redisDao.get(cartKey);
// 校验
if(StringUtils.isBlank(jsonStr)) {
return new ArrayList<>();
}
// 转换
Object o = JsonUtil.jsonToPojo(jsonStr, Object.class);
// 校验
if(o == null) {
return new ArrayList<>();
}
// 获取购物车
Map<String, Map<String, Object>> cart = (Map<String, Map<String, Object>>) o;
// 从购物车中获取要结算的商品
List<Map<String, Object>> list = new ArrayList<>();
for (String key : checkItem) {
list.add(cart.get(key));
}
// 返回结果
return list;
}
}
三.登录拦截器
@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Value("${user_cookie_name}")
private String userCookieName;
@Value("${sso_login_url}")
private String loginUrl;
@Value("${sso_check_login_url}")
private String checkLoginUrl;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从cookie中获取登录令牌
String userKey = CookieUtil.getCookieValue(request, userCookieName);
// 校验
if(StringUtils.isBlank(userKey)) {
// 跳转到登录页面
response.sendRedirect(loginUrl);
return false;
}
// 远程调用sso系统获取结果
String jsonStr = HttpClientUtil.doGet(checkLoginUrl + userKey);
// 校验
if(StringUtils.isBlank(jsonStr)) {
// 跳转到登录页面
response.sendRedirect(loginUrl);
return false;
}
// 转换
RpcResult result = JsonUtil.jsonToPojo(jsonStr, RpcResult.class);
// 校验
if(result == null || result.getStatus() != 200) {
// 跳转到登录页面
response.sendRedirect(loginUrl);
return false;
}
// 放行
return true;
}
}
<!--配置登录拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**"/>
<ref bean="loginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
四.提交订单
1.页面分析
order-cart.jsp
success.jsp
2.控制器
/**
* 生成订单
*
* @param order 订单相关的所有数据
* @param model 请求作用域
* @param req cookie操作使用
* @return
*/
@PostMapping("/create")
public String createOrder(BaizhanOrder order, Model model, HttpServletRequest req) {
try {
Map<String, String> result = orderService.createOrder(order, req);
model.addAllAttributes(result);
return "success";
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("message", "服务器忙!");
return "error/exception";
}
}
2.控制器
/**
* 生成订单
*
* @param order 订单相关的所有数据
* @param model 请求作用域
* @param req cookie操作使用
* @return
*/
@PostMapping("/create")
public String createOrder(BaizhanOrder order, Model model, HttpServletRequest req) {
try {
Map<String, String> result = orderService.createOrder(order, req);
model.addAllAttributes(result);
return "success";
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("message", "服务器忙!");
return "error/exception";
}
}
4.RPC代码
@Service
public class RpcOrderServiceImpl implements RpcOrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private OrderShippingMapper orderShippingMapper;
@Override
@Transactional
public RpcResult<?> createOrder(BaizhanOrder order) {
// 添加订单数据
int orderRows = orderMapper.insert(order);
// 校验
if(orderRows != 1) {
throw new RuntimeException("订单创建失败!");
}
// 添加订单物流信息
int shippingRows = orderShippingMapper.insert(order.getOrderShipping());
// 校验
if(shippingRows != 1) {
throw new RuntimeException("订单创建失败!");
}
// 添加订单项信息
for (OrderItem item : order.getOrderItems()) {
int rows = orderItemMapper.insert(item);
if(rows != 1) {
throw new RuntimeException("订单创建失败!");
}
}
return RpcResult.ok();
}
}