使用java实现云端资源共享小程序的代码

云端共享小程序:

首先介绍一些程序功能:多用户共享资源,创建一个共享服务器,服务器存储器可以存放资源,用户可以向服务器上传文件,也可以从服务器下载文件,实现了多用户分享资源的功能。
技术栈
1.集合框架(Map集合)
2.IO流(对象序列化,文件传输等)
3.多线程
4.网络编程(TCP/IP协议)
5.简单的GUI界面
来看下界面效果(本人喜欢粉色,用户可以自定义颜色…):

点击下载后:

具体不再详述,看程序:服务端:

package com.softeem.clound.server;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import com.softeem.clound.ToolsAndUI.Tools;

/***
 * 云端共享服务器:
 * 实现多用户云端共享资源
 * @author gq
 *
 */
public class CloudServer extends Thread {
	/** 套接字 */
	private Socket s;
	/** 文件Map集合 */
	Map<String, File> map = new HashMap<String, File>();
	/** 服务器暂存文件的文件夹(这里我用电脑作为服务器) */
	File file = new File("C:\\Users\\14252\\Desktop\\keepFiles");

	/**
	 * 定义构造器初始化套接字
	 *
	 * @param s
	 */
	public CloudServer(Socket s) {
		this.s = s;
	}

	@Override
	public void run() {
		File files[] = file.listFiles();
		// 先将服务器文件加入到结合中去
		for (File file : files) {
			map.put(file.getName(), file);
		}
		// 先询问用户下载还是上传
		try {
			/*
			 * // 将选择发送给用户 String msg = "欢迎进入云端共享(先选择您的操作)";
			 * Tools.sendMsg(s.getOutputStream(), msg);
			 */
			// 接收到用户的回复
			String s1 = Tools.getMsg(s.getInputStream());
			// 得到用户请求进行操作
			if (s1.equals("1")) {
				Tools.tips("用户选择了下载操作!");
				downLoad();
			} else if ("2".equals(s1)) {
				Tools.tips("用户选择了上传操作!");
				upLoad();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 下载文件
	 *
	 * @throws IOException
	 */
	private void downLoad() throws IOException {
		/**
		 * 将文件集合序列化传给用户
		 */
		Tools.transObject(map, s.getOutputStream());
		// 得到用户下载文件的名字(用户发来的名字可能有空格,去除空格)
		String name = Tools.getMsg(s.getInputStream()).trim();
		// 通过对面传过来的文件名找到文件
		File file = map.get(name);
		// 将文件传输给用户
		Tools.transFile(s.getOutputStream(), file);
		// 将传输成功的信息打印到控制台
		Tools.tips(file.getName() + ":传输完成");
		// 通过半关闭将输出流关闭,解决服务端阻塞问题
		s.shutdownOutput();
	}

	/**
	 * 用户上传文件
	 *
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	private void upLoad() throws ClassNotFoundException, IOException {
		// 通过对象序列化得到文件对象
		Object obj = Tools.getObject(s.getInputStream());
		File f = (File) obj;
		// 设置好文件路径
		file = new File(file, f.getName());
		// 传输信息解决阻塞问题
		Tools.sendMsg(s.getOutputStream(), "");
		// 获取文件
		Tools.getFile(s.getInputStream(), file);
		// 服务器控制台显示用户下载成功
		Tools.tips(file.getName() + " 文件上传成功");
	}

	public static void main(String[] args) throws IOException {
		// 设置一个端口为5555的服务器
		ServerSocket server = new ServerSocket(5555);
		// 不断循环接收多个用户请求
		while (true) {
			// 监听用户请求
			Socket s = server.accept();
			// 当监听到用户请求时,创建线程执行任务
			new CloudServer(s).start();
			// 将每个客户进入到服务器的信息打印到控制台
			Tools.tips("客户端访问了服务器:" + s.getInetAddress().getHostAddress());
		}
	}

}

工具类:

package com.softeem.clound.ToolsAndUI;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
/**
 * 工具类
 * @author 14252
 */
public class Tools {
	/**
	 * * 将套接字输出流包装成打印流并且打印信息
	 * @param os
	 * @param msg
	 * @throws IOException
	 */
	public static void Println(OutputStream os, String msg) throws IOException {

	}

	public static String getMsg(InputStream in) throws IOException {
		InputStreamReader isr = new InputStreamReader(in);
		BufferedReader br = new BufferedReader(isr);
		String s1 = null;
		s1 = br.readLine();
		return s1;
	}
	/**
	 * 简化输出语句
	 *
	 * @param s
	 */
	public static void tips(String s) {
		System.out.println(s);
	}

	/**
	 * 传输(发送)文件
	 * @param os
	 * @param file
	 * @throws IOException
	 */
	public static void transFile(OutputStream os, File file) throws IOException {
		BufferedOutputStream fos = new BufferedOutputStream(os);
		byte b[] = new byte[1024];
		FileInputStream fis = new FileInputStream(file);
		int len = 0;
		while ((len = fis.read(b)) != -1) {
			fos.write(b, 0, len);
		}
		fos.flush();

	}

	/**
	 * 发送消息
	 * @param os
	 * @param msg
	 */
	public static void sendMsg(OutputStream os, String msg) {
		PrintWriter pw = new PrintWriter(os);
		pw.println(msg);
		pw.flush();
	}
 /**
  * 接收文件
  * @param in
  * @param file
  * @throws IOException
  */
	public static void getFile(InputStream in, File file) throws IOException {
		BufferedInputStream bu = new BufferedInputStream(in);
		int len = 0;
		byte b[] = new byte[1024];
		// System.out.println("下载完成!");
		FileOutputStream fos = new FileOutputStream(file);
		while ((len = bu.read(b)) != -1) {
			fos.write(b, 0, len);
		}
		fos.flush();
	}
	/**
	 * 定义泛型方法传输序列化对象
	 * @param t
	 * @param os
	 * @throws IOException
	 */
	public static <T>void transObject(T t,OutputStream os) throws IOException{
		ObjectOutputStream oos=new ObjectOutputStream(os);
	  oos.writeObject(t);
	}
	/**
	 * 定义泛型方法反序列化序列化对象
	 * @param in
	 * @return
	 * @throws ClassNotFoundException
	 * @throws IOException
	 */
	public static Object getObject(InputStream in) throws ClassNotFoundException, IOException{
		ObjectInputStream ois = new ObjectInputStream(in);
		Object o= ois.readObject();
		return o;
	}

}

界面

package com.softeem.clound.ToolsAndUI;

import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * JFrame界面
 *
 * @author 14252
 *
 */
public class MyJFrame extends JFrame {

	private static final long serialVersionUID = -82252562835060372L;
	// 确认按钮
	public static JButton jb1 = new JButton("确认");
	public static JButton jb2 = new JButton("确认");
	public static JButton jbDown = new JButton("下载");
	public static JButton jbUp = new JButton("上传");
	// 文本框
	public static JTextArea jt2 = new JTextArea();
	public static JTextArea jt = new JTextArea();
	public static JTextArea jt1 = new JTextArea();
	public static JScrollPane js = new JScrollPane();
	// 标签
	public static JLabel j1 = new JLabel("输入您要下载的文件名");
	public static JLabel j2 = new JLabel("输入上传文件路径");

	/**
	 * 显示窗口
	 */
	public static void showJFrame() {
		JFrame jf = new JFrame();
		/** 设置窗口 */
		jf.setTitle("云端文件共享mini版");
		jf.setSize(520, 700);
		jf.setLayout(null);
		jf.setVisible(true);
		jf.setResizable(false);
		// 设置容器
		Container c = jf.getContentPane();
		/** 设置滚动条以及文本框 */
		js.setBounds(50, 50, 400, 200);
		c.add(js);
		jt.setFont(new Font("", 20, 16));
		jt.setBounds(50, 50, 400, 200);
		js.setViewportView(jt);
		c.add(jt);
		/** 设置上传下载按钮 */
		jbDown.setBounds(50, 280, 100, 40);
		jbUp.setBounds(350, 280, 100, 40);
		c.add(jbUp);
		c.add(jbDown);
		/** 设置按钮1以及文本框1以及标签1 */
		jb1.setBounds(350, 350, 100, 40);
		c.add(jb1);
		j1.setBounds(50, 360, 300, 100);
		j1.setFont(new Font("", 20, 20));
		j1.setForeground(Color.RED);
		c.add(j1);
		jt1.setBounds(50, 350, 240, 40);
		jt1.setFont(new Font("", 18, 18));
		js.setViewportView(jt);
		c.add(jt1);
		/** 设置按钮2以及文本框2以及标签2 */
		jb2.setBounds(350, 500, 100, 40);
		c.add(jb2);
		jt2.setBounds(50, 500, 240, 40);
		c.add(jt2);
		j2.setBounds(50, 510, 300, 100);
		j2.setFont(new Font("", 20, 20));
		j2.setForeground(Color.RED);
		c.add(j2);
		jt2.setFont(new Font("", 17, 17));
		/** 设置背景颜色 */
		c.setBackground(Color.PINK);

	}
}

服务端:

package com.softeem.clound.cilent;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import com.softeem.clound.ToolsAndUI.MyJFrame;
import com.softeem.clound.ToolsAndUI.Tools;

/**
 * 客户端
 *
 * @author gq
 */
public class CilentSharing {
	/** 套接字 */
	private Socket s;
	/** 下载到的路径 */
	File file1;
	/** 定义一个状态(1 下载 2 上传) */
	String ss;
	/** 服务器ip地址 */
	private String ip;
	/** 服务器端口号 */
	private int port;

	public CilentSharing(File file1, String ip, int port) {
		this.file1 = file1;
		this.ip = ip;
		this.port = port;
	}

	public CilentSharing() {

	}

	/**
	 * 选择进行的操作
	 *
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	private void choose() throws IOException, ClassNotFoundException {
		// 下载
		downLoad();
		// 上传
		upLoad();
	}

	/**
	 * 下载功能(点击下载按钮启动)
	 */
	private void downLoad() {
		// 点击下载按钮开始下载
		MyJFrame.jbDown.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					s = new Socket(ip, port);
				} catch (IOException e2) {
					e2.printStackTrace();
				}
				// 将你的选择发送给服务端(1,2)
				try {
					ss = "1";
					Tools.sendMsg(s.getOutputStream(), ss);
					// 启动下载线程
					new DownlownServer(s, file1).start();
					return;
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
	}

	/**
	 * 上传文件功能(点击上传按钮启动)
	 */
	private void upLoad() {
		MyJFrame.jbUp.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					MyJFrame.jt.setText("请输入您要上传文件所在路径!");
					s = new Socket(ip, port);
					// 将选择发给服务端
					ss = "2";
					Tools.sendMsg(s.getOutputStream(), ss);
					// 开启上传线程
					new UpServer(s).start();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
	}

	/**
	 * 开始任务
	 *
	 * @throws ClassNotFoundException
	 * @throws IOException
	 */
	public static void main(String[] args) throws ClassNotFoundException, IOException {
		// 启动界面
		MyJFrame.showJFrame();
		// 说明
		MyJFrame.jt.setText("欢迎使用云端共享!!!" + "\n" + "注意:" + "\n" + "在上传文件填写路径前或选择下载文件时" + ",先选择您的" + "\n" + "操作(上传/下载)");
		// 文件下载的路径(这里写自己的保存路径)
		File f = new File("C:\\Users\\14252\\Desktop\\新建文件夹 (4)");
		// 端口号
		int port = 5555;
		// ip地址
		String ip = "192.168.0.102";
		// 调用选择进行操作的方法
		new CilentSharing(f, ip, port).choose();

	}

}

客户端下载服务线程:

package com.softeem.clound.cilent;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import com.softeem.clound.ToolsAndUI.MyJFrame;
import com.softeem.clound.ToolsAndUI.Tools;

/**
 * 创建线程回应下载点击事件
 *
 * @author gq
 *
 */
public class DownlownServer extends Thread {
	/** socket套接字 */
	Socket s;
	/** 用户的下载路径 */
	File file;
	/** 接收传过来的map集合 */
	Map<String, File> map;
	/** 接收文本框内容 */
	String msg;
	/** 接受所有文件信息 */
	String show="";

	public DownlownServer(Socket s, File file) {
		this.s = s;
		this.file = file;
	}

	@Override
	public void run() {
		// 创建线程执行下载任务
		// 反对象序列化(得到map集合)
		Object obj = null;
		try {
			obj = Tools.getObject(s.getInputStream());
		} catch (ClassNotFoundException | IOException e2) {
			// TODO 自动生成的 catch 块
			e2.printStackTrace();
		}
		// 得到Map集合
		map = (HashMap<String, File>) obj;
		// 将服务器文件信息显示到这里
		map.forEach((k, v) -> {
			show = show + "文件名: " + k + "\n";
		});
		// 将可以下载的文件列出来
		MyJFrame.jt.setText(show);
		// 按钮点击事件下载文件
		MyJFrame.jb1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 将选择的文件名字传给服务端
				try {
					msg = MyJFrame.jt1.getText().trim();
					// 将下载文件名字传给服务器
					Tools.sendMsg(s.getOutputStream(), msg);
					// 将服务端文件下载下来
					File f = new File("");
					// 接收原路径
					f = file;
					file = new File(file, msg);
					// 接收文件
					Tools.getFile(s.getInputStream(), file);
					MyJFrame.j1.setText("下载成功!!!");
					// 恢复原路径可以多次下载
					file = f;
					//关闭套接字
					s.close;
				} catch (IOException e1) {
					e1.printStackTrace();
				}

			}
		});
	}

}

客户端上传线程:

package com.softeem.clound.cilent;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.Map;

import com.softeem.clound.ToolsAndUI.MyJFrame;
import com.softeem.clound.ToolsAndUI.Tools;

/***
 * 上传线程
 * @author 14252
 *
 */
public class UpServer extends Thread{
	/***/
	Socket s;
	File file;
	Map<String, File> map;
	String show;
	public UpServer(Socket s) {
		this.s = s;
	}
	@Override
	public void run() {
		MyJFrame.jb2.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				//得到输入的文件路径
				String content=MyJFrame.jt2.getText();
				file=new File(content);
				try {
					//将文件信息通过对象序列化传过去
					Tools.transObject(file, s.getOutputStream());
					//得到服务端响应避免阻塞
					Tools.getMsg(s.getInputStream());
					//开始传输文件
					Tools.transFile(s.getOutputStream(), file);
					//在界面显示显示上传成功
					MyJFrame.j2.setText("上传成功");
					MyJFrame.jt.setText(file.getName()+"上传成功!");
					// 通过半关闭将输出流关闭,解决服务端阻塞问题
					s.shutdownOutput();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
	}

}

总结:

这个小程序综合性比较强,所以代码量较多,可以一直下载或者上传,多线程之间互不影响,每次点击下载或者上传都会创建一个线程进行下载或上传,各个任务之间互不影响,上面程序还可以继续扩展和优化,比如加入进度显示,大厅通知所有人某个用户上传了什么,下载了什么,这里不再叙述。

到此这篇关于用java写一个云端资源共享小程序的文章就介绍到这了,更多相关java 云端资源共享小程序内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 微信小程序后端(java)开发流程的详细步骤

    微信小程序后端开发流程根据官网总结为两个步骤 1.前端调用 wx.login 返回了code,然后调用wx.getUserInfo获取到用户的昵称 头像 2.服务端根据code去微信获取openid, 接口地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html%EF%BC%9B%E5%90%8C%E6%97%B6%EF%BC%8C%E6%9B%B4

  • 使用weixin-java-miniapp配置进行单个小程序的配置详解

    在进行小程序后端接口开发方面,使用weixin-java-tools中的weixin-java-miniapp模块,往往可以事半功倍. 引入weixin-java-tools 在https://mvnrepository.com/中搜索weixin-java-miniapp,进入微信小程序 Java SDK这个项目中. 选择相应正式版本来进行使用. maven中在依赖中添加如下配置项: <dependency> <groupId>com.github.binarywang</

  • Java解密微信小程序手机号的方法

    本文实例为大家分享了Java解密微信小程序手机号的具体代码,供大家参考,具体内容如下 第一步:创建AES解密工具类:代码如下 import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySp

  • Java实现表白小程序

    今天闲来无事,教大家一个哄妹子的小case.我们需要创建一个心形图案,按照心形图案的位置和长度,对所创建的字符串进行截断并在所需的位置上输出,最终能呈现在屏幕上满满的爱心.废话不多说,直接上源码看效果 ~ package ddd; import java.awt.*; import javax.swing.JFrame; public class Cardioid extends JFrame { //获取屏幕大小 private static final int WIDTH = 500; pr

  • Java实现简单日历小程序 Java图形界面小日历开发

    今天给大家介绍一下如何用Java swing开发一款简单的小日历,下面我们来看代码: 首先创建一个CalendarBean类,用于基本的日期计算: package other1; import java.util.Calendar; public class CalendarBean { String day[]; int year=2005,month=0; public void setYear(int year) { this.year=year; } public int getYear

  • Java中基于Shiro,JWT实现微信小程序登录完整例子及实现过程

    小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html : 本文是对接微信小程序自定义登录的一个完整例子实现 ,技术栈为 : SpringBoot+Shiro+JWT+JPA+Redis. 如果对该例子比较感兴趣或者觉得言语表达比较啰嗦,可查看完整的项目地址 : https://github.com/EalenXie/shiro-jwt-applet

  • 使用java实现云端资源共享小程序的代码

    云端共享小程序: 首先介绍一些程序功能:多用户共享资源,创建一个共享服务器,服务器存储器可以存放资源,用户可以向服务器上传文件,也可以从服务器下载文件,实现了多用户分享资源的功能. 技术栈 1.集合框架(Map集合) 2.IO流(对象序列化,文件传输等) 3.多线程 4.网络编程(TCP/IP协议) 5.简单的GUI界面 来看下界面效果(本人喜欢粉色,用户可以自定义颜色-): 点击下载后: 具体不再详述,看程序:服务端: package com.softeem.clound.server; im

  • java仿windows记事本小程序

    本文实例为大家分享了java仿windows记事本小程序的具体代码,供大家参考,具体内容如下 import java.awt.CheckboxMenuItem; import java.awt.Font; import java.awt.Frame; import java.awt.Menu; import java.awt.MenuBar; import java.awt.MenuItem; import java.awt.MenuShortcut; import java.awt.TextA

  • 基于java socket实现 聊天小程序

    服务器 package demo04; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.DataInputStream; import java.io.DataOutp

  • java实现打字游戏小程序

    本文实例为大家分享了java实现打字游戏小程序的具体代码,供大家参考,具体内容如下 一.设计思路 1.创建一个窗体 2.在窗体上放置一个面板,用paint方法画出英文字母,随机放置字母位置,并随时间自动下落 3.设置得分扣分机制 4.在面板上添加键盘监听器,输入正确得分,输入错误则扣分 ps:面板和监听器用一个类实现(这样简单方便) 二.具体实现 MyPanel.java import java.awt.Color; import java.awt.Font; import java.awt.G

  • Java后台与微信小程序的数据交互实现

    想把自己写的一个小项目转成微信小程序,主要是因为小程序比较火,而且自己想学一下小程序的东西,所以抱着初学者的心态开始了这个痛苦的旅程.看过小程序的一点视频,个人感觉和HTML,css,js差不多,甚至比前端更简单一些,可能是微信小程序做不出来那些炫酷的动态效果. 首先,要从Java后台查询出一组数据,然后转成json串返回.我总共总结了2种方法返回数据.一种非常简单,一种显得繁琐. 第一种通过springmvc的组件@ResponseBod返回数据 /* * 查询用户 * 通过springmvc

  • Java实现简单计算器小程序

    本文实例为大家分享了Java实现简单计算器小程序的具体代码,供大家参考,具体内容如下 这学期没事学了一点点Java,想写个程序练手,因为只学了一点点,所以暂时只能先写个实现简单功能的计算器练练. 由于期末来了,没太多时间,所以暂时就实现最简单的功能. 个人不喜欢用大量文字记叙程序,而且该程序也相对简单,所以直接画了张程序框架图,再配合代码的注释,就明白程序的原理了. 图 计算器程序框架 代码如下: package tst.jframe; import java.awt.EventQueue; i

  • java gui实现计算器小程序

    本文实例为大家分享了java gui实现计算器小程序的具体代码,供大家参考,具体内容如下 废话不多说 , 直接贴代码 , 有详细的注释 , 我也是刚学GUI没多久 这个是效果图 : 代码: package gui; /** * 导入所需要的包 **/ import java.awt.*; // 这个是java的gui编程里面一个很重要的包 import java.awt.event.*; // 用来处理事件所需要 import java.util.Stack; // 栈 , 我用来处理运算的 p

  • Java中生成微信小程序太阳码的实现方案

    目录 背景 实现方案 生成有限制太阳码 实现步骤 获取小程序的access_token 调用微信api生成小程序太阳码 说明 参数说明 注意事项 获取小程序的access_token 调用微信api生成小程序太阳码 说明 参数说明 参数过长问题 解决方案 生成无限制太阳码 扩展功能 总结 背景 当前小程序盛行的时代,无论走在那里都会看到各种各样的小程序太阳码,小程序项目中经常也会用到小程序的太阳码,那么我们如何生成小程序的太阳码呢? 实现方案 我们可以通过如下的方法实现小程序太阳码生成. 生成有

  • java实现日历窗口小程序

    本文实例为大家分享了java实现日历窗口小程序的具体代码,供大家参考,具体内容如下 标签:java基础 功能: 1.按月翻页. 2.输入月份年份,直接跳转. 效果图: //CalendarMainClass.java public class CalendarMainClass{     public static void main(String args[]){         CalendarFrame frame = new CalendarFrame();         frame.

  • 微信小程序实用代码段(收藏版)

    前言 排名不分先后,按自己的习惯来的. 总结经验,不喜勿喷哦~ 一.tab切换 <view class=" {{currentTab==0 ? 'select' : ''}}" data-current="0" bindtap="swichNav"> tab1</view> <view class=" {{currentTab==1 ? 'select' : ''}}" data-current=

随机推荐