jsp网站开发实现增删改查,软文营销的特点,太原网站优化技术,网站注销备案高级Redis应用进阶 一站式Redis解决方案-Redis-2 Redis基础数据类型与基本使用 源代码在GitHub - 629y/food-social-contact-parent: redis项目-美食社交APP
1. Redis基本数据类型
1.字符串#xff08;strings#xff09; set username zhangsan get username mset age 18 …高级Redis应用进阶 一站式Redis解决方案-Redis-2 Redis基础数据类型与基本使用 源代码在GitHub - 629y/food-social-contact-parent: redis项目-美食社交APP
1. Redis基本数据类型
1.字符串strings set username zhangsan get username mset age 18 address bj 设置多个 mget username age 获取多个 incr num incr-递增1 num-变量从0开始 decr num decr-递减-1 incrby num 2 incrby-以每次2递增 decrby num 3 decrby-以每次-3递减 del num 删除数据 2.散列hashes hset userInfo username zhangsan age 18 address bj hget userInfo username hget userInfo age hmget userInfo username age 获取多个 hgetall userInfo 获取全部 hlen userInfo 获取key的数量 hincrby userInfo age 2 hincrby-age以每次2递增 hdel userInfo age 删除age del userInfo 删除userInfo 3.列表lists lpush student zhangsan lisi wangwu lpush-左插入 rpush student tianqi rpush-右插入 lpop student lpop-左弹出 rpop student rpop-右弹出 lrange student 0 1 student中从下标为0到1排序查看 4.集合sets-去重 sadd nums 1 2 3 sadd nums 1 1 2 2 3 3 不会添加重复的 smembers nums 查看nums中的所有 srem nums 2 移除2 spop nums 随机弹出 sadd nums1 1 2 3 sadd nums2 2 3 4 sinter nums1 nums2 sinter-交集-23 sdiff nums1 nums2 nums1相对于nums2的差集-1 sunion nums1 nums2 并集-1234 5.有序集合sorted sets zadd rank 66 zhangsan 88 lisi 77 wangwu 99 zhaoliu zadd rank 66 zhangsan 88 lisi 77 wangwu 99 zhaoliu 去重添加rank zrange rank 0 3 从下标0到3按权重输出 zrangebyscore rank 77 99 将分数是在77-99之间的按权重输出 zrem rank zhaoliu 移除zhaoliu zcard rank 统计rank中的数量 zcount rank 77 88 统计在包含在77-88之间的rank中的数量 zrank rank wangwu 查看wangwu在rank中的下标 zrevrank rank zhangsan 查看zhangsan在rank中的翻转下标 2. Redis之Sorted Set底层算法分析
二分查找 3. 认证中心需求分析
用户登录 4. 公共项目环境搭建
创建数据库
db_imooc.sql
/*Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version : 80018Source Host : localhost:3306Source Schema : db_imoocTarget Server Type : MySQLTarget Server Version : 80018File Encoding : 65001Date: 14/11/2020 19:06:41
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS 0;-- ----------------------------
-- Table structure for t_dictionary
-- ----------------------------
DROP TABLE IF EXISTS t_dictionary;
CREATE TABLE t_dictionary (id int(11) NOT NULL AUTO_INCREMENT,type varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,data varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,display_order int(11) NULL DEFAULT 0,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB AUTO_INCREMENT 415 CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT DYNAMIC;-- ----------------------------
-- Records of t_dictionary
-- ----------------------------
INSERT INTO t_dictionary VALUES (1, TableType , Regular|大厅, 0);
INSERT INTO t_dictionary VALUES (2, TableType , Bar|吧台, 0);
INSERT INTO t_dictionary VALUES (3, TableType , Window|靠窗, 0);
INSERT INTO t_dictionary VALUES (4, TableType , Outdoor|户外, 0);
INSERT INTO t_dictionary VALUES (5, TableType , Private|包间, 0);
INSERT INTO t_dictionary VALUES (7, RestaurantTag , 24|hours|24小时营业, 0);
INSERT INTO t_dictionary VALUES (8, RestaurantTag , Afternoon|tea|下午茶, 0);
INSERT INTO t_dictionary VALUES (9, RestaurantTag , All|you|can|eat|自助餐, 0);
INSERT INTO t_dictionary VALUES (10, RestaurantTag , Bistros|酒馆, 0);
INSERT INTO t_dictionary VALUES (11, RestaurantTag , Breakfast|早餐, 0);
INSERT INTO t_dictionary VALUES (12, RestaurantTag , Bund|view|外滩风景, 0);
INSERT INTO t_dictionary VALUES (13, RestaurantTag , Classic|Shanghai|老上海, 0);
INSERT INTO t_dictionary VALUES (14, RestaurantTag , Cocktails|鸡尾酒, 0);
INSERT INTO t_dictionary VALUES (15, RestaurantTag , Credit|cards|accepted|可刷卡, 0);
INSERT INTO t_dictionary VALUES (16, RestaurantTag , Delivery|可送外卖, 0);
INSERT INTO t_dictionary VALUES (17, RestaurantTag , Pet|friendly|宠物友好, 0);
INSERT INTO t_dictionary VALUES (18, RestaurantTag , Kids|friendly||适合小孩, 0);
INSERT INTO t_dictionary VALUES (19, RestaurantTag , Fine|dining|顶级餐厅, 0);
INSERT INTO t_dictionary VALUES (20, RestaurantTag , Free|parking|免费停车, 0);
INSERT INTO t_dictionary VALUES (21, RestaurantTag , Lounge|酒廊, 0);
INSERT INTO t_dictionary VALUES (22, RestaurantTag , Lunch|set|午市套餐, 0);
INSERT INTO t_dictionary VALUES (23, RestaurantTag , Group|dining|团体, 0);
INSERT INTO t_dictionary VALUES (24, RestaurantTag , Healthy|健康, 0);
INSERT INTO t_dictionary VALUES (25, RestaurantTag , Historic|building|历史建筑, 0);
INSERT INTO t_dictionary VALUES (26, RestaurantTag , Hotel|restaurant||酒店餐厅, 0);
INSERT INTO t_dictionary VALUES (27, RestaurantTag , Ice|cream|冰激凌, 0);
INSERT INTO t_dictionary VALUES (28, RestaurantTag , Late|night|dining|夜宵, 0);
INSERT INTO t_dictionary VALUES (29, RestaurantTag , Non-smoking|有无烟区, 0);
INSERT INTO t_dictionary VALUES (30, RestaurantTag , Notable|wine|list|葡萄酒, 0);
INSERT INTO t_dictionary VALUES (32, RestaurantTag , Outdoor|seating|户外餐桌, 0);
INSERT INTO t_dictionary VALUES (33, RestaurantTag , Performance|现场表演, 0);
INSERT INTO t_dictionary VALUES (34, RestaurantTag , Romantic||浪漫, 0);
INSERT INTO t_dictionary VALUES (35, RestaurantTag , Ramen|日式拉面, 0);
INSERT INTO t_dictionary VALUES (36, RestaurantTag , Salads|沙拉, 0);
INSERT INTO t_dictionary VALUES (37, RestaurantTag , Sandwiches Delis|三明治熟食, 0);
INSERT INTO t_dictionary VALUES (38, RestaurantTag , Smoothies|冰沙, 0);
INSERT INTO t_dictionary VALUES (39, RestaurantTag , Tapas|西班牙小吃, 0);
INSERT INTO t_dictionary VALUES (40, RestaurantTag , Themed|restaurant|主题餐厅, 0);
INSERT INTO t_dictionary VALUES (41, RestaurantTag , Villa|别墅, 0);
INSERT INTO t_dictionary VALUES (43, Cuisine , American|北美菜, 0);
INSERT INTO t_dictionary VALUES (45, Cuisine , Australian|澳洲菜, 0);
INSERT INTO t_dictionary VALUES (48, Cuisine , Barbecue|烧烤, 0);
INSERT INTO t_dictionary VALUES (50, Cuisine , Beijing|京菜, 0);
INSERT INTO t_dictionary VALUES (63, Cuisine , Dongbei|东北菜, 0);
INSERT INTO t_dictionary VALUES (65, Cuisine , Hunan|湘菜, 0);
INSERT INTO t_dictionary VALUES (68, Cuisine , French|法国菜, 0);
INSERT INTO t_dictionary VALUES (70, Cuisine , Fusion|创意菜, 0);
INSERT INTO t_dictionary VALUES (71, Cuisine , German|德国菜, 0);
INSERT INTO t_dictionary VALUES (72, Cuisine , Grocery|杂货, 0);
INSERT INTO t_dictionary VALUES (73, Cuisine , Halal|清真, 0);
INSERT INTO t_dictionary VALUES (76, Cuisine , Hot Pot|火锅, 0);
INSERT INTO t_dictionary VALUES (79, Cuisine , Indian|印度菜, 0);
INSERT INTO t_dictionary VALUES (80, Cuisine , Indonesian|印尼菜, 0);
INSERT INTO t_dictionary VALUES (81, Cuisine , Italian|意大利菜, 0);
INSERT INTO t_dictionary VALUES (82, Cuisine , Japanese|日本料理, 0);
INSERT INTO t_dictionary VALUES (84, Cuisine , Jiangxi|赣菜, 0);
INSERT INTO t_dictionary VALUES (88, Cuisine , Malaysian|马来西亚菜, 0);
INSERT INTO t_dictionary VALUES (91, Cuisine , Mediterranean|地中海菜, 0);
INSERT INTO t_dictionary VALUES (92, Cuisine , Mexican / Tex-Mex|墨西哥菜, 0);
INSERT INTO t_dictionary VALUES (94, Cuisine , Other|其他, 0);
INSERT INTO t_dictionary VALUES (102, Cuisine , Portuguese|葡国菜, 0);
INSERT INTO t_dictionary VALUES (103, Cuisine , Russian|俄国菜, 0);
INSERT INTO t_dictionary VALUES (104, Cuisine , Sandwiches Delis|三明治简食, 0);
INSERT INTO t_dictionary VALUES (107, Cuisine , Shaoxing|绍兴菜, 0);
INSERT INTO t_dictionary VALUES (111, Cuisine , Shanghainese|上海菜, 0);
INSERT INTO t_dictionary VALUES (112, Cuisine , Singaporean|新加坡菜, 0);
INSERT INTO t_dictionary VALUES (113, Cuisine , South American|南美菜, 0);
INSERT INTO t_dictionary VALUES (114, Cuisine , Spanish|西班牙菜, 0);
INSERT INTO t_dictionary VALUES (115, Cuisine , Steakhouse|牛排店, 0);
INSERT INTO t_dictionary VALUES (117, Cuisine , Taiwanese|台湾菜, 0);
INSERT INTO t_dictionary VALUES (118, Cuisine , Thai|泰国菜, 0);
INSERT INTO t_dictionary VALUES (121, Cuisine , Turkish|土耳其菜, 0);
INSERT INTO t_dictionary VALUES (122, Cuisine , Vegetarian|素食, 0);
INSERT INTO t_dictionary VALUES (123, Cuisine , Vietnamese|越南菜, 0);
INSERT INTO t_dictionary VALUES (124, Cuisine , Wine Bar|红酒吧, 0);
INSERT INTO t_dictionary VALUES (126, Cuisine , Yunnan|云南菜, 0);
INSERT INTO t_dictionary VALUES (129, Cuisine , Zhejiang|浙菜, 0);
INSERT INTO t_dictionary VALUES (130, nations , Afghanistan | 阿富汗, 0);
INSERT INTO t_dictionary VALUES (131, nations , Albania | 阿尔巴尼亚, 0);
INSERT INTO t_dictionary VALUES (132, nations , Algeria | 阿尔及利亚, 0);
INSERT INTO t_dictionary VALUES (133, nations , Andorra | 安道尔, 0);
INSERT INTO t_dictionary VALUES (134, nations , Angola | 安哥拉, 0);
INSERT INTO t_dictionary VALUES (135, nations , Argentina | 阿根廷, 0);
INSERT INTO t_dictionary VALUES (136, nations , Armenia | 亚美尼亚, 0);
INSERT INTO t_dictionary VALUES (137, nations , Australia | 澳大利亚, 0);
INSERT INTO t_dictionary VALUES (138, nations , Austria | 奥地利, 0);
INSERT INTO t_dictionary VALUES (139, nations , Azerbaijan | 阿塞拜疆, 0);
INSERT INTO t_dictionary VALUES (140, nations , Bahamas | 巴哈马, 0);
INSERT INTO t_dictionary VALUES (141, nations , Bahrain | 巴林, 0);
INSERT INTO t_dictionary VALUES (142, nations , Bangladesh | 孟加拉国, 0);
INSERT INTO t_dictionary VALUES (143, nations , Barbados | 巴巴多斯, 0);
INSERT INTO t_dictionary VALUES (144, nations , Belarus | 白俄罗斯, 0);
INSERT INTO t_dictionary VALUES (145, nations , Belgium | 比利时, 0);
INSERT INTO t_dictionary VALUES (146, nations , Belize | 伯利兹, 0);
INSERT INTO t_dictionary VALUES (147, nations , Benin | 柏林, 0);
INSERT INTO t_dictionary VALUES (148, nations , Bhutan | 不丹, 0);
INSERT INTO t_dictionary VALUES (149, nations , Bolivia | 玻利维亚, 0);
INSERT INTO t_dictionary VALUES (150, nations , Bosnia-Herzegovina | 波斯尼亚和黑塞哥维那, 0);
INSERT INTO t_dictionary VALUES (151, nations , Botswana | 博茨瓦纳, 0);
INSERT INTO t_dictionary VALUES (152, nations , Brazil | 巴西, 0);
INSERT INTO t_dictionary VALUES (154, nations , Brunei | 文莱, 0);
INSERT INTO t_dictionary VALUES (155, nations , Bulgaria | 保加利亚, 0);
INSERT INTO t_dictionary VALUES (156, nations , Burkina | 布基纳法索, 0);
INSERT INTO t_dictionary VALUES (157, nations , Burma (Myanmar) | 缅甸, 0);
INSERT INTO t_dictionary VALUES (158, nations , Burundi | 布隆迪, 0);
INSERT INTO t_dictionary VALUES (159, nations , Cambodia | 柬埔寨, 0);
INSERT INTO t_dictionary VALUES (160, nations , Cameroon | 喀麦隆, 0);
INSERT INTO t_dictionary VALUES (161, nations , Canada | 加拿大, 0);
INSERT INTO t_dictionary VALUES (162, nations , Cape Verde Islands | 佛得角群岛, 0);
INSERT INTO t_dictionary VALUES (163, nations , Chad | 乍得, 0);
INSERT INTO t_dictionary VALUES (164, nations , Chile | 智利, 0);
INSERT INTO t_dictionary VALUES (166, nations , Colombia | 哥伦比亚, 0);
INSERT INTO t_dictionary VALUES (167, nations , Congo | 刚果, 0);
INSERT INTO t_dictionary VALUES (168, nations , Costa Rica | 哥斯达黎加, 0);
INSERT INTO t_dictionary VALUES (169, nations , Croatia | 克罗地亚, 0);
INSERT INTO t_dictionary VALUES (170, nations , Cuba | 古巴, 0);
INSERT INTO t_dictionary VALUES (171, nations , Cyprus | 塞浦路斯, 0);
INSERT INTO t_dictionary VALUES (172, nations , Czech Republic | 捷克共和国, 0);
INSERT INTO t_dictionary VALUES (173, nations , Denmark | 丹麦, 0);
INSERT INTO t_dictionary VALUES (174, nations , Djibouti | 吉布提, 0);
INSERT INTO t_dictionary VALUES (175, nations , Dominica | 多米尼加, 0);
INSERT INTO t_dictionary VALUES (176, nations , Dominican Republic | 多米尼加国共和国, 0);
INSERT INTO t_dictionary VALUES (177, nations , Ecuador | 厄瓜多尔, 0);
INSERT INTO t_dictionary VALUES (178, nations , Egypt | 埃及, 0);
INSERT INTO t_dictionary VALUES (179, nations , El Salvador | 萨尔瓦多, 0);
INSERT INTO t_dictionary VALUES (180, nations , England | 英格兰, 0);
INSERT INTO t_dictionary VALUES (181, nations , Eritrea | 厄立特里亚, 0);
INSERT INTO t_dictionary VALUES (182, nations , Estonia | 爱沙尼亚, 0);
INSERT INTO t_dictionary VALUES (183, nations , Ethiopia | 埃塞俄比亚, 0);
INSERT INTO t_dictionary VALUES (184, nations , Fiji | 斐济, 0);
INSERT INTO t_dictionary VALUES (185, nations , Finland | 芬兰, 0);
INSERT INTO t_dictionary VALUES (186, nations , France | 法国, 0);
INSERT INTO t_dictionary VALUES (187, nations , Gabon | 加蓬, 0);
INSERT INTO t_dictionary VALUES (188, nations , Gambia | 冈比亚, 0);
INSERT INTO t_dictionary VALUES (189, nations , Georgia | 格鲁吉亚, 0);
INSERT INTO t_dictionary VALUES (190, nations , Germany | 德国, 0);
INSERT INTO t_dictionary VALUES (191, nations , Ghana | 加纳, 0);
INSERT INTO t_dictionary VALUES (192, nations , Greece | 希腊, 0);
INSERT INTO t_dictionary VALUES (193, nations , Grenada | 格林纳达, 0);
INSERT INTO t_dictionary VALUES (194, nations , Guatemala | 危地马拉, 0);
INSERT INTO t_dictionary VALUES (195, nations , Guinea | 几内亚, 0);
INSERT INTO t_dictionary VALUES (196, nations , Guyana | 圭亚那, 0);
INSERT INTO t_dictionary VALUES (197, nations , Haiti | 海地, 0);
INSERT INTO t_dictionary VALUES (198, nations , Netherlands | 荷兰, 0);
INSERT INTO t_dictionary VALUES (199, nations , Honduras | 洪都拉斯, 0);
INSERT INTO t_dictionary VALUES (200, nations , Hungary | 匈牙利, 0);
INSERT INTO t_dictionary VALUES (201, nations , Iceland | 冰岛, 0);
INSERT INTO t_dictionary VALUES (202, nations , India | 印度, 0);
INSERT INTO t_dictionary VALUES (203, nations , Indonesia | 印度尼西亚, 0);
INSERT INTO t_dictionary VALUES (204, nations , Iran | 伊朗, 0);
INSERT INTO t_dictionary VALUES (205, nations , Iraq | 伊拉克, 0);
INSERT INTO t_dictionary VALUES (206, nations , Ireland | 爱尔兰, 0);
INSERT INTO t_dictionary VALUES (207, nations , Italy | 意大利, 0);
INSERT INTO t_dictionary VALUES (208, nations , Jamaica | 牙买加, 0);
INSERT INTO t_dictionary VALUES (209, nations , Japan | 日本, 0);
INSERT INTO t_dictionary VALUES (210, nations , Jordan | 约旦, 0);
INSERT INTO t_dictionary VALUES (211, nations , Kazakhstan | 哈萨克斯坦, 0);
INSERT INTO t_dictionary VALUES (212, nations , Kenya | 肯尼亚, 0);
INSERT INTO t_dictionary VALUES (213, nations , Kuwait | 科威特, 0);
INSERT INTO t_dictionary VALUES (214, nations , Laos | 老挝, 0);
INSERT INTO t_dictionary VALUES (215, nations , Latvia | 拉脱维亚, 0);
INSERT INTO t_dictionary VALUES (216, nations , Lebanon | 黎巴嫩, 0);
INSERT INTO t_dictionary VALUES (217, nations , Liberia | 利比里亚, 0);
INSERT INTO t_dictionary VALUES (218, nations , Libya | 利比亚, 0);
INSERT INTO t_dictionary VALUES (219, nations , Liechtenstein | 列支敦士登, 0);
INSERT INTO t_dictionary VALUES (220, nations , Lithuania | 立陶宛, 0);
INSERT INTO t_dictionary VALUES (221, nations , Luxembourg | 卢森堡, 0);
INSERT INTO t_dictionary VALUES (222, nations , Macedonia马其顿, 0);
INSERT INTO t_dictionary VALUES (223, nations , Madagascar | 马达加斯加, 0);
INSERT INTO t_dictionary VALUES (224, nations , Malawi | 马拉维, 0);
INSERT INTO t_dictionary VALUES (225, nations , Malaysia | 马来西亚, 0);
INSERT INTO t_dictionary VALUES (226, nations , Maldives | 马尔代夫, 0);
INSERT INTO t_dictionary VALUES (227, nations , Mali | 马里, 0);
INSERT INTO t_dictionary VALUES (228, nations , Malta | 马耳他, 0);
INSERT INTO t_dictionary VALUES (229, nations , Mauritania | 毛里塔尼亚, 0);
INSERT INTO t_dictionary VALUES (230, nations , Mauritius | 毛里求斯, 0);
INSERT INTO t_dictionary VALUES (231, nations , Mexico | 墨西哥, 0);
INSERT INTO t_dictionary VALUES (232, nations , Moldova | 摩尔多瓦, 0);
INSERT INTO t_dictionary VALUES (233, nations , Monaco | 摩纳哥, 0);
INSERT INTO t_dictionary VALUES (234, nations , Mongolia | 蒙古, 0);
INSERT INTO t_dictionary VALUES (235, nations , Montenegro | 黑山, 0);
INSERT INTO t_dictionary VALUES (236, nations , Morocco | 摩洛哥, 0);
INSERT INTO t_dictionary VALUES (237, nations , Mozambique | 莫桑比克, 0);
INSERT INTO t_dictionary VALUES (239, nations , Namibia | 纳米比亚, 0);
INSERT INTO t_dictionary VALUES (240, nations , Nepal | 尼泊尔, 0);
INSERT INTO t_dictionary VALUES (242, nations , New Zealand | 新西兰, 0);
INSERT INTO t_dictionary VALUES (243, nations , Nicaragua | 尼加拉瓜, 0);
INSERT INTO t_dictionary VALUES (244, nations , Niger | 尼日尔, 0);
INSERT INTO t_dictionary VALUES (245, nations , Nigeria | 尼日利亚, 0);
INSERT INTO t_dictionary VALUES (246, nations , North Korea | 朝鲜, 0);
INSERT INTO t_dictionary VALUES (247, nations , Norway | 挪威, 0);
INSERT INTO t_dictionary VALUES (248, nations , Oman | 阿曼, 0);
INSERT INTO t_dictionary VALUES (249, nations , Pakistan | 巴基斯坦, 0);
INSERT INTO t_dictionary VALUES (250, nations , Panama | 巴拿马, 0);
INSERT INTO t_dictionary VALUES (251, nations , Papua New Guinea | 巴布亚新几内亚, 0);
INSERT INTO t_dictionary VALUES (252, nations , Paraguay | 巴拉圭, 0);
INSERT INTO t_dictionary VALUES (253, nations , Peru | 秘鲁, 0);
INSERT INTO t_dictionary VALUES (254, nations , Philippines | 菲律宾, 0);
INSERT INTO t_dictionary VALUES (255, nations , Poland | 波兰, 0);
INSERT INTO t_dictionary VALUES (256, nations , Portugal | 葡萄牙, 0);
INSERT INTO t_dictionary VALUES (257, nations , Qatar | 卡塔尔, 0);
INSERT INTO t_dictionary VALUES (258, nations , Romania | 罗马尼亚, 0);
INSERT INTO t_dictionary VALUES (259, nations , Russia | 俄罗斯, 0);
INSERT INTO t_dictionary VALUES (260, nations , Rwanda | 卢旺达, 0);
INSERT INTO t_dictionary VALUES (261, nations , Saudi Arabia | 沙特阿拉伯, 0);
INSERT INTO t_dictionary VALUES (262, nations , Scotland | 苏格兰, 0);
INSERT INTO t_dictionary VALUES (263, nations , Senegal | 塞内加尔, 0);
INSERT INTO t_dictionary VALUES (264, nations , Serbia | 塞尔维亚, 0);
INSERT INTO t_dictionary VALUES (265, nations , Seychelles | 塞舌尔, 0);
INSERT INTO t_dictionary VALUES (266, nations , Sierra Leone | 塞拉里昂, 0);
INSERT INTO t_dictionary VALUES (267, nations , Singapore | 新加坡, 0);
INSERT INTO t_dictionary VALUES (268, nations , Slovakia | 斯洛伐克, 0);
INSERT INTO t_dictionary VALUES (269, nations , Slovenia | 斯洛伐尼亚, 0);
INSERT INTO t_dictionary VALUES (270, nations , Solomon Islands | 所罗门群岛, 0);
INSERT INTO t_dictionary VALUES (271, nations , Somalia | 索马里, 0);
INSERT INTO t_dictionary VALUES (272, nations , South Africa | 南非, 0);
INSERT INTO t_dictionary VALUES (273, nations , South Korea | 韩国, 0);
INSERT INTO t_dictionary VALUES (274, nations , Spain | 西班牙, 0);
INSERT INTO t_dictionary VALUES (275, nations , Sri Lanka | 斯里兰卡, 0);
INSERT INTO t_dictionary VALUES (276, nations , Sudan | 苏丹, 0);
INSERT INTO t_dictionary VALUES (277, nations , Suriname | 苏里南, 0);
INSERT INTO t_dictionary VALUES (278, nations , Swaziland | 斯维士兰, 0);
INSERT INTO t_dictionary VALUES (279, nations , Sweden | 瑞典, 0);
INSERT INTO t_dictionary VALUES (280, nations , Switzerland | 瑞士, 0);
INSERT INTO t_dictionary VALUES (281, nations , Syria | 叙利亚, 0);
INSERT INTO t_dictionary VALUES (282, nations , Taiwan | 台湾, 0);
INSERT INTO t_dictionary VALUES (283, nations , Tajikistan | 塔吉克斯坦, 0);
INSERT INTO t_dictionary VALUES (284, nations , Tanzania | 坦桑尼亚, 0);
INSERT INTO t_dictionary VALUES (285, nations , Thailand | 泰国, 0);
INSERT INTO t_dictionary VALUES (286, nations , Togo | 多哥, 0);
INSERT INTO t_dictionary VALUES (287, nations , Trinidad and Tobago | 特里尼达和多巴哥, 0);
INSERT INTO t_dictionary VALUES (289, nations , Tunisia | 突尼斯, 0);
INSERT INTO t_dictionary VALUES (290, nations , Turkey | 土耳其, 0);
INSERT INTO t_dictionary VALUES (291, nations , Turkmenistan | 土库曼斯坦, 0);
INSERT INTO t_dictionary VALUES (292, nations , Tuvalu | 图瓦卢, 0);
INSERT INTO t_dictionary VALUES (293, nations , Uganda | 乌干达, 0);
INSERT INTO t_dictionary VALUES (294, nations , Ukraine | 乌克兰, 0);
INSERT INTO t_dictionary VALUES (295, nations , United Arab Emirates | 阿拉伯联合大公国, 0);
INSERT INTO t_dictionary VALUES (296, nations , United Kingdom | 联合王国, 0);
INSERT INTO t_dictionary VALUES (297, nations , U.S.A. | 美国, 0);
INSERT INTO t_dictionary VALUES (298, nations , Uruguay | 乌拉圭, 0);
INSERT INTO t_dictionary VALUES (299, nations , Uzbekistan | 乌兹别克斯坦, 0);
INSERT INTO t_dictionary VALUES (300, nations , Vanuatu | 瓦努阿图, 0);
INSERT INTO t_dictionary VALUES (301, nations , Vatican City | 梵蒂冈, 0);
INSERT INTO t_dictionary VALUES (302, nations , Venezuela | 委内瑞拉, 0);
INSERT INTO t_dictionary VALUES (303, nations , Vietnam | 越南, 0);
INSERT INTO t_dictionary VALUES (304, nations , Wales | 威尔士, 0);
INSERT INTO t_dictionary VALUES (305, nations , Western Samoa | 西萨摩亚, 0);
INSERT INTO t_dictionary VALUES (306, nations , Yemen | 也门, 0);
INSERT INTO t_dictionary VALUES (307, nations , Yugoslavia | 南斯拉夫, 0);
INSERT INTO t_dictionary VALUES (308, nations , Zaire | 扎伊尔, 0);
INSERT INTO t_dictionary VALUES (309, nations , Zambia | 赞比亚, 0);
INSERT INTO t_dictionary VALUES (310, nations , Zimbabwe | 津巴布韦, 0);
INSERT INTO t_dictionary VALUES (311, nations , Anhui | 安徽, 0);
INSERT INTO t_dictionary VALUES (312, nations , Fujian | 福建, 0);
INSERT INTO t_dictionary VALUES (313, nations , Gansu | 甘肃, 0);
INSERT INTO t_dictionary VALUES (314, nations , Guangdong | 广东, 0);
INSERT INTO t_dictionary VALUES (315, nations , Guizhou | 贵州, 0);
INSERT INTO t_dictionary VALUES (316, nations , Hainan | 海南, 0);
INSERT INTO t_dictionary VALUES (317, nations , Hebei | 河北, 0);
INSERT INTO t_dictionary VALUES (318, nations , Heilongjiang | 黑龙江, 0);
INSERT INTO t_dictionary VALUES (319, nations , Henan | 河南, 0);
INSERT INTO t_dictionary VALUES (320, nations , Hubei | 湖北, 0);
INSERT INTO t_dictionary VALUES (321, nations , Hunan | 湖南, 0);
INSERT INTO t_dictionary VALUES (322, nations , Jiangsu | 江苏, 0);
INSERT INTO t_dictionary VALUES (323, nations , Jiangxi | 江西, 0);
INSERT INTO t_dictionary VALUES (324, nations , Jilin | 吉林, 0);
INSERT INTO t_dictionary VALUES (325, nations , Liaoning | 辽宁, 0);
INSERT INTO t_dictionary VALUES (326, nations , Qinghai | 青海, 0);
INSERT INTO t_dictionary VALUES (327, nations , Shaanxi | 陕西, 0);
INSERT INTO t_dictionary VALUES (328, nations , Shandong | 山东, 0);
INSERT INTO t_dictionary VALUES (329, nations , Shanxi | 山西, 0);
INSERT INTO t_dictionary VALUES (330, nations , Sichuan | 四川, 0);
INSERT INTO t_dictionary VALUES (331, nations , Yunnan | 云南, 0);
INSERT INTO t_dictionary VALUES (332, nations , Zhejiang | 浙江, 0);
INSERT INTO t_dictionary VALUES (333, nations , Guangxi | 广西, 0);
INSERT INTO t_dictionary VALUES (334, nations , Inner Mongolia | 内蒙古, 0);
INSERT INTO t_dictionary VALUES (335, nations , Ningxia | 宁夏, 0);
INSERT INTO t_dictionary VALUES (336, nations , Xinjiang | 新疆, 0);
INSERT INTO t_dictionary VALUES (337, nations , Tibet | 西藏, 0);
INSERT INTO t_dictionary VALUES (338, nations , Beijing | 北京, 0);
INSERT INTO t_dictionary VALUES (339, nations , Chongqing | 重庆, 0);
INSERT INTO t_dictionary VALUES (340, nations , Shanghai | 上海, 0);
INSERT INTO t_dictionary VALUES (341, nations , Tianjin | 天津, 0);
INSERT INTO t_dictionary VALUES (342, nations , Hong Kong | 香港, 0);
INSERT INTO t_dictionary VALUES (343, nations , Macau | 澳门, 0);
INSERT INTO t_dictionary VALUES (346, RestaurantTag , Wifi|无线上网, 0);
INSERT INTO t_dictionary VALUES (349, RestaurantTag , Good|View|有景观位, 0);
INSERT INTO t_dictionary VALUES (351, RestaurantTag , Big|Party|大型宴会, 0);
INSERT INTO t_dictionary VALUES (352, RestaurantTag , Birthday|Party|生日宴会, 0);
INSERT INTO t_dictionary VALUES (353, RestaurantTag , BYOB|自带酒水, 0);
INSERT INTO t_dictionary VALUES (354, RestaurantStyle , 朋友聚餐, 0);
INSERT INTO t_dictionary VALUES (355, RestaurantStyle , 家庭聚会, 0);
INSERT INTO t_dictionary VALUES (356, RestaurantStyle , 随便吃吃, 0);
INSERT INTO t_dictionary VALUES (357, RestaurantStyle , 休闲小憩, 0);
INSERT INTO t_dictionary VALUES (358, RestaurantStyle , 情侣约会, 0);
INSERT INTO t_dictionary VALUES (359, RestaurantStyle , 商务宴请, 0);
INSERT INTO t_dictionary VALUES (360, InviteStatus , 即将接洽, 0);
INSERT INTO t_dictionary VALUES (361, InviteStatus , 等待老板决定, 0);
INSERT INTO t_dictionary VALUES (362, InviteStatus , 合同签署中, 0);
INSERT INTO t_dictionary VALUES (363, InviteStatus , 合同已经签订, 0);
INSERT INTO t_dictionary VALUES (370, Cuisine, All-You-Can-Eat|自助餐, 0);
INSERT INTO t_dictionary VALUES (371, Cuisine, Bar|酒吧, 0);
INSERT INTO t_dictionary VALUES (372, Cuisine, Cafe|咖啡厅, 0);
INSERT INTO t_dictionary VALUES (373, Cuisine, Cantonese|粤菜, 0);
INSERT INTO t_dictionary VALUES (374, Cuisine, Dessert|甜品, 0);
INSERT INTO t_dictionary VALUES (375, Cuisine, Global Cuisine|环球美食, 0);
INSERT INTO t_dictionary VALUES (376, Cuisine, Middle Eastern|中东菜, 0);
INSERT INTO t_dictionary VALUES (377, Cuisine, Southeast Asian|东南亚菜, 0);
INSERT INTO t_dictionary VALUES (378, Cuisine, Zhejiang|浙江菜, 0);
INSERT INTO t_dictionary VALUES (379, Cuisine, Fast Casual|小吃快餐, 0);
INSERT INTO t_dictionary VALUES (380, nations, Israel, 0);
INSERT INTO t_dictionary VALUES (381, nations, East Timor, 0);
INSERT INTO t_dictionary VALUES (382, nations, Central African Republic, 0);
INSERT INTO t_dictionary VALUES (383, nations, S?o Tomé and Principe, 0);
INSERT INTO t_dictionary VALUES (384, nations, Ivory Coast, 0);
INSERT INTO t_dictionary VALUES (385, nations, Lesotho, 0);
INSERT INTO t_dictionary VALUES (386, nations, Equatorial Guinea, 0);
INSERT INTO t_dictionary VALUES (387, nations, Guinea Bissau, 0);
INSERT INTO t_dictionary VALUES (400, Cuisine, Sushi|寿司, 0);
INSERT INTO t_dictionary VALUES (401, Cuisine, British|英国菜, 0);
INSERT INTO t_dictionary VALUES (402, Cuisine, Dim Sum|早茶点心, 0);
INSERT INTO t_dictionary VALUES (403, Cuisine, Xibei / Xinjiang|西北菜/新疆菜, 0);
INSERT INTO t_dictionary VALUES (405, Cuisine, Guizhou|黔菜, 0);
INSERT INTO t_dictionary VALUES (406, Cuisine, Pizza|披萨, 0);
INSERT INTO t_dictionary VALUES (408, Cuisine, Seafood|海鲜, 0);
INSERT INTO t_dictionary VALUES (409, Cuisine, Anhui|徽菜, 0);
INSERT INTO t_dictionary VALUES (411, Cuisine, Sichuan|川菜, 0);
INSERT INTO t_dictionary VALUES (412, Cuisine, Korean|韩国料理, 0);
INSERT INTO t_dictionary VALUES (413, Cuisine, Juice Beverages|果汁饮料, 0);
INSERT INTO t_dictionary VALUES (414, Cuisine, Bakery Pastries|面包烘焙, 0);-- ----------------------------
-- Table structure for t_diners
-- ----------------------------
DROP TABLE IF EXISTS t_diners;
CREATE TABLE t_diners (id int(11) NOT NULL AUTO_INCREMENT,username varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,nickname varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 昵称,phone varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,email varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,password varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,avatar_url varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 头像,roles varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT COMMENT 角色,is_valid tinyint(1) NULL DEFAULT NULL,create_date datetime(0) NULL DEFAULT NULL,update_date datetime(0) NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB AUTO_INCREMENT 6 CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci ROW_FORMAT DYNAMIC;-- ----------------------------
-- Records of t_diners
-- ----------------------------
INSERT INTO t_diners VALUES (1, abc, 昵称st, 13888888888, abcimooc.com, e10adc3949ba59abbe56e057f20f883e, /abc, ROLE_USER, 1, 2020-11-06 16:17:52, 2020-11-06 16:17:55);
INSERT INTO t_diners VALUES (2, test, test, 13666666666, NULL, e10adc3949ba59abbe56e057f20f883e, /test, ROLE_USER, 1, 2020-11-12 12:01:13, 2020-11-12 12:01:13);
INSERT INTO t_diners VALUES (3, test2, test2, 13666666667, NULL, e10adc3949ba59abbe56e057f20f883e, /test2, ROLE_USER, 1, 2020-11-12 17:47:12, 2020-11-12 17:47:12);
INSERT INTO t_diners VALUES (5, aaa, aaa, 12311112222, NULL, e10adc3949ba59abbe56e057f20f883e, /aaa, ROLE_USER, 1, 2020-11-13 12:29:49, 2020-11-13 12:29:49);-- ----------------------------
-- Table structure for t_feed
-- ----------------------------
DROP TABLE IF EXISTS t_feed;
CREATE TABLE t_feed (id int(11) NOT NULL AUTO_INCREMENT,content varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 内容,fk_diner_id int(11) NULL DEFAULT NULL,praise_amount int(11) NULL DEFAULT NULL COMMENT 点赞数量,comment_amount int(11) NULL DEFAULT NULL COMMENT 评论数量,fk_restaurant_id int(11) NULL DEFAULT NULL,create_date datetime(0) NULL DEFAULT NULL,update_date datetime(0) NULL DEFAULT NULL,is_valid tinyint(1) NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci ROW_FORMAT DYNAMIC;-- ----------------------------
-- Records of t_feed
-- ------------------------------ ----------------------------
-- Table structure for t_follow
-- ----------------------------
DROP TABLE IF EXISTS t_follow;
CREATE TABLE t_follow (id int(11) NOT NULL AUTO_INCREMENT,diner_id int(11) NULL DEFAULT NULL,follow_diner_id int(11) NULL DEFAULT NULL,is_valid tinyint(1) NULL DEFAULT NULL,create_date datetime(0) NULL DEFAULT NULL,update_date datetime(0) NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE,INDEX index_followeddiner_valid(follow_diner_id, is_valid) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT DYNAMIC;-- ----------------------------
-- Records of t_follow
-- ------------------------------ ----------------------------
-- Table structure for t_restaurant
-- ----------------------------
DROP TABLE IF EXISTS t_restaurant;
CREATE TABLE t_restaurant (id int(11) NOT NULL AUTO_INCREMENT,Name varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT the En Name of the restaurant,CnName varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,X double NULL DEFAULT NULL,Y double NULL DEFAULT NULL,Location varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT En location of the restaurant,CnLocation varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,Area varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT city.district.neighbourhood\r\nExample: Shanghai.Xuhui.Xujiahui,CnArea varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,Traffic varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT the information/descripton of the restaurant,Telephone varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT Phone of the restaurant,Email varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,Website varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,Cuisine varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,AveragePrice varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,AvgLunchPrice decimal(19, 0) NULL DEFAULT NULL COMMENT Average price of lunch,Introduction varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT Indtroduction of the restaurant,Status int(11) NULL DEFAULT 0 COMMENT 1Opened 0Closed,CreateDT datetime(0) NULL DEFAULT NULL,IsValid smallint(1) NULL DEFAULT 1 COMMENT 1Valid 0Invalid,Thumbnail varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT pics at the list, value would be:\r\nbasepath/original/picname,OpenHours varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,LikeVotes int(10) NULL DEFAULT 0 COMMENT the percentage of people like it,DislikeVotes int(10) NULL DEFAULT 0 COMMENT How many people votes,Amenities varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 设备,Tags varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT tags of the restaurant,OpenDate datetime(0) NULL DEFAULT NULL,closeDate datetime(0) NULL DEFAULT NULL,CityId int(11) NULL DEFAULT 21 COMMENT 城市id,PRIMARY KEY (id) USING BTREE,INDEX index_isvalid(IsValid) USING BTREE
) ENGINE InnoDB AUTO_INCREMENT 23 CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT DYNAMIC;-- ----------------------------
-- Records of t_restaurant
-- ----------------------------
INSERT INTO t_restaurant VALUES (14, 1931 Pub, 名古, 31.2158508275268, 121.461839852847, 112 Maoming Nan Lu, near Nanchang Lu, 茂名南路112号, 近南昌路, Xuhui.Fmr French Concession, , , 021 6472 5264, , , Shanghainese, Chinese, ¥¥, 0, , NULL, 2014-05-04 19:26:28, 1, , , 1, 0, , , 2016-01-04 11:22:23, 2016-01-04 11:22:23, 21);
INSERT INTO t_restaurant VALUES (15, 2001 Hong Kong Teahouse, 2001港式茶餐, 31.21385, 121.46051, 55 Shaanxi Nan Lu, near Changle Lu, 陕西南路55号, 近长乐路, Xuhui.Fmr French Concession, , , 021 5467 0205, , , Dim Sum, Chinese, ¥, 0, , NULL, 2014-05-04 19:26:28, 4, , , 0, 0, , , 2016-01-04 11:22:23, 2016-01-04 11:22:23, 21);
INSERT INTO t_restaurant VALUES (16, 2nd floor, 2nd floor, 31.2162, 121.447998, 2/F, 810 Changle Lu,near Changshu Lu, 长乐路810号2楼, 近常熟路, Xuhui.Fmr French Concession, , , 13761133471, , http://www.2ndfloor.asia, Cafe, ¥, 0, , NULL, 2014-05-04 19:26:28, 3, , , 1, 0, , , 2016-01-04 11:22:23, 2016-01-04 11:22:23, 21);
INSERT INTO t_restaurant VALUES (17, 400 Celsius, 400 Celsius, 31.19436, 121.43797, 1 Hongqiao Lu, 1/F, Grand Gateway, near Caoxi Bei Lu, Metro Line 1 Xujiahui Station, 虹桥路1号港汇广场1楼, 近漕溪北路, 地铁1号线徐家汇站, Xuhui.Xujiahui, , , 021 6447 0770, , , Steakhouse, ¥¥¥¥, 0, , NULL, 2014-05-04 19:26:28, 3, , , 0, 0, , , 2016-01-04 11:22:23, 2016-01-04 11:22:23, 21);
INSERT INTO t_restaurant VALUES (18, 5 on the Bund, 5 on the Bund, 31.234482, 121.490753, Five on the Bund,20 Guangdong Lu, near Zhongshan Dong Yi Lu, 广东路20号, 近中山东一路, Huangpu.The Bund, , , , , , Global Cuisine, ¥¥¥¥, 0, , NULL, 2014-05-04 19:26:28, 3, , , 0, 0, , , 2016-01-04 11:22:23, 2016-01-04 11:22:23, 21);
INSERT INTO t_restaurant VALUES (19, 5 Tables Bistro, 5桌餐厅, 31.2174481541175, 121.47318647082, 210 Danshui Lu, near Zizhong Lu, 淡水路210号, 近自忠路, Luwan.Xintiandi, , , 021 3304 1205, , www.weibo.com/5tables, European, ¥¥¥¥, 0, , NULL, 2014-05-04 19:26:28, 4, , , 0, 0, , , 2016-01-04 11:22:23, 2016-01-04 11:22:23, 21);
INSERT INTO t_restaurant VALUES (20, 57 Du Xiang, 57度湘, 31.2250117063411, 121.47824432639, 138 Huaihai Zhong Lu, Infinity Plaza, 4/F, Room 401, near Longmen Lu, 淮海路138号无限度广场4楼401室, 近龙门路, Xuhui.Huaihai Zhong Lu, , , 021 3315 0057, , , Hunan, Chinese, ¥, 0, , NULL, 2014-05-04 19:26:28, 1, restaurant/20/restaurant/T/160_160/1399622680327.JPG, Daily 11am-9pm, 17, 5, , , 2016-01-04 11:22:23, 2016-01-04 11:22:23, 21);
INSERT INTO t_restaurant VALUES (21, 609 Pho, 609 Pho, 31.237629, 121.438797, 609 Anyuan Lu, near Jiaozhou Lu, 安源路609号, 近胶州路, Jing\an, , , 18201753996, , , Vietnamese, ¥, 0, , NULL, 2014-05-04 19:26:28, 4, , , 0, 0, , , 2016-01-04 11:22:23, 2016-01-04 11:22:23, 21);
INSERT INTO t_restaurant VALUES (22, 70s Restaurant, 70后饭吧, 31.2398228737211, 121.438096413353, 1217 Changde Lu, near Changshou Lu, 常德路1217号, 近长寿路, Putuo, , , 021 6040 2808, , , Chinese, ¥¥, 0, , NULL, 2014-05-04 19:26:28, 1, restaurant/22/restaurant/160_160/14075670693130533.JPG, , 7, 2, , , 2016-01-04 11:22:23, 2016-01-04 11:22:23, 21);-- ----------------------------
-- Table structure for t_seckill_vouchers
-- ----------------------------
DROP TABLE IF EXISTS t_seckill_vouchers;
CREATE TABLE t_seckill_vouchers (id int(11) NOT NULL AUTO_INCREMENT,fk_voucher_id int(11) NULL DEFAULT NULL,amount int(11) NULL DEFAULT NULL,start_time datetime(0) NULL DEFAULT NULL,end_time datetime(0) NULL DEFAULT NULL,is_valid int(11) NULL DEFAULT NULL,create_date datetime(0) NULL DEFAULT NULL,update_date datetime(0) NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci ROW_FORMAT DYNAMIC;-- ----------------------------
-- Records of t_seckill_vouchers
-- ------------------------------ ----------------------------
-- Table structure for t_voucher
-- ----------------------------
DROP TABLE IF EXISTS t_voucher;
CREATE TABLE t_voucher (id int(10) NOT NULL AUTO_INCREMENT,title varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 代金券标题,thumbnail varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 缩略图,amount int(11) NULL DEFAULT NULL COMMENT 抵扣金额,price decimal(10, 2) NULL DEFAULT NULL COMMENT 售价,status int(10) NULL DEFAULT NULL COMMENT -1过期 0下架 1上架,expire_time datetime(0) NULL DEFAULT NULL COMMENT 过期时间,redeem_restaurant_id int(10) NULL DEFAULT NULL COMMENT 验证餐厅,stock int(11) NULL DEFAULT 0 COMMENT 库存,stock_left int(11) NULL DEFAULT 0 COMMENT 剩余数量,description varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 描述信息,clause varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 使用条款,create_date datetime(0) NULL DEFAULT NULL,update_date datetime(0) NULL DEFAULT NULL,is_valid tinyint(1) NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT DYNAMIC;-- ----------------------------
-- Records of t_voucher
-- ------------------------------ ----------------------------
-- Table structure for t_voucher_order
-- ----------------------------
DROP TABLE IF EXISTS t_voucher_order;
CREATE TABLE t_voucher_order (id int(11) NOT NULL AUTO_INCREMENT,order_no int(11) NULL DEFAULT NULL,fk_voucher_id int(11) NULL DEFAULT NULL,fk_diner_id int(11) NULL DEFAULT NULL,qrcode varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 图片地址,payment tinyint(4) NULL DEFAULT NULL COMMENT 0微信支付 1支付宝支付,status tinyint(1) NULL DEFAULT NULL COMMENT 订单状态-1已取消 0未支付 1已支付 2已消费 3已过期,fk_seckill_id int(11) NULL DEFAULT NULL COMMENT 如果是抢购订单时抢购订单的id,order_type int(11) NULL DEFAULT NULL COMMENT 订单类型0正常订单 1抢购订单,create_date datetime(0) NULL DEFAULT NULL,update_date datetime(0) NULL DEFAULT NULL,is_valid int(11) NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci ROW_FORMAT DYNAMIC;-- ----------------------------
-- Records of t_voucher_order
-- ----------------------------SET FOREIGN_KEY_CHECKS 1;创建commons模块
pom.xml
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdfood-social-contact-parent/artifactIdgroupIdcom.imooc/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdcommons/artifactIddependencies!-- lombok --dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependency!-- hutool --dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactId/dependency!-- guava --dependencygroupIdcom.google.guava/groupIdartifactIdguava/artifactId/dependency!-- swagger --dependencygroupIdcom.battcn/groupIdartifactIdswagger-spring-boot-starter/artifactId/dependency!-- security --dependencygroupIdorg.springframework.security/groupIdartifactIdspring-security-core/artifactId/dependency/dependencies/project
全局常量类 全局异常类 ParameterException.java
package com.imooc.commons.exception;import com.imooc.commons.constant.ApiConstant;
import lombok.Getter;
import lombok.Setter;/*** 全局异常类*/
Getter
Setter
public class ParameterException extends RuntimeException {private Integer errorCode;public ParameterException() {super(ApiConstant.ERROR_MESSAGE);this.errorCode ApiConstant.ERROR_CODE;}public ParameterException(Integer errorCode) {this.errorCode errorCode;}public ParameterException(String message) {super(message);this.errorCode ApiConstant.ERROR_CODE;}public ParameterException(Integer errorCode, String message) {super(message);this.errorCode errorCode;}}
断言工具类 AssertUtil.java
package com.imooc.commons.utils;import cn.hutool.core.util.StrUtil;
import com.imooc.commons.constant.ApiConstant;
import com.imooc.commons.exception.ParameterException;/*** 断言工具类*/
public class AssertUtil {/*** 必须登录** param accessToken*/public static void mustLogin(String accessToken) {if (StrUtil.isBlank(accessToken)) {throw new ParameterException(ApiConstant.NO_LOGIN_CODE, ApiConstant.NO_LOGIN_MESSAGE);}}/*** 判断字符串非空** param str* param message*/public static void isNotEmpty(String str, String... message) {if (StrUtil.isBlank(str)) {execute(message);}}/*** 判断对象非空** param obj* param message*/public static void isNotNull(Object obj, String... message) {if (obj null) {execute(message);}}/*** 判断结果是否为真** param isTrue* param message*/public static void isTrue(boolean isTrue, String... message) {if (isTrue) {execute(message);}}/*** 最终执行方法** param message*/private static void execute(String... message) {String msg ApiConstant.ERROR_MESSAGE;if (message ! null message.length 0) {msg message[0];}throw new ParameterException(msg);}}
公共返回对象 公共返回对象工具类 ResultInfoUtil.java
package com.imooc.commons.utils;import com.imooc.commons.constant.ApiConstant;
import com.imooc.commons.model.domain.ResultInfo;/*** 公共返回对象工具类*/
public class ResultInfoUtil {/*** 请求出错返回** param path 请求路径* param T* return*/public static T ResultInfoT buildError(String path) {ResultInfoT resultInfo build(ApiConstant.ERROR_CODE,ApiConstant.ERROR_MESSAGE, path, null);return resultInfo;}/*** 请求出错返回** param errorCode 错误代码* param message 错误提示信息* param path 请求路径* param T* return*/public static T ResultInfoT buildError(int errorCode, String message, String path) {ResultInfoT resultInfo build(errorCode, message, path, null);return resultInfo;}/*** 请求成功返回** param path 请求路径* param T* return*/public static T ResultInfoT buildSuccess(String path) {ResultInfoT resultInfo build(ApiConstant.SUCCESS_CODE,ApiConstant.SUCCESS_MESSAGE, path, null);return resultInfo;}/*** 请求成功返回** param path 请求路径* param data 返回数据对象* param T* return*/public static T ResultInfoT buildSuccess(String path, T data) {ResultInfoT resultInfo build(ApiConstant.SUCCESS_CODE,ApiConstant.SUCCESS_MESSAGE, path, data);return resultInfo;}/*** 构建返回对象方法** param code* param message* param path* param data* param T* return*/public static T ResultInfoT build(Integer code, String message, String path, T data) {if (code null) {code ApiConstant.SUCCESS_CODE;}if (message null) {message ApiConstant.SUCCESS_MESSAGE;}ResultInfo resultInfo new ResultInfo();resultInfo.setCode(code);resultInfo.setMessage(message);resultInfo.setPath(path);resultInfo.setData(data);return resultInfo;}}
5. Redis保存授权中心令牌
5.1. 创建ms-oauth2-server模块
5.2. 配置文件
pom.xml
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdfood-social-contact-parent/artifactIdgroupIdcom.imooc/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdms-oauth2-server/artifactIddependencies!-- eureka client --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!-- spring web --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!-- spring data redis --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency!-- mybatis --dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependency!-- mysql --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependency!-- spring cloud security --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-security/artifactId/dependency!-- spring cloud oauth2 --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-oauth2/artifactId/dependency!-- commons 公共项目 --dependencygroupIdcom.imooc/groupIdartifactIdcommons/artifactIdversion1.0-SNAPSHOT/version/dependency!-- 自定义的元数据依赖 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactIdoptionaltrue/optional/dependency/dependencies/project
5.3. Security 配置类
SecurityConfiguration.java
package com.imooc.oauth2.server.config;import cn.hutool.crypto.digest.DigestUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;import javax.annotation.Resource;/*** Security 配置类*/
Configuration
EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {//注入 Redis 连接工厂Resourceprivate RedisConnectionFactory redisConnectionFactory;//初始化 RedisTokenStore 用于将 token 存储至 RedisBeanpublic RedisTokenStore redisTokenStore(){RedisTokenStore redisTokenStore new RedisTokenStore(redisConnectionFactory);redisTokenStore.setPrefix(TOKEN:);//设置key的层级前缀方便查询return redisTokenStore;}//初始化密码编码器用 MD5 加密密码Beanpublic PasswordEncoder passwordEncoder(){return new PasswordEncoder() {/*** 加密* param rawPassword 原始密码* return*/Overridepublic String encode(CharSequence rawPassword) {return DigestUtil.md5Hex(rawPassword.toString());}/*** 校验密码* param rawPassword 原始密码* param encodedPassword 加密密码* return*/Overridepublic boolean matches(CharSequence rawPassword, String encodedPassword) {return DigestUtil.md5Hex(rawPassword.toString()).equals(encodedPassword);}};}//初始化认证管理对象BeanOverridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}//放行和认证规则Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests()//放行的请求.antMatchers(/oauth/**,/actuator/**).permitAll().and().authorizeRequests()//其他请求必须认证才能访问.anyRequest().authenticated();}
}application.yml
server:port: 8082 # 端口spring:application:name: ms-oauth2-server # 应用名# 数据库datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rooturl: jdbc:mysql://127.0.0.1:3306/db_imooc?serverTimezoneAsia/ShanghaicharacterEncodingutf8useUnicodetrueuseSSLfalse# Redisredis:port: 6379host: 127.0.0.1timeout: 3000database: 2password: 111111# swaggerswagger:base-package: com.imooc.oauth2title: 慕课美食社交食客API接口文档# Oauth2
client:oauth2:client-id: appId # 客户端标识 IDsecret: 123456 # 客户端安全码# 授权类型grant_types:- password- refresh_token# token 有效时间单位秒token-validity-time: 3600refresh-token-validity-time: 3600# 客户端访问范围scopes:- api- all# 配置 Eureka Server 注册中心
eureka:instance:prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${server.port}client:service-url:defaultZone: http://localhost:8080/eureka/# Mybatis
mybatis:configuration:map-underscore-to-camel-case: true # 开启驼峰映射# 指标监控健康检查
management:endpoints:web:exposure:include: * # 暴露的端点
5.5 客户端配置类
ClientOAuth2DataConfiguration.java
package com.imooc.oauth2.server.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** 客户端配置类*/
Component
ConfigurationProperties(prefix client.oauth2)
Data
public class ClientOAuth2DataConfiguration {// 客户端标识 IDprivate String clientId;// 客户端安全码private String secret;// 授权类型private String[] grantTypes;// token有效期private int tokenValidityTime;// refresh-token有效期private int refreshTokenValidityTime;// 客户端访问范围private String[] scopes;
}5.6. 登录逻辑
5.6.1 公共实体类
BaseModel.java
package com.imooc.commons.model.base;import lombok.Getter;
import lombok.Setter;import java.io.Serializable;
import java.util.Date;/*** 实体对象公共属性*/
Getter
Setter
public class BaseModel implements Serializable {private Integer id;private Date createDate;private Date updateDate;private int isValid;
}5.6.2 食客实体类
Diners.java
package com.imooc.commons.model.pojo;import com.imooc.commons.model.base.BaseModel;
import lombok.Getter;
import lombok.Setter;/*** 食客实体类*/
Getter
Setter
public class Diners extends BaseModel {// 主键private Integer id;// 用户名private String username;// 昵称private String nickname;// 密码private String password;// 手机号private String phone;// 邮箱private String email;// 头像private String avatarUrl;// 角色private String roles;}
5.6.4 登录校验
UserService.java
package com.imooc.oauth2.server.service;import com.imooc.commons.model.pojo.Diners;
import com.imooc.commons.utils.AssertUtil;
import com.imooc.oauth2.server.mapper.DinersMapper;
import io.swagger.annotations.Authorization;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import javax.annotation.PreDestroy;
import javax.annotation.Resource;/*** 登录校验*/
Service
public class UserService implements UserDetailsService {Resourceprivate DinersMapper dinersMapper;Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {AssertUtil.isNotEmpty(username,请输入用户名);Diners diners dinersMapper.selectByAccountInfo(username);if (diners null){throw new UsernameNotFoundException(用户名或密码错误请重新输入);}return new User(username, diners.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(diners.getRoles()));}
}5.4 授权服务
AuthorizationServerConfiguration.java
package com.imooc.oauth2.server.config;import com.imooc.oauth2.server.service.UserService;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;import javax.annotation.Resource;/*** 授权服务*/
Configuration
EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {// 客户端配置类Resourceprivate ClientOAuth2DataConfiguration clientOAuth2DataConfiguration;//密码编码器Resourceprivate PasswordEncoder passwordEncoder;// 认证管理对象Resourceprivate AuthenticationManager authenticationManager;// RedisTokenSoreResourceprivate RedisTokenStore redisTokenStore;// 登录校验Resourceprivate UserService userService;/*** 配置令牌端点安全约束* param security* throws Exception*/Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {// 允许访问 token 的公钥默认 /oauth/token_key 是受保护的security.tokenKeyAccess(permitAll())// 允许检查 token 的状态默认 /oauth/check_token 是受保护的.checkTokenAccess(permitAll());}/*** 客户端配置 - 授权模型* param clients* throws Exception*/Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient(clientOAuth2DataConfiguration.getClientId()) // 客户端标识 ID.secret(passwordEncoder.encode(clientOAuth2DataConfiguration.getSecret())) // 客户端安全码.authorizedGrantTypes(clientOAuth2DataConfiguration.getGrantTypes()) // 授权类型.accessTokenValiditySeconds(clientOAuth2DataConfiguration.getTokenValidityTime()) // token 有效期.refreshTokenValiditySeconds(clientOAuth2DataConfiguration.getRefreshTokenValidityTime()) // 刷新 token 的有效期.scopes(clientOAuth2DataConfiguration.getScopes()); // 客户端访问范围}/*** 配置授权以及令牌的访问端点和令牌服务* param endpoints the endpoints configurer* throws Exception*/Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {// 认证器endpoints.authenticationManager(authenticationManager)// 具体登录的方法.userDetailsService(userService)// token 存储的方式Redis.tokenStore(redisTokenStore);}}5.7 启动类
Oauth2ServerApplication.java
package com.imooc.oauth2.server;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;MapperScan(com.imooc.oauth2.server.mapper)
SpringBootApplication
public class Oauth2ServerApplication {public static void main(String[] args) {SpringApplication.run(Oauth2ServerApplication.class,args);}
}5.8 测试
启动RegistryApplication、Oauth2ServerApplication
用postman测试 6. 重构认证授权中心增强令牌返回结果
6.1 重构认证端点返回结果
OAuthController.java
package com.imooc.oauth2.server.controller;import com.imooc.commons.model.domain.ResultInfo;
import com.imooc.commons.utils.ResultInfoUtil;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.util.LinkedHashMap;
import java.util.Map;/*** Oauth2 控制器*/
RestController
RequestMapping(oauth)
public class OAuthController {Resourceprivate TokenEndpoint tokenEndpoint;Resourceprivate HttpServletRequest request;PostMapping(token)public ResultInfo postAccessToken(Principal principal, RequestParam MapString, String parameters)throws HttpRequestMethodNotSupportedException {return custom(tokenEndpoint.postAccessToken(principal, parameters).getBody());}/*** 自定义 Token 返回对象* param accessToken* return*/private ResultInfo custom(OAuth2AccessToken accessToken) {DefaultOAuth2AccessToken token (DefaultOAuth2AccessToken) accessToken;MapString, Object data new LinkedHashMap(token.getAdditionalInformation());data.put(accessToken, token.getValue());data.put(expireIn, token.getExpiresIn());data.put(scopes, token.getScope());if (token.getRefreshToken() ! null) {data.put(refreshToken, token.getRefreshToken().getValue());}return ResultInfoUtil.buildSuccess(request.getServletPath(), data);}}6.2 重构登录逻辑增加令牌返回结果
添加登录认证对象
SignInIdentity.java
package com.imooc.commons.model.domain;import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** 登录认证对象*/
Getter
Setter
public class SignInIdentity implements UserDetails {// 主键private Integer id;// 用户名private String username;// 昵称private String nickname;// 密码private String password;// 手机号private String phone;// 邮箱private String email;// 头像private String avatarUrl;// 角色private String roles;// 是否有效 0无效 1有效private int isValid;// 角色集合, 不能为空private ListGrantedAuthority authorities;// 获取角色信息Overridepublic Collection? extends GrantedAuthority getAuthorities() {if (StrUtil.isNotBlank(this.roles)){// 获取数据库中的角色信息Lists.newArrayList();this.authorities Stream.of(this.roles.split(,)).map(role - {return new SimpleGrantedAuthority(role);}).collect(Collectors.toList());}else{// 如果角色为空则设置为 ROLE_USERthis.authorities AuthorityUtils.commaSeparatedStringToAuthorityList(ROLE_USER);}return this.authorities;}Overridepublic String getPassword() {return this.password;}Overridepublic boolean isAccountNonExpired() {return true;}Overridepublic boolean isAccountNonLocked() {return true;}Overridepublic boolean isCredentialsNonExpired() {return true;}Overridepublic boolean isEnabled() {return this.isValid ! 0 ;}
}修改登录认证对象
UserService.java 令牌增强对象增强返回的结果
AuthorizationServerConfiguration.java 7. 食客服务登录业务完善
7.1 添加依赖
pom.xml(ms-diners)
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdfood-social-contact-parent/artifactIdgroupIdcom.imooc/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdms-diners/artifactIddependencies!-- eureka client --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!-- spring web --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!-- mysql --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependency!-- spring data redis --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency!-- mybatis --dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependency!-- commons 公共项目 --dependencygroupIdcom.imooc/groupIdartifactIdcommons/artifactIdversion1.0-SNAPSHOT/version/dependency!-- 自定义的元数据依赖 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactIdoptionaltrue/optional/dependency/dependencies/project
7.2 配置文件
application.yml(ms-diners)
server:port: 8081 # 端口spring:application:name: ms-diners # 应用名# 数据库datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rooturl: jdbc:mysql://127.0.0.1:3306/db_imooc?serverTimezoneAsia/ShanghaicharacterEncodingutf8useUnicodetrueuseSSLfalse# Redisredis:port: 6379host: 127.0.0.1timeout: 3000password: 111111# swaggerswagger:base-package: com.imooc.dinerstitle: 慕课美食社交食客API接口文档# Oauth2 客户端信息
oauth2:client:client-id: appIdsecret: 123456grant_type: passwordscope: api# oauth2 服务地址
service:name:ms-oauth-server: http://ms-oauth2-server/# 配置 Eureka Server 注册中心
eureka:instance:prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${server.port}client:service-url:defaultZone: http://localhost:8080/eureka/# Mybatis
mybatis:configuration:map-underscore-to-camel-case: true # 开启驼峰映射
7.3 客户端配置类
OAuth2ClientConfiguration.java
package com.imooc.diners.config;import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** 客户端配置类*/
Getter
Setter
Component
ConfigurationProperties(prefix oauth2.client)
public class OAuth2ClientConfiguration {private String clientId;private String secret;private String grant_type;private String scope;
}7.4 Rest配置类
RestTemplateConfiguration.java
package com.imooc.diners.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.client.RestTemplate;/*** Rest 配置类*/
Configuration
public class RestTemplateConfiguration {LoadBalancedBeanpublic RestTemplate restTemplate(){return new RestTemplate();}}7.6 实体类
OAuthDinerInfo.java 视图对象实体类
LoginDinerInfo.java 7.5 登录逻辑
最终调用的是授权认证中心
食客服务业务逻辑层
DinersService.java
package com.imooc.diners.service;import cn.hutool.core.bean.BeanUtil;
import com.imooc.commons.constant.ApiConstant;
import com.imooc.commons.model.domain.ResultInfo;
import com.imooc.commons.utils.AssertUtil;
import com.imooc.commons.utils.ResultInfoUtil;
import com.imooc.diners.config.OAuth2ClientConfiguration;
import com.imooc.diners.domain.OAuthDinerInfo;
import com.imooc.diners.vo.LoginDinerInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;
import java.util.LinkedHashMap;/*** 食客服务业务逻辑层*/
Service
public class DinersService {Resourceprivate RestTemplate restTemplate;Value(${service.name.ms-oauth-server})private String oauthServiceName;Resourceprivate OAuth2ClientConfiguration oAuth2ClientConfiguration;/*** 登录* param account 帐号用户名或手机或邮箱* param password 密码* param path 请求路径* return*/public ResultInfo signIn(String account,String password,String path){// 1.参数校验AssertUtil.isNotEmpty(account,请输入登录账号);AssertUtil.isNotEmpty(password,请输入登录密码);// 2.构建请求头HttpHeaders headers new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);// 3.构建请求体请求参数MultiValueMapString, Object body new LinkedMultiValueMap();body.add(username,account);body.add(password,password);body.setAll(BeanUtil.beanToMap(oAuth2ClientConfiguration));HttpEntityMultiValueMapString, Object entity new HttpEntity(body, headers);// 4.设置 AuthorizationrestTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(oAuth2ClientConfiguration.getClientId(),oAuth2ClientConfiguration.getSecret()));// 5.发送请求ResponseEntityResultInfo result restTemplate.postForEntity(oauthServiceName oauth/token, entity, ResultInfo.class);// 6.处理返回结果AssertUtil.isTrue(result.getStatusCode() ! HttpStatus.OK,登录失败);ResultInfo resultInfo result.getBody();if (resultInfo.getCode() ! ApiConstant.SUCCESS_CODE){// 登录失败resultInfo.setData(resultInfo.getMessage());return resultInfo;}// 这里的 Data 是一个 LinkedHashMap 转成了域对象 OAuthDinerInfoOAuthDinerInfo dinerInfo BeanUtil.fillBeanWithMap((LinkedHashMap) resultInfo.getData(),new OAuthDinerInfo(),false);// 根据业务需求返回视图对象LoginDinerInfo loginDinerInfo new LoginDinerInfo();loginDinerInfo.setToken(dinerInfo.getAccessToken());loginDinerInfo.setAvatarUrl(dinerInfo.getAvatarUrl());loginDinerInfo.setNickname(dinerInfo.getNickname());return ResultInfoUtil.buildSuccess(path,loginDinerInfo);}}DinersController.java
package com.imooc.diners.controller;import com.imooc.commons.model.domain.ResultInfo;
import com.imooc.diners.service.DinersService;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;/*** 食客服务控制层*/
RestController
Api(tags 食客相关接口)
public class DinersController {Resourceprivate DinersService dinersService;Resourceprivate HttpServletRequest request;GetMapping(signin)public ResultInfo signIn(String account, String password){return dinersService.signIn(account,password, request.getServletPath());}
}7.7 启动类
DinersApplication.java 7.8 测试
http://localhost:8081/signin?accounttestpassword123456 8. 读取Redis登录用户信息和清空Redis用户信息
1.用户登录信息对象
common 公共项目添加用户登录信息对象
SignInDinerInfo.java
package com.imooc.commons.model.vo;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;Getter
Setter
ApiModel(value SignInDinerInfo,description 登录用户信息)
public class SignInDinerInfo {ApiModelProperty(主键)private Integer id;ApiModelProperty(用户名)private String username;ApiModelProperty(昵称)private String nickname;ApiModelProperty(手机号)private String phone;ApiModelProperty(邮箱)private String email;ApiModelProperty(头像)private String avatarUrl;ApiModelProperty(角色)private String roles;
}2.用户中心
UserController.java
package com.imooc.oauth2.server.controller;import cn.hutool.core.bean.BeanUtil;
import com.imooc.commons.model.domain.ResultInfo;
import com.imooc.commons.model.domain.SignInIdentity;
import com.imooc.commons.model.vo.SignInDinerInfo;
import com.imooc.commons.utils.ResultInfoUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;/*** 用户中心*/
RestController
public class UserController {Resourceprivate HttpServletRequest request;GetMapping(user/me)public ResultInfo getCurrentUser(Authentication authentication){// 获取登录用户的信息然后设置SignInIdentity signInIdentity (SignInIdentity) authentication.getPrincipal();// 转为前端可用的视图对象SignInDinerInfo dinerInfo new SignInDinerInfo();BeanUtils.copyProperties(signInIdentity,dinerInfo);return ResultInfoUtil.buildSuccess(request.getServletPath(),dinerInfo);}}3.认证失败处理
MyAutheticationEntryPoint.java
package com.imooc.oauth2.server.config;import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.commons.constant.ApiConstant;
import com.imooc.commons.model.domain.ResultInfo;
import com.imooc.commons.utils.ResultInfoUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** 认证失败处理*/
Component
public class MyAutheticationEntryPoint implements AuthenticationEntryPoint {Resourceprivate ObjectMapper objectMapper;Overridepublic void commence(HttpServletRequest request, HttpServletResponse response,AuthenticationException authException) throws IOException{//返回JSONresponse.setContentType(application/json;charsetutf-8);// 状态码 401response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);// 写出PrintWriter out response.getWriter();String errorMessage authException.getMessage();if (StringUtils.isBlank(errorMessage)){errorMessage 登录失败;}ResultInfo result ResultInfoUtil.buildError(ApiConstant.ERROR_CODE,errorMessage, request.getRequestURI());out.write(objectMapper.writeValueAsString(result));out.flush();out.close();}
}4.资源服务
ResourceServerConfig.java
package com.imooc.oauth2.server.config;import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;import javax.annotation.Resource;/*** 资源服务*/
Configuration
EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {Resourceprivate MyAutheticationEntryPoint autheticationEntryPoint;Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {resources.authenticationEntryPoint(autheticationEntryPoint);}Overridepublic void configure(HttpSecurity http) throws Exception {// 配置放行的资源http.authorizeRequests().anyRequest().authenticated().and().requestMatchers().antMatchers(/user/**);}
}5.测试
重新启动Oauth2ServerApplication http://localhost:8082/user/me?access_token73853d2d-9a99-4428-98e5-8354408b9255 这种方法也可以 UserController.java
package com.imooc.oauth2.server.controller;import cn.hutool.core.bean.BeanUtil;
import com.imooc.commons.model.domain.ResultInfo;
import com.imooc.commons.model.domain.SignInIdentity;
import com.imooc.commons.model.vo.SignInDinerInfo;
import com.imooc.commons.utils.ResultInfoUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;/*** 用户中心*/
RestController
public class UserController {Resourceprivate HttpServletRequest request;Resourceprivate RedisTokenStore redisTokenStore;GetMapping(user/me)public ResultInfo getCurrentUser(Authentication authentication){// 获取登录用户的信息然后设置SignInIdentity signInIdentity (SignInIdentity) authentication.getPrincipal();// 转为前端可用的视图对象SignInDinerInfo dinerInfo new SignInDinerInfo();BeanUtils.copyProperties(signInIdentity,dinerInfo);return ResultInfoUtil.buildSuccess(request.getServletPath(),dinerInfo);}// http://localhost:8082/user/me?access_tokenfee64a86-489f-493b-b622-dfa7c23cb501/*** 安全退出* param access_token* param authorization* return*/GetMapping(user/logout)public ResultInfo logout(String access_token,String authorization){//判断access_token是否为空为空将authorization 赋值给access_tokenif (StringUtils.isBlank(access_token)){access_token authorization;}//判断authorizaiton 是否为空if (StringUtils.isBlank(access_token)){return ResultInfoUtil.buildSuccess(request.getServletPath(),退出成功);}//判断bearer token 是否为空if (access_token.toLowerCase().contains(bearer .toLowerCase())){access_token access_token.toLowerCase().replace(bearer ,);}//清除redis token 信息OAuth2AccessToken oAuth2AccessToken redisTokenStore.readAccessToken(access_token);if (oAuth2AccessToken ! null){redisTokenStore.removeAccessToken(oAuth2AccessToken);OAuth2RefreshToken refreshToken oAuth2AccessToken.getRefreshToken();redisTokenStore.removeRefreshToken(refreshToken);}return ResultInfoUtil.buildSuccess(request.getServletPath(),退出成功);}
}再次重启服务 Oauth2ServerApplication
http://localhost:8082/user/logout?access_token73853d2d-9a99-4428-98e5-8354408b9255 或者这种方式 9. 网关登录校验 - 验证Redis中心令牌是否有效
1.配置文件
pom.xml(ms-gateway)
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdfood-social-contact-parent/artifactIdgroupIdcom.imooc/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdms-gateway/artifactIddependencies!-- spring cloud gateway --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency!-- eureka client --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!-- commons 公共项目 --dependencygroupIdcom.imooc/groupIdartifactIdcommons/artifactIdversion1.0-SNAPSHOT/version!-- 和 webflux 冲突 --exclusionsexclusiongroupIdcom.battcn/groupIdartifactIdswagger-spring-boot-starter/artifactId/exclusion/exclusions/dependency!-- 自定义的元数据依赖 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactIdoptionaltrue/optional/dependency/dependencies/project
2.配置文件
application.yml 3.白名单
网关白名单配置类
IgnoreUrlsConfig.java
package com.imooc.gateway.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import java.util.List;/*** 网关白名单配置*/
Data
Component
ConfigurationProperties(prefix secure.ignore)
public class IgnoreUrlsConfig {private ListString urls;
}4.Rest配置类
RestTemplateConfiguration.java
package com.imooc.gateway.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;Configuration
public class RestTemplateConfiguration {LoadBalancedBeanpublic RestTemplate restTemplate(){return new RestTemplate();}
}5.登录返回处理
HandleException.java
package com.imooc.gateway.component;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.commons.constant.ApiConstant;
import com.imooc.commons.model.domain.ResultInfo;
import com.imooc.commons.utils.ResultInfoUtil;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.Resource;import java.nio.charset.Charset;Component
public class HandleException {Resourceprivate ObjectMapper objectMapper;public MonoVoid writeError(ServerWebExchange exchange,String error){ServerHttpResponse response exchange.getResponse();ServerHttpRequest request exchange.getRequest();response.setStatusCode(HttpStatus.OK);response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);ResultInfo resultInfo ResultInfoUtil.buildError(ApiConstant.NO_LOGIN_CODE,ApiConstant.NO_LOGIN_MESSAGE,request.getURI().getPath());String resultInfoJson null;DataBuffer buffer null;try {resultInfoJson objectMapper.writeValueAsString(resultInfo);buffer response.bufferFactory().wrap(resultInfoJson.getBytes(Charset.forName(UTF-8)));} catch (JsonProcessingException ex) {ex.printStackTrace();}return response.writeWith(Mono.just(buffer));}
}6.全局过滤器 AuthGlobalFilter.java
package com.imooc.gateway.filter;import com.imooc.gateway.component.HandleException;
import com.imooc.gateway.config.IgnoreUrlsConfig;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.Resource;/*** 网关全局过滤器*/
Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {//网关白名单配置Resourceprivate IgnoreUrlsConfig ignoreUrlsConfig;Resourceprivate RestTemplate restTemplate;//集中返回处理Resourceprivate HandleException handleException;/*** 身份校验处理* param exchange* param chain* return*/Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1.判断当前的请求是否在白名单中AntPathMatcher pathMatcher new AntPathMatcher();boolean flag false;String path exchange.getRequest().getURI().getPath();for (String url : ignoreUrlsConfig.getUrls()) {if (pathMatcher.match(url,path)){flag true;break;}}//2.白名单放行if (flag){return chain.filter(exchange);}//3.获取 access_tokenString access_token exchange.getRequest().getQueryParams().getFirst(access_token);//4.判断 access_token 是否为空if (StringUtils.isBlank(access_token)){return handleException.writeError(exchange,请登录);}//5.校验 token 是否有效//ms-oauth2-server 注册中心服务名String checkTokenUrl http://ms-oauth2-server/oauth/check_token?token.concat(access_token);try {//6.发送远程请求验证tokenResponseEntityString entity restTemplate.getForEntity(checkTokenUrl, String.class);//token 无效的业务逻辑处理if (entity.getStatusCode() ! HttpStatus.OK){return handleException.writeError(exchange,Token was not recognised,token: .concat(access_token));}if (StringUtils.isBlank(entity.getBody())){return handleException.writeError(exchange,This token is invalid: .concat(access_token));}}catch (Exception e){return handleException.writeError(exchange,Token was not recognised,token: .concat(access_token));}//7.放行return chain.filter(exchange);}/*** 网关过滤器的排序数字越小优先级越高* return*/Overridepublic int getOrder() {return 0;}
}
7.测试
重新启动GatewayApplication localhost:80相当于网关
http://localhost/diners/signin?accounttestpassword123456 http://localhost/auth/user/me?access_token653cd330-951a-4909-a6e9-4b3be46d2de0 http://localhost/auth/oauth/check_token?token653cd330-951a-4909-a6e9-4b3be46d2de0 http://localhost/auth/user/logout?access_token653cd330-951a-4909-a6e9-4b3be46d2de0 10. 认证授权中心业务时序图总结
客户端请求资源未登录执行流程 请求资源-判断是否有令牌-没有令牌请登录 http://localhost/diners/hello?nameredis 客户发起登录请求-白名单放行-校验账号密码-账号密码不合法
客户发起登录请求-白名单放行-校验账号密码-登录-登录校验-生成令牌并存储至Redis-返回令牌信息 客户端请求资源已登录执行流程 请求资源-判断是否有令牌-校验令牌-令牌有效-放行继续请求资源-业务处理-返回
http://localhost/auth/user/me?access_token83932db5-34a5-4f83-b1c9-9d37e61eb56f
http://localhost/diners/hello?nameredisaccess_token83932db5-34a5-4f83-b1c9-9d37e61eb56f 实现单点登录
http://localhost/auth/user/logout?access_token5fb694e8-58b0-48e1-a20f-2340d485a47a 11. Redis保存手机短信验证码
11.1 Redis 配置类
RedisTemplateConfiguration.java
package com.imooc.diners.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;Configuration
public class RedisTemplateConfiguration {/*** redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类* param redisConnectionFactory* return*/Beanpublic RedisTemplateObject, Object redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplateObject, Object redisTemplate new RedisTemplate();redisTemplate.setConnectionFactory(redisConnectionFactory);// 使用Jackson2JsonRedisSerialize 替换默认序列化Jackson2JsonRedisSerializer jackson2JsonRedisSerializer new Jackson2JsonRedisSerializer(Object.class);ObjectMapper objectMapper new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);jackson2JsonRedisSerializer.setObjectMapper(objectMapper);// 设置key和value的序列化规则redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();return redisTemplate;}
}11.2 公共枚举类
RedisKeyConstant.java
package com.imooc.commons.constant;import lombok.Getter;Getter
public enum RedisKeyConstant {verify_code(verify_code:, 验证码);private String key;private String desc;RedisKeyConstant(String key,String desc){this.key key;this.desc desc;}
}11.3 Service
SendVerifyCodeService.java
package com.imooc.diners.service;import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.imooc.commons.constant.RedisKeyConstant;
import com.imooc.commons.utils.AssertUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;/*** 发送验证码业务逻辑层*/
Service
public class SendVerifyCodeService {Resourceprivate RedisTemplateString,String redisTemplate;/*** 发送验证码* param phone*/public void send(String phone){//1.检查非空AssertUtil.isNotEmpty(phone,手机号不能为空);//2.根据手机号查询是否已生成验证码已生成直接返回if (!checkCodeIsExpired(phone)){return;}//3.生成6位验证码String code RandomUtil.randomNumbers(6);//4.调用短信服务发送短信//5.发送成功将code 保存至 Redis ,失效时间 60sString key RedisKeyConstant.verify_code.getKey() phone;redisTemplate.opsForValue().set(key,code,60, TimeUnit.SECONDS);}/*** 根据手机号查询是否已生成验证码* param phone* return*/private boolean checkCodeIsExpired(String phone){String key RedisKeyConstant.verify_code.getKey() phone;String code redisTemplate.opsForValue().get(key);return StrUtil.isBlank(code) ? true : false;}}11.4 Controller
SendVerifyCodeController.java
package com.imooc.diners.controller;import com.imooc.commons.model.domain.ResultInfo;
import com.imooc.commons.utils.ResultInfoUtil;
import com.imooc.diners.service.SendVerifyCodeService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;/*** 发送验证码控制层*/
RestController
public class SendVerifyCodeController {Resourceprivate SendVerifyCodeService sendVerifyCodeService;Resourceprivate HttpServletRequest request;/*** 发送验证码* param phone* return*/GetMapping(send)public ResultInfo send(String phone){sendVerifyCodeService.send(phone);return ResultInfoUtil.buildSuccess(发送成功,request.getServletPath());}
}
11.5 网关配置
application.yml 11.6 测试
重新启动服务
http://localhost/diners/send?phone12311112222 12. 用户注册功能
12.1 是否已注册
Mapper
DinersMapper
package com.imooc.diners.mapper;import com.imooc.commons.model.pojo.Diners;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;/*** 食客Mapper*/
public interface DinersMapper {//根据手机号查询食客信息Select(select id, username, phone, email, is_vaild from t_diners where phone #{phone})Diners selectByPhone(Param(phone) String phone);
}DinersService.java DinersController application.yml 重新启动DinersApplication、GatewayApplication服务
数据库有的
http://localhost/diners/checkPhone?phone12311112222 数据库没有的
http://localhost/diners/checkPhone?phone12311112223 要写一个全局异常处理给客户端返回一个友好的提示 12.2 全局异常处理
handler
GlobalExceptionHandler.java
package com.imooc.diners.handler;import com.imooc.commons.exception.ParameterException;
import com.imooc.commons.model.domain.ResultInfo;
import com.imooc.commons.utils.ResultInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;RestControllerAdvice //将输出的内容写入到 ResponseBody 中
Slf4j //开启日志
public class GlobalExceptionHandler {Resourceprivate HttpServletRequest request;ExceptionHandler(ParameterException.class)public ResultInfoMapString,String handlerParameterException(ParameterException ex){String path request.getRequestURI();ResultInfoMapString,String resultInfo ResultInfoUtil.buildError(ex.getErrorCode(), ex.getMessage(), path);return resultInfo;}ExceptionHandler(Exception.class)public ResultInfoMapString,String handlerException(Exception ex){log.info(未知异常:{},ex);String path request.getRequestURI();ResultInfoMapString,String resultInfo ResultInfoUtil.buildError(path);return resultInfo;}
}
重新启动DinersApplication服务
http://localhost/diners/checkPhone?phone12311112223 返回正常
12.3 完成注册
12.3.1 DTO
DinersDTO.java
package com.imooc.commons.model.dto;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;import java.io.Serializable;Getter
Setter
ApiModel(description 注册用户信息)
public class DinersDTO implements Serializable {ApiModelProperty(用户名)private String username;ApiModelProperty(密码)private String password;ApiModelProperty(手机号)private String phone;ApiModelProperty(验证码)private String verifyCode;}
12.3.2 Mapper
DinersMapper.java
package com.imooc.diners.mapper;import com.imooc.commons.model.dto.DinersDTO;
import com.imooc.commons.model.pojo.Diners;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;/*** 食客Mapper*/
public interface DinersMapper {//根据手机号查询食客信息Select(select id, username, phone, email, is_valid from t_diners where phone #{phone})Diners selectByPhone(Param(phone) String phone);//根据用户名查询食客信息Select(select id, username, phone, email, is_valid from t_diners where username #{username})Diners selectByUsername(Param(username) String username);//新增食客信息Insert(insert into t_diners (username, password, phone, roles, is_valid, create_date,update_date) values (#{username}, #{password}, #{phone}, \ROLE_USER\, 1, now(),now()))int save(DinersDTO dinersDTO);}
12.3.3 Service
SendVerifyCodeService.java DinersService.java Resourceprivate SendVerifyCodeService sendVerifyCodeService;/*** 用户注册* param dinersDTO* param path* return*/public ResultInfo register(DinersDTO dinersDTO,String path){//1.参数非空校验String username dinersDTO.getUsername();AssertUtil.isNotEmpty(username,请输入用户名);String password dinersDTO.getPassword();AssertUtil.isNotEmpty(password,请输入密码);String phone dinersDTO.getPhone();AssertUtil.isNotEmpty(phone,请输入手机号);String verifyCode dinersDTO.getVerifyCode();AssertUtil.isNotEmpty(verifyCode,请输入验证码);//2.验证码一致性校验验证码是否已过期String code sendVerifyCodeService.getCodeByPhone(phone);// 验证码是否过期AssertUtil.isNotEmpty(code,验证码已过期请重新发送);//验证码一致性校验AssertUtil.isTrue(!dinersDTO.getVerifyCode().equals(code),验证码不一致请重新输入);//3.验证用户名是否已注册Diners diners dinersMapper.selectByUsername(username.trim());AssertUtil.isTrue(diners !null,用户名已存在请重新输入);//4.注册// 密码加密dinersDTO.setPassword(DigestUtil.md5Hex(password.trim()));dinersMapper.save(dinersDTO);// 自动登录return signIn(username.trim(),password.trim(),path);}
12.3.4 Controller
DinersController.java 12.3.5 网关配置
application.yml(ms-gateway) 12.3.6 测试
1.检测是否注册
http://localhost/diners/checkPhone?phone12311113333 2.发送验证码 3.拿验证码 4.登录60s会过期再发一遍就可以了 下面是一些其它错误展示
1.请输入用户名或者密码、手机号、验证码 2.验证码已过期请重新发送 3.验证码不一致请重新输入