这个网上花店系统是我去年为本地连锁花店"芳菲阁"做的数字化转型项目,用Java+SSM做后端、Django管理后台,实现了从浏览到配送的全流程线上化。上线后三个月内,门店线上订单占比从12%飙升到47%,最远一单鲜花配送距离达到327公里。
传统花店常受限于营业时间和地理半径,而这个系统打破了时空限制——凌晨两点的生日花束、跨城急救的道歉玫瑰,都成了可能。技术上我们采用双框架协作:SSM处理高并发的订单和支付,Django快速迭代营销活动页面,这种组合在促销期间扛住了日均8000+的访问量。
选择SSM(Spring+SpringMVC+MyBatis)作为主框架不是偶然。在情人节压力测试中,我们发现:
Django-admin则完美适配了非技术人员操作:
第二期我们将系统拆分为三个微服务:
关键决策:没有盲目上Spring Cloud,而是根据模块特性混合使用技术栈。比如配送服务需要服务注册发现,但商品服务的缓存策略用Spring Cache更合适。
用Three.js实现的3D花束构建器是最大亮点:
java复制// 后端组合逻辑示例
public FlowerBouquet composeBouquet(List<FlowerVO> flowers) {
// 校验花材搭配合理性
if(flowers.stream().mapToInt(f->f.getToxicity()).sum() >0) {
throw new ToxicCombinationException();
}
// 计算包装材料
int stemDiameter = flowers.stream().mapToInt(f->f.getStemWidth()).sum();
Wrapper wrapper = wrapperDAO.selectByDiameter(stemDiameter);
// 生成3D场景描述文件
return new FlowerBouquet(flowers, wrapper);
}
客户可以:
结合鲜花特性的特殊调度规则:
python复制# Django后台任务示例
@app.task
def dispatch_order(order_id):
order = Order.objects.get(pk=order_id)
# 优先配送鲜花类型
if order.has_flower_type('玫瑰'):
priority = timedelta(hours=2)
elif order.has_flower_type('郁金香'):
priority = timedelta(hours=4)
# 计算最优骑手
riders = Rider.objects.filter(
cooling_box__gte=order.required_capacity()
).annotate(
distance=Distance('location', order.delivery_address)
).order_by('distance')[0]
# 更新状态
order.assign_to(riders, priority)
促销期首日,商品详情页响应时间突然从800ms飙升到12s。阿里云ARMS监控显示:
解决方案:
javascript复制// 检测WebP支持后重写图片URL
function checkWebP(callback) {
const img = new Image();
img.onload = function() {
callback(img.width>0 && img.height>0);
};
img.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
}
java复制@WebFilter("/upload/*")
public class ImageSizeFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException {
if(request.getContentLength() > MAX_IMAGE_SIZE) {
((HttpServletResponse)response).sendError(413);
return;
}
chain.doFilter(request, response);
}
}
当用户同时操作购物车和优惠券时出现数据不一致:
最终方案:
采用TCC柔性事务+本地消息表:
java复制public class FlowerInventoryTccService {
@Transactional
public boolean tryReserve(Long flowerId, int count) {
// 预占库存
int affected = flowerMapper.reduceFreeStock(flowerId, count);
if(affected ==0) return false;
// 记录预备操作
tccLogMapper.insert(new TccLog(flowerId, count));
return true;
}
@Transactional
public boolean confirmReserve(Long logId) {
// 正式扣减
TccLog log = tccLogMapper.selectById(logId);
flowerMapper.reduceActualStock(log.getFlowerId(), log.getCount());
return true;
}
}
针对黄牛抢购限量款花束:
java复制// 基于Spring EL的风控规则
@PreAuthorize("@riskControl.check(#user, T(java.time.LocalTime).now())")
public Result placeOrder(User user, OrderDTO dto) {
// 订单处理逻辑
}
在订单导出功能中实现:
python复制# Django中间件示例
class DataMaskingMiddleware:
def process_response(self, request, response):
if 'application/json' in response['Content-Type']:
data = json.loads(response.content)
# 手机号脱敏
if 'phone' in data:
data['phone'] = re.sub(r'(\d{3})\d{4}(\d{4})', r'\1****\2', data['phone'])
response.content = json.dumps(data)
return response
通过SkyWalking实现:
xml复制<!-- 拦截器配置 -->
<bean id="swInterceptor" class="org.apache.skywalking.apm.toolkit.trace.TraceAnnotationInterceptor"/>
<aop:config>
<aop:advisor advice-ref="swInterceptor"
pointcut="@annotation(org.apache.skywalking.apm.toolkit.trace.Trace)"/>
</aop:config>
python复制# settings.py
INSTALLED_APPS += ['skywalking']
SW_AGENT_NAME = 'flower-shop-backend'
SW_AGENT_COLLECTOR_BACKEND_SERVICES = 'skywalking-oap:11800'
使用Docker Compose编排:
yaml复制version: '3'
services:
ssm-service:
image: flower-shop-ssm:v1.2
deploy:
resources:
limits:
cpus: '2'
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
django-admin:
image: flower-admin:v2.1
depends_on:
- redis
environment:
CELERY_BROKER_URL: redis://redis:6379/1
用ELK+ClickHouse构建:
java复制// Logback配置
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>logstash:5044</destination>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<pattern>
<pattern>
{ "app": "flower-shop", "traceId": "%X{traceId}" }
</pattern>
</pattern>
</providers>
</encoder>
</appender>
sql复制-- ClickHouse查询
SELECT
funnel(3)(
has(events, 'view_product'),
has(events, 'add_cart'),
has(events, 'checkout')
) AS conversion_rate
FROM user_sessions
WHERE toDate(timestamp) = today()
基于XGBoost的智能调价:
python复制# Django管理命令
class Command(BaseCommand):
def handle(self, *args, **options):
model = load_model('/models/price_xgb.pkl')
flowers = Flower.objects.filter(
stock__lt=F('alert_stock')
)
for f in flowers:
features = [
f.sales_7d,
holidays_remaining(),
weather.get_temperature()
]
f.suggest_price = model.predict([features])[0]
f.save()
这套系统让我深刻体会到:技术方案没有绝对优劣,就像搭配花束,关键是把合适的组件放在对的位置。最近我们正在试验用WebAssembly加速图片处理,或许下次能聊聊Wasm在花卉行业的另类应用。