当前位置: 首页>C语言>正文

零售管理系統,【第十六篇】商城系統-認證系統構建

零售管理系統,【第十六篇】商城系統-認證系統構建

在這里插入圖片描述

商城認證服務

一、搭建認證服務環境

??結合我們前面介紹的商城的架構我們需要單獨的搭建一個認證服務。

image.png

1.創建項目

零售管理系統。??首先創建一個SpringBoot項目,然后添加對應的依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.12</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.msb.mall</groupId><artifactId>mall-auth-server</artifactId><version>0.0.1-SNAPSHOT</version><name>mall-auth_server</name><description>認證服務</description><properties><java.version>1.8</java.version><spring-cloud.version>2020.0.1</spring-cloud.version></properties><dependencies><!-- 公共依賴 --><dependency><groupId>com.msb.mall</groupId><artifactId>mall-commons</artifactId><version>0.0.1-SNAPSHOT</version><exclusions><exclusion><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

2.注冊中心配置

??我們需要把認證服務注冊到Nacos中,添加對應的依賴,然后完成對應的配置

# Nacos服務注冊
spring:cloud:nacos:discovery:server-addr: 192.168.56.100:8848application:name: mall-auth_server# 統一的全局的--設置服務器響應給客戶端的日期時間格式jackson:date-format: yyyy-MM-dd HH:mm:ssthymeleaf:cache: false # 關閉Thymeleaf的緩存
server:port: 30000

放開Nacos注冊中心

image.png

企業統一認證平臺登錄,然后啟動測試

image.png

3.登錄和注冊頁面

??然后我們整理登錄和注冊的相關資源,首先把登錄和注冊的模板文件拷貝進項目

image.png

新零售平臺系統、然后把對應的靜態文件拷貝到Nginx中。

image.png

然后我們需要在host文件中添加對應的配置

image.png

華為商城實名認證不了?修改Nginx的反向代理的配置

image.png

然后重啟Nginx的服務image.png

然后修改網關服務

聚惠商城有沒有官方認證?image.png

最后調整登錄和注冊頁面的靜態資源文件的路徑.

注冊服務的名稱:msb-auth,啟動對應的服務,測試

登錄頁面

點購商城實名認證安全嗎,image.png

注冊頁面

image.png

4.注冊功能

4.1 手機驗證碼

??先處理驗證碼的頁面,使其能夠倒數操作

認證就有額度的商城。image.png

image.png

JS代碼

$(function(){$("#sendCode").click(function(){if($(this).hasClass("d1")){// 說明正在倒計時}else{// 給指定的手機號發送驗證碼timeoutChangeStyle()}});})var num = 10function timeoutChangeStyle(){$("#sendCode").attr("class","d1")if(num == 0){// 說明1分鐘到了,可以再次發送驗證碼了$("#sendCode").text("發送驗證碼")num= 10;$("#sendCode").attr("class","")}else{setTimeout('timeoutChangeStyle()',1000)$("#sendCode").text(num+"s后再次發送")}num --;}

4.2 短信驗證接口

??通過阿里云的短信服務來實現。我們直接購買0元15次就可以了。https://www.aliyun.com/

image.png

image.png

進入到對應的管理控制臺,查看對應的信息

image.png

通過短信供應商提供的相關的編程語言的開發模板開發即可

image.png

供應商提供了對應的HttpUtils工具類,我們需要下載保存到我們自己的項目中。

image.png

然后封裝對應的發送驗證碼的接口

package com.msb.mall.third.utils;import lombok.Data;
import org.apache.http.HttpResponse;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;/*** 短信組件*/
@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms")
@Data
@Component
public class SmsComponent {private String host;private String path;private String method = "POST";private String appCode;/*** 發送短信驗證碼* @param phone 發送的手機號* @param code 發送的短信驗證碼*/public void sendSmsCode(String phone,String code){Map<String, String> headers = new HashMap<String, String>();//最后在header中的格式(中間是英文空格)為Authorization:APPCODE 83359fd73fe94948385f570e3c139105headers.put("Authorization", "APPCODE " + appCode);//根據API的要求,定義相對應的Content-Typeheaders.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");Map<String, String> querys = new HashMap<String, String>();Map<String, String> bodys = new HashMap<String, String>();bodys.put("content", "code:"+code);bodys.put("phone_number", phone);bodys.put("template_id", "TPL_0000");try {HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);System.out.println(response.toString());//獲取response的body//System.out.println(EntityUtils.toString(response.getEntity()));} catch (Exception e) {e.printStackTrace();}}
}

添加對應的屬性信息

image.png

image.png

4.3 短信功能

??然后我們將短信功能串聯起來

image.png

4.3.1 third服務

??我們需要在第三方服務中提供對外的接口服務

@RestController
public class SMSController {@Autowiredprivate SmsComponent smsComponent;/*** 調用短信服務商提供的短信API發送短信* @param phone* @param code* @return*/@GetMapping("/sms/sendcode")public R sendSmsCode(@RequestParam("phone") String phone,@RequestParam("code") String code){smsComponent.sendSmsCode(phone,code);return R.ok();}
}

image.png

4.3.2 認證服務

??我們需要在認證服務中通過feign來調用third中提供的短信服務,同時給客戶端提供訪問的接口

        <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>

放開注解

image.png

然后聲明Feign的接口

image.png

定義對應的Controller

@Controller
public class LoginController {@Autowiredprivate ThirdPartFeginService thirdPartFeginService;@ResponseBody@GetMapping("/sms/sendCode")public R sendSmsCode(@RequestParam("phone") String phone){// 生成隨機的驗證碼String code = UUID.randomUUID().toString().substring(0, 5);thirdPartFeginService.sendSmsCode(phone,code);return R.ok();}
}

4.3.3 客戶端

??然后我們需要在頁面中通過jQuery的異步提交來發送短信

image.png

4.3.4 驗證碼存儲

??當我們把驗證碼通過短信的形式發送給你客戶手機,然后我們需要把手機號和對應的驗證碼存儲起來,后面可能會集群部署,這時我們把這個信息存在在Redis中。

image.png

添加配置

image.png

存儲數據

image.png

image.png

搞定

4.3.5 60秒間隔

??針對驗證碼發送的間隔必須是60秒以上,這時我們可以在保存到Redis中的數據的值我們加上發送的時間來處理

image.png

模板頁面也需要做出對應的處理

image.png

4.4 注冊數據驗證

??表單提交的注冊數據我們通過JSR303來驗證。

首先定義VO對象

package com.msb.mall.vo;import lombok.Data;
import org.hibernate.validator.constraints.Length;import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;/*** 注冊用戶的VO對象*/
@Data
public class UserRegisterVo {@NotEmpty(message = "賬號不能為空")@Length(min = 3,max = 15,message = "賬號必須是3~15位")private String userName; // 賬號@NotEmpty(message = "密碼不能為空")@Length(min = 3,max = 15,message = "密碼必須是3~15位")private String password; // 密碼@NotEmpty(message = "手機號不能為空")@Pattern(regexp = "^[1][3-9][0-9]{9}$",message = "手機號不合法")private String phone;  // 手機號@NotEmpty(message = "驗證碼不能為空")private String code;  // 驗證碼
}

然后就是控制器的邏輯代碼

    @PostMapping("/sms/register")public String register(@Valid UserRegisterVo vo, BindingResult result, Model model){if(result.hasErrors()){// 表示提交的數據不合法List<FieldError> fieldErrors = result.getFieldErrors();Map<String,String> map = new HashMap<>();for (FieldError fieldError : fieldErrors) {String field = fieldError.getField();String defaultMessage = fieldError.getDefaultMessage();map.put(field,defaultMessage);}model.addAttribute("error",map);return "/reg";}// 表單提交的注冊的數據是合法的return "redirect:/login.html";}

然后就是頁面代碼處理

image.png

image.png

驗證碼的校驗

image.png

4.5 完整的注冊功能

image.png

會員服務處理

控制器

   /*** 會員注冊* @return*/@PostMapping("/register")public R register(@RequestBody MemberReigerVO vo){try {memberService.register(vo);}catch (UsernameExsitException exception){return R.error(BizCodeEnume.USERNAME_EXSIT_EXCEPTION.getCode(),BizCodeEnume.USERNAME_EXSIT_EXCEPTION.getMsg());}catch (PhoneExsitExecption exsitExecption) {return R.error(BizCodeEnume.PHONE_EXSIT_EXCEPTION.getCode(),BizCodeEnume.PHONE_EXSIT_EXCEPTION.getMsg());}catch (Exception e){return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());}return R.ok();}

然后對應的Service

   /*** 完成會員的注冊功能* @param vo*/@Overridepublic void register(MemberReigerVO vo) throws PhoneExsitExecption,UsernameExsitException{MemberEntity entity = new MemberEntity();// 設置會員等級 默認值MemberLevelEntity memberLevelEntity = memberLevelService.queryMemberLevelDefault();entity.setLevelId(memberLevelEntity.getId()); // 設置默認的會員等級// 添加對應的賬號和手機號是不能重復的checkUsernameUnique(vo.getUserName());checkPhoneUnique(vo.getPhone());entity.setUsername(vo.getUserName());entity.setMobile(vo.getPhone());BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();String encode = encoder.encode(vo.getPassword());// 需要對密碼做加密處理entity.setPassword(encode);// 設置其他的默認值this.save(entity);}

auth服務通過Fegin遠程調用

image.png

遠程調用

    @PostMapping("/sms/register")public String register(@Valid UserRegisterVo vo, BindingResult result, Model model){Map<String,String> map = new HashMap<>();if(result.hasErrors()){// 表示提交的數據不合法List<FieldError> fieldErrors = result.getFieldErrors();for (FieldError fieldError : fieldErrors) {String field = fieldError.getField();String defaultMessage = fieldError.getDefaultMessage();map.put(field,defaultMessage);}model.addAttribute("error",map);return "/reg";}else{// 驗證碼是否正確String code = (String)redisTemplate.opsForValue().get(SMSConstant.SMS_CODE_PERFIX + vo.getPhone());code = code.split("_")[0];if(!code.equals(vo.getCode())){// 說明驗證碼不正確map.put("code","驗證碼錯誤");model.addAttribute("error",map);return "/reg";}else{// 驗證碼正確  刪除驗證碼redisTemplate.delete(SMSConstant.SMS_CODE_PERFIX + vo.getPhone());// 遠程調用對應的服務 完成注冊功能R r = memberFeginService.register(vo);if(r.getCode() == 0){// 注冊成功return "redirect:http://msb.auth.com/login.html";}else{// 注冊失敗map.put("msg",r.getCode()+":"+r.get("msg"));model.addAttribute("error",map);return "/reg";}}}//return "redirect:/login.html";}

完成對應的服務注冊

image.png

校驗提示

image.png

5.登錄功能

??通過最基礎的登錄操作來完成登錄處理

登錄頁面處理

image.png

認證服務的處理

/*** 注冊的方法* @return*/@PostMapping("/login")public String login(LoginVo loginVo , RedirectAttributes redirectAttributes){R r = memberFeginService.login(loginVo);if(r.getCode() == 0){// 表示登錄成功return "redirect:http://msb.mall.com/home";}redirectAttributes.addAttribute("errors",r.get("msg"));// 表示登錄失敗,重新跳轉到登錄頁面return "redirect:http://msb.auth.com/login.html";}

會員中心的認證邏輯

@RequestMapping("/login")public R login(@RequestBody MemberLoginVO vo){MemberEntity entity = memberService.login(vo);if(entity != null){return R.ok();}return R.error(BizCodeEnume.USERNAME_PHONE_VALID_EXCEPTION.getCode(),BizCodeEnume.USERNAME_PHONE_VALID_EXCEPTION.getMsg());}

service中的具體認證處理

    @Overridepublic MemberEntity login(MemberLoginVO vo) {// 1.根據賬號或者手機號來查詢會員信息MemberEntity entity = this.getOne(new QueryWrapper<MemberEntity>().eq("username", vo.getUserName()).or().eq("mobile", vo.getUserName()));if(entity != null){// 2.如果賬號或者手機號存在 然后根據密碼加密后的校驗來判斷是否登錄成功BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();boolean matches = encoder.matches(vo.getPassword(), entity.getPassword());if(matches){// 表明登錄成功return entity;}}return null;}

6.Auth2.0

??OAuth2.0是OAuth協議的延續版本,但不向前兼容OAuth 1.0(即完全廢止了OAuth1.0)。 OAuth
2.0關注客戶端開發者的簡易性。要么通過組織在資源擁有者和HTTP服務商之間的被批準的交互動作代表用戶,要么允許第三方應用代表用戶獲得訪問的權限。

image.png

6.1 微博開放平臺

地址:https://open.weibo.com/

image.png

創建應用

image.png

image.png

創建后的基本信息:

image.png

授權設置:

image.png

社交認證文檔:

image.png

微博Web端授權的操作:

image.png

image.png

引導用戶點擊按鈕跳轉到對應的授權頁面

image.png

image.png

點擊授權按鈕后查看回調接口的code信息

image.png

獲取到了code信息:59d62e59e5ead5a4ea89c6f9cf212568

然后根據code信息我們可以去授權服務器獲取對應的AccessToken。

https://api.weibo.com/oauth2/access_token?client_id=1093598037&client_secret=1085c8de04dee49e9bb110eaf2d3cf62&grant_type=authorization_code&redirect_uri=http://msb.auth.com/success.html&code=59d62e59e5ead5a4ea89c6f9cf212568

獲取Token信息只支持POST方式提交

image.png

在PostMan中通過post方式提交成功獲取到了對應的token信息

image.png

獲取到了Token信息后我們就可以去資源服務器獲取對象的信息

image.png

6.2 百度開放平臺

地址:

Auth2.0操作:https://developer.baidu.com/wiki/index.php?title=docs/oauth

image.png

創建應用:http://developer.baidu.com/console#app/project

image.png

image.png

創建完成:

image.png

引導用戶跳轉到授權地址:

http://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&scope=email&display=popup

地址修改為我們自己的:http://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=MmvAkQM7HtrQnKDDhhmTSib5&redirect_uri=http://www.baidu.com&display=popup

image.png

獲取到的Code信息

image.png

code:d789d0160b2fa99bb1f840002569526e

獲取到對應的token信息

image.png

Token:121.6966ae0e0f3cd19fa36a375489342b08.YmfrSxYqsOt1eUoPzkC60yCsa7W09OmqTbPsuVL.zmdMFg

token訪問地址:https://openapi.baidu.com/rest/2.0/passport/users/getLoggedInUser?access_token=121.6966ae0e0f3cd19fa36a375489342b08.YmfrSxYqsOt1eUoPzkC60yCsa7W09OmqTbPsuVL.zmdMFg

image.png

7.社交登錄實現

7.1 code處理

??在后臺服務中獲取code并對應的獲取Token信息

image.png

image.png

然后需要同步的調整引入的鏈接地址:

image.png

7.2 獲取Token信息

??根據上一步獲取的code信息,我們可以獲取對應的Token信息

    @RequestMapping("/oauth/weibo/success")public String weiboOAuth(@RequestParam("code") String code) throws Exception {Map<String,String> body = new HashMap<>();body.put("client_id","1093598037");body.put("client_secret","1085c8de04dee49e9bb110eaf2d3cf62");body.put("grant_type","authorization_code");body.put("redirect_uri","http://msb.auth.com/oauth/weibo/success");body.put("code",code);// 根據Code獲取對應的Token信息HttpResponse post = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", new HashMap<>(), null, body);int statusCode = post.getStatusLine().getStatusCode();if(statusCode != 200){// 說明獲取Token失敗,就調回到登錄頁面return "redirect:http://msb.auth.com/login.html";}// 說明獲取Token信息成功String json = EntityUtils.toString(post.getEntity());SocialUser socialUser = JSON.parseObject(json, SocialUser.class);// 注冊成功就需要調整到商城的首頁return "redirect:http://msb.mall.com/home.html";}

7.3 登錄和注冊

??表結構中新增對應的

image.png

然后在對應的實體對象中添加對應的屬性

image.png

service中實現注冊和登錄的邏輯

    /*** 社交登錄* @param vo* @return*/@Overridepublic MemberEntity login(SocialUser vo) {String uid = vo.getUid();// 如果該用戶是第一次社交登錄,那么需要注冊// 如果不是第一次社交登錄 那么就更新相關信息 登錄功能MemberEntity memberEntity = this.getOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));if(memberEntity != null){// 說明當前用戶已經注冊過了 更新token和過期時間MemberEntity entity = new MemberEntity();entity.setId(memberEntity.getId());entity.setAccessToken(vo.getAccessToken());entity.setExpiresIn(vo.getExpiresIn());this.updateById(entity);// 在返回的登錄用戶信息中我們同步的也保存 token和過期時間memberEntity.setAccessToken(vo.getAccessToken());memberEntity.setExpiresIn(vo.getExpiresIn());return memberEntity;}// 表示用戶是第一提交,那么我們就需要對應的來注冊MemberEntity entity = new MemberEntity();entity.setAccessToken(vo.getAccessToken());entity.setExpiresIn(vo.getExpiresIn());entity.setSocialUid(vo.getUid());// 通過token調用微博開發的接口來獲取用戶的相關信息try {Map<String,String> querys = new HashMap<>();querys.put("access_token",vo.getAccessToken());querys.put("uid",vo.getUid());HttpResponse response = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", "get", new HashMap<>(), querys);if(response.getStatusLine().getStatusCode() == 200){String json = EntityUtils.toString(response.getEntity());JSONObject jsonObject = JSON.parseObject(json);String nickName = jsonObject.getString("screen_name");String gender = jsonObject.getString("gender");entity.setNickname(nickName);entity.setGender("m".equals(gender)?1:0);}}catch (Exception e){}// 注冊用戶信息this.save(entity);return entity;}

7.4 登錄的串聯

在Auth服務中我們需要通過Feign來調用MemberService中的相關服務來完成最后的串聯

    @RequestMapping("/oauth/weibo/success")public String weiboOAuth(@RequestParam("code") String code) throws Exception {Map<String,String> body = new HashMap<>();body.put("client_id","1093598037");body.put("client_secret","1085c8de04dee49e9bb110eaf2d3cf62");body.put("grant_type","authorization_code");body.put("redirect_uri","http://msb.auth.com/oauth/weibo/success");body.put("code",code);// 根據Code獲取對應的Token信息HttpResponse post = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", new HashMap<>(), null, body);int statusCode = post.getStatusLine().getStatusCode();if(statusCode != 200){// 說明獲取Token失敗,就調回到登錄頁面return "redirect:http://msb.auth.com/login.html";}// 說明獲取Token信息成功String json = EntityUtils.toString(post.getEntity());SocialUser socialUser = JSON.parseObject(json, SocialUser.class);R r = memberFeginService.socialLogin(socialUser);if(r.getCode() != 0){// 登錄錯誤return "redirect:http://msb.auth.com/login.html";}String entityJson = (String) r.get("entity");System.out.println("----------------->" + entityJson);// 注冊成功就需要調整到商城的首頁return "redirect:http://msb.mall.com/home";}

二、分布式session

1.session問題

image.png

image.png

image.png

image.png

image.png

image.png

2.SpringSession整合

??我們通過SpringSession來實現Session的共享,Session數據存儲在Redis中

image.png

SpringSession的操作指南:

https://docs.spring.io/spring-session/docs/2.5.6/reference/html5/guides/boot-redis.html

導入相關的依賴

        <dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency>

設置對應的配置

image.png

最后我們需要添加對有的注解,放開操作

image.png

然后在Auth服務和商城首頁都整合SpringSession后,我們再商城首頁可以看到Session的數據,注意這兒是手動修改Cookie的域名

image.png

image.png

3.自定義Cookie

??通過自定義Cookie實現session域名的調整

@Configuration
public class MySessionConfig {/*** 自定義Cookie的配置* @return*/@Beanpublic CookieSerializer cookieSerializer(){DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();cookieSerializer.setDomainName("msb.com"); // 設置session對應的一級域名cookieSerializer.setCookieName("msbsession");return cookieSerializer;}/*** 對存儲在Redis中的數據指定序列化的方式* @return*/@Beanpublic RedisSerializer<Object> redisSerializer(){return new GenericJackson2JsonRedisSerializer();}
}

4.單點登錄案例演示

??xxl-sso案例代碼地址:https://gitee.com/xuxueli0323/xxl-sso?_from=gitee_search

下載下來的代碼解壓縮后通過idea導入,然后修改server和simple中的屬性文件,同時我們需要在host中設置對應的域名

127.0.0.1 ssoserver.com
127.0.0.1 msb1.com
127.0.0.1 msb2.com

在server的配置文件中,修改Redis的服務地址

image.png

然后在simple中修改server的地址和redis服務的地址

image.png

然后分別啟動服務測試即可

image.png

https://www.nshth.com/c/338882.html
>

相关文章:

  • 零售管理系統
  • 企業統一認證平臺登錄
  • 新零售平臺系統
  • 華為商城實名認證不了
  • 聚惠商城有沒有官方認證
  • 點購商城實名認證安全嗎
  • 認證就有額度的商城
  • 系統構建
  • 常用加密方式有哪些,不可逆加密:說一下你常用的加密算法
  • 各種資源網址
  • GItHub頻繁驗證郵箱?Please verify your email address????
  • 零售管理系統,【第十六篇】商城系統-認證系統構建
  • 將一列數據導入另一列,excel將B列數據放在A列后面
  • 將圖片內容轉化為excel文檔,插入 PNG 圖片至 Excel
  • DDG檢測的臨床意義,DDPG中的Ornstein-Uhlenbeck過程怎么理解
  • 單片機編程入門教程,新手入門單片機實戰超詳細以及遇到一些坑-避障小車1【更新中】
  • 基于STM32視覺檢測程序設計,畢業設計 單片機stm32廚房環境檢測系統 - 物聯網 嵌入式
  • 學生成績管理系統數據庫設計,基于C#結合SQL設計學生成績系統系統
  • 電腦搜索文件的軟件,【記錄】everything搜索不到電腦上文件的解決方案
  • everything搜索工具,everything搜到不到文件的設置問題
  • 蘋果電腦怎么搜索文件,mac搜索文件為什么啥都搜不出來?
  • 七大編程語言難度排名,編程語言“破劍式”——編程語言學什么?
  • 小程序一鍵生成工具,微信小程序頭像上傳+(C#)服務端接收
  • simulink整流器模塊,Simulink取最大(小)值方法總結
  • oracle題庫及答案,ORACLE找出最大的數返回 GREATEST()函數
  • 輾轉相除法求最小公倍數的方法,【常用算法】輾轉相除法求最大公約數
  • 整數大小的比較方法,判斷較大整數
  • 軟件行業的發展前景,這不是你想象中的軟件產業
  • 一篇文章,還有一篇
  • 人臉識別特征點,特征點數量與人臉識別準確度沒有直接關系
  • dinkelbach算法介紹,two-stage算法一點思考
  • dsra9110e connection is closed,resent101-DSSD報錯solution
  • 小青蛙跳臺階的另類思考
  • 青蛙游戲 linux,小青蛙2048
  • k8s容器化部署,K8S之POD調度
  • 【JS逆向系列】某乎x96參數與jsvmp初體驗
  • 未能寫入文件,未能寫入輸出文件..”--“拒絕訪問。”的解決辦法 [轉]
  • unity游戲紅色感嘆號崩潰,[Unity]讀取本地圖片ArgumentException: A null reference or invalid value