spring boot 整合 mail 發(fā)送郵件 【用戶注冊以及找回密碼】(轉(zhuǎn))

https://blog.csdn.net/zhaihuilin0986/article/details/78530657














一.在 pox.xml 中 加入 <!--email依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>

二。創(chuàng)建一個(gè)用戶實(shí)體

/**

* .

*/

@Data

@Entity

@NoArgsConstructor

@AllArgsConstructor

@RequiredArgsConstructor

public class Member implements Serializable {

? ? @Id

? ? @GenericGenerator(name = "sys_uid",strategy = "com.zhaihuilin.util.KeyGeneratorUtils",parameters = {

? ? ? ? ? ? @Parameter(name = "k",value = "M")

? ? })

? ? @GeneratedValue(generator = "sys_uid")

? ? private? String? id;

? ? //用戶名

? ? @NonNull

? ? private? String? username;

? ? //昵稱

? ? private? String? nickname;

? ? @NonNull

? ? //密碼

? ? private? String? password;

? ? @NonNull

? ? //郵箱

? ? private? String? email;

? ? //電話號碼

? ? private? String? smscode;

? ? //用戶狀態(tài)

? ? private? String? state;

? ? public Member( String username, String nickname, String password, String email, String smscode, String state) {

? ? ? ? this.username = username;

? ? ? ? this.nickname = nickname;

? ? ? ? this.password = password;

? ? ? ? this.email = email;

? ? ? ? this.smscode = smscode;

? ? ? ? this.state = state;

? ? }

? ? public Member(String username, String nickname, String password, String email, String state) {

? ? ? ? this.username = username;

? ? ? ? this.nickname = nickname;

? ? ? ? this.password = password;

? ? ? ? this.email = email;

? ? ? ? this.state = state;

? ? }

}

三.配置文件?

1.application-dev.yml

spring:

? jpa:

? ? show-sql: true

? ? hibernate:

? ? ? ddl-auto: update

? datasource:

? ? url: jdbc:mysql://127.0.0.1:3306/sms?characterEncoding=UTF-8

? ? username: root

? ? password: root

? ? driver-class-name: com.mysql.jdbc.Driver

? ? minIdle: 2

? ? maxAction: 20

? ? maxWaitMillis: 8000

? cache:

? ? type: redis

? redis:

? ? database: 2

? ? host: 127.0.0.1

? ? port: 6379

? ? timeout: 20000

? ? pool:

? ? ? max-active: 8

? ? ? min-idle: 0

? ? ? max-idle: 8

? ? ? max-wait: -1

2.application-.yml

server:

? tomcat:

? ? uri-encoding: utf-8

? port: 8087

? context-path: /

spring:

? profiles:

? ? active: dev

? mail:

? ? host: smtp.163.com

? ? username: 郵箱?

? ? password: 郵箱的登錄密碼

? ? port: 25

? ? default-encoding: UTF-8

? ? protocol: smtp

? ? properties:

? ? ? mail:

? ? ? ? smth:

? ? ? ? ? auth: true

? ? ? ? ? starttls:

? ? ? ? ? ? enable: true

? ? ? ? ? ? required: true

四。編寫相應(yīng)的 dao ?service ?[此處省略]

五。編寫工具類

//實(shí)體類主鍵生成策略

public class KeyGeneratorUtils extends AbstractUUIDGenerator implements Configurable {

? ? public String k;

? ? @Override

? ? public void configure(Type type, Properties properties, ServiceRegistry serviceRegistry) throws MappingException {

? ? ? ? k = properties.getProperty("k");

? ? }

? ? @Override

? ? public Serializable generate(SessionImplementor sessionImplementor, Object o) throws HibernateException {

? ? ? ? SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");

? ? ? ? return k + simpleDateFormat.format(new Date());

? ? }

}

//時(shí)間處理類

public class NormalTools {

? ? public static String getFileType(String fileName) {

? ? ? ? if(fileName!=null && fileName.indexOf(".")>=0) {

? ? ? ? ? ? return fileName.substring(fileName.lastIndexOf("."), fileName.length());

? ? ? ? }

? ? ? ? return "";

? ? }

? ? /**

? ? * 判斷文件是否為圖片文件

? ? * @param fileName

? ? * @return

? ? */

? ? public static Boolean isImageFile(String fileName) {

? ? ? ? String [] img_type = new String[]{".jpg", ".jpeg", ".png", ".gif", ".bmp"};

? ? ? ? if(fileName==null) {return false;}

? ? ? ? fileName = fileName.toLowerCase();

? ? ? ? for(String type : img_type) {

? ? ? ? ? ? if(fileName.endsWith(type)) {return true;}

? ? ? ? }

? ? ? ? return false;

? ? }

? ? public static String curDate(String pattern) {

? ? ? ? SimpleDateFormat sdf = new SimpleDateFormat(pattern);

? ? ? ? return sdf.format(new Date());

? ? }

? ? public static String curDate() {

? ? ? ? return curDate("yyyy-MM-dd HH:mm:ss");

? ? }

}

//隨機(jī)生成6位數(shù)

public class RandomTools {

? ? /** 隨機(jī)6位數(shù) */

? ? public static String randomCode() {

? ? ? ? Integer res = (int)(Math.random()*1000000);

? ? ? ? return res+"";

? ? }

}

//加密 解密

public class SecurityUtil {

public static String md5(String password) throws NoSuchAlgorithmException {

MessageDigest md = MessageDigest.getInstance("MD5");

md.update(password.getBytes());

return new BigInteger(1,md.digest()).toString(16);

}

public static String md5(String username,String password) throws NoSuchAlgorithmException {

MessageDigest md = MessageDigest.getInstance("MD5");

md.update(username.getBytes());

md.update(password.getBytes());

return new BigInteger(1,md.digest()).toString(16);

}

}

//非空判斷

public class StringUtils {

? ? public static boolean isNotEmpty(String str){

? ? ? ? if(str != null && str.trim().length() != 0){

? ? ? ? ? ? return true;

? ? ? ? }

? ? ? ? return false;

? ? }

}

//郵件發(fā)送工具

@Component

public class SendEmailUtils {

? ? @Autowired

? ? private JavaMailSender javaMailSender; //注入 javaMailSender

? ? @Value("${spring.mail.username}")

? ? private? String username;? ? // 發(fā)送郵件者 郵箱 【誰發(fā)的】

? ? /**

? ? * 發(fā)送郵件

? ? * @param title? 標(biāo)題

? ? * @param titleWithName? 是否在標(biāo)題后添加 名稱

? ? * @param content? ? ? ? 內(nèi)容

? ? * @param contentWithName? 是否在內(nèi)容后添加 名稱

? ? * @param email? ? 接收者的郵箱【注冊人】

? ? */

? ? private? void? sendNormalEmail(

? ? ? ? ? ? String title,boolean titleWithName,

? ? ? ? ? ? String content, boolean contentWithName, String email ){

? ? ? ? String dName="個(gè)人博客";

? ? ? ? MimeMessage mimeMessage=null;

? ? ? ? try {

? ? ? ? ? ? mimeMessage= javaMailSender.createMimeMessage();//創(chuàng)建要發(fā)送的信息

? ? ? ? ? ? MimeMessageHelper helper=new MimeMessageHelper(mimeMessage,true);

? ? ? ? ? ? helper.setFrom(new InternetAddress(username,dName,"UTF-8")); //設(shè)置 誰發(fā)送的

? ? ? ? ? ? helper.setTo(email);//發(fā)給誰 【接收者的郵箱】

? ? ? ? ? ? title= titleWithName?title +"-"+dName:title; //標(biāo)題內(nèi)容

? ? ? ? ? ? helper.setSubject(title);//發(fā)送郵件的辯題

? ? ? ? ? ? if(contentWithName) {

? ? ? ? ? ? ? ? content += "<p style='text-align:right'>" +dName+ "</p>";

? ? ? ? ? ? ? ? content += "<p style='text-align:right'>" + NormalTools.curDate("yyyy-MM-dd HH:mm:ss")+ "</p>";

? ? ? ? ? ? }

? ? ? ? ? ? helper.setText(content,true);//發(fā)送的內(nèi)容 是否為html

? ? ? ? }catch (Exception e){

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? ? ? ? ? javaMailSender.send(mimeMessage);

? ? }

? ? /**

? ? * 發(fā)送 注冊時(shí)的驗(yàn)證碼

? ? * @param email? 接收者的郵箱【注冊人】

? ? * @param code? ? 驗(yàn)證碼

? ? */

? ? public? void? sendRegisterCode(final String email, String code){

? ? ? ? ? final StringBuffer sb= new StringBuffer();//實(shí)例化一個(gè)StringBuffer

? ? ? ? ? sb.append("<h2>"+email+",您好!<h2>")

? ? ? ? ? ? ? ? ? .append("<p style='color:red'>此次注冊的驗(yàn)證碼是:"+code+"</p>");

? ? ? ? ? new Thread(new Runnable() {

? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? public void run() {

? ? ? ? ? ? ? ? ? sendNormalEmail("驗(yàn)證碼", true, sb.toString(), true, email);

? ? ? ? ? ? ? }

? ? ? ? ? }).start();

? ? }

? ? /**

? ? * 注冊成功時(shí)的提示郵件

? ? * @param email 接收的郵箱地址 【注冊人】

? ? * @param pwd 初始密碼

? ? * @param url 登陸地址

? ? */

? ? public void sendRegisterSuc(final String email, String pwd, String url) {

? ? ? ? final StringBuffer sb = new StringBuffer();

? ? ? ? sb.append("<h3>恭喜您,注冊成功!</h3>")

? ? ? ? ? ? ? ? .append("<h2>初始化密碼是:<b style='color:#F00'>").append(pwd).append("</b>,請不要告訴任何人!</h2>")

? ? ? ? ? ? ? ? .append("請及時(shí)<a href='").append(url).append("'>登陸網(wǎng)站</a>修改密碼。");

? ? ? ? new Thread(new Runnable() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void run() {

? ? ? ? ? ? ? ? sendNormalEmail("注冊成功", true, sb.toString(), true, email);

? ? ? ? ? ? }

? ? ? ? }).start();

? ? }

? ? /**

? ? * 注冊成功時(shí)的提示郵件

? ? * @param email 接收的郵箱地址? 【注冊人】

? ? * @param pwd 初始密碼

? ? * @param url 登陸地址

? ? */

? ? public void sendFindPwdSuc(final String email, String pwd, String url) {

? ? ? ? final StringBuffer sb = new StringBuffer();

? ? ? ? sb.append("<h3>恭喜您,密碼找回成功!</h3>")

? ? ? ? ? ? ? ? .append("<h2>系統(tǒng)隨機(jī)密碼是:<b style='color:#F00'>").append(pwd).append("</b>,請不要告訴任何人!</h2>")

? ? ? ? ? ? ? ? .append("請及時(shí)<a href='").append(url).append("'>登陸網(wǎng)站</a>修改密碼。");

? ? ? ? new Thread(new Runnable() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void run() {

? ? ? ? ? ? ? ? sendNormalEmail("成功找回密碼", true, sb.toString(), true, email);

? ? ? ? ? ? }

? ? ? ? }).start();

? ? }

? ? /**

? ? * 新用戶注冊通過

? ? * @param email 接收郵箱地址(管理員的)

? ? * @param nickname 注冊人姓名

? ? * @param regEmail 注冊人郵箱

? ? * @param url 地址

? ? */

? ? public void sendOnRegister(final String email, String nickname, String regEmail, String url) {

? ? ? ? final StringBuffer sb = new StringBuffer();

? ? ? ? sb.append("<a href='").append(url).append("'><h1>姓名:").append(nickname).append("</h1></a>");

? ? ? ? sb.append("<h3>注冊郵箱:").append(regEmail).append("</h3>");

? ? ? ? new Thread(new Runnable() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void run() {

? ? ? ? ? ? ? ? sendNormalEmail("新用戶注冊通知", true, sb.toString(), true, email);

? ? ? ? ? ? }

? ? ? ? }).start();

? ? }

}

六.編寫 配置類

@Configuration

public class EmailConfig {

? ? @Value("http://localhost:8080/member/updatePwd")

? ? public String URL;

? ? //管理員郵箱? 此處隨便寫一個(gè)郵箱

? ? @Value("111@qq.com")

? ? public String MEMEMAIL;

}

七.編寫 controller

@RestController

@Log4j

@RequestMapping(value = "/member")

public class MemberController {

? ? @Autowired

? ? private MemberService memberService;

? ? @Autowired

? ? private SendEmailUtils sendEmailUtils;

? ? @Autowired

? ? private EmailConfig? emailConfig;

? ? /**

? ? * 發(fā)送郵箱驗(yàn)證碼

? ? * @param email? 接收者的郵箱 【注冊人】

? ? * @param request

? ? * @return

? ? */

? ? @RequestMapping(value = "/sendCode")

? ? public? String sendCode(

? ? ? ? ? ? @RequestParam(value = "email",defaultValue = "",required = true) String email,

? ? ? ? ? ? HttpServletRequest request ){

? ? ? ? try {

? ? ? ? ? ? String code =RandomTools.randomCode();//產(chǎn)生隨機(jī)的驗(yàn)證碼

? ? ? ? ? ? request.getSession().setAttribute("registerCode",code);

? ? ? ? ? ? //發(fā)送郵件開始? 發(fā)送驗(yàn)證碼

? ? ? ? ? ? log.info("開始發(fā)送郵件驗(yàn)證碼------");

? ? ? ? ? ? sendEmailUtils.sendRegisterCode(email,code);

? ? ? ? }catch (Exception e){

? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? return? "0";

? ? ? ? }

? ? ? ? return "1";

? ? }

? ? @RequestMapping(value = "/register")

? ? public ReturnMessages register(

? ? ? ? ? ? @RequestParam(value = "email",defaultValue = "",required = true) String email,

? ? ? ? ? ? @RequestParam(value = "username",defaultValue = "",required = true) String username,

? ? ? ? ? ? @RequestParam(value = "nickname",defaultValue = "",required = false) String nickname,

? ? ? ? ? ? @RequestParam(value = "smscode",defaultValue = "",required = false) String smscode,

? ? ? ? ? ? @RequestParam(value = "code",defaultValue = "",required = true) String code,

? ? ? ? ? ? HttpServletRequest request

? ? ){

? ? ? ? ? ? ReturnMessages? returnMessages=null;

? ? ? ? ? ? if (!StringUtils.isNotEmpty(email)){

? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"郵箱不能為空!",null);

? ? ? ? ? ? }

? ? ? ? ? ? if (!StringUtils.isNotEmpty(username)){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"用戶名不能為空!",null);

? ? ? ? ? ? }

? ? ? ? ? ? if (memberService.existMemberByemail(email)){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"郵箱已存在!",null);

? ? ? ? ? ? }

? ? ? ? ? ? if (memberService.existMemberByusername(username)){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"用戶名已存在!",null);

? ? ? ? ? ? }

? ? ? ? ? ? if (!StringUtils.isNotEmpty(code)){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"驗(yàn)證碼不能為空!",null);

? ? ? ? ? ? }

? ? ? ? ? ? // 此處測試的時(shí)候 無法獲取到 session 值

//? ? ? ? ? ? String registerCode = (String) request.getSession().getAttribute("registerCode");

//? ? ? ? ? ? if (!registerCode.equals(code)){

//? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"驗(yàn)證碼輸入不正確!",null);

//? ? ? ? ? ? }

? ? ? ? ? ? String pwd = RandomTools.randomCode(); //隨機(jī)密碼

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? Member member=new Member();

? ? ? ? ? ? ? ? member.setEmail(email);

? ? ? ? ? ? ? ? member.setNickname(nickname);

? ? ? ? ? ? ? ? member.setState(StateConstant.USER_STATE_CHECK_ING.toString());

? ? ? ? ? ? ? ? member.setUsername(username);

? ? ? ? ? ? ? ? member.setPassword(SecurityUtil.md5(email,pwd));

? ? ? ? ? ? ? ? member=memberService.saveMember(member);

? ? ? ? ? ? ? ? if (member !=null){

? ? ? ? ? ? ? ? ? ? //注冊成功后 通知注冊人

? ? ? ? ? ? ? ? ? ? sendEmailUtils.sendRegisterSuc(email,pwd, emailConfig.URL+"?username="+username+"&code="+pwd);//注冊成功后

? ? ? ? ? ? ? ? ? ? //注冊成功后 通知管理員

? ? ? ? ? ? ? ? ? ? sendEmailUtils.sendOnRegister(emailConfig.MEMEMAIL,username,email,"#");//注冊成功后

? ? ? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.SUCCESS,"注冊成功!",member);

? ? ? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"注冊失敗!",null);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? } catch (Exception e) {

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"注冊失??!",null);

? ? ? ? ? ? }

? ? }

? ? /**

? ? * 修改密碼

? ? * @param code? ? ? ? ? 初始密碼

? ? * @param newPassword? 新密碼

? ? * @param request

? ? * @return

? ? */

? ? @RequestMapping(value = "/updatePwd")

? ? public? ReturnMessages updatePwd(

? ? ? ? ? ? @RequestParam(value = "code",defaultValue = "",required = true) String code,

? ? ? ? ? ? @RequestParam(value = "username",defaultValue = "",required = true) String username,

? ? ? ? ? ? @RequestParam(value = "newPassword",defaultValue = "",required = true) String newPassword,

? ? ? ? ? ? HttpServletRequest request

? ? ){

? ? ? ? ? ? ReturnMessages returnMessages=null;

? ? ? ? ? ? if (!StringUtils.isNotEmpty(code)){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"初始密碼不能為空!",null);

? ? ? ? ? ? }

? ? ? ? ? ? if (!StringUtils.isNotEmpty(newPassword)){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"新密碼不能為空!",null);

? ? ? ? ? ? }

? ? ? ? ? ? Member member = memberService.findMemberByusername(username);

? ? ? ? ? ? if (member ==null){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"該用戶不存在!",null);

? ? ? ? ? ? }

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? if ( StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(newPassword)){

? ? ? ? ? ? ? ? ? ? member.setPassword(SecurityUtil.md5(member.getEmail(),newPassword));

? ? ? ? ? ? ? ? ? ? member=memberService.updateMember(member);

? ? ? ? ? ? ? ? ? ? if (member !=null){

? ? ? ? ? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.SUCCESS,"修改密碼成功!",member);

? ? ? ? ? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"修改密碼失?。?,null);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"修改密碼失??!",null);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }catch (Exception e){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"修改密碼失敗!",null);

? ? ? ? ? ? }

? ? }

? ? /**

? ? * 找回密碼

? ? * @param email? ? 用戶郵箱

? ? * @param request

? ? * @return

? ? */

? ? @RequestMapping(value ="/findPwd")

? ? public? ReturnMessages findPwd(

? ? ? ? ? ? @RequestParam(value = "email",defaultValue = "",required = true) String email,

? ? ? ? ? ? HttpServletRequest request

? ? ){

? ? ? ? ? ReturnMessages returnMessages=null;

? ? ? ? ? if (!StringUtils.isNotEmpty(email)){

? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"郵箱不能為空!",null);

? ? ? ? ? }

? ? ? ? ? Member member= memberService.findMemeberByemail(email);

? ? ? ? ? if (member ==null){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"該用戶不存在!",null);

? ? ? ? ? }

? ? ? ? ? try {

? ? ? ? ? ? ? String url="http:192.168.0.17:8080/member/login";

? ? ? ? ? ? ? String randPwd = RandomTools.randomCode();//隨機(jī)產(chǎn)生一個(gè)密碼

? ? ? ? ? ? ? member.setPassword(SecurityUtil.md5(email,randPwd));

? ? ? ? ? ? ? member=memberService.updateMember(member);

? ? ? ? ? ? ? //發(fā)送郵件通知 用戶

? ? ? ? ? ? ? sendEmailUtils.sendFindPwdSuc(email,randPwd,url);

? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.SUCCESS,"找回密碼成功!",member);

? ? ? ? ? }catch (Exception e){

? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"找回密碼失敗!",null);

? ? ? ? ? }

? ? }

? ? /**

? ? * 登錄

? ? * @param email? ? ? 郵箱

? ? * @param password? 密碼

? ? * @param request

? ? * @return

? ? */

? ? @RequestMapping(value = "/login")

? ? public? ReturnMessages login(

? ? ? ? ? ? @RequestParam(value = "email",defaultValue = "",required = true) String email,

? ? ? ? ? ? @RequestParam(value = "password",defaultValue = "",required = true) String password,

? ? ? ? ? ? HttpServletRequest request

? ? ){

? ? ? ? ReturnMessages returnMessages=null;

? ? ? ? try {

? ? ? ? ? ? if (!StringUtils.isNotEmpty(email)){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"郵箱不能為空!",null);

? ? ? ? ? ? }

? ? ? ? ? ? if (!StringUtils.isNotEmpty(password)){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"密碼不能為空!",null);

? ? ? ? ? ? }

? ? ? ? ? ? Member member=memberService.findMemeberByemail(email);

? ? ? ? ? ? if (member== null){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"用戶不存在!",null);

? ? ? ? ? ? }

? ? ? ? ? ? String pwd=SecurityUtil.md5(email,password);

? ? ? ? ? ? if (member.getPassword().equals(pwd)){

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.SUCCESS,"登錄成功!",null);

? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"密碼錯(cuò)誤,登錄失??!",null);

? ? ? ? ? ? }

? ? ? ? }catch (Exception e){

? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? return? new? ReturnMessages(RequestState.ERROR,"登錄失??!",null);

? ? ? ? }

? ? }

}

---------------------

作者:zhaihuilin0986

來源:CSDN

原文:https://blog.csdn.net/zhaihuilin0986/article/details/78530657

版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容