待解决:1.自处理复杂的sql语句

2.xutils自定义类型的属性

Xutils 数据库存储自定义类型和自定义数据类型集合 - 简书 (jianshu.com)

(1条消息) xUtils系列之DbUtils-保存自定义类型_轻度强迫症患者的博客-CSDN博客

(1条消息) xUtils 3 中,如何存储自定义实体类字段类型_WymanWong的博客-CSDN博客

一.引入Xutils包

1.首先需要引入Xutils包,在buil.gradle中添加如下内容:

implementation 'org.xutils:xutils:3.9.0'

2.在AndroidManifest.xml文件中添加网络权限等

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

3.然后需要在自定义Application中添加初始化内容:(放在onCreate方法中)

x.Ext.init(this);//注册Xutils
//x.Ext.setDebug(false); // 是否输出debug日志,开启debug会影响性能,暂时未用到
//自定义特殊类型的转换器,
//ColumnConverterFactory.registerColumnConverter(GeometryField.class, new GeometryColumnConverter());
initDBManager();//数据库模块使用的,自定义的一个用来初始化数据库的函数

二.数据库模块-DbUtils

1.创建数据库

//数据库初始化private void initDBManager() {//data/data/com.iot.gis/databases/gis_report.dbFile dbFile = this.getDatabasePath("gis_report.db");//getDatabasePath函数是用来获取右侧手机路径:/data/user/0/应用包名/databases/参数名 下的文件boolean dbFileOk = copyDb(dbFile);//因为项目需要自带数据,所以就把数据都放到一个SQLite的数据库文件中了,之后把db文件放到了assets文件夹下面。//copyDb函数然后判断手机路径下是否有db文件,如果没有,就把assets下的db文件数据,复制到对应目录下,如果有,则表示已经复制过了,就不需要创建了。if (!dbFileOk) {Logger.eTag(TAG, ResUtils.getString(R.string.db_file_not_exists));return;}DbManager.DaoConfig daoConfig = new DbManager.DaoConfig().setDbName("gis_report.db")//设置数据库名称.setDbVersion(1)//设置数据库版本.setAllowTransaction(true)//设置是否允许事务,默认true.setDbDir(dbFile.getParentFile())// 不设置dbDir时, 默认存储在app的私有目录..setDbOpenListener( new DbManager.DbOpenListener() {//设置数据库打开的监听@Overridepublic void onDbOpened(DbManager db) {//开启数据库支持多线程操作,提升性能,对写入加速提升巨大db.getDatabase().enableWriteAheadLogging();}})//下面这2个暂时还没用到/* .setTableCreateListener( new DbManager.TableCreateListener(){//设置表创建的监听@Overridepublic void onTableCreated(DbManager db, TableEntity<?> table) {Log.i("JAVA", "onTableCreated:" + table.getName());}}).setDbUpgradeListener(new DbManager.DbUpgradeListener() {//设置数据库更新的监听@Overridepublic void onUpgrade(DbManager db, int oldVersion, int newVersion) {}})*/;try {db = x.getDb(daoConfig);//gisDB = new GISDbManager(db);//gisDB是学长创建的用来查询复杂的sql语句的,里面还包含了事务Logger.iTag(TAG, db.getDatabase().getPath());} catch (DbException e) {Logger.eTag(TAG, e);}}private boolean copyDb(File dbFileTargetPath) {try {if (!dbFileTargetPath.exists()) {   //判断该文件是否存在于手机中InputStream dbFileIS = this.getAssets().open("gis_report.db");//以数据流的形式获取左侧AS中assets文件夹中对应文件名的内容return FileIOUtils.writeFileFromIS(dbFileTargetPath, dbFileIS);//将读取的输入流写入文件}} catch (IOException e) {Logger.eTag(TAG, e);return false;}return true;}

2.创建数据库中一个表对应的实体类

import org.xutils.db.annotation.Column;
import org.xutils.db.annotation.Table;
//数据库中表的实体类
@Table(name = "Common_Using_rock_soil_sample")  //确定表名
public class SampleModel {//样本ID@Column(name = "sample_id", isId = true, autoGen = false)//isId为true代表为主键,autoGen为true代表自增,不写autoGen这个属性,默认是自增长的属性//@Column(name = "sample_id",property ="NOT NULL")//添加约束条件,这里不能为空。//如果普通属性没有加上@Column标签,生成表中的字段就不会包含该属性public long sample_id;//项目ID@Column(name = "project_id")//name是用来设置列名的public long project_id;//样本编号@Column(name = "sample_code")public String sample_code;//样本类型@Column(name = "sample_type")public String sample_type;//动作关联ID@Column(name = "action_relation_id")public long action_relation_id;//版本号@Column(name = "sync_version_number")public long sync_version_number;//备注@Column(name = "remark")public String remark;//野外名称@Column(name = "field_name")public String field_name;//勘调对象ID@Column(name = "survey_target_id")public long survey_target_id;public SampleModel() {//必须要有无参构造,否则创建表不成功}//有参构造方法和相关set、get方法根据自己的需求来,使用AS快捷键创建会方便很多
}

3.对数据表进行操作

 //插入public static void insertSamples(List<SampleModel> sampleModels) {for (SampleModel sampleModel : sampleModels) {try {GISApplication.db.saveOrUpdate(sampleModel);    //更新保存单个样例***主要用saveOrUpdate} catch (DbException e) {Log.e("eee", "samplemodel");}}try {GISApplication.db.save(sampleModels);//保存实体类或实体类的List到数据库//db.replace(list);保存或更新实体类或实体类的List到数据库, 根据id和其他唯一索引判断数据是否存在//db.saveOrUpdate(list);保存或更新实体类或实体类的List到数据库, 根据id对应的数据是否存在.//db.saveBindingId(list);保存实体类或实体类的List到数据库,如果该类型的id是自动生成的, 则保存完后会给id赋值./*** 1.如果在你建表的时候你的主键设置成自增长,那么你在插入数据的时候直接调replace方法就可以了,*   但是saveOrUpdate只能达到插入的效果,达不到更新原有数据的效果.* 2.如果在你建表的时候你的主键设置成不是自增长,replace方法当然可以插入,saveOrUpdate方法既可以插入也可以达到更新的效果*/} catch (DbException e) {Log.e("eee", "samplemodels");}}//查询public static List<SampleModel> selectSamples() {try {SampleModel sampleModel1 = GISApplication.db.findById(SampleModel.class, 2);//根据主键来查找表里的数据SampleModel sampleModel2 = GISApplication.db.findFirst(SampleModel.class);//返回当前表的第一条数据//查询所有数据List<SampleModel> all = GISApplication.db.findAll(SampleModel.class);//按条件查找,查询年龄大于15的List<DbModel> dbModelAll = GISApplication.db.findDbModelAll(new SqlInfo("select * from student where age > 15"));//findDbModelFirstfor (int i = 0; i < dbModelAll.size(); i++) {DbModel dbModel = dbModelAll.get(i);String name = dbModel.getString("name");Log.i("tag", "查询的数据: name=" + name);}//第二种条件查找,我用的这种List<SampleModel> all1 = GISApplication.db.selector(SampleModel.class)//***主要用这种查询条件.where("age", ">", 14).and("age", "<", 16).findAll();//.findFirst();.count();/**List<DbModel> list = db.selector(Child.class)    //复杂的参考样例.where("age", "<", 18).groupBy("parentId").having(WhereBuilder.b("COUNT(parentId)", ">", 1)).select("parentId, COUNT(parentId) as childNum").findAll();**///和上面那种应该是等价的WhereBuilder b = WhereBuilder.b();b.and("id",">",2); //构造修改的条件b.and("id","<",4);List<SampleModel> all2 = GISApplication.db.selector(SampleModel.class).where(b).findAll();//第三种List<SampleModel> all3 = GISApplication.db.selector(SampleModel.class).expr("age>14 and age<17").findAll();if (all1 == null) {all1 = new ArrayList<>();}return all1;} catch (DbException e) {return new ArrayList<>();}}//删除public static void deleteSamples() {try {//第一种,根据主键来删除GISApplication.db.deleteById(SampleModel.class,5);//删除主键为5的值//第二种方法,找到符合条件的第一条数据  .findAll()就是找所有符合条件的了SampleModel student = GISApplication.db.selector(SampleModel.class).where("name", "=", "学生11").findFirst();GISApplication.db.delete(student);//先找到,再删除 ,需要判断为不为空//第三种,删除那name=学生9 且 sex=女 的数据GISApplication.db.delete(SampleModel.class, WhereBuilder.b("name","=" ,"学生9").and("sex","=","女"));//第二种写法,添加删除条件:WhereBuilder b = WhereBuilder.b();b.and("id",">",2); //构造修改的条件b.and("id","<",4);GISApplication.db.delete(SampleModel.class, b);//第四种,删除所有数据,但是表还在GISApplication.db.delete(SampleModel.class);//db.dropTable(Student.class);删除表//db.dropDb();删除数据库} catch (DbException e) {e.printStackTrace();}}

三.网络模块-HttpUtils

数据传输他这里有同步请求和异步请求,同步请求需要自己单独再开一个线程,我这里认为如果你需要同时传多个数据对应多个接受数据的时候,把这几个同步传输,然后放到一个子线程中。

1.在Thread中的同步请求

new Thread(new Runnable() {@Overridepublic void run() {///相关传输数据的函数getActivity().runOnUiThread(new Thread(() -> {}));}}).start();
///下面这种是用lamdba表达式
new Thread(() -> {///相关传输数据的函数postData();getActivity().runOnUiThread(new Thread(() -> {}));}).start();

2.同步上传数据

 public void postData(String POST_Url){RequestParams params = new RequestParams(POST_Url); //POST_Url为post上传的 地址+函数名称JSONObject js_request = new JSONObject();//服务器需要传参的json对象js_request.put("geom", "XXX");//根据实际需求添加相应键值对,put是一个一个添加的Map<String, Object> attrs=new HashMap<>();attrs.put("eguid", "1");attrs.put("survey_target_id", 2);js_request.putAll(attrs);   //添加一群键值对params.setAsJsonContent(true);  //以json形式提交body参数//params.setAsJsonArrayContent(true); //以json array形式提交body参数params.setBodyContent(js_request.toString());//设置body参数中的内容try {String data = x.http().postSync(params, String.class);       //JSONObject.class//data} catch (Throwable throwable) {//处理报错}}//参考地址:http://42.192.6.203:9904/api/EntityAttributeTable/postBo?<{"delete_flag":0,"sync_version_number":21}>

3.同步下载数据

 public void getData(String GET_Url){RequestParams params2 = new RequestParams(GET_Url); //GET_Url为get下载的 地址+函数名称params2.addQueryStringParameter("work_point_id", 1);params2.addQueryStringParameter("p", 2);//这个可以添加多个,通过类的反射机制,自动用for循环添加类的各个属性//下面这2个参数可能主要还是为了实现断点下载,虽然好像暂时没用到?params2.setAutoResume(true);//设置是否在下载是自动断点续传,默认的也是为true,可以不设置params2.setCancelFast(true);    是否可以被立即停止try {String data = x.http().getSync(params2, String.class); //data是获取到的数据,如果是json数据,可以采用对应的方法转换成对应的类} catch (Throwable throwable) {//报错,进行处理}}
//参考地址:http://42.192.6.200:9900/api/EntityAttributeTable/getBou?id=1&name="2"

4.同步上传文件

public void postFile(String POST_Url,String path){RequestParams params = new RequestParams(POST_Url); //POST_Url为post上传的 地址+函数名称//传输文件params.setMultipart(true);params.addBodyParameter("file", new File(path));    //适用于POST请求方式;添加到Body体的参数。params.setAutoRename(true);//文件的自动命名,服务器端设置的重复的文件名会覆盖掉try {File data = x.http().postSync(params, File.class);//Log.e("eee2", data.toString());//如果是请求json,使用String.class,如果下载文件,使用File.class。这里上传的感觉用String也可以?} catch (Throwable throwable) {//报错处理}}//参考地址:http://42.192.6.200:9900/api/EntityAttributeTable/PostFile?<file=/storage/emulated/0/YingHe/sketchPhoto/2022-03-30_092143.png>

5.同步下载文件

public void getFile(String GET_Url,String path){    //path是要保存到手机中的地址,参考:/storage/emulated/0/Pictures/1/224.jpgRequestParams params2 = new RequestParams(GET_Url); //GET_Url为get下载的 地址+Photos+文件名params2.setMultipart(true);//传输文件,使用multipart表单params2.setSaveFilePath(path);//设置下载文件时文件保存的路径和文件名try {File data = x.http().getSync(params2, File.class);//Log.e("eee2", data.getAbsolutePath());} catch (Throwable throwable) {//报错,进行处理}}
//参考地址:http://42.192.6.203:9904/Photos/2022-03-30_092143.png?

6.上传数据还有另一种格式

public void postFileName(){RequestParams requestParams = new RequestParams(POST_FileName);Log.e("eee1","eee1");requestParams.addBodyParameter("TableName", "eee");requestParams.addBodyParameter("ProjectId", 2);requestParams.addBodyParameter("photoFileName", "223.png");requestParams.setAutoResume(true);requestParams.setCancelFast(true);try {String data = x.http().postSync(requestParams, String.class);Log.e("eee2",data);}catch (Throwable throwable) {throwable.printStackTrace();Log.e("eee3","eee3");}}/**JSONObject  jsonObject;try {jsonObject = x.http().getSync(params, JSONObject.class);} catch (Throwable throwable) {throwable.printStackTrace();}
**/

7.异步传输

暂时还不太会

参考网址:

GitHub - wyouflf/xUtils3: Android orm, bitmap, http, view inject...

Android Xutils3 完全解析 - 上七旗娃儿 - 博客园 (cnblogs.com)

(1条消息) XUtils3的使用(Get,Post,断点下载,上传文件,数据库,bitmap的下载与缓存)_Dawn仧的博客-CSDN博客_xutils3上传bitmap

xUtils使用详细介绍 - favour - 博客园 (cnblogs.com)

Android xUtils3.0使用手册(一)- 基础功能使用 - 大西瓜3721 - 博客园 (cnblogs.com)

Android使用xUtils3.0实现文件上传_Android_萬仟网 (10qianwan.com)

xUtils 3.0 post使用详解 - 丶贰九 - 博客园 (cnblogs.com)

xUtils3 注解模块 - Vitality - 博客园 (cnblogs.com)

public  void postData(){JSONObject js_request = new JSONObject();//服务器需要传参的json对象js_request.put("key", "value");//根据实际需求添加相应键值对js_request.put("key1", "value1");js_request.put("key2", "value2");RequestParams params = new RequestParams("http://www.baidu.com");params.setAsJsonContent(true);params.setBodyContent(js_request.toString());//params.addBodyParameter("pageNo","1");//params.addBodyParameter("pageSize","20");//post这里改成request就一样x.http().post(params, new Callback.CacheCallback<String>() {//发起传参为json的post请求,// Callback.CacheCallback<String>的泛型为后台返回数据的类型,// 根据实际需求更改@Overridepublic boolean onCache(String result) {return false;}@Overridepublic void onSuccess(String result) {//此处请求成功后的逻辑Log.e("eee2",result);}@Overridepublic void onError(Throwable ex, boolean isOnCallback) {Log.i("tag", "请求异常");}@Overridepublic void onCancelled(CancelledException cex) {Log.i("tag", "取消请求的回调方法");}@Overridepublic void onFinished() {Log.i("tag", "请求完成,并不一定是请求成功,断开了连接就会执行该方法");}});}public void get(){
RequestParams params = new RequestParams(url);params.addQueryStringParameter("username","abc");params.addQueryStringParameter("password","123");Callback.Cancelable cancelable = x.http().get(params, new Callback.CommonCallback<string>() {@Overridepublic void onSuccess(String result) {Log.i("JAVA", "onSuccess result:" + result);}//请求异常后的回调方法@Overridepublic void onError(Throwable ex, boolean isOnCallback) {}//主动调用取消请求的回调方法@Overridepublic void onCancelled(CancelledException cex) {}@Overridepublic void onFinished() {}});}public void posfile(){String path="/mnt/sdcard/Download/icon.jpg";RequestParams params = new RequestParams("地址");params.setMultipart(true);params.addBodyParameter("file",new File(path));//设置上传的文件路径x.http().post(params, new Callback.CommonCallback<String>() {@Overridepublic void onSuccess(String result) {}@Overridepublic void onError(Throwable ex, boolean isOnCallback) {}@Overridepublic void onCancelled(CancelledException cex) {}@Overridepublic void onFinished() {}});
}public void getfile(){RequestParams params = new RequestParams(url);//自定义保存路径,Environment.getExternalStorageDirectory():SD卡的根目录params.setSaveFilePath(Environment.getExternalStorageDirectory()+"/myapp/");//自动为文件命名params.setAutoRename(true);x.http().get(params, new Callback.ProgressCallback<file>() {@Overridepublic void onSuccess(File result) {//apk下载完成后,调用系统的安装方法Intent intent = new Intent(Intent.ACTION_VIEW);intent.setDataAndType(Uri.fromFile(result), "application/vnd.android.package-archive");getActivity().startActivity(intent);}@Overridepublic void onError(Throwable ex, boolean isOnCallback) {}@Overridepublic void onCancelled(CancelledException cex) {}@Overridepublic void onFinished() {}//网络请求之前回调@Overridepublic void onWaiting() {}//网络请求开始的时候回调@Overridepublic void onStarted() {}//下载的时候不断回调的方法@Overridepublic void onLoading(long total, long current, boolean isDownloading) {//当前进度和文件总大小Log.i("JAVA","current:"+ current +",total:"+total); }});
}//使用缓存
public void cache(){RequestParams params = new RequestParams(url);params.setCacheMaxAge(1000*60); //为请求添加缓存时间Callback.Cancelable cancelable = x.http().get(params, new Callback.CacheCallback<string>() {@Overridepublic void onSuccess(String result) {Log.i("JAVA","onSuccess:"+result);}@Overridepublic void onError(Throwable ex, boolean isOnCallback) {}@Overridepublic void onCancelled(CancelledException cex) {}@Overridepublic void onFinished() {}//result:缓存内容@Overridepublic boolean onCache(String result) {//在setCacheMaxAge设置范围(上面设置的是60秒)内,如果再次调用GET请求,//返回true:缓存内容被返回,相信本地缓存,返回false:缓存内容被返回,不相信本地缓存,仍然会请求网络Log.i("JAVA","cache:"+result);return true;}});
}断点下载:pulblic  void duan(){
//设置请求参数RequestParams params = new RequestParams(pathApk);params.setAutoResume(true);//设置是否在下载是自动断点续传params.setAutoRename(false);//设置是否根据头信息自动命名文件params.setSaveFilePath("/sdcard/xutils/xUtils_1.avi");params.setExecutor(new PriorityExecutor(2, true));//自定义线程池,有效的值范围[1, 3], 设置为3时, 可能阻塞图片加载.params.setCancelFast(true);//是否可以被立即停止.//下面的回调都是在主线程中运行的,这里设置的带进度的回调cancelable = x.http().get(params, new Callback.ProgressCallback<File>() {@Overridepublic void onCancelled(CancelledException arg0) {Log.i("tag", "取消"+Thread.currentThread().getName());}@Overridepublic void onError(Throwable arg0, boolean arg1) {Log.i("tag", "onError: 失败"+Thread.currentThread().getName());progressDialog.dismiss();}@Overridepublic void onFinished() {Log.i("tag", "完成,每次取消下载也会执行该方法"+Thread.currentThread().getName());progressDialog.dismiss();}@Overridepublic void onSuccess(File arg0) {Log.i("tag", "下载成功的时候执行"+Thread.currentThread().getName());}@Overridepublic void onLoading(long total, long current, boolean isDownloading) {if (isDownloading) {progressDialog.setProgress((int) (current*100/total));Log.i("tag", "下载中,会不断的进行回调:"+Thread.currentThread().getName());}}@Overridepublic void onStarted() {Log.i("tag", "开始下载的时候执行"+Thread.currentThread().getName());progressDialog.show();}@Overridepublic void onWaiting() {Log.i("tag", "等待,在onStarted方法之前执行"+Thread.currentThread().getName());}});}

添加到请求body体的参数, 只有POST, PUT, PATCH, DELETE请求支持.

四.注解模块-HttpUtils

暂未使用,用时百度。

五.图片模块-HttpUtils

暂未使用,用时百度。

Xutils-Android中数据存储和网络传输的框架相关推荐

  1. 【Android】数据存储,文件,数据库

    Android中数据存储 一.在内部存储读写文件 1.文件io读写 写文件 //写入数据 private fun saveFile() {//将文件写入内部存储空间时,只能在本应用的目录中写入,不能写 ...

  2. 005 Android之数据存储

    文章目录 Android文件系统 Android文件的访问权限 文件访问权限实例 数据存储方式 内部存储 内部存储实例 外部存储 Shared Preferences Shared Preferenc ...

  3. android 储存方案,Android本地数据存储方案(一)

    Android系列的博客主要是记录和总结自己在平时学习之中遇到的问题,方便日后用到时查看,同时也希望对读者有所帮助.不足之处,欢迎指正~ 在说到Android数据存储之前,先提一下数据持久化,所谓数据 ...

  4. Android的数据存储之一------SharedPreferences

    下面将介绍下Android的数据存储,Android提供了5种方式存储数据: 1.SharedPreferences存储数据; 2.文件存储数据: 3.SQLite数据库存储数据: 4.使用Conte ...

  5. 数据存储加密和传输加密_将时间存储网络应用于加密预测

    数据存储加密和传输加密 I'm not going to string you along until the end, dear reader, and say "Didn't achie ...

  6. android SharedPreferences数据存储

    android  SharedPreferences数据存储 很多时候我们开发的软件需要向用户提供软件参数设置功能,例如我们常用的QQ,用户可以设置是否允许陌生人添加自己为好友.对于软件配置参数的保存 ...

  7. android存储视频文件夹在哪,Android 中 视频存储路径的一个方案

    版权声明:本文为博主原创文章,未经博主允许不得转载. 在进行视频的下载时,我们经常会面临存储路径的选择,选择一个好的存储路径能对Android系统中的内存起到优化的作用.主流app下载路径分析和常见的 ...

  8. Android之数据存储-刘志远-专题视频课程

    Android之数据存储-17742人已学习 课程介绍         本课程介绍了Android中几种数据存储方式,让大家对Android中的数据存储一个系统的认识 课程收益     本课程介绍了A ...

  9. android app数据存储,基于Android开发的APP数据存储研究

    谢原武+龙文 摘要: 作为一个完整的应用程序,数据存储操作是必不可少的.Android系统一共提供了四种数据存储方式分别为File文件存储.Shared Preferences存储.ContentPr ...

  10. Android常用数据存储之SharedPreferences存储和读取用法分享

    一:Android常用数据存储,一共有五种方式,分别是 1.SharedPreferences储存数据, 2.文件存储 3.SQLite数据存储 4.ContentProvider储存数据 5.网络存 ...

最新文章

  1. HTC VIVE 虚拟现实眼镜VR游戏体验
  2. interp3函数-----三维数据插值
  3. oracle 方言报错,ORACLE11g:No Dialect mapping for JDBC type: -9解决方案详解
  4. c++ 6.0 没有找到mspdb60.dll 问题的解决
  5. 预训练永不止步,游戏问答语言模型实操
  6. 电脑常见的VGA、DVI、PS/2、USB等接口知识笔记,值得收藏!
  7. vsftpd的主配置文件是什么linux,vsftpd.conf配置文件详解
  8. (24)System Verilog多个线程间通信(信箱)
  9. sql server根据表中数据生成insert语句
  10. 麻省理工线性代数第一讲
  11. python计算器功能介绍_python计算器功能如何实现?这篇文章给你最实用的代码
  12. 初使用tbs的x5内核所遇到的坑,初学者如何第一次跑起x5内核
  13. MATLAB工具箱下载地址总汇
  14. 【历史上的今天】2 月 4 日:Unix 之父诞生;Facebook 上线;微软大洗牌
  15. 【模块】ESP32连接PS4手柄
  16. 《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该恰好瓜还是恰坏瓜
  17. N沟道的Vgs是正的,P沟道的Vgs是负的
  18. stunserver 的几个公网地址及其问题
  19. 建设工程管理系统(二)
  20. 京东到家订单订单查询服务演进

热门文章

  1. rssi参数获取_如何获取WlanGetNetworkBssList函数返回值的Rssi值
  2. 对四旋翼飞行器的分析
  3. PCB生产工艺流程博大精深
  4. ug建模减速器_UG NX一级减速器整体建模
  5. 未来计算机2020500,500kV变电站计算机监控系统的实施策略原稿
  6. MAC中安装Navicat Premium
  7. 转载:细数飞机设计专用软件,知道5个你就很牛了
  8. java字符串下标替换_java字符串下标替换
  9. 2006年100款最佳安全工具谱
  10. 蓝桥杯第八届等差素数列