- 博客(0)
- 资源 (4)
- 收藏
- 关注
JVM调优话术
java基础知识关于jvm的知识点 JVM调优就是GC是什么,为什么要有GC?
GC就是垃圾回收,java这种语言是动态分配内存大小的,并且依靠
垃圾回收机制来完成对分配内存空间的回收,从而来避免内存溢出的问题,
也在一定程度上降低了程序员工作的复杂度。
2018-05-09
JS组件Bootstrap Table使用方法详解
JS组件Bootstrap Table使用方法详解
转载 2016年03月21日 15:06:09
标签:
Bootstrap Table
最近客户提出需求,想将原有的管理系统,做下优化,通过手机也能很好展现,想到2个方案:
a方案:保留原有的页面,新设计一套适合手机的页面,当手机访问时,进入m.zhy.com(手机页面),pc设备访问时,进入www.zhy.com(pc页面)
b方案:采用bootstrap框架,替换原有页面,自动适应手机、平板、PC 设备
采用a方案,需要设计一套界面,并且要得重新写适合页面的接口,考虑到时间及成本问题,故项目采用了b方案
一、效果展示
二、BootStrap table简单介绍
bootStrap table 是一个轻量级的table插件,使用AJAX获取JSON格式的数据,其分页和数据填充很方便,支持国际化
三、使用方法
1、引入js、css
[js] view plain copy
<!--css样式-->
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet">
<link href="css/bootstrap/bootstrap-table.css" rel="stylesheet">
<!--js-->
[removed][removed]
[removed][removed]
[removed][removed]
[removed][removed]
2、table数据填充
bootStrap table获取数据有两种方式,一是通过table 的data-url属性指定数据源,二是通过JavaScript初始化表格时指定url来获取数据
[xhtml] view plain copy
...
...
[xhtml] view plain copy
$('#table').bootstrapTable({
url: 'data.json'
});
第二种方式交第一种而言在处理复杂数据时更为灵活,一般使用第二种方式来进行table数据填充。
[js] view plain copy
$(function () {
//1.初始化Table
var oTable = new TableInit();
oTable.Init();
//2.初始化Button的点击事件
/* var oButtonInit = new ButtonInit();
oButtonInit.Init(); */
});
var TableInit = function () {
var oTableInit = new Object();
//初始化Table
oTableInit.Init = function () {
$('#tradeList').bootstrapTable({
url: '/VenderManager/TradeList', //请求后台的URL(*)
method: 'post', //请求方式(*)
toolbar: '#toolbar', //工具按钮用哪个容器
striped: true, //是否显示行间隔色
cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
pagination: true, //是否显示分页(*)
sortable: false, //是否启用排序
sortOrder: "asc", //排序方式
queryParams: oTableInit.queryParams,//传递参数(*)
sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*)
pageNumber:1, //初始化加载第一页,默认第一页
pageSize: 50, //每页的记录行数(*)
pageList: [10, 25, 50, 100], //可供选择的每页的行数(*)
strictSearch: true,
clickToSelect: true, //是否启用点击选中行
height: 460, //行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度
uniqueId: "id", //每一行的唯一标识,一般为主键列
cardView: false, //是否显示详细视图
detailView: false, //是否显示父子表
columns: [{
field: 'id',
title: '序号'
}, {
field: 'liushuiid',
title: '交易编号'
}, {
field: 'orderid',
title: '订单号'
}, {
field: 'receivetime',
title: '交易时间'
}, {
field: 'price',
title: '金额'
}, {
field: 'coin_credit',
title: '投入硬币'
}, {
field: 'bill_credit',
title: '投入纸币'
}, {
field: 'changes',
title: '找零'
}, {
field: 'tradetype',
title: '交易类型'
},{
field: 'goodmachineid',
title: '货机号'
},{
field: 'inneridname',
title: '货道号'
},{
field: 'goodsName',
title: '商品名称'
}, {
field: 'changestatus',
title: '支付'
},{
field: 'sendstatus',
title: '出货'
},]
});
};
//得到查询的参数
oTableInit.queryParams = function (params) {
var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
limit: params.limit, //页面大小
offset: params.offset, //页码
sdate: $("#stratTime").val(),
edate: $("#endTime").val(),
sellerid: $("#sellerid").val(),
orderid: $("#orderid").val(),
CardNumber: $("#CardNumber").val(),
maxrows: params.limit,
pageindex:params.pageNumber,
portid: $("#portid").val(),
CardNumber: $("#CardNumber").val(),
tradetype:$('input:radio[name="tradetype"]:checked').val(),
success:$('input:radio[name="success"]:checked').val(),
};
return temp;
};
return oTableInit;
};
field字段必须与服务器端返回的字段对应才会显示出数据。
3、后台获取数据
a、servlet获取数据
[js] view plain copy
BufferedReader bufr = new BufferedReader(
new InputStreamReader(request.getInputStream(),"UTF-8"));
StringBuilder sBuilder = new StringBuilder("");
String temp = "";
while((temp = bufr.readLine()) != null){
sBuilder.append(temp);
}
bufr.close();
String json = sBuilder.toString();
JSONObject json1 = JSONObject.fromObject(json);
String sdate= json1.getString("sdate");//通过此方法获取前端数据
...
b、springMvc Controller里面对应的方法获取数据
[js] view plain copy
public JsonResult GetDepartment(int limit, int offset, string orderId, string SellerId,PortId,CardNumber,Success,maxrows,tradetype)
{
...
}
4、分页(遇到问题最多的)
使用分页,server端返回的数据必须包括rows和total,代码如下:
[js] view plain copy
...gblst = SqlADO.getTradeList(sql,pageindex,maxrows);
JSONArray jsonData=new JSONArray();
JSONObject jo=null;
for (int i=0,len=gblst.size();i<len;i++)
{
TradeBean tb = gblst.get(i);
if(tb==null)
{
continue;
}
jo=new JSONObject();
jo.put("id", i+1);
jo.put("liushuiid", tb.getLiushuiid());
jo.put("price", String.format("%1.2f",tb.getPrice()/100.0));
jo.put("mobilephone", tb.getMobilephone());
jo.put("receivetime", ToolBox.getYMDHMS(tb.getReceivetime()));
jo.put("tradetype", clsConst.TRADE_TYPE_DES[tb.getTradetype()]);
jo.put("changestatus", (tb.getChangestatus()!=0)?"成功":"失败");
jo.put("sendstatus", (tb.getSendstatus()!=0)?"成功":"失败");
jo.put("bill_credit", String.format("%1.2f",tb.getBill_credit()/100.0));
jo.put("changes",String.format("%1.2f",tb.getChanges()/100.0));
jo.put("goodroadid", tb.getGoodroadid());
jo.put("SmsContent", tb.getSmsContent());
jo.put("orderid", tb.getOrderid());
jo.put("goodsName", tb.getGoodsName());
jo.put("inneridname", tb.getInneridname());
jo.put("xmlstr", tb.getXmlstr());
jsonData.add(jo);
}
int TotalCount=SqlADO.getTradeRowsCount(sql);
JSONObject jsonObject=new JSONObject();
jsonObject.put("rows", jsonData);//JSONArray
jsonObject.put("total",TotalCount);//总记录数
out.print(jsonObject.toString()); ...
5、分页界面内容介绍
前端获取分页数据,代码如下:
[js] view plain copy
...oTableInit.queryParams = function (params) {
var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
limit: params.limit, //第几条记录
offset: params.offset, //显示一页多少记录
sdate: $("#stratTime").val(),
};
return temp;
};...
后端获取分页数据,代码如下:
[js] view plain copy
...int pageindex=0;
int offset = ToolBox.filterInt(json1.getString("offset"));
int limit = ToolBox.filterInt(json1.getString("limit"));
if(offset !=0){
pageindex = offset/limit;
}
pageindex+= 1;//第几页...
以上就是为大家分享的Bootstrap Table使用方法,希望对大家熟练掌握Bootstrap Table使用方法有所帮助。
转自:http://www.jb51.net/article/79033.htm
2018-04-27
java面试题
int和Integer有什么区别?
答:int是java的原始数据类型,Integer是java为int提供的封装类,java为每个原始数据类型都提供了封装类。
String和StringBuffer的区别?
答:String是不可变的对象,每次对String类型进行改变都相当于产生了一个新的对象,StringBuffer是可变的字符序列,所以如果要经常改变某个字符串的话建议使用StringBuffer。
list、set、map问题?
答:set 不允许重复,无序
list 允许重复,有序
map 成对的数据结构,键值必须具有唯一性
Servlet和CGI的区别?
答:Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式允许其service方法,一个实例可以服务于多个请求,并且其实例一般不会被销毁,而CGI对每个请求都产生新的进程,服务完后就销毁,所以效率上低于Servlet。
面向对象的特征?
答:1:封装:通过定义类并且给类的属性和方法加上访问控制
2:继承:子类继承父类,子类可以拥有父类中已定义的方法,并且子类可以修改父类中的方法使其更适合特殊需求。
3:多台:不同对象对统一消息作出不同响应称之为多态
4:抽象:忽略与当前主题无关的那些方面,将注意力集中在与当前目标有关的方面
运行时异常和一般异常有何异同?
答:运行时异常时(JVM)java虚拟机在运行过程中发生的问题,比如:内存溢出等问题。这类异常没法要求程序员去一一捕获并抛出,一般异常是Java类库或程序员自己写的代码发生的错误,这类异常可以由我们去一一捕获并抛出。
多线程几种实现方法,同步?
答:多线程有两种实现方法,一种是继承Thread类或者实现Runnable接口。同步就是在方法返回类型后面加上synchronized。
c#中的委托,事件是不是委托?
答:委托就是将方法作为一个参数带入另一个方法叫做委托,事件是一种特殊的委托。
应用程序域?
答:应用程序域可以理解为一种轻量级的进程,起到安全的作用,占用资源小。
Class.forName作用?
答:调用该访问返回一个以字符串指定类名的类对象。
JDO?
答:JDO是java对象持久化的新的规范,为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。
CORBA?
答:CORBA标准是公共对象请求代理结构,用途为:用不同的程序设计语言书写,在不同的进程中运行,为不同的操作系统开发。
xml解析技术?
答:常用的DOM、SAX等
DOM:处理大型文件时性能下降的非常厉害,适合对xml的随机访问
SAX:事件驱动型的xml解析方法,适合对xml的顺序访问
jsp常用动作?
答:jsp:include 引入一个文件
jsp:useBean 实例化JavaBean
jsp:setProperty 设置JavaBean属性
jsp:getProperty 输出JavaBean属性
jsp:forward 转发
CTS、CLS、CLR分别作何解释?
答:CTS 通用类型系统、CLS 通用语言规范、CLR 公共语言运行时。
Struts1和Struts2原理和区别?
答:Struts1和Struts2是两个完全不同的框架,Struts1以ActionServlet作为核心控制器,由ActionServlet负责拦截用户的所有请求。Struts2以核心控制器FilterDispatcher为基础,包含了框架内部的控制流程和处理机制。
Hibernate工作原理,Hibernate数据持久化?
答:Hibernate工作原理:
1:读取并解析映射信息,创建SessionFactory
2:打开Session
3:创建事物
4:持久化操作
5:提交事务
6:关闭Session
7:关闭SessionFactory
Hibernate持久化:Hibernate根据定义的映射规则将对象持久化保存到数据库,这就实现了对象的持久化。
Spring由那几个模块组成?
答:Spring主要由7个模块组成:
1:Spring核心容器:提供了Spring框架的基本功能
2:Spring AOP:通过配置管理特性
3:Spring ORM:Spring框架集成了若干ORM框架
4:Spring DAO:打开关闭数据库连接
5:Spring WEB:为基于WEB服务的应用程序提供上下文服务
6:Spring Context:向Spring框架提供上下文信息
7:Spring MVC:分离模型、视图、控制器、以便更容易定制
折构函数和虚函数?
答:折构函数式销毁一个类的函数,虚函数是为了C++的动态绑定而设计的。
描述你的编程风格?
答:类名首字母大写,常量一般全部大写,给自己的代码加注释。
控制流程?
答:控制流程一般使用if判断条件。有第二分支,多分支,循环结构。循环本质上也是通过判断来实现的。
多形与继承?
答:多形:一个类中多个同名方法。继承:子类继承父类。
jsp内置对象?
答:request 用户端请求
response 回应
pageContext 网页属性
session 会话
out 输出
page 当前网页
exception 错误网页
application servlet正在执行的内容
config servlet构架部件
Struts模型驱动?
答:封装请求参数。
简述JDBC?
答:JDBC数据库连接,是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一访问。
什么情况下不建议使用Hibernate?
答:当数据量大,并且表关系复杂的时候不建议使用。
sleep()和wait()有什么区别?
答:sleep()是线程类的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但监控状态依然保持,到时候会自动恢复。
wait()是Object类的方法,对此对象调用了wait方法导致本线程放弃对象锁,进入等待锁定池,只有针对此对象发出notify方法后本线程才进入对象锁定池准备获得对象锁进入运行状态。
同步和异步,在什么情况下分别使用?
答:如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步。在很多情况下采用异步往往更有效率。
数据库三大范式?
答:1:确保每列都是不可分割的原子值
2:确保每列都和主键相关
3:确保每列都和主键直接相关,而不是间接相关
单例模式有哪些好处?
答:单例模式是一种比较常见的设计模式,带给我们以下好处:
1:控制资源的使用
2:控制实例的产生数量
3:让多个不相关的两个线程或进程之间实现通信
为什么要用spring?
答:1、主要将各个框架有效的联系起来,缩短实际编程时间。
2、可以将各个框架进行有效的管理和控制,让数据传输安全。
spring的IOC和DI?
答:控制反转和依赖注入是spring的两大基础作用。主要是将所有组件在spring提供的外部容器中加载。提高安全性,减低耦合性,使各个框架或者类之间的依赖性降低。
什么是声明式的事务管理?为什么要用?spring如何实现声明式的事务管理?
答:声明式的事务管理主要是将在进行对数据库中数据的添加或者修改时需要执行事务管理,主要是为了避免在执行添加或修改的时候添加或修改不完全正确,导致数据丢失。spring使用AOP面向切面的思想进行事务管理的。
spring和Hibernate继承后,定义事务管理特性的时候查询为什么要定义为read-only?
答:因为添加、删除和更新都涉及到了数据库的修改,而查询并未涉及到数据库修改,所以只需要定义只读,这样可以提高效率,进行更加方便的事务管理。
请你谈谈对Hibernate OR映射的理解?
答:将数据库中的每一张表都映射成一个实体。
配置了lazy="true"一定会懒加载吗?
答:不一定,如果在配置中你也使用了fetch属性的话此时lazy就会失效。
Hibernate数据库标识与主键之间的认识?
答:标识是为了方便和简介映射文件,主键是为了让数据不会重复。
为什么每次请求都要创建一个Action对象?
答:Struts2每次请求的时候都会创建一个action实例,这样会保证线程的安全。Struts1只是在第一次请求的时候创建一个action实例,以后每次相同的请求都直接从内存中去读取,它是单例模式,安全性较差。
Struts2是如何实现MVC模式的?
答:在Struts2里面是将每次页面的请求进行处理,然后将请求需要输出的数据转发到需要做数据显示的页面。Struts2只是起到一个数据接收和转接的功能,就是Controller控制器,而传来数据的页面叫view显示层,Struts2将数据提交给进行处理的类叫Model模型层,专门进行数据处理和数据库的连接。
heap和stack有什么区别?
答:栈是一种线形集合,其添加和删除元素的操作应在同一段完成,栈按照后进先出的方式进行处理。堆是栈的一个组成元素。
EJB和JavaBean的区别?
答:EJB不是一般的JavaBean,EJB是企业级的JavaBean,EJB一共分为3种,实体Bean,消息Bean,会话Bean。书写EJB要遵循一定的规范,另外要运行EJB,你需要有相应的EJB容器,比如WebLogic、jboss等,而JavaBean不需要,只需要安装Tomcat就可以了。EJB用于服务端的应用开发,而JavaBean用于客户端应用开发。
触发器?
答:触发器是一种特殊的存储过程,主要通过事件来触发而被执行。
什么是存储过程?用什么调用?
答:存储过程是一个预编译的SQL语句,优点是允许模块化的设计。就是说只需要创建一次,以后再程序中就可以调用多次。使用存储过程比单纯的SQL语句要快,可以用一个命令对象来调用存储过程。
索引优缺点?
答:索引可以提高对数据库中数据的检索,缺点是减慢了数据录入速度,同时也增加了数据库的尺寸大小。
什么是事务?什么是事锁?
答:事务就是被绑定在一起,作为一个逻辑单元执行的SQL语句。如果任何一个操作失败,那么整个就失败。共同失败或共同成功。锁可以保证事务的完整性和并发性。
什么是视图?游标是什么?
答:视图是一种虚拟的表,具有和物理表相同的功能。游标是对查询出来的结果集作为一个单元来有效的处理,可以对结果集的当前行做修改。
select执行顺序?
答:from
where
group by
having
select
order by
Collection和Collections的区别?
答:Collection是集合类的父类,继承它的主要由set和list
Collections是针对集合类的帮助类,它提供了一系列针对集合的搜索,排序,线程安全化等操作。
final、finally、finalize的区别?
答:final用于声明属性方法和类,分别表示:属性不可变,方法不可覆盖,类不可继承。
finally是异常处理语句的一部分,表示总是执行。
finalize是Object的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。
assert是什么?什么时候用到?
答:断言,可以将断言看成是异常处理的一种高级形式,可以用来判断某个特定的表达式或值是否为真。
接口是否可以继承接口?抽象类是否可以实现接口?抽象类是否可以继承实体类?
答:接口可以继承接口,抽象类可以实现接口,抽象类可以继承实体类。
引用传递和值传递?
答:引用传递:形参改变影响实参
值传递:形参改变不影响实参
当一个线程进入一个对象的synchronized方法后,其他线程是否可进入此对象的其他方法?
答:其他方法前是否加了synchronized关键字,如果没加则能。
说出servlet生命周期?
答:servlet实例化时调用init方法,得到请求时调用service方法,service方法自动派遣doget或dopost方法,最后当实例销毁时调用destroy方法。
error和exception有什么区别?
答:error是指错误,通常程序员不能通过代码来解决。底层环境或硬件问题。
exception是指异常,可以通过代码来解决的问题。
forward和redirect的区别?
答:forward是转发,浏览器跳转后不显示新的地址。
redirect是重定向,浏览器跳转后显示新的地址。
对比之下forward更加高效,并且它有助于隐藏实际地址,但是有些情况则必须使用redirect,否则会报异常。
jsp中动态include和静态include的区别?
答:动态include用jsp:include实现,适用于动态页面,可以携带参数
静态include用include伪码实现,适用于静态页面
math.round(11.5)等于多少?math.round(-11.5)等于多少?
答:Math.round()对数字进行四舍五入
Math.round(11.5)=12
Math.round(-11.5)=11
String s=new String("xyz");创建了几个String Object?
答:创建了两个String对象,一个保存的引用地址,一个保存实际的值。
数组有没有length()这个方法?String呢?
答:数组里面没有length()方法,而是length属性。String有length()这个方法。
swtich()能否作用在byte、long、String上?
答:swtich()传递的应该是一个整数表达式,所以它的值只能是:int、short、char、byte所以long和String都不能作用在swtich()上。
jsp和servlet之间的联系?
答:jsp前段动态页面,servlet是纯java类
jsp被编译之后会转换为servlet执行
java基本数据类型有哪些?String是不是基本数据类型,他们有何区别?
答:基本数据类型8种:int、short、byte、long、float、double、char、boolean
String不是基本数据类型,引用数据类型。
区别:基本数据类型比较实用“==”,引用数据类型实用equest,并且引用数据类型存放的是地址而不是具体的值。
写一个方法,实现字符串的替换,如:输入bbbwlirbbb,输出bbbhhtccc?
答:String s="bbbwlirbbb";
s.replaceAll("wlirbbb","hhtccc");
如何将数值型字符转换为数字(Integer,Double)?
答:可以用Integer.parseInt()和Double.parseDouble()方法
如何将数字转换为字符?
答:可以使用String的valueOf()方法。
如何取得1970到现在的毫秒数?
答:可以用getTime()方法。
如何格式化日期?
答:可以用SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");
判断是否有子文件?判断是否有子目录?判断文件是否存在?
答:判断是否有子文件使用file.isFile()
判断是否有子目录使用file.isDirectory()
判断文件是否存在使用file.exists()
继承、重载、覆盖问题?
答:继承:子类继承父类,子类可以拥有父类中已定义的方法,并且子类可以修改父类中的方法使其更适合特殊需求。
重载:在一个类中方法名和返回类型相同,参数不同。
覆盖:在子类中覆盖父类的某个方法,要求方法名相同,参数类型相同。
Statement和PreparedStatement之间的区别?
答:Statement比PreparedStatement速度慢
PreparedStatement是预编译,插入时速度高于Statement
Statement创建速度很慢,常用选择PreparedStatement
Session机制?
答:session机制是一种服务器端机制,服务器使用一种类似于散列表的结构来保存信息。
jsp和servlet中的请求转发分别如何实现?
答:jsp可以使用jsp:forward标签转发
servlet可以使用request.getRequestDispatcher()实现转发
介绍j2ee、j2se、j2me的区别?
答:j2ee(企业版):主要用于企业web开发
j2se(标准版):主要用于web开发,但缺少企业版的一些特性
j2me(微小版):主要用于手机开发
J2ee提供的技术?
答:j2ee提供的技术有EJB、servlet、jsp等。
什么是Application Server?
答:Application Server 应用服务器
简单介绍连接池的优点和原理?
答:数据库连接和关闭是比较花费时间的一件事,而连接池可以提高我们的工作效率。
刚开始创建一定数量的池连接,当需要时从池连接中拿出一个,用完之后再把这个连接重新放回连接池。
Web.xml的作用?
答:Web.xml会在程序启动时执行,如果想在程序刚启动的时候执行一些方法的话可以配置在Web.xml中。
简单介绍您所了解的MVC?
答:在项目中使用MVC模式会使项目分工更加明确,结构更加清晰
M model 模型层:JavaBean
V view 视图层:jsp html
C controller 控制层:servlet
简单介绍你所了解的XML?
答:XML可扩展标记语言,可以用来标记数据,定义数据结构,是一种允许用户自定义标记的语言
简单介绍您所了解的structs、spring和hibernate?
答:struts:控制层Action,页面标签和Model数据,调用业务层
Spring:Aop管理事务控制,IOC管理各个组件的耦合
Hibernate:负责数据库和对象的映射,负责Dao层
因为你去公司面试,公司让你写笔试,不可能说XX一个题目写两页纸写的太详细,所以以上答案有的可能比较简短,没有说出重点,请大家补充,如果大家有什么更好的答案请拿出来一起分享
2018-04-27
Redis和Memcache的区别总结
1、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等;
2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;
3、虚拟内存--Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘;
4、过期策略--memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10;
5、分布式--设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从;
6、存储数据安全--memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化);
7、灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;
8、Redis支持数据的备份,即master-slave模式的数据备份;
2018-04-26
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人