瘋玩了一個月,效率好低,今天開始撿起來蒼穹外賣~
1. 為什么不需要單獨引入HttpClient的dependency?
? ? ? ? 因為我們在sky-common的pom.xml中已經引入了aliyun-sdk-oss的依賴,而這個依賴低層就引入了httpclinet的依賴,根據依賴傳遞的原則,不需要單獨再引入了
HttpClient的maven坐標
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
2. 操作HttpClient請求發送的步驟
-
創建HttpClient對象
-
創建Http請求對象
-
調用HttpClient的execute方法發送請求
3. 微信登錄功能需求和接口設計
4.?基于微信登錄實現小程序的登錄功能(如果是新用戶則自動完成注冊)
(1)接口設計
?這個請求實現了“微信登錄過程流程圖”中的哪個部分?
(2)如果是新用戶,則實現自動注冊。在后端還得設計user表來存儲用戶信息
?(3)代碼開發
1)在application-dev.yml和application.yml中配置微信登錄需要的配置項
2)在application.yml中配置為微信用戶生成jwt令牌的配置項
- admin-secret-key:管理端設置jwt簽名時使用的秘鑰
- user-secret-key:用戶端設置jwt簽名時使用的秘鑰
在JWT中,秘鑰用于簽名JWT以確保其完整性和真實性。JWT通常由三部分組成:頭部(Header)、載荷(Payload)、簽名(Signature)。在創建JWT時,會將頭部和載荷進行Base64編碼,然后用秘鑰對編碼后的頭部和載荷進行簽名,生成簽名部分。
簽名過程:
- 創建 JWT 的頭部(Header)和載荷(Payload)。
- 將頭部和載荷編碼為 JSON 字符串,并使用 Base64 編碼。
- 將編碼后的頭部和載荷通過一個字符(如".")連接起來形成一個字符串。
- 使用選定的加密算法(如HMAC、RSA、md5等)和預先配置的秘鑰對上一步生成的字符串進行簽名,生成簽名部分。
- 將簽名添加到JWT的尾部,生成最終的JWT。
驗證過程:
- 接收到JWT后,將其分解為頭部、載荷和簽名三部分。
- 將頭部和載荷進行相同的編碼處理以及連接操作,生成一個字符串。
- 使用相同的加密算法和預先配置的秘鑰對生成的字符串進行簽名,生成一個新的簽名。
- 將新生成的簽名與JWT中的簽名進行比較。如果兩者相匹配,則JWT是有效的。
- admin-token-name和user-token-name
? ? ? ? 對于管理員身份的JWT,前端應該使用名為"token"的字段來傳遞JWT
? ? ? ? 對于用戶身份的JWT,前端用名為“authentication”的字段來傳遞JWT
????????
3)設計VO和DTO
發送的請求中有參數,接收參數需要DTO
VO用來接收返回數據
4)根據接口定義創建Controller方法
@RestController
@RequestMapping("/user/user")
@Api(tags = "C端用戶相關接口")
@Slf4j
public class UserController {@Autowiredprivate UserService userService;@Autowiredprivate JwtProperties jwtProperties;/*** 微信登錄* @param userLoginDTO* @return*/@PostMapping("/login")@ApiOperation("微信登錄")public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){log.info("微信用戶登錄:{}",userLoginDTO.getCode());// 微信登錄User user = userService.wxLogin(userLoginDTO);// 為微信用戶生成jwt令牌Map<String,Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.USER_ID,user.getId());String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);UserLoginVO userLoginVO = UserLoginVO.builder().id(user.getId()).openid(user.getOpenid()).token(token).build();return Result.success(userLoginVO);}
5) Service方法——傳入微信登錄授權碼,返回id、openid和token
public interface UserService {/*** 微信登錄* @param userLoginDTO* @return*/User wxLogin(UserLoginDTO userLoginDTO);
}
6) ServiceImpl——獲得微信用戶openid、返回id、openid、token方法的實現類
發送請求,傳入微信登錄授權碼,獲得微信用戶的openid.
調用微信接口服務、傳給微信服務端的數據都被封裝在map里
/*** 調用微信接口服務,獲取微信用戶的openid* @param code* @return*/private String getOpenid(String code){Map<String, String> map = new HashMap<>();map.put("appid",weChatProperties.getAppid());map.put("secret",weChatProperties.getSecret());map.put("js_code", code);map.put("grant_type","authorization_code");String json = HttpClientUtil.doGet(WX_LOGIN, map);JSONObject jsonObject = JSON.parseObject(json);String openid = jsonObject.getString("openid");return openid;}
獲取到openid之后,就可以實現微信登錄
/*** 微信登錄* @param userLoginDTO* @return*/public User wxLogin(UserLoginDTO userLoginDTO){// 調用微信接口服務,獲得當前微信用戶的openidString openid = getOpenid(userLoginDTO.getCode());// 判斷openid是否為空,如果是空表示登錄失敗,拋出業務異常if(openid == null){throw new LoginFailedException(MessageConstant.LOGIN_FAILED);}// 判斷當前用戶是否是新用戶User user = userMapper.getByOpenid(openid);// 如果是新用戶,自動完成注冊if(user == null){user = User.builder().openid(openid).createTime(LocalDateTime.now()).build();userMapper.insert(user);}// 返回這個用戶對象return user;}
7) UserMapper的建立
為了在ServiceImpl中判斷用戶是否已經注冊,需要獲得user表的信息,因此我們創建UserMapper,以便能夠通過openid查詢用戶是否已經注冊
@Select("select * from user where openid = #{openid}")User getByOpenid(String openid);
將新用戶插入user表的功能實現
/*** 插入數據* @param user*/void insert(User user);
還需要再userMapper.xml中添加insert語句
<insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into user (openid, name, phone, sex, id_number, avatar, create_time)values (#{openid}, #{name}, #{phone}, #{sex}, #{idNumber}, #{avatar}, #{createTime})</insert>
8) 編寫用戶JWT的攔截器
5. 商品瀏覽功能的需求分析
6. 查詢分類
后面還有根據分類id查詢菜品、根據分類id查詢套餐、根據套餐id查詢菜品的功能,答案都在黑馬的文檔里面