IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 短信、邮箱、http请求工具 -> 正文阅读

[网络协议]短信、邮箱、http请求工具

一、短信

1、容联云短信

(1)官网:https://www.yuntongxun.com/member/main
(2)登录注册,进入控制台首页

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LkLXYcoR-1645931890185)(/1.png)]

(3)开发文档

https://doc.yuntongxun.com/p/5f0299f4a80948a1006e775e

(4)导入依赖
<dependency>
    <groupId>com.cloopen</groupId>
    <artifactId>java-sms-sdk</artifactId>
    <version>1.0.3</version>
</dependency>
(5)调用示例测试
//生产环境请求地址:app.cloopen.com
    String serverIp = "app.cloopen.com";
    //请求端口
    String serverPort = "8883";
    //主账号,登陆云通讯网站后,可在控制台首页看到开发者主账号ACCOUNT SID和主账号令牌AUTH TOKEN
    String accountSId = "你的accountSId";
    String accountToken = "你的auth token";
    //请使用管理控制台中已创建应用的APPID
    String appId = "你的appId";
    CCPRestSmsSDK sdk = new CCPRestSmsSDK();
    sdk.init(serverIp, serverPort);
    sdk.setAccount(accountSId, accountToken);
    sdk.setAppId(appId);
    sdk.setBodyType(BodyType.Type_JSON);
    String to = "1352*******";
    String templateId= "templateId";
    String[] datas = {"变量1","变量2","变量3"};
    //String subAppend="1234";  //可选 扩展码,四位数字 0~9999
    //String reqId="fadfafas";  //可选 第三方自定义消息id,最大支持32位英文数字,同账号下同一自然天内不允许重复
    HashMap<String, Object> result = sdk.sendTemplateSMS(to,templateId,datas);
    //HashMap<String, Object> result = sdk.sendTemplateSMS(to,templateId,datas,subAppend,reqId);
    if("000000".equals(result.get("statusCode"))){
        //正常返回输出data包体信息(map)
        HashMap<String,Object> data = (HashMap<String, Object>) result.get("data");
        Set<String> keySet = data.keySet();
        for(String key:keySet){
            Object object = data.get(key);
            System.out.println(key +" = "+object);
        }
    }else{
        //异常返回输出错误码和错误信息
        System.out.println("错误码=" + result.get("statusCode") +" 错误信息= "+result.get("statusMsg"));
    }
(6)正式调用环境
  • application.yml

    spring:
      sms:
        #生产环境请求地址:app.cloopen.com
        serverIp: app.cloopen.com
        #请求端口
        serverPort: 8883
        #开发者主账号ACCOUNT SID
        accountSId: 你的accountSId
        #主账号令牌AUTH TOKEN
        accountToken: 你的AUTH TOKEN
        #请使用管理控制台中已创建应用的APPID
        appId: 你的AppID
    
  • SmsTools

    import com.cloopen.rest.sdk.BodyType;
    import com.cloopen.rest.sdk.CCPRestSmsSDK;
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    import java.util.HashMap;
    import java.util.Set;
    
    @Data
    @ConfigurationProperties(prefix = "spring.sms")
    @Component
    public class SmsTools {
    
        //生产环境请求地址:app.cloopen.com
        private String serverIp;
        //请求端口
        private String serverPort;
        //主账号,登陆云通讯网站后,可在控制台首页看到开发者主账号ACCOUNT SID和主账号令牌AUTH TOKEN
        private String accountSId;
        private String accountToken;
        //请使用管理控制台中已创建应用的APPID
        private String appId;
    
        /**
         * 发送短信验证方法
         * @param to 发送给谁,最多发送200个,用逗号隔开
         * @param templateId  短信注册验证码的模板id,容联云测试模板id=1
         * @param datas
         * @return
         */
        public Boolean sendSms(String to,String templateId,String[] datas){
    
            CCPRestSmsSDK sdk = new CCPRestSmsSDK();
            sdk.init(serverIp, serverPort);
            sdk.setAccount(accountSId, accountToken);
            sdk.setAppId(appId);
            sdk.setBodyType(BodyType.Type_JSON);
    
            HashMap<String, Object> result = sdk.sendTemplateSMS(to,templateId,datas);
            if("000000".equals(result.get("statusCode"))){
                //正常返回输出data包体信息(map)
                HashMap<String,Object> data = (HashMap<String, Object>) result.get("data");
                Set<String> keySet = data.keySet();
                for(String key:keySet){
                    Object object = data.get(key);
                    System.out.println(key +" = "+object);
                }
                return true;
            }else{
                //异常返回输出错误码和错误信息
                System.out.println("错误码=" + result.get("statusCode") +" 错误信息= "+result.get("statusMsg"));
                return false;
            }
        }
    }
    
    
  • 调用测试

    	@Resource
    	private SmsTools smsTools;
    
    	@Test
        void sendSms(){
            Boolean sendSms = smsTools.sendSms("18886330640", "1", new String[]{"2345", "5"});
            System.out.println(sendSms);
        }
    
  • 随机生成4位数验证码代码

    	public static int getRandomCode(){		
    		int max=9999;
            int min=1111;
            Random random = new Random();
            return random.nextInt(max)%(max-min+1) + min;		
    	}
    

    ?

2、阿里云

参考这个链接:https://www.yuque.com/zhangshuaiyin/guli-mall/ktswm9

二、邮箱

QQ邮箱接入手册
https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=371

1、引入依赖
	   <!--邮箱依赖包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <!--freemarker模板引擎是为了后面发送模板邮件 不需要的可以不引入-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
2、MailTools
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.IOException;
import java.util.Map;

/**
 * 发送电子邮件的工具类
 * @author lyh 2021/7/26
 * @since 1.0.0
 */
@Component
@ConfigurationProperties(prefix = "spring.mail")
@Data
public class MailTools {
    @Resource
    private JavaMailSenderImpl mailSender;
    @Resource
    private FreeMarkerConfigurer freeMarkerConfigurer;
    private String subject;
    private String from;


    /**
     * 发送普通的电子邮件
     * @param mailContent 邮件内容
     * @param to 发送给谁 可以设置多个
     * @return 成功或者失败
     */
    public void sendSimpleEmail(String mailContent,String...to){
        this.sendSimpleEmail(subject,mailContent,to);
    }
    /**
     * 发送普通的电子邮件
     * @param subject 邮件主题
     * @param mailContent 邮件内容
     * @param to 发送给谁 可以设置多个
     * @return 成功或者失败
     */
    public void sendSimpleEmail(String subject,String mailContent,String...to){
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setSubject(subject);//设置邮件主题
        mailMessage.setTo(to);//设置发送给谁
        mailMessage.setFrom(from);//设置谁发送的邮件
        mailMessage.setText(mailContent);//设置邮件内容
        mailSender.send(mailMessage);
    }

    /**
     * 发送带附件和html格式的邮件
     * @param subject 主题
     * @param mailContent 邮件内容
     * @param to 发送给谁
     * @throws MessagingException 邮件异常对象
     */
    public void sendMimeMail(String subject,String mailContent,String...to) throws MessagingException {
        this.sendMimeMail(subject,mailContent,null,to);
    }

    /**
     * 发送带附件和html格式的邮件
     * @param mailContent 邮件内容
     * @param to 发送给谁
     * @throws MessagingException 邮件异常对象
     */
    public void sendMimeMail(String mailContent,String...to) throws MessagingException {
        this.sendMimeMail(this.subject,mailContent,null,to);
    }

    /**
     * 发送带附件和html格式的邮件
     * @param subject 主题
     * @param mailContent 邮件内容
     * @param files 附件文件
     * @param to 发送给谁
     * @throws MessagingException 邮件异常对象
     */
    public void sendMimeMail(String subject, String mailContent, File[] files, String...to) throws MessagingException {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);//这个true表示发送带附件的邮件
        helper.setFrom(from);
        helper.setTo(to);
        //设置主题
        helper.setSubject(subject);
        helper.setText(mailContent,true);//表示html类型的邮件
        //设置附件
        if(files!=null && files.length>0){
            for (File file:files){
                if(file!=null){
                    String filename = file.getName();//获取上传文件名称
                    helper.addAttachment(filename,file);
                }
            }
        }
        mailSender.send(mimeMessage);
    }

    /**
     * 发送模板邮件
     * @param subject 邮件主题
     * @param model   用于替换模板中需要替换的内容的map集合
     * @param templatePath 模板名称
     * @param to       发送给谁
     * @throws IOException
     * @throws TemplateException
     * @throws MessagingException
     */
    public void sendTemplateMail(String subject, Map<String,Object> model, String templatePath, String...to) throws IOException, TemplateException, MessagingException {
        // 获得模板
        Template mailTemplate = freeMarkerConfigurer.getConfiguration().getTemplate(templatePath);
        // 传入数据模型到模板,替代模板中的占位符,并将模板转化为html字符串
        String templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(mailTemplate,model);
        // 该方法本质上还是发送html邮件,调用之前发送html邮件的方法
        this.sendMimeMail(subject,templateHtml,to);
    }

}

3、application.yml
spring:
  #QQ邮箱
  mail:
    protocol: smtp              
    host: smtp.qq.com           
    port: 587                   
    username: 40594@qq.com   #你的QQ账号
    password: 你的密码  #获取密码
    from: 40594@qq.com  #发送账号

  freemarker:
    template-loader-path: classpath:/templates/mail/  
    suffix: .ftl                                      
    cache: false                                      
    charset: UTF-8                                    
4、邮件模板account_active.ftl
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
        .content{
            text-indent: 2em;
            color: green;
            font-size: 20px;
        }
        .footer{
            text-align: right;
        }
    </style>
</head>
<body>
<div id="content_box">
    <h2>尊敬的${name},您好!</h2>
    <p class="content">
        欢迎成为XXX家族成员的一份子,您此次账户注册的激活码为:${code},该激活码用于注册用户激活账户使用,请妥善保管!
        请于30分钟内输入激活!
    </p>
    <div class="footer">
        <span>XXX</span></br>
        <span>${datetime}</span>
    </div>
</div>
</body>
</html>
5、测试调用
	@Resource
    private MailTools mailTools;

    @Test
    void sendMail() throws TemplateException, IOException, MessagingException {
        String templateName = "account_active.ftl";//模板名称
        //用于设置你要替换模板中的哪个一个占位符,以及值
        Map<String,Object> model = new HashMap<>();
        //把日期格式转化成字符串
        Date date = new Date();
        String strDateFormat = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
        String datetime = sdf.format(date);
        model.put("name","昵称");
        model.put("code","6270");
        model.put("datetime",datetime);
        mailTools.sendTemplateMail("邮箱注册主题",model,templateName,"9605940@qq.com");
    }
6、pom.xml
    <build>
    	<resources>
            <resource>
                <directory>${basedir}/src/main/java</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

三、第三方请求方式工具HttpUtils

HttpUtils.java地址:https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java

pom.xml地址:https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.15</version>
		</dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.2.1</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>9.3.7.v20160115</version>
        </dependency>
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

public class HttpUtils {
	
	/**
	 * get
	 * 
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doGet(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpGet request = new HttpGet(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }
        
        return httpClient.execute(request);
    }
	
	/**
	 * post form
	 * 
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param bodys
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPost(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			Map<String, String> bodys)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (bodys != null) {
            List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();

            for (String key : bodys.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            request.setEntity(formEntity);
        }

        return httpClient.execute(request);
    }	
	
	/**
	 * Post String
	 * 
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param body
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPost(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			String body)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
        	request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }
	
	/**
	 * Post stream
	 * 
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param body
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPost(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			byte[] body)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
        	request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }
	
	/**
	 * Put String
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param body
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPut(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			String body)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
        	request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }
	
	/**
	 * Put stream
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param body
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPut(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			byte[] body)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
        	request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }
	
	/**
	 * Delete
	 *  
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doDelete(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }
        
        return httpClient.execute(request);
    }
	
	private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
    	StringBuilder sbUrl = new StringBuilder();
    	sbUrl.append(host);
    	if (!StringUtils.isBlank(path)) {
    		sbUrl.append(path);
        }
    	if (null != querys) {
    		StringBuilder sbQuery = new StringBuilder();
        	for (Map.Entry<String, String> query : querys.entrySet()) {
        		if (0 < sbQuery.length()) {
        			sbQuery.append("&");
        		}
        		if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
        			sbQuery.append(query.getValue());
                }
        		if (!StringUtils.isBlank(query.getKey())) {
        			sbQuery.append(query.getKey());
        			if (!StringUtils.isBlank(query.getValue())) {
        				sbQuery.append("=");
        				sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
        			}        			
                }
        	}
        	if (0 < sbQuery.length()) {
        		sbUrl.append("?").append(sbQuery);
        	}
        }
    	
    	return sbUrl.toString();
    }
	
	private static HttpClient wrapClient(String host) {
		HttpClient httpClient = new DefaultHttpClient();
		if (host.startsWith("https://")) {
			sslClient(httpClient);
		}
		
		return httpClient;
	}
	
	private static void sslClient(HttpClient httpClient) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(X509Certificate[] xcs, String str) {
                	
                }
                public void checkServerTrusted(X509Certificate[] xcs, String str) {
                	
                }
            };
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = httpClient.getConnectionManager();
            SchemeRegistry registry = ccm.getSchemeRegistry();
            registry.register(new Scheme("https", 443, ssf));
        } catch (KeyManagementException ex) {
            throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
        	throw new RuntimeException(ex);
        }
    }
}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:49:22  更:2022-03-03 16:53:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:20:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码