谷粒学院7-13天
谷粒學院7-13天總結
1.課程發布
1.1.前端實現
1.項目結構
1.1.1.info里面的二級聯動
1.1.1.1.首先喃我們先來寫添加的時候
這個在created里面進行初始化,我們就可以進行選擇。
這個后端方法我們在課程分類里面也就已經實現了。
1.1.1.2.回顯的時候二級聯動
①.首先喃我們要進行判斷我們的路徑里面是有有courseID 因為這樣我們才知道你究竟是回顯還是添加來做出不同 的邏輯
②.然后就是根據我們couseId 查詢出對應的課程信息,包括一級分類id和二級分類id這都是我們需要的
? 然后在查詢所有的學科分類(里面包含了我們一級分類和二級分類)我們需要根據courseID查詢出來的數據進行 對比然后就可以得到我們回顯數據里面那個一級分類所對應的二級分類。
1.1.2.阿里云視頻的上傳
①先看我們的vue封裝的組件
②.刪除視頻就是根據我們的id來進行刪除,刪除多個也是如此(但是刪除多個后端實現的方法有所不同)
③.進行路由跳轉
1.1.3.最終發布
這個前端沒有什么新的技術,就是后端寫了sql語句
1.2.后端實現
1.2.1.后端二級聯動的實現
①.這個其實就是基礎的業務邏輯代碼,我在課程分類那個筆記里面已經寫了,就不重新進行贅述
1.2.2.微服務的調用
為什么上傳視頻服務要使用微服務
-
首先我們上傳視頻的接口是寫在新的模板里的,不是寫在service-edu模板里面的,那么我們要想調用就只有使用微服務把他們都弄在一個微服務里面進行注冊
-
那么我們nacos自然是不可少的
-
首先要引入依賴這里
-
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
-
-
然后就可以在我們要使用上傳視頻那個模塊創建一個client
-
啟動類的配置
-
下面就是調用,我們寫的一個服務的接口
1.2.3.阿里云視頻上傳
①.阿里云上是有基本的sdk的就是根據阿里云的幫助文檔就可以實現,而且基本上都是固定的,就是需要你的keyID和你的keySercet 然后修改小部分進行實現
②.這里就是將我們上傳后,然后就可以得到我們視頻的id然后返回給前端
public String uploadAlyVideo(MultipartFile file) {// MultipartFile 表示的是文件// 得到文件的原始名稱 String originalFilename = file.getOriginalFilename();// title 在阿里云顯示的名稱(自己定義)// 這個就是根據我們這個本身的文件名進行截取的String title = originalFilename.substring(0, originalFilename.lastIndexOf("."));// fileName 上傳文件原始名稱String fileName = file.getOriginalFilename();// inputStream 上傳視頻到阿里云里面InputStream inputStream = null;try {// 得到輸入流inputStream = file.getInputStream();} catch (IOException e) {e.printStackTrace();}UploadStreamRequest request = new UploadStreamRequest(keyid,keysecret,title, fileName, inputStream);UploadVideoImpl uploader = new UploadVideoImpl();UploadStreamResponse response = uploader.uploadStream(request);//如果設置回調URL無效,不影響視頻上傳,可以返回VideoId同時會返回錯誤碼。// 其他情況上傳失敗時,VideoId為空,此時需要根據返回錯誤碼分析具體錯誤原因// 得到視頻的idString videoId = response.getVideoId();if (!response.isSuccess()) {String errorMessage = "阿里云上傳錯誤:" + "code:" + response.getCode() + ", message:" + response.getMessage();log.warn(errorMessage);if(StringUtils.isEmpty(videoId)){throw new GuliException(20001, errorMessage);}}// 返回視頻idreturn videoId;}
1.2.4.nginx的配置
我們由于使用了nginx來實現調用的,但是nginx有一個限制,就是你上傳的東西的內存,會經過nginx但是東西過大就不能到達后臺,就給你攔截了,所以上傳視頻會受到限制,因此我們要對nginx的配置文件進行修改。
1.2.5.阿里云視頻刪除
①.首先是刪除單個視頻的
那什么時候是刪除多個視頻喃 就是等你想要刪除章節或者這個課程的話就是刪除多個視頻
public R removeAlyVideo(@PathVariable String id){try {// 初始化對象DefaultAcsClient client = InitObject.initVodClient("LTAI5tQF4MgKKFNSbKbciX2j", "EScpFOFDJFHdQlL2YFQ35KFlLumK5S");// 創建刪除視頻request對象DeleteVideoRequest request = new DeleteVideoRequest();// 向request設置id值// 這個設置的id 就是我們刪除視頻的id 這個我們前端會傳給我們的// 這個request.setVideoIds(id);// 調用初始化實現的方法// 實現刪除client.getAcsResponse(request);return R.ok();}catch (Exception e){e.printStackTrace();throw new GuliException(20001,"視頻刪除失敗");}}
那么刪除多個視頻肯定區別不到就是我們不止一個id就是了但是 request.setVideoIds(id);有一個上傳多個視頻的格式
2.NUXT框架
1.特點
2.nuxt的結構
3.最主要的核心
4.動態路由和固定路由
固定路由:就是一個很大概的意思,一般就是固定不變的訪問地址 就比如首頁,全部講師,全部課程 這樣的訪問路徑不會改變的。
動態路由:就是針對某一個東西,就比如查詢每個老師的詳情,那每個老師都有自己的詳情,所以每個老師所對應的路徑是有差別的,就相當于有自己的id。然后根據id來查詢就可以了。
5.由于nuxt沒有vue的框架,我們請求不到后臺,所以我們還要下載axios來實現
npm install axios
然后根據vue的特性,自己寫一個request.js來實現我們的axios的封裝
-
注意的是我們自己封裝的與原來vue-element-tempate是有一點差別的是什么喃
-
就是我們不是后面都會使用箭頭函數把 resp => { resp.data.data} 這個是nuxt的框架 我們原來vue自帶的框架是自動幫助我們封裝了一層data,所以原來我們寫的vue的箭頭函數就是 resp.data.這樣,但是我們這個需要自己進行封裝,但是不想封裝的話就要使用兩個data
然后就可以進行正常的調用了
3.登錄注冊功能
3.1.后端實現
三種登錄方式
3.1.1.jwt令牌
這個就相當于我們的steam令牌,需要這個令牌才能獲取你的信息,然后生成對應的token來實現
至于怎么寫出jwt我們也不用擔心,這就是一個工具類,你只需要會用就行了
那么這個工具類具體有什么方法喃
package com.atguigu.commonutils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;import javax.servlet.http.HttpServletRequest;
import java.util.Date;/*** @author helen* @since 2019/10/16*/
public class JwtUtils {// 常量 過期時間public static final long EXPIRE = 1000 * 60 * 60 * 24;// 這個是我們密鑰// 這個一般都是公司會給的public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";// 生成token的方法// 根據用戶id 和 用戶名稱生成的tokenpublic static String getJwtToken(String id, String nickname){String JwtToken = Jwts.builder().setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256").setSubject("guli-user").setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + EXPIRE)).claim("id", id) // 設置主體部分 存儲用戶信息.claim("nickname", nickname).signWith(SignatureAlgorithm.HS256, APP_SECRET) // 聲明hash.compact();return JwtToken;}/*** 判斷token是否存在與有效* @param jwtToken* @return*/public static boolean checkToken(String jwtToken) {if(StringUtils.isEmpty(jwtToken)) return false;try {Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 判斷token是否存在與有效(頭信息)* @param request* @return*/public static boolean checkToken(HttpServletRequest request) {try {String jwtToken = request.getHeader("token");if(StringUtils.isEmpty(jwtToken)) return false;Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 根據token獲取用戶id* @param request* @return*/public static String getMemberIdByJwtToken(HttpServletRequest request) {String jwtToken = request.getHeader("token");if(StringUtils.isEmpty(jwtToken)) return "";Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);Claims claims = claimsJws.getBody();return (String)claims.get("id");}
}
上面的4個方法我們直接使用就可以了。
-
在我們登錄過程中會進行一系列的判斷,最終就可以知道賬號密碼是否正確,這個時候我們就可以是jwt工具類來生成一個token 根據我們用戶id 和 用戶名 然后返回給前端。
3.1.2.MD5加密處理
我們將用戶的密碼存入數據庫是不可能以一種明文的形式存入數據庫的不然,會存在極大的安全隱患。
因此我們就可以使用MD5進行加密(md5只能加密,不能解密)
也是一個工具類,我們直接拿來用就可以了
3.1.3.騰訊云短信驗證
-
首先我們需要開通騰訊云的短信服務,得到我們的id 和 key
-
然后根據騰訊云提供的sdk文檔進行操作
-
首先你要自己寫一個生成幾位數的驗證碼的工具類
-
然后就是根據騰訊云提供的api進行復制然后修改為你的就行
-
@Overridepublic boolean sendSms(String phone, String code) {try {// 整合騰訊云短信服務發送Credential cred = new Credential(secretID, secretKey);// 實例化一個http選項,可選,沒有特殊需求可以跳過HttpProfile httpProfile = new HttpProfile();httpProfile.setReqMethod("POST");/* SDK有默認的超時時間,非必要請不要進行調整* 如有需要請在代碼中查閱以獲取最新的默認值 */httpProfile.setConnTimeout(60);/* 指定接入地域域名,默認就近地域接入域名為 sms.tencentcloudapi.com ,也支持指定地域域名訪問,例如廣州地域的域名為 sms.ap-guangzhou.tencentcloudapi.com */httpProfile.setEndpoint("sms.tencentcloudapi.com");/* 非必要步驟:* 實例化一個客戶端配置對象,可以指定超時時間等配置 */ClientProfile clientProfile = new ClientProfile();/* SDK默認用TC3-HMAC-SHA256進行簽名* 非必要請不要修改這個字段 */clientProfile.setSignMethod("HmacSHA256");clientProfile.setHttpProfile(httpProfile);SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);/* 實例化一個請求對象,根據調用的接口和實際情況,可以進一步設置請求參數* 你可以直接查詢SDK源碼確定接口有哪些屬性可以設置* 屬性可能是基本類型,也可能引用了另一個數據結構* 推薦使用IDE進行開發,可以方便的跳轉查閱各個接口和數據結構的文檔說明 */SendSmsRequest req = new SendSmsRequest();/* 填充請求參數,這里request對象的成員變量即對應接口的入參* 你可以通過官網接口文檔或跳轉到request對象的定義處查看請求參數的定義* 基本類型的設置:* 幫助鏈接:* 短信控制臺: https://console.cloud.tencent.com/smsv2* sms helper: https://cloud.tencent.com/document/product/382/3773 *//* 短信應用ID: 短信SdkAppId在 [短信控制臺] 添加應用后生成的實際SdkAppId,示例如1400006666 */String sdkAppId = "1400742926";req.setSmsSdkAppId(sdkAppId);/* 短信簽名內容: 使用 UTF-8 編碼,必須填寫已審核通過的簽名,簽名信息可登錄 [短信控制臺] 查看 */String signName = "林謀不萌"; // 這個必須寫的req.setSignName(signName);/* 國際/港澳臺短信 SenderId: 國內短信填空,默認未開通,如需開通請聯系 [sms helper] */String senderid = "";req.setSenderId(senderid);/* 用戶的 session 內容: 可以攜帶用戶側 ID 等上下文信息,server 會原樣返回 */String sessionContext = "";req.setSessionContext(sessionContext);/* 短信號碼擴展號: 默認未開通,如需開通請聯系 [sms helper] */String extendCode = "";req.setExtendCode(extendCode);/* 模板 ID: 必須填寫已審核通過的模板 ID。模板ID可登錄 [短信控制臺] 查看 */String templateId = "1557106";req.setTemplateId(templateId);/* 下發手機號碼,采用 E.164 標準,+[國家或地區碼][手機號]* 示例如:+8613711112222, 其中前面有一個+號 ,86為國家碼,13711112222為手機 號,最多不要超過200個手機號 *///String[] phoneNumberSet = {"+8618777777777", "+8615888888888","+8618555555555","+8618333333333","+8613566666666"};String[] phoneNumberSet = {"+86" + phone};req.setPhoneNumberSet(phoneNumberSet);/* 模板參數: 若無模板參數,則設置為空 */String[] templateParamSet = {code};req.setTemplateParamSet(templateParamSet);/* 通過 client 對象調用 SendSms 方法發起請求。注意請求方法名與請求對象是對應的* 返回的 res 是一個 SendSmsResponse 類的實例,與請求對象對應 */SendSmsResponse res = client.SendSms(req);// 輸出json格式的字符串回包System.out.println(SendSmsResponse.toJsonString(res));// 也可以取出單個值,你可以通過官網接口文檔或跳轉到response對象的定義處查看返回字段 的定義System.out.println(res.getSendStatusSet()[0].getCode());if ("Ok".equals(res.getSendStatusSet()[0].getCode())) {return true;}} catch (TencentCloudSDKException e) {e.printStackTrace();return false;}return false;}就可以發送成功了。
-
-
首先我們將phone作為key,驗證碼作為value然后存入redis里面,并且設置過期時長,等到用戶輸入驗證碼的時候,根據用戶輸入的phone獲取里面的value(驗證碼) 然后進行比對,如果正確了則能進行注冊。
3.1.4.獲取登錄用戶的信息
這個就要使用到token了,我們的token就存儲了他的id 和 昵稱的信息
通過前端頁面發來請求里面的請求體也就是我們的request 然后通過里面的token得到id
實現查詢返回給前端
3.2.前端實現
3.2.1.注冊
- 首先就是定義出我們發送短信的api這樣就可以實現
- 根據前端的數據,創建對應的實體類
3.2.2.登錄
- 首先我們需要一個攔截器,這攔截器就你每一次發送請求都會去執行的,目的就得能一直得到用戶的信息,那么前端的攔截器是怎么實現。
- 使用cookie,我們將token上傳到cookie里面,然后在取出來,然后回調我們方法,根據token得到該用戶的信息,那么我們就能在那個登錄的地方進行回顯。
-
登錄接口
?
-
攔截器
攔截器就是幫助我們把token設置在請求頭上,以后我們每一次的請求里面都會有token
-
從cookie里面獲取用戶信息
首先是要引入cookie,然后對cookie里面的值進行判斷不然就會有讀取為空,程序可能就有錯
4.微信掃碼登錄功能
4.1.前端實現
先來簡單說明一下微信登錄與密碼登錄的區別,我實現的這個喃就是,如果你是微信登錄的話,那么你的token就會顯示在首頁的路徑上面,我們正好通過路徑來獲取你的token,就不是通過后臺返回了。
然后我們就可以得到這token,操作和我們登錄的操作基本上是一樣的。
然后我們前端獲取路徑中的值與以往vue獲取的方式有一點不一樣
將得到的token設置到cookie里面,然后又再次調用那個根據token查詢用戶信息的方法就可以實現了
4.2.后端實現
4.2.1.生成二維碼
首先我們要有微信開放平臺的賬號,要去申請,得到我們一些基本的密鑰、id等
但是值的注意的是,我們這里不能使用restContrloler,因為我們是要重定向到某一個地址,而不是將這個地址返回給誰。
然后訪問微信給出來的固定的地址
使用我們c語言的占位符的形式來實現參數的賦值
4.2.2.掃描二維碼
我們掃描二維碼后 原本是該區 http://guli_shop/…什么那個地址
但是我們是沒有辦法實現的,于是尚硅谷就幫我寫了一個程序掃描后是跳轉到我們本地的一個地址,
然后我們手動添加邏輯就可以了
還需要將回調的地址與我們下面新的域名請求的地址要一樣,這樣就能自動執行到我們接口的方法
這個參數有code,和state我們也要加上
// 獲取掃描人信息,添加數據@GetMapping("callback")public String callback(String code, String state) {try {// 1.code 獲取code值 臨時票據 類似于驗證碼// 2.拿著code去請求微信固定的一個地址// 得到access_token 和 openid//向認證服務器發送請求換取access_tokenString baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +"?appid=%s" +"&secret=%s" +"&code=%s" +"&grant_type=authorization_code";String accessTokenUrl = String.format(baseAccessTokenUrl,ConstantWxUtils.WX_OPEN_APP_ID,ConstantWxUtils.WX_OPEN_APP_SECRET,code);
// accessTokenUrl 就是我們最終訪問的地址// 請求拼接好的值 得到那兩個返回值String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);
// System.out.println("accessTokenInfo:" + accessTokenInfo);// 從accessTokenInfo獲取我們的open_id 和 access_token// 先將我們的字符串轉為map集合 根據map的key就可以得到Gson gson = new Gson();// 當然huuutoll也是建議使用的HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class);String accessToken = (String) mapAccessToken.get("access_token");String openid = (String) mapAccessToken.get("openid");// 判斷數據庫是否有相同的微信id openId// 沒有的話就查找得到用戶信息再進行保存 如果存在了 就直接跳過UcenterMember ucenterMember = ucenterMemberService.getOpenId(openid);if(ucenterMember == null) {// 3.拿著我們的 access_token 和 openid 去請求微信固定的地址 獲取掃碼人信息//訪問微信的資源服務器,獲取用戶信息String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +"?access_token=%s" +"&openid=%s";// 拼接參數(就是我們的地址了)String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);// 發送請求String userInfo = HttpClientUtils.get(userInfoUrl);// 這個就是我們用戶信息
// System.out.println("userInfo:" + userInfo);// 獲取返回userInfo掃碼人的信息HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);String openid1 = (String) userInfoMap.get("openid");// 這個openid 和上面的openid是一樣的// 昵稱String nickname = (String) userInfoMap.get("nickname");// 頭像String headimgurl = (String) userInfoMap.get("headimgurl");// 幫助用戶注冊// 表示新用戶// 進行添加ucenterMember = new UcenterMember();ucenterMember.setOpenid(openid);ucenterMember.setNickname(nickname);ucenterMember.setAvatar(headimgurl);ucenterMemberService.save(ucenterMember);}// 使用jwt 根據member對象生成一個token字符串String jwtToken = JwtUtils.getJwtToken(ucenterMember.getId(), ucenterMember.getNickname());// 然后就跳轉到我們的前端的頁面// 所以說為什么我們前端是query.token喃// 將token放在路徑里面,然后進行重定向return "redirect:http://localhost:3000?token=" + jwtToken;} catch (Exception e) {e.printStackTrace();throw new GuliException(20001,"登陸失敗");}
}
這樣我們掃碼登錄也就實現了
總結
- 上一篇: java中的asList_Java Ar
- 下一篇: java中函数是什么_[一] java8