腾讯云位置服务地图
如果未开通,前端会报错
开通腾讯位置服务
①、腾讯官网https://lbs.qq.com
②、进行注册,并登录
③、进入控制台
④、创建应用,应用类型选择出行
⑤、为创建的应用添加key
代码开发
①、配置文件common-account.yaml
②、对应的service-map模块中
@Slf4j
@Tag(name="地图API接口管理")
@RestController
@RequestMapping("/map")
public class MapController{
@Autowired
private MapService mapService;
@Operation(summary = "计算驾驶线路")
@PostMapping("/calculateDrivingLine")
public Result<DrivingLineVo> calculateDrivingLine(@RequestBody CalculateDrivingLineForm calculateDrivingLineForm){
DrivingLineVo drivingLineVo = mapService.calculateDrivingLine(calculateDrivingLineForm);
return Result.ok(drivingLineVo);
}
}
传递的参数类型
public class CalculateDrivingLineForm{
@Schema(description = "起始地点经度")
private BigDecimal startPointLongitude;
@Schema(description = "起始地点纬度")
private BigDecimal startPointLatitude;
@Schema(description = "结束地点经度")
private BigDecimal endPointLongitude;
@Schema(description = "结束地点经度")
private BigDecimal endPointLatitude;
}
返回的结果类型
@Data
public class DrivingLineVo{
@Schema(description = "方案总距离,单位:千米")
private BigDecimal distance;
@Schema(description = "方案估算时间(结合路况),单位:分钟")
private BigDecimal duration;
@Schema(description = "方案路线坐标点串")
private JSONArray polyline
}
service实现类
@Slf4j
@Service
public class MapServiceImpl implements MapService{
@Autowired
private RestTemplate restTemplate;
@Value("${tencent.map.key}")
private String key;
//计算驾驶路线
@Override
public DrivingLineVo calculateDrivingLine(CalculateDrivingLineForm calculateDrivingLineForm){
//请求腾讯提供的接口,按照接口要求传递相关参数,返回需要的结果
//调用第三方的项目,可以通过HttpClient
//也可以通过Spring封装的工具RestTemplate
String url = "https://apis.map.qq.com/ws/direction/v1/driving/?from={from}&to={to}&key={key}";
Map<String,String> map = new HashMap<>();
map.put("from",calcalateDrivingLineForm.getStartPointLatitude()+","+calcalateDrivingLineForm.getStartPointLongitude());
map.put("to",calcalateDrivingLineForm.getEndPointLatitude()+","+calcalateDrivingLineForm.getEndPointLongitude());
map.put("key",key);
JSONObject result = restTemplate.getForObject(url,JSONObject.class,map);
if(result.getIntValue("status")!=0){
throw new GuiguException(ResultCodeEnum.MAP_FAIL);
}
//获取返回路线信息(第一条)
JSONObject route = result.getJSONObject("result").getJSONArray("routes").getJSONObject(0);
//封装到返回对象(封装预估时间和距离、路线)
DrivingLineVo drivingLineVo = new DrivingLineVo();
drivingLineVo.setDuration(route.getBigDecimal("duration"));
drivingLineVo.setDistance(route.getBigDecimal("distance")
.divideToIntEgralValue(new BigDecimal(1000))
.setScale(2,RoundingMode.HALF_UP));//米转换成千米,保留两位小数,向上取值
divingLineVo.setPolyline(route.getJSONArray("polyline"));
return divingLineVo;
}
}
@Configuration
public class MapConfig{
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
规则引擎Drools
入门案例
drools官网地址:https://drools.org
源码下载地址:https://github.com/kiegroup/drools
①、依赖
drools-core drools-compiler drools-decisiontables drools-mvel
②、配置类
@Configuration
public class DroolsConfig{
private static final KieServices kieServices = KieServices.Factory.get();
//指定规则文件的路径
@Bean
public KieContainer kieContainer(){
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
KieModle kieModule = kieBuilder.getKieModule();
KieContainer kieContainer = kieService.newKieContainer(kieModule.getReleaseId());
return kieContainer;
}
}
③、实体类和规则文件
public class Order{
private double amout;//订单金额
private double score;//积分
//省略get set方法
}
规则文件order.drl
//订单积分规则
package com.atguigu.order
import com.atguitu.drools.model.Order
//规则一:100元以下,不加分
rule "order_rule_1"
when
$order:Order(amout < 100)
then
$order.setScore(0);
System.out.println("成功匹配到规则一:100元以下 不加分");
end
//规则二:100元-500元 加100分
rule "order_rule_2"
when
$order:Order(amout >=100 && amout < 100)
then
$order.setScore(100);
System.out.println("成功匹配到规则二:100元-500元 加100分");
end
//规则三:500元-1000元 加500分
rule "order_rule_3"
when
$order:Order(amout >=500 && amout < 1000)
then
$order.setScore(500);
System.out.println("成功匹配到规则三:500元-1000元 加500分");
end
//规则四:1000元以上 加1000分
rule "order_rule_4"
when
$order:Order(amout >= 1000)
then
$order.setScore(1000);
System.out.println("成功匹配到规则四:1000元以上 加1000分");
end
④、应用
@SpringBootTest
public class DroolsDemosApplicationTests{
@Autowired
private KieContainer kieContainer;
@Test
public void test(){
//从kie容器对象中获取会话对象
KieSession session = KieContainer.newKieSession();
//Fact对象,事实对象
Order order = new Order();
order.setAmout(1300);
//将Order对象插入到工作内存中
session.insert(order);
//激活规则,由Drols框架自动进行规则匹配,如果规则匹配成功,执行当前规则
session.fireAllRules();
//关闭会话
session.dispose();
System.out.println("订单金额:"+ order.getAmout() + ",添加积分:" + order.getScore());
}
}
Drools内置方法
update 更新工作内存中的数据,并让相关的规则重新匹配
insert 向工作内存中插入数据,并让相关的规则重新匹配
retract 删除工作内存中的数据,并让规则重新匹配
规则属性
- salience 执行优先级
- no-loop 放置死循环
global全局变量
订单Order
public class Order{
private double amout;//金额
//省略get set方法
}
积分Integral
public class Integral{
private double score;
//省略get set 方法
}
规则文件
package com.order
import com.atguigu.drools.model.Order
global com.atguigu.drools.model.Integral integral; //全局变量
rule "order_rule_1"
no-loop true //防止死循环
when
$order:Order(amout < 100)
then
integral.setScore(10);
update($order);
System.out.println("成功匹配到规则一:100元以下 不加分");
end
测试
@Test
public void test(){
KieSession session = kieContainer.newKieSession();
Order order = new Order();
order.setAmout(30);
//全局变量的设置
Integral integral = new Integral();
session.setGlobal("integral",integral);//"integral"必需与规则文件中的 保持一致
session.insert(order);
session.fireAllRules();
session.dispose();
System.out.println("订单金额"+ order.getAmout() + ",添加积分:" + order.getScore());
}
项目中整合规则引擎实现预估订单功能
①、依赖
drools-core drools-compiler drools-decisiontables drools-mvel
②、Drools配置类
@Slf4j
@Configuration
public class DroolsConfig{
//指定规则文件路径
private static final String RULES_CUSTOMER_RULES_DRL = "rules/FeeRule.drl"
@Bean
public KieContainer kieContainer(){
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));
KieBuilder kb = kieServies.newKieBuilder(keiFileSystem);
kb.buildAll();
KieModule kieModule = kb.getKieModule();
KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());
return kieContainer;
}
}
③、创建规则文件
package com.atguigu.daijia
import com.atguigu.daijia.model.form.rules.FeeRuleRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
global com.atguigu.daijia.model.vo.rules.FeeRuleRsponse feeRuleResponse;
/**
起步价
00:00:00-06:59:59 19元(含3公里)
07:00:00-23:59:59 19元(含5公里)
*/
rule "起步价 00:00:00-06:59:59 19元(含3公里"
salience 10 //指定优先级,数值越大,优先级越高,不指定的情况下由上到下执行
no-loop true //防止陷入死循环
when
/**
$rule是绑定变量名 可以任意命名
到工作内存中查找FeeRuleRequest对象
可以在then部分操作fact对象
*/
$rule:FeeRuleRequest(startTime>= "00:00:00" && startTime <= "06:59:59")
then
feeRuleResponse.setBaseDistance(new BigDecimal("3.0"));
feeRuleResponse.setBaseDistanceFee(new BigDecimal("19.0"));
feeRuleResponse.setExceedDistance(new BigDecimal("0.0"));
feeRuleResponse.setExceedDistancePrice(new BigDecimal("4.0"));
System.out.println("00:00:00-06:59:59" + feeRuleResponse.getBaseDistance() + "公里,起步价:"+ feeRuleResponse.getBaseDistanceFee() + "元");
end
rule "起步价 07:00:00-23:59:59 19元(含5公里)"
salience 10
no-loop true
when
$rule:FeeRuleRequest(startTime >= "07:00:00" && startTime <= "23:59:59")
then
feeRuleResponse.setBaseDistance(new BigDecimal("5.0"));
feeRuleResponse.setBaseDistanceFee(new BigDeciml(19.0));
feeRuleResponse.setExceedDistance(new BigDecimal("0.0"));
feeRuleResponse.setExceedDistancePrice(new BigDecimal("3.0"));
System.out.println("07:00:00-23:59:59" + feeRuleResponse.getBaseDistance() + "公里,起步价:")
end
rule ""
when
then
end
rule ""
when
then
end
输入对象
@Data
public class FeeRuleRequest{
@Schema(description="代驾里程")
private BigDecimal distance;
@Schema(description="代驾时间")
private String startTime;
@Schema(description="等候分钟")
private Integer waitMinute;
}
输出对象
@Data
public class FeeRuleResponse{
@Schema(description="总金额")
private BigDecimal totalAmount;
@Schema(description="里程费")
private BigDecimal distanceFee;
@Schema(description="等时费用")
private BigDecimal waitFee;
@Schema(description="远程费")
private BigDecimal longDistanceFee;
@Schema(description="基础里程(公里)")
private BigDecimal baseDistance;
@Schema(description="超出基础里程的里程(公里)")
//.......
}
④、预估订单金额接口
@Slf4j
@RestController
@RequestMapping("/rules/fee")
public class FeeRuleController{
@Autowired
private FeeRuleService feeRuleService;
@Operation(summary="计算订单费用")
@PostMapping("/calculateOrderFee")
public Rest<FeeRuleResponseVo> calculateOrderFee(@RequestBody FeeRuleRequestForm calculateOrderFeeForm){
return Result.ok(feeRuleService.calculateOrderFee(calculateOrderFeeForm));
}
}
实现类方法
@Autowired
private KieContainer kieContainer;
@Override
public FeeRuleResponseVo calculateOrderFee(FeeRuleRequestForm feeRuleRequestForm){
//封装输入对象
FeeRuleRequest feeRuleRequest = new FeeRuleRequest();
feeRuleRequest.setDistance(calculateOrderFeeForm.getDistance());
Date startTime = calculateOrderFeeForm.getStartTime();
feeRuleRequest.setStartTime(new DateTime(startTime).toString("HH:mm:ss"));
feeRuleRequest.setWaitMinute(calculateOrderFeeForm.getWaitMinute());
//Drools使用
KieSession keiSession = kieContainner.newKieSession();
//封装返回对象
FeeRuleResponse feeRuleResponse = new FeeRuleResponse();
kieSession.setGlobal("feeRuleResponse",feeRuleResponse);//操作规则文件中全局
kieSession.insert(feeRuleRequest);
kieSession.fireAllRules();
kieSession.dispose();
//封装数据FeeRuleResponseVo返回
FeeRuleResponseVo feeRuleResponseVo = new FeeRuleResponseVo();
BeanUtils.copyProperties(feeRuleResponse,feeRuleResponseVo);
return feeRuleResponseVo;
}
⑤、定义远程调用接口
@PostMapping("/rules/fee/calculateOrderFee")
Result<FeeRuleResponseVo> calcalateOrderFee(@RequestBody FeeRuleRequestForm calculateOrderFeeForm);
⑥、乘客调用web
@Autowired
private OrderService orderService
@Operation(summary="预估订单数据")
@GuiguLogin
@PostMapping()
public Result<ExpectOrderVo> expectOrder(@RequestBody ExpectOrderForm expectOrderForm){
return Reusslt.ok(orderService.expectOrder(expectOrderForm));
}
@Autowired
private MapFeignClient mapFeignClient;
@Autowired
private FeeRuleFeignClient feeRuleFeignClient;
@Override
public ExpectOrderVo expectOrder(ExpectOrderForm expectOrderForm){
//获取驾驶线路
CalculateDrivingLineForm calculateDrivingLineForm = new CalculateDrivingLineForm();
BeanUtils.copyProperties(expectOrderForm,calculateDrivingLineForm);
Result<DrivingLineVo> drivingLineVoResult = mapFeignClient.calculateDrivingLine();
DrivingLineVo drivingLineVo = drivingLineVoResult.getData();
//获取订单费用
FeeRuleRequestForm calculateOrderFeeForm = new FeeRuleRequestForm();
calculateOrderFeeForm.setDietance(drivingLineVo.getDietance());
calculateOrderFeeForm.setStartTime(new Date());
calculateOrderFeeForm.setWaitMinute(0);
Result<FeeRuleResponseVo> feeRuleResponseVoResult = feeRuleFeignClient.calculateOrerFee(calculateOrderFeeForm);
feeRuleResponseVo feeRuleResponseVo = feeRuleResponseVoResult.getData();
//封装ExpectOrderVo
ExpectOrderVo expectOrderVo = new ExpectOrderVo();
expectOrderVo.setDrivingLineVo(drivinLineVo);
expectOrderVo.setFeeRuleResponseVo(feeRuleResponseVo);
return expectOrderVo;
}
项目中整合规则引擎实现系统奖励
①、输入、输出参数的类
@Data
public class RewardRuleRequestForm{
@Schema(description="订单个数")
private Long orderNum;
}
@Data
public class RewardRuleResponseVo{
@Schema(description="奖励规则ID")
private Long rewardRuleId;
@Schema(description="奖励金额")
private BigDecimal rewardAmount;
}
②、规则文件RewardRule.drl
package com.atguigu.daijia
import com.atguigu.daijia.model.form.rules.RewardRuleRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
global com.atguigu.daijia.moel.vo.rules.RewardRuleResponse rewardRuleResponse;
/**
00:00:00-06:59:59 完成5单后,每单奖励5元
07:00:00-23:59:59 完成10单后,每单奖励2元
*/
rule "00:00:00-06:59:59 完成5单后,每单奖励5元"
salience 10
no-loop true
when
$rule:RewardRuleRequest(startTime>="" && startTime<="" && orderNum>5)
then
rewardRuleResponse.etRewardAmount(new BigDecimal("5.0"));
System.out.println("00:00:00-06:59:59 奖励:" + rewardRuleResponse.getRewardAmount()+ "元");
end
rule "07:00:00-23:59:59 完成10单后,每单奖励2元"
salience 10
no-loop true
when
$rule:RewardRuleRequest(startTime >= "07:00:00" && startTime <= "23:59:59" && orderNum>10)
then
rewardRuleResponse.setRewardAmount(new BigDecimal("2.0"));
System.out.println("07:00:00-23:59:59 奖励:" + rewardRuleResponse.getRewardAmount()+ "元");
end
③、添加规则引擎工具类
public class DroolsHelper{
private static final String RULES_CUSTOMER_RULES_DRL = "rules/FeeRule.drl";
public static KieSession loadForRule(String drlStr){
//获取KieServices
KieServices kieServices = KieServices.Factory.get();
//通过KieServices获取kieFileSystem,然后通过kieFileSystem读取规则文件RewardRule.drl
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
kieFileSystem.write(ResourceFactory.newClassPathResource(drlStr));
//通过KieServices获取获取KieBuilder
KieBuilder kb = kieServices.newKieBuilder(kieFileSystem);
kb.build();
//通过KieBuilder获取KieModule
KieModule kieModule = kb.getKieModule();
//通过KieServices和KieModule获取KieContainer,最终获取KieSession
KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());
return kieContainer.newKieSession();
}
}
④、编写系统奖励接口
@Autowired
private RewardRuleService rewardRuleService;
@Operation(summary="计算订单奖励费用")
@PostMapping("/calculateOrderRewardFee")
public Result<RewardRuleResponseVo> calculateOrderRewardFee(@RequestBody RewardRuleRequestForm rewardRuleRequestForm){
return Result.ok(rewardRuleService.calculateOrderRewardFee(rewardRuleRequestForm));
}
private static final String RULES_CUSTOMER_RULES_DRL = "rules/RewardRule.drl";
@Override
public RewardRuleResponseVo calculateOrderRewardFee(RewardRuleRequestForm rewardRuleRequestForm){
//封装传入参数对象
RewardRuleRequest rewardRuleRequest = new RewardRuleRequest();
rewardRuleRequest.setOrderNum(rewardRuleRequestForm.getOrderNum());
//创建规则引擎对象
KieSession kieSession = DroolsHelper.loadForRule(RULES_CUSTOMER_RULES_DRL);
//封装返回对象
RewardRuleResponse rewardRuleResponse = new RewardRuleResponse();
kieSession.setGlobal("rewardRuleResponse",rewardRuleResponse);
kieSession.insert(rewardRuleRequest);
kieSession.fireAllRules();
//终止会话
kieSession.dispose();
//封装
RewardRuleResponseVo rewardRuleResponseVo = new RewardRuleResponseVo();
rewardRuleResponseVo.setRewardAmount(rewardRuleResponse.getRewardAmount());
return rewardRuleResponseVo;
}
项目中整合规则引擎实现平台抽成
①、规则文件profitshardingRule.drl(略)
//package对应的不一定是真正的目录,可以任意写com.abc,同一个包下的drl文件可以互相访问
package.com.atguigu.daijia
import com.atguigu.daijia.model.form.rules.ProfitshardingRuleRequest;
import java.math.BigDecimal;
import java.math.RoudingMode;
global com.atguigu.daijia.model.vo.rules.ProfitsharingRuleResponse;
/**
支付微信平台费率:0.6%
global BigDecimal paymentRate = new BigDecimal(0.006);
*/
rule "支付微信平台费用 平台费率:0.6%"
salience 10
no-loop true
when
$rule:ProfitsharingRuleRequest()
then
profitsharingRuleResponse.setOrderAmount($rule.getOrderAmount());
profitsharingRuleResponse.setPaymentRate(new BigDecimal("0.006"));
BigDecimal paymentFee = profitshardingRuleResponse.getOrderAmount().multiply(profitshardingRuleResponse.getPaymentRate())
.setScale(2,RoundingModel.HALF_UP);
profitsharingRuleResponse.setPaymentFee(paymentFee);
System.out.println("支付微信平添费用"+profitsharingRuleResponse.getPaymentFee()+"元");
end
rule "订单金额小于等于100 当天完成订单<"
when
then
end