腾讯云位置服务地图+规则引擎Drools

腾讯云位置服务地图

如果未开通,前端会报错
在这里插入图片描述

开通腾讯位置服务

①、腾讯官网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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值