【学习日记2023.5.30】之 管理端订单模块完善_调用百度地图优化用户端提交订单是否超出配送距离

9. 管理端订单模块完善

  • 订单搜索
  • 各个状态的订单数量统计
  • 查询订单详情
  • 接单
  • 拒单
  • 取消订单
  • 派送订单
  • 完成订单

9.1 需求分析和涉及

接口设计

1)订单搜索
请添加图片描述

2)各个状态的订单数量统计
请添加图片描述

3)查询订单详情
请添加图片描述

4)接单
请添加图片描述

5)拒单
请添加图片描述

6)取消订单
请添加图片描述

7)派送订单
请添加图片描述

8)完成订单
请添加图片描述

9.2 代码开发

Controller层
package com.sky.controller.admin;

import com.sky.dto.OrdersCancelDTO;
import com.sky.dto.OrdersConfirmDTO;
import com.sky.dto.OrdersPageQueryDTO;
import com.sky.dto.OrdersRejectionDTO;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.OrderService;
import com.sky.vo.*;
import com.sky.enumeration.CallType;
import com.sky.vo.OrderStatisticsVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequestMapping("/admin/order")
@Api(tags = "商家端订单接口")
public class OrderController {
    @Autowired
    private OrderService orderService;
    
    /**
     * 订单搜索
     * @param ordersPageQueryDTO
     * @return
     */
    @GetMapping("/conditionSearch")
    @ApiOperation("订单搜索")
    public Result<PageResult> historyOrders(OrdersPageQueryDTO ordersPageQueryDTO){
        PageResult pageResult= orderService.historyOrders(ordersPageQueryDTO, CallType.ADMIN);
        log.info("查询到了{}条数据",pageResult.getTotal());
        return Result.success(pageResult);
    }

    /**
     * 订单数量统计
     * @return
     */
    @GetMapping("/statistics")
    @ApiOperation("各个状态的订单数量统计")
    public Result<OrderStatisticsVO> getNumByStatistics(){
        log.info("各个状态的订单数量统计:");
        OrderStatisticsVO orderStatisticsVO = orderService.getNumByStatistics();
        return Result.success(orderStatisticsVO);
    }
    
    /**
     * 查看订单详情
     * @param id
     * @return
     */
    @ApiOperation("查询订单详情")
    @GetMapping("/details/{id}")
    public Result<OrderAndDetailVO> queryDetailById(@PathVariable Long id){
        log.info("订单id为:{}",id);
        OrderAndDetailVO orderAndDetailVO = orderService.getByOrderId(id);
        return Result.success(orderAndDetailVO);
    }

    /**
     * 接单
     * @param ordersConfirmDTO
     * @return
     */
    @ApiOperation("接单")
    @PutMapping("/confirm")
    public Result confirm(@RequestBody OrdersConfirmDTO ordersConfirmDTO){
        log.info("接单数据为:{}",ordersConfirmDTO);
        orderService.confirm(ordersConfirmDTO);
        return Result.success();
    }

    /**
     * 拒绝接单
     * @param ordersRejectionDTO
     * @return
     */
    @PutMapping("/rejection")
    @ApiOperation("拒绝接单")
    public Result<String> rejection(@RequestBody OrdersRejectionDTO ordersRejectionDTO){
        orderService.rejection(ordersRejectionDTO);
        log.info("拒绝接单接口执行");
        return Result.success();
    }

    /**
     * 取消订单
     *
     * @return
     */
    @PutMapping("/cancel")
    @ApiOperation("取消订单")
    public Result cancel(@RequestBody OrdersCancelDTO ordersCancelDTO) {
        orderService.cancel(ordersCancelDTO);
        return Result.success();
    }
    
    /**
     * 派送订单
     * @param id
     * @return
     */
    @PutMapping("/delivery/{id}")
    @ApiOperation("派送订单")
    public Result delivery(@PathVariable long id){
        log.info("派送订单:{}",id);
        orderService.delivery(id);
        return Result.success();
    }

    /**
     * 完成订单
     * @param id
     * @return
     */
    @PutMapping("/complete/{id}")
    @ApiOperation("完成订单")
    public Result complete(@PathVariable long id){
        log.info("完成订单:{}",id);
        orderService.complete(id);
        return Result.success();
    }

}
Service层接口
/**
 * 历史订单查询 or 管理端订单搜索(已完成)
 * @param ordersPageQueryDTO
 * @return
 */
PageResult historyOrders(OrdersPageQueryDTO ordersPageQueryDTO,CallType callType);

/**
 * 订单数量统计
 * @return
 */
OrderStatisticsVO getNumByStatistics();

/**
 * 查询订单详情
 * @param orderId
 * @return
 */
OrderAndDetailVO getByOrderId(Long orderId);

/**
 * 接单
 * @param ordersConfirmDTO
 */
void confirm(OrdersConfirmDTO ordersConfirmDTO);


/**
 * 拒单
 * @param ordersRejectionDTO
 */
void rejection(OrdersRejectionDTO ordersRejectionDTO);

/**
 * 用户取消订单
 * @param id
 */
void userCancelById(Long id);

/**
 * 派送订单
 * @param id
 */
void delivery(long id);

/**
 * 完成订单
 * @param id
 */
void complete(long id);
Service层实现类
/**
 * 历史订单查询 or 管理端订单搜索(已完成)
 *
 * @param ordersPageQueryDTO
 * @return
 */
@Override
public PageResult historyOrders(OrdersPageQueryDTO ordersPageQueryDTO,CallType callType) {
    //开启分页插件
    PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());

    //如果是用户端就加入userid查询
    if (callType==CallType.USER){
        ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());
    }

    //查询出所有订单数据
    Page<Orders> page = orderMapper.getByOrders(ordersPageQueryDTO);
    //判断是否查询到数据
    if (page == null) {
        throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
    }

    //遍历每个订单,取出其中每个明细表并封装为OrderAndDetailVO
    List<OrderAndDetailVO> orderAndDetailVOS = new ArrayList<>();
    for (Orders order : page) {
        Long id = order.getId();
        //获取订单中对应的多条明细数据
       List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(id);
       //临时创建一个orderAndDetailVO用于封装订单和明细数据
       OrderAndDetailVO orderAndDetailVO=new OrderAndDetailVO();
       BeanUtils.copyProperties(order,orderAndDetailVO);

       orderAndDetailVO.setOrderDetailList(orderDetails);
       //封装完成的orderAndDetailVO再添加到集合中
       orderAndDetailVOS.add(orderAndDetailVO);
    }
    PageResult pageResult=new PageResult();
    pageResult.setTotal(page.getTotal());
    pageResult.setRecords(orderAndDetailVOS);

    return pageResult;
}

/**
 * 订单数量统计
 * @return
 */
@Override
public OrderStatisticsVO getNumByStatistics() {
    OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
    orderStatisticsVO.setToBeConfirmed(orderMapper.getNumByStatistics(Orders.TO_BE_CONFIRMED));
    orderStatisticsVO.setConfirmed(orderMapper.getNumByStatistics(Orders.CONFIRMED));
    orderStatisticsVO.setDeliveryInProgress(orderMapper.getNumByStatistics(Orders.DELIVERY_IN_PROGRESS));
    return orderStatisticsVO;
}

/**
 * 查询订单详情(已完成,与用户端查询订单同一个接口)
 * @param orderId
 * @return
 */
@Override
public OrderAndDetailVO getByOrderId(Long orderId) {
    Orders order  = orderMapper.getByOrdersId(orderId);
    List<OrderDetail> list = orderDetailMapper.getByOrderId(order.getId());
    OrderAndDetailVO orderAndDetailVO = new OrderAndDetailVO();
    //将order信息存入订单及订单详情里
    BeanUtils.copyProperties(order,orderAndDetailVO);
    orderAndDetailVO.setOrderDetailList(list);
    return orderAndDetailVO;
}

/**
 * 管理端接单
 * @param ordersConfirmDTO
 */
@Override
public void confirm(OrdersConfirmDTO ordersConfirmDTO) {
    //判断订单是否支付完成
    if (isPay(ordersConfirmDTO.getId(),OrderStatusType.CONFIRMED))
        orderMapper.update(Orders.builder().id(ordersConfirmDTO.getId()).status(ordersConfirmDTO.getStatus()==null?Orders.CONFIRMED:ordersConfirmDTO.getStatus()).build());
}

/**
 * 判断是否支付
 * @param id
 * @param orderStatusType
 * @return
 */
private boolean isPay(Long id, OrderStatusType orderStatusType){
    switch (orderStatusType){
        case TO_BE_CONFIRMED://待接单
        case CONFIRMED://接单
            //判断订单是否支付完成
            Orders orders = orderMapper.getByOrdersId(id);
            if (orders.getPayStatus() != Orders.PAID){
                throw new OrderBusinessException(MessageConstant.ORDER_PAYSTATUS_ERROR);
            }
    }
    return true;
}

/**
 * 拒绝接单
 * @param ordersRejectionDTO
 */
@Override
public void rejection(OrdersRejectionDTO ordersRejectionDTO) {
//根据订单id查询到订单状态
    Orders orders = orderMapper.getByOrdersId(ordersRejectionDTO.getId());

    if (orders.getStatus()==Orders.TO_BE_CONFIRMED){

        //如果已经支付,需要先退款
        Integer payStatus = orders.getPayStatus();
        if (payStatus==1){
            //调用微信支付退款接口
            try {
                weChatPayUtil.refund(
                        orders.getNumber(), //商户订单号
                        orders.getNumber(), //商户退款单号
                        new BigDecimal(0.01),//退款金额,单位 元
                        new BigDecimal(0.01));//原订单金额
            } catch (Exception e) {
                e.printStackTrace();
                throw new OrderBusinessException(MessageConstant.ORDER_REFUND_ERROR);
            }
        }

        Orders build = Orders.builder()
                .id(ordersRejectionDTO.getId())
                .status(Orders.CANCELLED)
                .payStatus(Orders.REFUND)//支付状态修改为 退款
                .rejectionReason(ordersRejectionDTO.getRejectionReason())
                .build();
        orderMapper.update(build);
    }
}


/**
 * 取消订单(已完成,与用户端取消订单同一个接口)
 * @param ordersCancelDTO
 */
@Override
public void cancel(OrdersCancelDTO ordersCancelDTO) throws Exception {

    //根据id查询订单
    Orders orders = orderMapper.getByOrdersId(ordersCancelDTO.getId());
    //如果已经支付,需要先退款
        Integer payStatus = orders.getPayStatus();
        if (payStatus==1){
            //调用微信支付退款接口
            try {
                weChatPayUtil.refund(
                        orders.getNumber(), //商户订单号
                        orders.getNumber(), //商户退款单号
                        new BigDecimal(0.01),//退款金额,单位 元
                        new BigDecimal(0.01));//原订单金额
            } catch (Exception e) {
                e.printStackTrace();
                throw new OrderBusinessException(MessageConstant.ORDER_REFUND_ERROR);
            }
            //支付状态修改为 退款
            orders.setPayStatus(Orders.REFUND);
        }
    //修改订单状态:
    //取消时间
    orders.setCancelTime(LocalDateTime.now());
    //前端传入的取消原因
    orders.setCancelReason(ordersCancelDTO.getCancelReason());
    //修改订单状态至取消
    orders.setStatus(Orders.CANCELLED);
    //更新订单数据
    orderMapper.update(orders);
}

/**
 * 派送订单
 * @param id
 */
@Override
public void delivery(long id) {
    if(orderMapper.getorders(id).getStatus() == Orders.CONFIRMED){
        orderMapper.update(Orders.builder().status(Orders.DELIVERY_IN_PROGRESS).id(id).build());
    }else{
        throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
    }
}

/**
 * 完成订单
 * @param id
 */
@Override
public void complete(long id) {
    if(orderMapper.getorders(id).getStatus() == Orders.DELIVERY_IN_PROGRESS){
        orderMapper.update(Orders.builder().status(Orders.DELIVERY_IN_PROGRESS).id(id).build());
    }else{
        throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
    }
}
Mapper层

OrderMapper.java

/**
 * 根据条件查询一个/多个订单(已完成)
 * @param ordersPageQueryDTO
 * @return
 */
Page<Orders> getByOrders(OrdersPageQueryDTO ordersPageQueryDTO);

/**
 * 订单数量统计
 * @param status
 * @return
 */
@Select("select count(*) from orders where status =#{status}")
Integer getNumByStatistics(Integer status);

/**
 * 根据id查询一个订单数据
 */
@Select("select * from orders where id=#{id}")
Orders getByOrdersId(Long id);

/**
 * 修改订单信息(已完成)
 * @param orders
 */
void update(Orders orders);

OrderDetailMapper.java

/**
 * 根据id查询订单数据(已完成)
 * @param id
 * @return
 */
@Select("select * from order_detail where order_id=#{id}")
List<OrderDetail> getByOrderId(Long id);

OrderMapper.xml

<!--根据条件查询一个/多个订单-->
<select id="getByOrders" resultType="com.sky.entity.Orders">
    select * from orders
   <where>
      <if test="status != null">
         and status=#{status}
      </if>
      <if test="number != null">
         and number like concat('%',#{number},'%')
      </if>
      <if test="phone != null">
         and phone like concat('%',#{phone},'%')
      </if>
      <if test="beginTime != null and endTime !=null">
         and order_time between #{beginTime} and #{endTime}
      </if>
   </where>
      order by order_time desc
</select>
<!--根据条件更新订单-->
<update id="update">
	update orders
	<set>
		<if test="cancelReason != null and cancelReason!='' ">
			cancel_reason=#{cancelReason},
		</if>
		<if test="rejectionReason != null and rejectionReason!='' ">
			rejection_reason=#{rejectionReason},
		</if>
		<if test="cancelTime != null">
			cancel_time=#{cancelTime},
		</if>
		<if test="payStatus != null">
			pay_status=#{payStatus},
		</if>
		<if test="payMethod != null">
			pay_method=#{payMethod},
		</if>
		<if test="checkoutTime != null">
			checkout_time=#{checkoutTime},
		</if>
		<if test="status != null">
			status = #{status},
		</if>
		<if test="deliveryTime != null">
			delivery_time = #{deliveryTime}
		</if>
	</set>
	where id = #{id}
</update>

9.3 功能测试

前后端联调

订单搜索
请添加图片描述
请添加图片描述
请添加图片描述

各个状态的订单数量统计
请添加图片描述

查询订单详情
请添加图片描述

接单
请添加图片描述
请添加图片描述

拒单
请添加图片描述

取消订单
请添加图片描述
请添加图片描述

派送订单
请添加图片描述
请添加图片描述

完成订单
请添加图片描述
请添加图片描述

9.4 提交代码

commit—>describe—>push

9.5 优化用户下单功能,引入距离判断

优化用户下单功能,加入校验逻辑,如果用户的收货地址距离商家门店超出配送范围(配送范围为5公里内),则下单失败。

提示:

​ 1. 基于百度地图开放平台实现(https://lbsyun.baidu.com/)

​ 2. 注册账号—>创建应用获取AK(服务端应用)—>调用接口

  1. 相关接口

    https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding

    https://lbsyun.baidu.com/index.php?title=webapi/directionlite-v1

  2. 商家门店地址可以配置在配置文件中,例如:

    sky:
      shop:
        address: 北京市海淀区上地十街10号
    

application-dev.yml

sky:
  baiduopenmap:
    ak: AewmQZZPsxQhcwGZe5mYUOwKt4iy4Yxj
    ret-coordtype: gcj02ll #gcj02ll(国测局坐标)、bd09mc(百度墨卡托坐标)
    output: json #json或xml
    geocoding-url: https://api.map.baidu.com/geocoding/v3/ #地理编码请求地址
    path-planning-url: https://api.map.baidu.com/directionlite/v1/driving #轻量级路线规划请求地址
    delivery-area: 5000 #配送范围(米)
    business-address: 重庆市沙坪坝区西永大道二期xxxxxx #商家地址

application.yml

sky:
  baiduopenmap:
    ak: ${sky.baiduopenmap.ak}
    ret-coordtype: ${sky.baiduopenmap.ret-coordtype}
    output: ${sky.baiduopenmap.output}
    geocoding-url: ${sky.baiduopenmap.geocoding-url}
    path-planning-url: ${sky.baiduopenmap.path-planning-url}
    delivery-area: ${sky.baiduopenmap.delivery-area}
    business-address: ${sky.baiduopenmap.business-address}

创建BaiduOpenMapProperties类,使用ConfigurationProperties注解注入配置文件中对应的值到数据中

package com.sky.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @Auther: Yishooo
 * @Date: 2023-5-28 - 05 - 28 - 21:56
 * @Description:
 */
@Component
@ConfigurationProperties(prefix = "sky.baiduopenmap")
@Data
public class BaiduOpenMapProperties {
    private String ak; //申请注册的key,自v2开始参数修改为“ak”
    private String retCoordtype; //返回国测局经纬度坐标或百度米制坐标
    private String output; //输出格式为json或者xml
    private String geocodingUrl; //地理编码请求地址
    private String pathPlanningUrl;//轻量级路线规划请求地址
    private Integer deliveryArea;//配送范围(米),行车路径
    private String businessAddress;//商家地址
}

创建BaiduOpenMapUtils类,完善获取坐标和判断距离两个方法(注意:百度开放地图接口调用距离地址经纬度的值为反的,传入值为【纬度,经度】)

package com.sky.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Auther: Yishooo
 * @Date: 2023-5-28 - 05 - 28 - 22:10
 * @Description:
 */
@Data
@AllArgsConstructor
@Slf4j
public class BaiduOpenMapUtils {

    private String ak; //申请注册的key,自v2开始参数修改为“ak”
    private String retCoordtype; //返回国测局经纬度坐标或百度米制坐标
    private String output; //输出格式为json或者xml
    private String geocodingUrl; //地理编码请求地址
    private String pathPlanningUrl;//轻量级路线规划请求地址
    private Integer deliveryArea;//配送范围(米),行车路径
    private String businessAddress;//商家地址

    public boolean IsOutOfRange(String origin) {
        //载入商家坐标
        String destination = getLocation(businessAddress);
        Integer distance = null;
        Map<String,String> map = new HashMap<>();
        map.put("origin",origin);
        map.put("destination",destination);
        map.put("ak",ak);
        String body = HttpClientUtil.doGet(pathPlanningUrl,map);
        log.info("返回路径地址:{}",body);
        JSONObject jsonObject = JSON.parseObject(body);
        Map<String, Object> mapResult = new HashMap<>();
        //查询 返回状态 status 并存入集合
        getKeyMap(jsonObject, "status", mapResult);
        if (Integer.valueOf(mapResult.get("status").toString()) == 0) {
            getKeyMap(jsonObject, "distance", mapResult);
            distance = Integer.parseInt(mapResult.get("distance").toString());
            log.info("商家距离客户:{}米",distance);
        }
        if (distance <= deliveryArea){//小于默认配送返回,则返回false,标识没有超出范围
            return false;
        }
        return true;
    }

    /**
     * 获取经纬度坐标
     * @param address
     * @return  字符串:lat,lng
     * @throws Exception
     */
    public String getLocation(String address) {
        String location = null;
        //封装地址传参路径 map 集合
        Map<String,String> map = new HashMap<>();
        map.put("address",address);
        map.put("output",output);
        map.put("ak",ak);
        map.put("ret_coordtype",retCoordtype);
        //发送请求得到响应返回的json串
        String body = HttpClientUtil.doGet(geocodingUrl, map);
        //将json串转换为json对象
        JSONObject jsonObject = JSON.parseObject(body);
        //定义Map集合保存要返回查询的键值对
        Map<String, Object> mapResult = new HashMap<>();
        //查询 返回状态 status 并存入集合
        getKeyMap(jsonObject, "status", mapResult);
        //如果状态返回为 0(成功) 继续执行后续取值操作
        if (Integer.parseInt(mapResult.get("status").toString()) == 0) {
            getKeyMap(jsonObject, "lng", mapResult);
            getKeyMap(jsonObject, "lat", mapResult);
            //经度
            double lng = ((BigDecimal) mapResult.get("lng")).setScale(6, RoundingMode.HALF_UP).doubleValue();
            //纬度
            double lat = ((BigDecimal) mapResult.get("lat")).setScale(6, RoundingMode.HALF_UP).doubleValue();
            location = lat + "," + lng;
        }
        return location;
    }

    /**
     * 查询json对象类中指定key的值存入传入的map集合,只适用于查询第一次键值,包含多层key相同的只取第一次查到的值
     * @param object json对象
     * @param keyword 要查询关键字
     * @param jsonMap 保存查询的数据
     */
    public void getKeyMap(Object object, String keyword, Map<String, Object> jsonMap){
        //判断传入对象是否属于JSONObject对象
        if (object instanceof JSONObject){
            JSONObject jsonObject = (JSONObject) object;
            //将对象进行遍历迭代,先迭代第一层键值对,符合则存入跳出循环,否则递归遍历直到结束
            Iterator<Map.Entry<String, Object>> iterator = jsonObject.entrySet().iterator();
            while (iterator.hasNext()){
                Map.Entry<String, Object> entry = iterator.next();
                String key = entry.getKey();
                Object value = entry.getValue();
                if (keyword.equals(key)){
                    //存在key为指定key的,判断值为json数组,只取第一个值
                    if (value instanceof JSONArray){
                        JSONArray valueArr = (JSONArray) value;
                        value = valueArr.get(0);
                    }
                    //将查找到的值存入指定map中
                    jsonMap.put(key, value);
                    break;
                }else {
                    //没有采用递归进行第二次键值对查找
                    getKeyMap(value, keyword, jsonMap);
                }
            }
            //是否属于JSONArray对象
        } else if (object instanceof JSONArray){
            JSONArray jsonArray = (JSONArray) object;
            Iterator<Object> iterator = jsonArray.iterator();
            while (iterator.hasNext()){
                Object value = iterator.next();
                getKeyMap(value, keyword, jsonMap);
            }
        }
    }

}

HTTPClientUtil工具类

package com.sky.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Http工具类
 */
public class HttpClientUtil {

    static final  int TIMEOUT_MSEC = 5 * 1000;

    /**
     * 发送GET方式请求
     * @param url
     * @param paramMap
     * @return
     */
    public static String doGet(String url,Map<String,String> paramMap){
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();

        String result = "";
        CloseableHttpResponse response = null;

        try{
            URIBuilder builder = new URIBuilder(url);
            if(paramMap != null){
                for (String key : paramMap.keySet()) {
                    builder.addParameter(key,paramMap.get(key));
                }
            }
            URI uri = builder.build();

            //创建GET请求
            HttpGet httpGet = new HttpGet(uri);

            //发送请求
            response = httpClient.execute(httpGet);

            //判断响应状态
            if(response.getStatusLine().getStatusCode() == 200){
                result = EntityUtils.toString(response.getEntity(),"UTF-8");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                response.close();
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return result;
    }

    /**
     * 发送POST方式请求
     * @param url
     * @param paramMap
     * @return
     * @throws IOException
     */
    public static String doPost(String url, Map<String, String> paramMap) throws IOException {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";

        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);

            // 创建参数列表
            if (paramMap != null) {
                List<NameValuePair> paramList = new ArrayList();
                for (Map.Entry<String, String> param : paramMap.entrySet()) {
                    paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
                httpPost.setEntity(entity);
            }

            httpPost.setConfig(builderRequestConfig());

            // 执行http请求
            response = httpClient.execute(httpPost);

            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }

    /**
     * 发送POST方式请求
     * @param url
     * @param paramMap
     * @return
     * @throws IOException
     */
    public static String doPost4Json(String url, Map<String, String> paramMap) throws IOException {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";

        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);

            if (paramMap != null) {
                //构造json格式数据
                JSONObject jsonObject = new JSONObject();
                for (Map.Entry<String, String> param : paramMap.entrySet()) {
                    jsonObject.put(param.getKey(),param.getValue());
                }
                StringEntity entity = new StringEntity(jsonObject.toString(),"utf-8");
                //设置请求编码
                entity.setContentEncoding("utf-8");
                //设置数据类型
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }

            httpPost.setConfig(builderRequestConfig());

            // 执行http请求
            response = httpClient.execute(httpPost);

            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }
    private static RequestConfig builderRequestConfig() {
        return RequestConfig.custom()
                .setConnectTimeout(TIMEOUT_MSEC)
                .setConnectionRequestTimeout(TIMEOUT_MSEC)
                .setSocketTimeout(TIMEOUT_MSEC).build();
    }

}

创建OpenMapConfiguration配置类,初始化百度开放地图工具类。

package com.sky.config;

import com.sky.properties.BaiduOpenMapProperties;
import com.sky.utils.BaiduOpenMapUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Auther: Yishooo
 * @Date: 2023-5-28 - 05 - 28 - 23:49
 * @Description:
 */
@Slf4j
@Configuration
public class OpenMapConfiguration {

    /**
     * 通过spring管理对象
     * @param baiduOpenMapProperties
     * @return
     */
    @Bean
    @ConditionalOnMissingBean//没有才创建,保证工具类唯一
    public BaiduOpenMapUtils baiduOpenMapUtils(BaiduOpenMapProperties baiduOpenMapProperties){
        log.info("开始创建百度开放地图工具类……");
        return new BaiduOpenMapUtils(baiduOpenMapProperties.getAk()
                ,baiduOpenMapProperties.getRetCoordtype()
                ,baiduOpenMapProperties.getOutput()
                ,baiduOpenMapProperties.getGeocodingUrl()
                ,baiduOpenMapProperties.getPathPlanningUrl()
                ,baiduOpenMapProperties.getDeliveryArea()
                ,baiduOpenMapProperties.getBusinessAddress());
    }
}

优化OrderServiceImpl类中的提交订单部分

/**
 * 用户下单
 * @param ordersSubmitDTO
 * @return
 */
@Override
@Transactional
public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {
    //1.检验提交数据是否异常,增强程序的健壮性
    //1.1 用户地址簿是否为空
    //...代码省略....
    //1.2 用户购物车数据是否为空
    //...代码省略....
    //1.3 校验地址是否超出配送范围
    String userAddress =
            currentAddress.getProvinceName()+currentAddress.getCityName()+currentAddress.getDistrictName()+currentAddress.getDetail();
    String userLocation = null;
    //获取用户地址的经纬度
    userLocation = baiduOpenMapUtils.getLocation(userAddress);
    if (baiduOpenMapUtils.IsOutOfRange(userLocation)){
        throw new OrderBusinessException(MessageConstant.ORDER_OUTOFRANGE_ERROR);
    }

    //...代码省略....
}

前后端联调
请添加图片描述
后台日志如下所示:
请添加图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值