提交 5d62c194 编写于 作者: Q qinyingjie

Initial commit

上级
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.study</groupId>
<artifactId>design</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>design</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.study.design;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DesignApplication {
public static void main(String[] args) {
SpringApplication.run(DesignApplication.class, args);
}
}
package com.study.design;
import com.study.design.items.node.ProductItem;
import java.util.ArrayList;
import java.util.List;
public class MockDb {
public static ProductItem ProductItem = new ProductItem();
static {
ProductItem.setId(1);
ProductItem.setPid(0);
ProductItem.setName("书籍");
List<ProductItem> child = new ArrayList<>();
ProductItem c1 = new ProductItem();
c1.setId(2);
c1.setPid(1);
c1.setName("技术书籍");
ProductItem c2 = new ProductItem();
c2.setId(3);
c2.setPid(1);
c2.setName("历史书籍");
List<ProductItem> child1 = new ArrayList<>();
ProductItem c3 = new ProductItem();
c3.setId(4);
c3.setPid(2);
c3.setName("并发编程");
ProductItem c4 = new ProductItem();
c4.setId(5);
c4.setPid(2);
c4.setName("JVM");
child1.add(c3);
child1.add(c4);
c1.setChild(child1);
child.add(c1);
child.add(c2);
ProductItem.setChild(child);
}
}
package com.study.design.auditlog;
import com.study.design.auditlog.pojo.AuditLog;
import java.util.Date;
public abstract class AbstractAuditLogProcessor {
// 创建我们的 AuditLog (基础部分)
public final AuditLog buildAuditLog(String account, String action, String orderId){
AuditLog auditLog = new AuditLog();
auditLog.setAccount(account);
auditLog.setAction(action);
auditLog.setOrderId(orderId);
auditLog.setDate(new Date());
return auditLog;
}
protected abstract AuditLog buildDetails(AuditLog auditLog);
public final void sendToQueue(AuditLog auditLog) {
//send toQueue(auditLog)
}
public final void processAuditLog(String account, String action, String orderId) {
this.sendToQueue(buildDetails(buildAuditLog(account, action, orderId)));
}
}
package com.study.design.auditlog;
import com.study.design.auditlog.pojo.AuditLog;
import org.springframework.stereotype.Component;
@Component
public class LoginLogProcessor extends AbstractAuditLogProcessor{
@Override
protected AuditLog buildDetails(AuditLog auditLog) {
return auditLog;
}
}
package com.study.design.auditlog;
import com.study.design.auditlog.pojo.AuditLog;
import org.springframework.stereotype.Component;
@Component
public class OrderLogProcessor extends AbstractAuditLogProcessor{
@Override
protected AuditLog buildDetails(AuditLog auditLog) {
String orderId = auditLog.getOrderId();
String productDetails = "通过 orderId 获取";
auditLog.setDetails(productDetails);
System.out.println(auditLog);
return auditLog;
}
}
package com.study.design.auditlog;
import com.study.design.auditlog.pojo.AuditLog;
import org.springframework.stereotype.Component;
@Component
public class PayLogProcessor extends AbstractAuditLogProcessor{
@Override
protected AuditLog buildDetails(AuditLog auditLog) {
String orderId = auditLog.getOrderId();
String allDetails = "通过 orderId 或者是参数 获取产品信息,金额,支付方式";
auditLog.setDetails(allDetails);
System.out.println(auditLog);
return auditLog;
}
}
package com.study.design.auditlog.pojo;
import java.util.Date;
public class AuditLog {
private String account;
private String action;
private Date date;
private String orderId;
private Object details; //订单创建需要有相关产品信息;
// 订单支付需要有相关产品信息以及支付方式和支付金额。
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public Object getDetails() {
return details;
}
public void setDetails(Object details) {
this.details = details;
}
@Override
public String toString() {
return "AuditLog{" +
"account='" + account + '\'' +
", action='" + action + '\'' +
", date=" + date +
", orderId='" + orderId + '\'' +
", details=" + details +
'}';
}
}
package com.study.design.controller;
import com.study.design.service.EsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EsController {
@Autowired
private EsService esService;
@PostMapping("es")
public Boolean query(@RequestParam String query, Long fetchSize) {
return esService.query(query, fetchSize);
}
}
package com.study.design.controller;
import com.study.design.items.node.ProductItem;
import com.study.design.service.EsService;
import com.study.design.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ItemController {
@Autowired
private ItemService itemService;
@GetMapping("get")
public ProductItem getItem() {
return itemService.getItem();
}
@PostMapping("del")
public ProductItem delItem(@RequestBody ProductItem productItem) {
return itemService.delItem(productItem);
}
@PostMapping("add")
public ProductItem addItem(@RequestBody ProductItem productItem) {
return itemService.addItem(productItem);
}
}
package com.study.design.controller;
import com.study.design.order.pojo.Order;
import com.study.design.pay.pojo.PayBody;
import com.study.design.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("mkOrder")
public Order createOrder(@RequestParam Integer oid) {
return orderService.createOrder(oid);
}
@PostMapping("/pay")
public Order payOrder(@RequestBody PayBody payBody){
return orderService.pay(payBody);
}
@GetMapping("/send")
public Order send(@RequestParam Integer oid) {
return orderService.send(oid);
}
@GetMapping("/receive")
public Order receive(@RequestParam Integer oid) {
return orderService.receive(oid);
}
}
package com.study.design.controller;
import com.study.design.pojo.TicketParam;
import com.study.design.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/suggest")
public List<String> suggestRequirement(@RequestParam String username) {
return userService.suggestRequirement(username);
}
@PostMapping("/ticket")
public Object getTicket(@RequestBody TicketParam ticketParam) {
return userService.getTicket(ticketParam);
}
@PostMapping("/login")
public Boolean login(@RequestParam String name, @RequestParam String pwd, @RequestParam String type) {
return userService.login(name, pwd, type);
}
}
package com.study.design.esquery;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Spliterators;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@Component
public class EsQueryProcessor {
//1. 我们要用stream 返回 为了节省内存
public Stream<Map<String, Object>> scrollEsStream(String query, Long fetchSize) {
return StreamSupport.stream(Spliterators
.spliteratorUnknownSize(new ScrollIterator(query, fetchSize), 0), false);
}
//2. 我们要 迭代器
private class ScrollIterator implements Iterator<Map<String, Object>> {
private String scrollId;
private List<String> columns;
Iterator<Map<String, Object>> iterator;
RestTemplate restTemplate = new RestTemplate(); // 真是项目中使用resttemplate的时候
//一定是进行过我们的 bean 配置注入的。这里边直接用new关键字是为了访问我们的es 接口。
//构造函数进行第一次查询,并且初始化我们后续需要使用的 columns 和 iterator 和 scroll
public ScrollIterator(String query, Long fetchSize) {
EsSqlResult esSqlResult = restTemplate.postForObject("http://localhost:9200/_sql?format=json",
new EsSqlQuery(query, fetchSize), EsSqlResult.class);//第一次访问的结果出来了
this.scrollId = esSqlResult.getCursor();
this.columns = esSqlResult.getColumns()
.stream().map(x->x.get("name"))
.collect(Collectors.toList());
this.iterator = convert(columns, esSqlResult).iterator();
}
// hasNext 根据 是否 scrollId 为null进行后续的 第二次,第三次,,,的访问,直到 scrollId 为null
@Override
public boolean hasNext() {
return iterator.hasNext() || scrollNext();
}
private boolean scrollNext() {
if(iterator == null || this.scrollId == null) {
return false;
}
EsSqlResult esSqlResult = restTemplate.postForObject("http://localhost:9200/_sql?format=json",
new EsSqlQuery(this.scrollId), EsSqlResult.class);//第二次访问的结果出来了
this.scrollId = esSqlResult.getCursor();
this.iterator = convert(columns, esSqlResult).iterator();
return iterator.hasNext();
}
@Override
public Map<String, Object> next() {
return iterator.next();
}
}
//3. 返回结果传统一点 List<map>
private List<Map<String, Object>> convert(List<String> columns, EsSqlResult esSqlResult) {
List<Map<String, Object>> results = new ArrayList<>();
for(List<Object> row : esSqlResult.getRows()) {
Map<String, Object> map = new HashMap<>();
for(int i = 0; i < columns.size(); i++) {
map.put(columns.get(i), row.get(i));
}
results.add(map);
}
return results;
}
}
package com.study.design.esquery;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties
public class EsSqlQuery {
private String query;
private Long fetchSize;
private String cursor;
public EsSqlQuery(String cursor) {
this.cursor = cursor;
}
public EsSqlQuery(String query, Long fetchSize) {
this.query = query;
this.fetchSize = fetchSize;
}
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
public Long getFetchSize() {
return fetchSize;
}
public void setFetchSize(Long fetchSize) {
this.fetchSize = fetchSize;
}
public String getCursor() {
return cursor;
}
public void setCursor(String cursor) {
this.cursor = cursor;
}
}
package com.study.design.esquery;
import java.util.List;
import java.util.Map;
public class EsSqlResult {
private List<Map<String, String>> columns;
private List<List<Object>> rows;
private String cursor;
public List<Map<String, String>> getColumns() {
return columns;
}
public void setColumns(List<Map<String, String>> columns) {
this.columns = columns;
}
public List<List<Object>> getRows() {
return rows;
}
public void setRows(List<List<Object>> rows) {
this.rows = rows;
}
public String getCursor() {
return cursor;
}
public void setCursor(String cursor) {
this.cursor = cursor;
}
}
package com.study.design.handler;
import com.study.design.pojo.UserInfo;
import java.util.List;
public abstract class AbstractSuggestRequirementHandler {
abstract void processHandler(UserInfo userInfo, List<String> suggestLists);
}
package com.study.design.handler;
import com.study.design.pojo.UserInfo;
import java.util.List;
public class CityCheckHandler extends AbstractSuggestRequirementHandler{
@Override
public void processHandler(UserInfo userInfo, List<String> suggestLists) {
//通过获取 userinfo 的 city 属性
String city = userInfo.getCity();
// 通过city 和 之前保留的 4 个 业务信息进行对比。然后筛选出剩余的 3 个 业务投放
suggestLists.remove("1");
}
}
package com.study.design.handler;
import com.study.design.pojo.UserInfo;
import com.sun.org.apache.bcel.internal.generic.NEW;
import java.util.ArrayList;
import java.util.List;
public class NewCheckHandler extends AbstractSuggestRequirementHandler{
@Override
public void processHandler(UserInfo userInfo, List<String> suggestLists) {
//通过获取 userinfo 的 buyProducts 属性
boolean newUser = userInfo.isNewUser();
if(newUser) {
suggestLists = new ArrayList<>(); // 特定的新用户奖励
}
}
}
package com.study.design.handler;
import com.study.design.pojo.UserInfo;
import java.util.List;
public class PersonnalCheckHandler extends AbstractSuggestRequirementHandler{
@Override
public void processHandler(UserInfo userInfo, List<String> suggestLists) {
// 通过个人资质的check,我们找到了 4 个可以投放的业务。放到 suggestLists 中。
suggestLists.add("1");
suggestLists.add("2");
suggestLists.add("3");
suggestLists.add("4");
}
}
package com.study.design.handler;
import com.study.design.pojo.UserInfo;
import java.util.List;
public class RecentCheckHandler extends AbstractSuggestRequirementHandler{
@Override
public void processHandler(UserInfo userInfo, List<String> suggestLists) {
//通过获取 userinfo 的 buyProducts 属性
List<String> buyProducts = userInfo.getBuyProducts();
// buyProducts 和 之前保留的 3 个 业务信息进行对比。然后筛选出剩余的 2 个 业务投放
suggestLists.remove("2");
}
}
package com.study.design.handler;
import com.study.design.pojo.UserInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class SuggestRequirementHandlerProcess {
@Value("#{'${suggest.requirement.handler}'.split(',')}")
private List<String> handlers;
public void process(UserInfo userInfo, List<String> suggestLists) {
// 如果想要实时的进行顺序的调整或者是增减。那必须要使用配置中心进行配置。
// 比如springcloud里边自带的 git 的这种配置中心; applo 配置中心。
try {
for(String handler : handlers) {
AbstractSuggestRequirementHandler handle =
(AbstractSuggestRequirementHandler) Class.forName(handler).newInstance();
handle.processHandler(userInfo, suggestLists);
}
} catch (Exception e) {
}
}
}
package com.study.design.items.node;
public abstract class AbstractProductItem {
public abstract void removeChild(AbstractProductItem item);
public abstract void addChild(AbstractProductItem item);
}
package com.study.design.items.node;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ProductItem extends AbstractProductItem{
private int id;
private int pid;
private String name;
private List<ProductItem> child = new ArrayList<>();
@Override
public void removeChild(AbstractProductItem item) {
ProductItem removeItem = (ProductItem) item;
this.child = child.stream().filter(x->x.getId() != removeItem.getId()).collect(Collectors.toList());
}
@Override
public void addChild(AbstractProductItem item) {
this.child.add((ProductItem) item);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ProductItem> getChild() {
return child;
}
public void setChild(List<ProductItem> child) {
this.child = child;
}
}
package com.study.design.items.visitor;
import com.study.design.MockDb;
import com.study.design.items.node.ProductItem;
import org.springframework.stereotype.Component;
@Component
public class AddItemVisitor implements ItemVisitor<ProductItem>{
// 入参是 id 2, pid为 1
@Override
public ProductItem visitor(ProductItem productItem) {
ProductItem currentItem = MockDb.ProductItem; // 从缓存来的 to do
if(productItem.getId() == currentItem.getId()) {
throw new UnsupportedOperationException("根节点是唯一的。");
}
if(productItem.getPid() == currentItem.getId()) {
currentItem.addChild(productItem);
return currentItem;
}
addChild(productItem, currentItem);
return currentItem;
}
private void addChild(ProductItem productItem, ProductItem currentItem) {
for(ProductItem item : currentItem.getChild()) {
if(item.getId() == productItem.getPid()) {
item.addChild(productItem);
break;
} else {
addChild(productItem, item);
}
}
}
}
package com.study.design.items.visitor;
import com.study.design.MockDb;
import com.study.design.items.node.ProductItem;
import org.springframework.stereotype.Component;
@Component
public class DelItemVisitor implements ItemVisitor<ProductItem>{
// 入参是 id 2, pid为 1
@Override
public ProductItem visitor(ProductItem productItem) {
ProductItem currentItem = MockDb.ProductItem; // 从缓存来的 to do
if(productItem.getId() == currentItem.getId()) {
throw new UnsupportedOperationException("根节点不能删。");
}
if(productItem.getPid() == currentItem.getId()) {
currentItem.removeChild(productItem);
return currentItem;
}
delChild(productItem, currentItem);
return currentItem;
}
private void delChild(ProductItem productItem, ProductItem currentItem) {
for(ProductItem item : currentItem.getChild()) {
if(item.getId() == productItem.getPid()) {
item.removeChild(productItem);
break;
} else {
delChild(productItem, item);
}
}
}
}
package com.study.design.items.visitor;
import com.study.design.items.node.ProductItem;
public interface ItemVisitor<T> {
T visitor(ProductItem productItem);
}
package com.study.design.order;
import com.study.design.order.pojo.Order;
import com.study.design.order.pojo.OrderState;
import com.study.design.order.pojo.OrderStateChangeAction;
import org.springframework.messaging.Message;
import org.springframework.statemachine.annotation.OnTransition;
import org.springframework.statemachine.annotation.WithStateMachine;
import org.springframework.stereotype.Component;
// 监听器是监听到 action 后进行状态的一个变更。
@Component("orderStateListener")
@WithStateMachine(name="orderStateMachine")
public class OrderStateListener {
@OnTransition(source = "ORDER_WAIT_PAY", target = "ORDER_WAIT_SEND")
public boolean payToSend(Message<OrderStateChangeAction> message){
Order order = (Order) message.getHeaders().get("order");
order.setOrderState(OrderState.ORDER_WAIT_SEND);
return true;
}
@OnTransition(source = "ORDER_WAIT_SEND", target = "ORDER_WAIT_RECEIVE")
public boolean sendToReceive(Message<OrderStateChangeAction> message){
Order order = (Order) message.getHeaders().get("order");
order.setOrderState(OrderState.ORDER_WAIT_RECEIVE);
return true;
}
@OnTransition(source = "ORDER_WAIT_RECEIVE", target = "ORDER_FINISH")
public boolean receiveToFinish(Message<OrderStateChangeAction> message){
Order order = (Order) message.getHeaders().get("order");
order.setOrderState(OrderState.ORDER_FINISH);
return true;
}
}
package com.study.design.order.config;
import com.study.design.order.pojo.Order;
import com.study.design.order.pojo.OrderState;
import com.study.design.order.pojo.OrderStateChangeAction;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.support.DefaultStateMachineContext;
import java.util.EnumSet;
@Configuration
@EnableStateMachine(name="orderStateMachine")
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderState, OrderStateChangeAction> {
public void configure(StateMachineStateConfigurer<OrderState, OrderStateChangeAction> states) throws Exception {
states.withStates().initial(OrderState.ORDER_WAIT_PAY)
.states(EnumSet.allOf(OrderState.class));
}
public void configure(StateMachineTransitionConfigurer<OrderState, OrderStateChangeAction> transitions) throws Exception {
transitions.withExternal().source(OrderState.ORDER_WAIT_PAY)
.target(OrderState.ORDER_WAIT_SEND)
.event(OrderStateChangeAction.PAY_ORDER)
.and()
.withExternal().source(OrderState.ORDER_WAIT_SEND)
.target(OrderState.ORDER_WAIT_RECEIVE)
.event(OrderStateChangeAction.SEND_ORDER)
.and()
.withExternal().source(OrderState.ORDER_WAIT_RECEIVE)
.target(OrderState.ORDER_FINISH)
.event(OrderStateChangeAction.RECEIVE_ORDER);
}
// 配置状态机持久化
@Bean
public DefaultStateMachinePersister machinePersister() {
return new DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, Order>() {
@Override
public void write(StateMachineContext<Object, Object> stateMachineContext, Order order) throws Exception {
//持久化操作。可以通过任何形式进行持久化。redis 、 mongodb、mysql,ecache
}
@Override
public StateMachineContext<Object, Object> read(Order order) throws Exception {
// 本来是应该从持久化组件里进行读取的。但是没做持久化
return new DefaultStateMachineContext(order.getOrderState(), null, null, null);
}
});
}
}
package com.study.design.order.pojo;
//状态转化的一个控制机。状态机:初始化状态;配置我们的所有状态之间的转化关系;
//一些持久化的工作(redis)。
public class Order {
private Integer orderId;
private OrderState orderState;//订单状态
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public OrderState getOrderState() {
return orderState;
}
public void setOrderState(OrderState orderState) {
this.orderState = orderState;
}
}
package com.study.design.order.pojo;
public enum OrderState {
ORDER_WAIT_PAY, // 待支付
ORDER_WAIT_SEND, // 待发货
ORDER_WAIT_RECEIVE, // 待收货
ORDER_FINISH; // 完成订单
}
package com.study.design.order.pojo;
public enum OrderStateChangeAction {
PAY_ORDER, // 支付操作
SEND_ORDER, // 发货操作
RECEIVE_ORDER; // 收货操作
}
package com.study.design.pay.additionalDecorator;
import com.study.design.pay.pojo.PayBody;
import com.study.design.pay.strategyContext.AbstractPayContext;
public abstract class AbstractAddFuncDecorator extends AbstractPayContext {
// 这是我们的装饰器类。专门干装修的。 专门添加新功能的(平台币,红包)
// 装饰的是谁啊? 我作为一个称职的装饰器,我必须得知道装饰的是谁,不然我咋干活儿啊。
private AbstractPayContext abstractPayContext = null;
public AbstractAddFuncDecorator(AbstractPayContext abstractPayContext) {
this.abstractPayContext = abstractPayContext;
}
// 开始干活儿
//1. 老活儿。 支付。但是我又不能修改支付代码,也不能修改支付逻辑。
@Override
public Boolean execute(PayBody payBody) {
return abstractPayContext.execute(payBody);
}
//2. 老活儿不合适,没你装饰器照样能execute。 新活儿:平台币,红包)
public abstract void additionalFunction(PayBody payBody);
}
package com.study.design.pay.additionalDecorator;
import com.study.design.pay.pojo.PayBody;
import com.study.design.pay.strategyContext.AbstractPayContext;
/**
* abstractPayContext 不是共享的,因为有的小伙伴选择 zfb 支付,有的小伙伴选择wx支付,等等。。。
*
* @author : qinyingjie
* @version : 2.2.0
* @date : 2022/9/27 02:20
*/
public class AddFuncDecorator extends AbstractAddFuncDecorator {
public AddFuncDecorator(AbstractPayContext abstractPayContext) {
super(abstractPayContext);
}
/**
* 新活儿
*
* @param payBody
*/
@Override
public void additionalFunction(PayBody payBody) { // 共享的,跟支付策略没有任何关系
String product = payBody.getProduct();
// 从db里边获取 product的详细信息。
// 从配置中心(redis缓存)里获取产品的更新策略。
// 根据策略更新用户平台币 或(和) 发放红包。
System.out.println("更新平台币成功,发送红包到用户优惠券模块成功。");
}
@Override
public Boolean execute(PayBody payBody) { // 算共享的。共享的调用逻辑
Boolean result = super.execute(payBody); //老活儿
this.additionalFunction(payBody); // 新活儿. 新活儿的各种重试,失败补偿
return result;
}
}
package com.study.design.pay.facade;
import com.study.design.pay.additionalDecorator.AddFuncDecorator;
import com.study.design.pay.factory.AddFuncFactory;
import com.study.design.pay.pojo.PayBody;
import com.study.design.pay.strategy.PayStrategy;
import com.study.design.pay.strategyContext.PayContext;
import com.study.design.pay.strategyEnum.StrategyEnum;
import com.study.design.pay.factory.StrategyFactory;
// 最终我们只暴露我们的门面,对于里边的这些所有的工厂。策略啊。策略枚举啊,统统不暴露。
// 门面就是我们的超强封装。
public class StrategyFacade {
// 定义一个map,将对应关系提前初始化好。
// 双十一的时候,有大量的用户进行下单(千万级),就会造成千万级的pay接口的调用。
// 很可惜,这部分代码里边有两个 new 关键字(new PayContext(payStrategy) 和 new AddFuncDecorator)。
// 如果瞬时见。有几十万的并发进来,那么会创建几十万个 context对象和 addFunc对象,造成 年轻代的eden区的频繁对象创建
// 虽然说调用完就进行了对象的垃圾收集,但是这么多的访问对象进来会造成,minorgc。
// 1. 单例模式吗?PayContext创建是基于payStrategy,不止一种paycontext啊,用单例不行呀。 AddFuncDecorator 是基于PayContext
// 创建的,PayContext 不止一种,AddFuncDecorator 也不止一种。
// 2. 享元模式。享元模式是单例模式的一种思想升级。单例模式,针对的是同一种对象,没有任何不同的细节。而享元模式,针对多个对象。
// 多个对象:同一种class,但是里边的属性有些许不同。PayContext是同一种对象吧?是的; PayContext 是不是有细节上的不同呢?是的,
// payStrategy不同; 那么我们是否可以知道这个PayContext的种类数量呢?是的,目前有三种。 享元模式能够对这可控数量的有不同细节的
//同一种class对象进行共享,保证我们的程序不频繁的创建对象。
public static Boolean pay(PayBody payBody) {
//获取我们的 策略枚举
StrategyEnum strategyEnum = getStrategyEnum(payBody.getType());
if(strategyEnum == null) {
return false;
}
//获取我们的策略对象
PayStrategy payStrategy = StrategyFactory.getPayStrategy(strategyEnum);
//生成我们的策略上下文
PayContext context = new PayContext(payStrategy); // TO DO
// 装饰一下 context,。立马多了一个功能
// 我看这行代码啊,就不顺眼。代理模式搞他。
AddFuncDecorator addFuncDecorator = (AddFuncDecorator) AddFuncFactory.getAddFunc(context);
//进行扣款
return addFuncDecorator.execute(payBody);
}
private static StrategyEnum getStrategyEnum(int type) {
switch (type) {
case 0:
return StrategyEnum.ZfbPayStrategy;
case 1:
return StrategyEnum.WcPayStrategy;
case 2:
return StrategyEnum.BkPayStrategy;
default:
return null;
}
}
}
package com.study.design.pay.factory;
import com.study.design.pay.additionalDecorator.AbstractAddFuncDecorator;
import com.study.design.pay.additionalDecorator.AddFuncDecorator;
import com.study.design.pay.strategyContext.PayContext;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class AddFuncFactory {
// 工厂的目的是生产 AddFuncDecorator; 生产几个啊? 多个:享元
// key 应该是能够和 AbstractAddFuncDecorator 做成对应的东西。
// 这个map最多保存是三个对象。
public final static Map<PayContext, AbstractAddFuncDecorator> maps = new ConcurrentHashMap<>();
public static AbstractAddFuncDecorator getAddFunc(PayContext payContext) {
if(maps.get(payContext) == null) {
AddFuncDecorator addFuncDecorator = new AddFuncDecorator(payContext);
maps.put(payContext, addFuncDecorator);
}
return maps.get(payContext);
}
}
package com.study.design.pay.factory;
import com.study.design.pay.strategy.PayStrategy;
import com.study.design.pay.strategyEnum.StrategyEnum;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 我们的工厂类依靠我们的策略枚举返回策略类
* 我们以后永远不需要修改我们的Factory。他是一个无状态的
*
* @author : qinyingjie
* @version : 2.2.0
* @date : 2022/9/27 02:21
*/
public class StrategyFactory {
//那个时候我们 引出他是为了讲解 单例模式,其实那个时候我们已经利用了单例模式
//思想升级之后的享元,模式了。
private static final Map<String, PayStrategy> strategyMaps = new ConcurrentHashMap();
public static PayStrategy getPayStrategy(StrategyEnum strategyEnum) {
PayStrategy payStrategy = strategyMaps.get(strategyEnum.getValue());
if (payStrategy == null) {
try {
// 每次调用都需要进行一次反射。优化调整。
payStrategy = (PayStrategy) Class.forName(strategyEnum.getValue()).newInstance();
strategyMaps.put(strategyEnum.getValue(), payStrategy);
} catch (Exception e) {
//异常
}
}
return payStrategy;
}
// 工厂模式的变种比较多。虽然这里边我写了一个 有静态方法的 工厂类,但是要与我们平时
//写的 utils 类进行区分,utils 是以功能(生成uuid,日期转化)为导向的工具类。
// 而 我写的factory类,他是以产出(一类行为类:策略)为导向的
}
package com.study.design.pay.pojo;
public class PayBody {
private String account;
private int type;
private String product;
private int amount;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
package com.study.design.pay.proxy;
import com.study.design.pay.pojo.PayBody;
import com.study.design.pay.strategyContext.AbstractPayContext;
public class ContextProxy extends AbstractPayContext {
private AbstractPayContext abstractPayContext = null;
public ContextProxy(AbstractPayContext abstractPayContext) {
this.abstractPayContext = abstractPayContext;
}
@Override
public Boolean execute(PayBody payBody) {
return null;
}
}
package com.study.design.pay.strategy;
import com.study.design.pay.pojo.PayBody;
public class BkPayStrategy implements PayStrategy{
@Override
public Boolean pay(PayBody payBody) {
// 支付细节省略
return true;
}
}
package com.study.design.pay.strategy;
import com.study.design.pay.pojo.PayBody;
/**
* // 增加一个付款方式的话,需要写一个 strategy的子类实现类,类似Wc。
* // 枚举类增加一个枚举,就一行代码。
* // 门面类 中枚举获取的修改。
* // 扩展性良好,而且不影响 调用端。我们的任何改动,不需要让调用端知道。
*
* @author : qinyingjie
* @version : 2.2.0
* @date : 2022/9/27 02:22
*/
public interface PayStrategy {
Boolean pay(PayBody payBody);
// 之所以使用interface,是因为我们的所有的策略接口下的方法都是需要复写的,
// 没有公共的、可重用的方法。
//abstract class 他能够有自己的 抽象方法(需要子类复写的)
// abstract class 他也能够有自己的可执行方法(普通的方法,不抽象的)
}
package com.study.design.pay.strategy;
import com.study.design.pay.pojo.PayBody;
public class WcPayStrategy implements PayStrategy{
@Override
public Boolean pay(PayBody payBody) {
// 支付细节省略
return true;
}
}
package com.study.design.pay.strategy;
import com.study.design.pay.pojo.PayBody;
public class ZfbPayStrategy implements PayStrategy{
@Override
public Boolean pay(PayBody payBody) {
//支付细节省略
return true;
}
}
package com.study.design.pay.strategyContext;
import com.study.design.pay.pojo.PayBody;
public abstract class AbstractPayContext {
public abstract Boolean execute(PayBody payBody);
}
package com.study.design.pay.strategyContext;
import com.study.design.pay.strategy.PayStrategy;
import com.study.design.pay.pojo.PayBody;
/**
* // 动态地给一个对象添加一些额外的职责. 就得在根儿上添加。
* //PayContext 就是我们的被装饰者,因为我们想给payContext添加额外功能:平台币更新和红包
* // 所以我们选择使用装饰者模式。被装饰者必须要有 接口或者抽象类。也就是类图中的
*
* @author : qinyingjie
* @version : 2.2.0
* @date : 2022/9/27 02:22
*/
public class PayContext extends AbstractPayContext {
private PayStrategy payStrategy;
public PayContext(PayStrategy payStrategy) {
this.payStrategy = payStrategy;
}
@Override
public Boolean execute(PayBody payBody) {
return this.payStrategy.pay(payBody);
}
}
package com.study.design.pay.strategyEnum;
public enum StrategyEnum {
ZfbPayStrategy("com.study.design.pay.strategy.ZfbPayStrategy"),
WcPayStrategy("com.study.design.pay.strategy.WcPayStrategy"),
BkPayStrategy("com.study.design.pay.strategy.BkPayStrategy");
String value = "";
StrategyEnum(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
package com.study.design.pojo;
public class TicketParam {
/**
* 真实的项目里,我们的account是set到用户的请求头里的 ,header里。过我们的网管的时候就已经记录了
*/
private String account;
private String title;
private String bankInfo;
private String productId;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBankInfo() {
return bankInfo;
}
public void setBankInfo(String bankInfo) {
this.bankInfo = bankInfo;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
}
package com.study.design.pojo;
import java.util.List;
public class UserInfo {
private String username;
private String city;
private List<String> buyProducts;
private boolean isNewUser;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public List<String> getBuyProducts() {
return buyProducts;
}
public void setBuyProducts(List<String> buyProducts) {
this.buyProducts = buyProducts;
}
public boolean isNewUser() {
return isNewUser;
}
public void setNewUser(boolean newUser) {
isNewUser = newUser;
}
}
package com.study.design.service;
import com.study.design.esquery.EsQueryProcessor;
import com.study.design.order.pojo.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
@Service
public class EsService {
@Autowired
private EsQueryProcessor esQueryProcessor;
public Boolean query(String query, Long fetchSize) {
Stream<Map<String, Object>> mapStream = esQueryProcessor
.scrollEsStream(query, fetchSize);
mapStream.forEach(x -> System.out.println(x));
return true;
}
}
package com.study.design.service;
import com.study.design.MockDb;
import com.study.design.items.node.ProductItem;
import com.study.design.items.visitor.AddItemVisitor;
import com.study.design.items.visitor.DelItemVisitor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ItemService {
@Autowired
private DelItemVisitor delItemVisitor;
@Autowired
private AddItemVisitor addItemVisitor;
/**
* 这部分只有初始化的时候获取一次 或者 直接预热到缓存中
*/
public ProductItem getItem() {
System.out.println("从DB 获取所有的目录");
System.out.println("将数据组装为 ProductItem");
System.out.println("将组装好的 ProductItem 放入缓存中,永不过期 ");
return MockDb.ProductItem;
}
public ProductItem delItem(ProductItem productItem) {
ProductItem item = delItemVisitor.visitor(productItem);
MockDb.ProductItem = item;
System.out.println("update db");
return item;
}
public ProductItem addItem(ProductItem productItem) {
ProductItem item = addItemVisitor.visitor(productItem);
MockDb.ProductItem = item;
System.out.println("update db");
return item;
}
}
package com.study.design.service;
import com.study.design.auditlog.OrderLogProcessor;
import com.study.design.auditlog.PayLogProcessor;
import com.study.design.order.pojo.Order;
import com.study.design.order.pojo.OrderState;
import com.study.design.order.pojo.OrderStateChangeAction;
import com.study.design.pay.facade.StrategyFacade;
import com.study.design.pay.pojo.PayBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class OrderService {
@Autowired
private StateMachine<OrderState, OrderStateChangeAction> orderStateMachine;
@Autowired
private StateMachinePersister<OrderState, OrderStateChangeAction, Order> stateMachinePersister;
@Autowired
private PayLogProcessor payLogProcessor;
@Autowired
private OrderLogProcessor orderLogProcessor;
/**
* 模拟一个存储
*/
private final List<Object> orders = new ArrayList<>();
public Order createOrder(Integer oid) {
Order order = new Order();
order.setOrderState(OrderState.ORDER_WAIT_PAY);
order.setOrderId(oid);
// 创建的order是不是得入库啊?如果不入库,下次访问的时候,是不是找不到了啊。
orders.add(order); //模拟存储到 db
orderLogProcessor.processAuditLog("acccount", "createOrder", oid.toString());
return order;
}
// 将来我们删除或者增加或者修改任何关于付款的模块,无需改动service。
//不会对调用层产生任何代码的改动。
// 调用层使用我们的pay 模块,无需关系实现的逻辑,只需要将入参传给我们的pay模块即可。
public Order pay(PayBody payBody) {
// 书写我们的付款逻辑
boolean flag = false;
flag = StrategyFacade.pay(payBody);
if(flag) {
Order order = (Order) orders.get(0); // 模拟查询db代码
payLogProcessor.processAuditLog(payBody.getAccount(), "pay", order.getOrderId().toString());
Message message = MessageBuilder
.withPayload(OrderStateChangeAction.PAY_ORDER).setHeader("order", order).build();
//发送消息,发送给谁?和状态机有没有关系啊? 有
if(changeStateAction(message,order)) {
return order;
}
//如果是 true,我们要保存到db
saveToDb(payBody);
}
return null;
}
private void saveToDb(PayBody payBody) {
}
public Order send(Integer oid) {
Order order = (Order) orders.get(0); // 模拟查询db代码
Message message = MessageBuilder
.withPayload(OrderStateChangeAction.SEND_ORDER).setHeader("order", order).build();
if(changeStateAction(message,order)) {
return order;
}
return null;
}
public Order receive(Integer oid) {
Order order = (Order) orders.get(0); // 模拟查询db代码
Message message = MessageBuilder
.withPayload(OrderStateChangeAction.RECEIVE_ORDER).setHeader("order", order).build();
if(changeStateAction(message,order)) {
return order;
}
return null;
}
private boolean changeStateAction(Message<OrderStateChangeAction> message, Order order) {
try {
orderStateMachine.start();
stateMachinePersister.restore(orderStateMachine, order); // 待议
boolean res = orderStateMachine.sendEvent(message);
stateMachinePersister.persist(orderStateMachine, order); // 持久
return res;
} catch (Exception e) {
e.printStackTrace();
} finally {
orderStateMachine.stop();
}
return false;
}
}
package com.study.design.service;
import com.study.design.handler.SuggestRequirementHandlerProcess;
import com.study.design.pojo.TicketParam;
import com.study.design.pojo.UserInfo;
import com.study.design.ticket.builder.CompanyTicketBuilder;
import com.study.design.ticket.builder.PersonalTicketBuilder;
import com.study.design.ticket.builder.TicketBuilder;
import login.implementor.LoginFunc;
import login.implementor.WbLoginFunc;
import login.implementor.abstractlogin.AbstractLoginProcessor;
import login.implementor.abstractlogin.ThirdPartLogin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserService {
@Autowired
private SuggestRequirementHandlerProcess suggestRequirementHandlerProcess;
public List<String> suggestRequirement(String username) {
//获取用户信息。因为用户已经登录了,那么user的信息是保存在我们的缓存里的。
UserInfo userInfo = getUserInfo(username);
List<String> results = new ArrayList<>();
// 你可以发现,调用方无需关心任何 handler。完全对其屏蔽的。而且是
// 完全解耦
suggestRequirementHandlerProcess.process(userInfo, results);
return results;
}
//因为这部分是需要查询 缓存(如果缓存没有,需要查库)不应该写到 service层,但是为了代码书写简便
//这部分我模拟在service 层。
private UserInfo getUserInfo(String username) {
return new UserInfo();
}
public Object getTicket(TicketParam ticketParam) {
TicketBuilder builder = null;
String bankInfo = null;
if(ticketParam.getBankInfo() != null) {
bankInfo = "from 3rd party interface check.";
builder = new CompanyTicketBuilder();
} else {
builder = new PersonalTicketBuilder();
}
builder.setParam(ticketParam.getAccount(), ticketParam.getTitle());
String content = "from config center";
String product = "from db";
builder.setContent(content);
builder.setProduct(product);
builder.setBankInfo(bankInfo);
// 详细的逻辑细节控制以及从配置中心或者是db中获取的逻辑步骤就是简单的 crud,自己明白即可
return builder.buildTicket();
}
public Boolean login(String name, String pwd, String type) {
// 这部分我就不进行封装了,直接在 service里做了。小伙伴可以自行实现封装,类似享元。
// 这部分是桥接模式的实现。
// if(type.equals("wb")) {
// LoginFunc func = new WbLoginFunc();
// AbstractLoginProcessor processor = new ThirdPartLogin(func);
// return processor.loginExecute(name, pwd, type);
// }
return true;
}
}
package com.study.design.ticket;
import com.study.design.ticket.pojo.CompanyTicket;
import com.study.design.ticket.pojo.PersonalTicket;
public class TicketConstant {
// 保存只具有公共属性的对象,供clone使用。
public static PersonalTicket personalTicket = new PersonalTicket();
public static CompanyTicket companyTicket = new CompanyTicket();
static {
personalTicket.setType("type");
personalTicket.setFooter("footer");
companyTicket.setType("type");
companyTicket.setFooter("footer");
}
}
package com.study.design.ticket.builder;
import com.study.design.ticket.TicketConstant;
import com.study.design.ticket.pojo.CompanyTicket;
public class CompanyTicketBuilder extends TicketBuilder<CompanyTicket> {
/**
* new 关键字
*/
private CompanyTicket companyTicket = TicketConstant.companyTicket.clone();
@Override
public void setBankInfo(String bankInfo) {
companyTicket.setBankInfo(bankInfo);
}
@Override
public void setParam(String account, String title) {
companyTicket.setTitle(title);
companyTicket.setAccount(account);
}
@Override
public void setContent(String content) {
companyTicket.setContent(content);
}
@Override
public void setProduct(String product) {
companyTicket.setProduct(product);
}
@Override
public CompanyTicket buildTicket() {
return companyTicket;
}
}
package com.study.design.ticket.builder;
import com.study.design.ticket.TicketConstant;
import com.study.design.ticket.pojo.PersonalTicket;
public class PersonalTicketBuilder extends TicketBuilder<PersonalTicket> {
/**
* new 关键字 改成clone的形式,只clone我们的
* <p>
* 不可变部分。对于可变部分和自定义用户提交部分,不进行clone
*/
private PersonalTicket personalTicket = TicketConstant.personalTicket.clone();
@Override
public void setParam(String account, String title) {
personalTicket.setTitle(title);
personalTicket.setAccount(account);
}
@Override
public void setContent(String content) {
personalTicket.setContent(content);
}
@Override
public void setProduct(String product) {
personalTicket.setProduct(product);
}
@Override
public PersonalTicket buildTicket() {
return personalTicket;
}
}
package com.study.design.ticket.builder;
public abstract class TicketBuilder<T> {
public abstract void setParam(String account, String title);
public abstract void setContent(String content); // 配置中心 或 DB 或缓存
public abstract void setProduct(String product); // db
public void setBankInfo(String bankInfo){}; //需要校验的,校验通过才能设置
public abstract T buildTicket();
}
package com.study.design.ticket.pojo;
public class CompanyTicket implements Cloneable{
private String type;
private String footer;
private String content; //配置中心 或者 DB里边获取。(缓存里获取,只不过如果万一DB 或配置中心有修改,需要同时更新缓存)
private String product; //大部分情况db里获取(缓存里是有一些热门产品的)
private String bankInfo; //校验我们的银行卡信息(通过我们的第三方银行相关接口进行的校验)
private String account;
private String title;
public String getFooter() {
return footer;
}
public void setFooter(String footer) {
this.footer = footer;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public String getBankInfo() {
return bankInfo;
}
public void setBankInfo(String bankInfo) {
this.bankInfo = bankInfo;
}
@Override
public CompanyTicket clone() {
CompanyTicket companyTicket = null;
try {
companyTicket = (CompanyTicket) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return companyTicket;
}
}
package com.study.design.ticket.pojo;
public class PersonalTicket implements Cloneable{
private String type;
private String footer;
private String content; //配置中心 或者 DB里边获取。(缓存里获取,只不过如果万一DB 或配置中心有修改,需要同时更新缓存)
private String product; //大部分情况db里获取(缓存里是有一些热门产品的)
private String account; // 接口入参获取
private String title; // 接口入参获取
public String getFooter() {
return footer;
}
public void setFooter(String footer) {
this.footer = footer;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
@Override
public PersonalTicket clone() {
PersonalTicket personalTicket = null;
try {
personalTicket = (PersonalTicket) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return personalTicket;
}
}
package login.implementor;
public interface LoginFunc {
public boolean login(String name, String pwd, String type);
}
package login.implementor;
public class WbLoginFunc implements LoginFunc{
@Override
public boolean login(String name, String pwd, String type) {
// 进行第三方账号的校验流程。
System.out.println("Wb 验证通过,可以登录。");
return true;
}
}
package login.implementor;
public class ZfbLoginFunc implements LoginFunc{
@Override
public boolean login(String name, String pwd, String type) {
// 进行第三方账号的校验流程。
System.out.println("Zfb 验证通过,可以登录。");
return true;
}
}
package login.implementor.abstractlogin;
import login.implementor.LoginFunc;
public abstract class AbstractLoginProcessor {
protected LoginFunc loginFunc;
public AbstractLoginProcessor(LoginFunc loginFunc) {
this.loginFunc = loginFunc;
}
public abstract boolean loginExecute(String name, String pwd, String type);
}
package login.implementor.abstractlogin;
import login.implementor.LoginFunc;
public class ThirdPartLogin extends AbstractLoginProcessor{
public ThirdPartLogin(LoginFunc loginFunc) {
super(loginFunc);
}
@Override
public boolean loginExecute(String name, String pwd, String type) {
return super.loginFunc.login(name, pwd, type);
}
}
server.port = 8080
### \u6BD4\u55BB\u6210\u914D\u7F6E\u4E2D\u5FC3
suggest.requirement.handler = com.study.design.handler.PersonnalCheckHandler,com.study.design.handler.CityCheckHandler,com.study.design.handler.RecentCheckHandler,com.study.design.handler.NewCheckHandler
\ No newline at end of file
{
"columns": [
{
"name": "username",
"type": "String"
},
{
"name": "age",
"type": "String"
}
],
"rows": [
[
"zhao",
"11"
],
[
"qian",
"12"
],
[
"sun",
"11"
],
[
"li",
"14"
],
[
"zhou",
"11"
]
],
"cursor": "DIXPnoOPhGJSDOIPANhnnaioHVNgyuyBKMLLYURrghoivpvptFTyguhuiOHIPBVGIYGFUYGFFYVfuvyhubiOHIOHIoht78t78t786rt6r7RFFYVJVHJVHJbkjbkj=="
}
=======================================================================================
{
"rows": [
[
"wu",
"9"
],
[
"zheng",
"11"
],
[
"wang",
"11"
]
]
}
======================================
普通策略:
1. 进行第一次访问,然后获取 columns ,rows 和 cursor。
2. 转化我们的第一次结果为 map 形式的 json
3. 拿第一次的 corsor id,进行第二次访问。
4. 用第一次记录的 columns 组装第二次的 rows结果为 map 形式的json
以此类推。
5. 把所有的转化结果存储到 一个 对象(数据量太大,占用内存)里,返回给调用者
(数据量太大,带宽受不了)。
升级策略:迭代器模式
1. 将我们访问封装到我们的迭代器中;(第一次访问以迭代器的构造函数访问,初始化我们的columns供
后续使用;将第一次的结果转化为 map 形式的json 供 迭代器使用)
2. hasnext 方法里,进行我们的后续的多次访问。
1. DB 存储
id parentId name
1 0 书籍
--------------------------
2 1 技术书籍
---------------------------
3 1 历史书籍
---------------------------
4 2 并发编程
---------------------------
5 2 JVM
2. 当我们的项目进行初始化的时候,就会将我们的DB里的这些目录进行如下的查询转化为如下对象存储:
{
"id": 1,
"itemName": "书籍",
"pid": 0,
"childItems": [{
"id": 2,
"itemName": "技术书籍",
"pid": 1,
"childItems": [{
"id": 4,
"itemName": "并发编程",
"pid": 2,
"childItems": null
}, {
"id": 5,
"itemName": "JVM",
"pid": 2,
"childItems": null
}]
}, {
"id": 3,
"itemName": "历史书籍",
"pid": 1,
"childItems": null
}]
}
3. 将这个对象存储到我们的 Nginx 本地缓存,并设置为永不过期。
4. App 、 页面进行调用的时候,从 Nginx 获取这份儿目录。并且 APP 端进行缓存,每隔 24小时进行一次 标记位的访问(如果业务对我们的目录结构有增删,标记位(序号)就会有所变化,前端会再次对数据进行重新的同步)
5. 如果有修改,后端是先 修改缓存,只针对缓存中需要修改的部分进行修改,然后更新缓存(目录层结构+标志位)。 缓存更新成功后,再更新DB.
package com.study.design;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DesignApplicationTests {
@Test
void contextLoads() {
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册