【Android】数据存储

news2024/11/24 8:33:04

一、文件存储

特点:openFileInput()和openFileOutput()读取设备上的文件。
优点:适用于存储大量的数据,可以存储图片、视频、文本等数据。
缺点:如果采用内部存储的方式,存储过量的数据可能会导致内存的不足;如果采用外部sdcard存储的方式,删除或者卸载应用,相关的数据需要手动进行删除,比较麻烦。

默认位置:/data/data/<包>/files/.

![在这里插入图片描述](https://img-blog.csdnimg.cn/4e39e97b20104f6f93512e6d64a3035c.png

(一)内部存储

// 将数据存储到指定的文件中
// name为文件名,mode为文件的操作模式
FileOutputStream fos = openFileOutput(String name,int mode);
// 读取指定文件中的数据
FileInputStream  fis = openFileInput(String name);

mode的取值如下:

MODE_PRIVATE:该文件只能被当前程序读写 ;
MODE_APPEND:该文件的内容可以追加;
MODE_WORLD_READABLE:该文件的内容可以被其他程序读;
MODE_WORLD_WRITEABLE:该文件的内容可以被其他程序写

注意:Android系统有一套自己的安全模型,默认情况下任何应用创建的文件都是私有的,其他程序无法访问。

1.写入文件步骤

String fileName = “data.txt”; // 文件名称
String content = “helloworld”; // 保存数据
FileOutputStream fos = openFileOutput(fileName, MODE_PRIVATE);
fos.write(content.getBytes()); //将数据写入文件中
fos.close(); //关闭输出流

2.读取文件步骤

String content = “”;
FileInputStream fis = null;
fis = openFileInput(“data.txt”); //获得文件输入流对象
byte[] buffer = new byte[fis.available()]; // 创建缓冲区,并获取文件长度
fis.read(buffer); // 将文件内容读取到buffer缓冲区
content = new String(buffer);//转换成字符串
fis.close(); //关闭输入流

3. 实现存储和读取用户名和密码实例

创建UserInfoIO工具类,实现存储数据方法(saveUserInfo)和读取数据方法(getUserInfo)

public class UserInfoIO {
	// 数据的写入
	public static boolean saveUserInfo(String username, String password, Context context){
	    // openFileOutput(要操作的文件名,文件访问模式)
	    FileOutputStream fos = null;
	    String msg = null;
	    try { // 在操作文件的时候可能会报异常,需要进行捕获
	        fos = context.openFileOutput("MyData.txt",Context.MODE_PRIVATE);
	        msg = username + ":" + password;
	        // getBytes()将字符串转换为字节流
	        fos.write(msg.getBytes());
	        return true;
	    } catch (IOException e) {
	        e.printStackTrace();
	        return false;
	    }
	    finally {
	        try {
	            fos.close(); // 流是系统中的稀缺资源,在使用完后要及时关闭
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	}
}
// 用户数据的读取
public static Map<String,String> getUserInfo(Context context){
    // 获取文件输入流
    FileInputStream fis = null;
    try {
        fis = context.openFileInput("MyData.txt");
        byte[] buffer = new byte[fis.available()];
        fis.read(buffer);
        // 字节转换为字符串
        String msg = new String(buffer);
        String[] userInfo = msg.split(":");
        Map<String,String> userMap = new HashMap<>();
        userMap.put("username",userInfo[0]);
        userMap.put("password",userInfo[1]);
        return userMap;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
    finally {
        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
}

二、SharedPreferences存储

特点:以XML格式将数据存储到设备。
优点:简单、方便、轻量级、易理解。
缺点:适用于存储少量的数据,并且数据的格式只能是基本的数据类型(int、float、long、boolean)、字符串类型(string),无法进行条件查询等操作。

SharedPreferences是一个轻量级的存储类,特别适合用于保存软件配置参数,其背后是用xml文件存放数据,文件存放在/data/data//shared_prefs目录下。

1.写入文件步骤

SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。

SharedPreferences sp = getSharedPreferences(“data”,MODE_PRIVATE);//获取SharedPreferences对象
SharedPreferences.Editor editor = sp.edit(); // 获取编辑器对象
editor.putString(“name”, “张三”); // 存入String类型数据
editor.putInt(“age”, 8); // 存入int类型数据
editor.commit(); // 提交数据

2.读取文件步骤

SharedPreferences sp = getSharedPreferences(“data”,MODE_PRIVATE);
String data= sp.getString(“name”,“”);

3.删除文件中数据

editor.remove(“name”); // 根据key删除数据
editor.clear(); // 删除所有数据

4. 实现存储和读取用户名和密码实例

创建UserInfoSharePre工具类,实现存储数据方法(saveUserInfo)和读取数据方法(getUserInfo)

public class UserInfoSharedPre {
    // 用户数据的存储
    public static boolean saveUserInfo(String username, String password, Context context) {
        // 获取SharedPreferences对象,同时指定文件名称和访问权限
        SharedPreferences sp = context.getSharedPreferences("MyData", Context.MODE_PRIVATE);
        // 获取获取SharedPreferences的编辑器对象
        SharedPreferences.Editor edit = sp.edit();
        // 通过编辑器进行数据的存储
        edit.putString("Uname",username);
        edit.putString("Pwd",password);
        edit.commit();
        return true;
    }

   // 读取用户数据
   public static Map<String,String> getUserInfo(Context context) {
       // 获取SharedPreferences对象,同时指定文件名称和访问权限
       SharedPreferences sp = context.getSharedPreferences("MyData", Context.MODE_PRIVATE);
       String username = sp.getString("Uname", "");
       String password = sp.getString("Pwd","");
       Map<String,String> userMap = new HashMap<>();
       userMap.put("username",username);
       userMap.put("password",password);
       return userMap;
   }
}

三、SQLite数据库存储

特点:运算速度快,占用资源少,还支持基本SQL语法。
优点:适合存储结构化数据、轻量级、安全性、隔离性、独立性。
缺点:并发的读写性能不好。

1. 创建数据库步骤

(一)定义数据库帮助类

SQLiteOpenHelper是SQLiteDatabase的一个帮助类,用来管理数据库的创建和版本的更新

class MyDbHelper extends SQLiteOpenHelper {
    // 构造器的作用:(参数:上下文,数据库文件的名称,结果集工厂,版本号)定义数据库
    public MyDbHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }
    // 数据库初始化时创建的表,用于创建表或视图文件
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create table user(user_id integer primary key autoincrement,userName varchar(10),password varchar(10))");
    }
    // 升级方法(当数据库的版本号增加时调用)
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}
(二)创建数据库和表
// 设置数据库的相关参数,初始化数据库
MyDbHelper myDbHelper = new MyDbHelper(SQLiteActivity.this,"MyDatabase.db",null,1);
// 通过帮助类获取到数据库对象
SQLiteDatabase db = myDbHelper.getWritableDatabase();

通过数据库对象可以执行如下方法:
在这里插入图片描述

1.插入方法insert
// 创建ContentValues对象用于存储记录的字段值(键值对方式:键对应字段名,值对应字段具体的值)
ContentValues contentValues = new ContentValues();
contentValues.put("userName","张三");
contentValues.put("password","123456");
db.insert("user",null,contentValues);

上面等同于

db.execSQL("insert into user(userName,password) values (?,?)",new Object[]{"张三","123456"});

执行完之后

db.close();
2.查询方法query

调用query方法查询数据库中的数据,返回一个行数集合cursor

public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)

各参数说明:
table:表名称
colums:列名称数组,返回那些字段,null表示所有字段
selection:查询条件子句,相当于select语句where关键字后面的部分,在条件子句允许使用占位符“?” selectionArgs:对应于selection语句中占位符的值,值在数组中的位置与占位符在语句中的位置必须一致, 否则就会有异常。
groupBy:相当于select语句group by关键字后面的部分
having:相当于select语句having关键字后面的部分
orderBy:排序类
limit:分页查询的限制,指定偏移量和获取的记录数
Cursor:返回值,相当于结果集ResultSet

// Cursor: 结果集,内有游标指向结果集中的某一条记录,初始时指向第一条
Cursor cursor = db.query("user", new String[]{"userName,password"}, null, null, null, null, null, null);
cursor.moveToFirst();
while (cursor.moveToNext()) { // 移动游标指向下一行数据
	showInfo.append("\n" + "用户名" + cursor.getString(0) + ",密码" + 	cursor.getString(1));
}
cursor.close();
db.close();

对于cursor也提供了一些方法如下:
在这里插入图片描述

3.删除方法delete

返回删除的记录条数

public boolean deleteData(String deleteId) {
	int i = db.delete("user", "id=?", new String[]{deleteId});
	return i > 0 ? true : false;
}
3.修改方法update

返回更新的记录条数

ContentValues contentValues = new ContentValues();
contentValues.put("userName","李四");
contentValues.put("password","123123");
int i = db.update("user", contentValues, "id=?", new String[]{updateId});

等同于

db.execSQL("update user set userName=?,password=? where id=?",new Object[]{username1,password1,id});

四、ContentProvider存储

特点:ContentProvider主要用于不同应用程序之间共享数据,ContentProvider更好的提供了数据共享接口的统一性,使不同应用共享数据更规范和安全。
优点:能够实现所有应用程序共享的一种数据存储方式,可以存储音频,视频,图片和通讯录等。
缺点:不能单独使用,必须与其他存储方式结合使用。

内容提供者(ContentProvider)是Android系统四大组件之一,它是不同应用程序之间进行数据共享的标准API,通过ContentResolver类可以访问ContentProvider中共享的数据。

ContentProvider的工作原理如下:
在这里插入图片描述

常见的使用场景:QQ和微信中文件的相互转发;安装完某个app第一次启动的时候获取权限(联系人、拍照、位置等)

ContentProvider 使用基于数据库模型的简单表格来提供需要共享的数据,在该表格中,每一行表示一条记录,而每一列代表特定类型和含义的数据,并且其中每一条数据记录都包含一个名为“_ID”的字段类标识每条数据,可以根据同一个ID查询几个相关表中的信息。知道各个字段对应的数据类型后,可根据Cursor对象提供的相关的方法,如,getInt()、getString()、getLong()等查询字段对应的值。

在这里插入图片描述
简单理解:A程序共享数据实际上就是共享一张表,B程序要去获取数据实际上就是要去对表执行查询操作。
问题:B程序如何精确地找到A程序所共享出来的表?

ContentResolver提供一系列增删改查的方法对数据进行操作,并且这些方法以Uri的形式对外提供数据。
Uri为内容提供者中的数据建立了唯一标识符。它主要由三部分组成,scheme、authorities(主机名/域名)和path。

扩展:uriurl功能类似,通过uri可以指向安卓系统中唯一的某个资源。也就是说通过它可以指向共享出来的唯一的某个表文件
如下:
在这里插入图片描述

scheme部分,“content://”是一个标准的前缀。
authority(主机名/域名)部分,是在创建内容提供者时指定的authorities属性值,通常采用程序包名的方式命名。
path部分,“/person”代表资源(或者数据),可以动态改变。

UriMatcher类:用于对ContentProvider中的Uri进行匹配

1、初始化UriMatcher

 UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
 // 常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)

2、将Uri注册到UriMatcher中

matcher.addURI("cn.itcast.contentprovider", "people", 1);  
// 添加需要匹配uri,如果匹配就会返回匹配码"1"
matcher.addURI("cn.itcast.contentprovider", "person/#", 2);
// #表示通配符,任意内容的意思
1.创建数据库与表提供数据
public class MyDBhelper extends SQLiteOpenHelper {
    public MyDBhelper(Context context) {
        super(context, "person.db", null, 1);
    }
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create table user(id integer primary key autoincrement,userName varchar(10),phone varchar(10))");
    }
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}
2.创建内容提供者继承ContentProvider父类

在程序包名处右击选择【New】—>【Other】—>【Content Provider】选项
输入内容提供者的Class Name(类名称)和URI Authorities(唯一标识,通常使用包名)

内容提供者创建完成后,Android Studio会自动在AndroidManifest.xml中对内容提供者进行注册。

<application ......>
    ......	
    <provider
        android:name=".MyContentProvider"
        android:authorities="cn.com.myapp"
        android:enabled="true"
        android:exported="true" >
   </provider>
</application>

属性含义如下:
(1)android:name:该属性是一个类的全名称
(2)android:authorities:列出一个或者多个由content provider的提供的URI的authorities,多个authorities由分号隔开(自定义)。
(3)android:enabled:该属性表明了该content provider是否可以被实例化,默认情况下该属性值是true。
(4)android:exported:该属性指示了content provider是否可以被其他应用程序使用。

public class MyContentProvider extends ContentProvider {
    private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    private static final int SUCCESS = 1;
    private MyDBhelper myDBhelper;
    // 静态代码块,MyContentProvider对象没有创建出来之前就已经存在
    static {
        // 加载时为uri适配器添加匹配规则
        uriMatcher.addURI("cn.com.myapp","user",SUCCESS);
        // 查询表中的某条记录
        uriMatcher.addURI("cn.com.myapp","user/#",2);
    }
    public MyContentProvider() {
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public String getType(Uri uri) {
        // TODO: Implement this to handle requests for the MIME type of the data
        // at the given URI.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public boolean onCreate() {
        // 创建数据库和初始化表的内容
        myDBhelper = new MyDBhelper(getContext());
        return false;
    }

    @Override
    // 未来会有另外一个app通过uri来调用query方法
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.
        // 匹配传入的uri,如果匹配得上再做相应的查询
        int match = uriMatcher.match(uri);
        if(match == 1) {
            // 查询user表中的数据并返回
            SQLiteDatabase db = myDBhelper.getWritableDatabase();
            return db.query("user",projection,selection,selectionArgs,null,null,sortOrder);
        } else if(match == 2) {
            // 查询表中的某条记录
        } else {
            return null;
        }
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
3.在第一个app的Activity中给数据库添加数据
public class firstApplicationActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first_application);
        MyDBhelper myDBhelper = new MyDBhelper(firstApplicationActivity.this);
        SQLiteDatabase db = myDBhelper.getWritableDatabase();
        db.execSQL("insert into user(userName,phone) values ('tom','8888')");
        db.execSQL("insert into user(userName,phone) values ('jeny','18888')");
        db.execSQL("insert into user(userName,phone) values ('jack','38888')");
    }
}
4.创建第二个App作为访问者

布局文件,通过点击按钮获取第一个app的数据用TextView展示出来

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".secondApplicationActivity"
    android:orientation="vertical"
    >
    <TextView
        android:id="@+id/show"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="9"/>
    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="获取共享数据"
        />
</LinearLayout>

java文件

public class secondApplicationActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn;
private TextView tv_show;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second_application);
        initViews();
        setListener();
    }

    protected void initViews() {
        btn = findViewById(R.id.btn);
        tv_show = findViewById(R.id.show);
    }

    protected void setListener() {
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn:
                // 创建uri,通过uri来指向共享的数据文件
                Uri uri = Uri.parse("content://cn.com.myapp/user");
                // 获取访问对象(内容解析者)
                ContentResolver contentResolver = getContentResolver();
                Cursor cursor = contentResolver.query(uri, new String[]{"userName", "phone"}, null, null, null);
                while (cursor.moveToNext()) {
                    tv_show.append("用户名:" + cursor.getString(0) + "----:" + cursor.getString(1) + "\n");
                }
        }
    }
}

最后,两个app都启动,点击第二个app的按钮拿到了第一个app共享的值
在这里插入图片描述

五、网络存储

特点:通过网络上提供的存储空间来上传(存储)或下载(获取)我们存储在网络空间中的数据信息
优点:无需考虑内存的影响。
缺点:受网络的状态的影响、需要耗费流量等成本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/89660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2022年度手机行业排行榜(年度手机行业分析)

如今&#xff0c;随着手机普及率的不断增长&#xff0c;当前手机市场在逐渐饱和。在这一的态势下&#xff0c;手机行业中细分市场成为发展的必然趋势&#xff0c;随着市场细分和目标人群锁定的不断明确&#xff0c;手机市场中中小品牌手机的生存空间在逐渐被挤压&#xff0c;手…

消息队列,Unix的通信机制之一

最简单的消息内存的使用流程 ①ftok函数生成键值 ②msgget函数创建消息队列 ③msgsnd函数往消息队列发送消息 ④msgrcv函数从消息队列读取消息 ⑤msgctl函数进行删除消息队列 一个消息数据应该由以下一个结构体组成&#xff0c;举个例子 struct mymesg{long int mtype; /…

教你如何使用eBPF追踪Linux内核

【推荐阅读】 浅析linux内核网络协议栈--linux bridge 深入理解SR-IOV和IO虚拟化 深入linux内核架构--进程&线程 1. 还是先进入内核目录&#xff0c;执行下面的命令&#xff0c;确保内核代码是干净的。 $ make mrproper 2. 执行以下命令&#xff0c;开始对内核进行配…

Feign的性能优化

Feign底层的客户端实现有三种模式 1&#xff09;URLConnection&#xff1a;默认实现&#xff0c;不支持连接池&#xff1b;&#xff08;Feign发送http请求时&#xff0c;默认使用的客户端&#xff09; 2&#xff09;Apache HttpClient &#xff1a;支持连接池&#xff1b; 3&…

深度学习Week10-YOLOv5-Backbone模块实现(Pytorch)

● &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 ● &#x1f366; 参考文章&#xff1a;Pytorch实战 |第P9周&#xff1a;YOLOv5-Backbone模块实现(训练营内部成员可读) ● &#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 类似于上周内…

也谈特征值和特征向量的几何意义

在当前的大数据分析时代&#xff0c;数据降维是一个重要的分析技术。而谈到数据降维&#xff0c;就离不开一门最为抽象难懂的数学学科分支——线性代数。有人可能会问&#xff1a;一堆向量和矩阵符号的线性代数到底有鸟用&#xff1f;简单地不科学地说&#xff0c;线性代数就是…

【tiktok小店运营小知识】 tiktok小店也会被封吗?有哪些原因呢?

最近开tiktok小店的小伙伴越来越多&#xff0c;运营过程中也会碰到很多问题。有小伙伴问&#xff0c; tiktok小店也会被封吗&#xff1f;有哪些原因呢&#xff1f; tiktok小店也会被封吗&#xff1f;有哪些原因呢&#xff1f; 答案是肯定的。TikTok需要进一步规范店铺经营&…

SRM是什么意思?盘点4个顶级SRM系统

SRM是什么意思&#xff1f;SRM系统&#xff0c;一般指供应商关系管理系统。供应商管理系统是采购管理系统的一个重要模块&#xff0c;强调企业与供应商之间协作共赢。相信在市场动荡的今天&#xff0c;企业与供应商之间的强关联、共命运对于企业来说不失为稳固根基、扩张业务的…

JavaScript系列之ES6默认导出与默认导入

文章の目录一、默认导出二、默认导入三、按需导出四、按需导入五、直接导入并执行模块代码写在最后一、默认导出 语法&#xff1a; export default 默认导出的成员每个模块中&#xff0c;只允许使用唯一的一次 export default&#xff0c;否则会报错&#xff01; 二、默认导入…

Generative Modeling by Estimating Gradients of the Data Distribution阅读笔记

目录概述传统score-based generative modeling介绍score matchingLangevin dynamics传统score-based generative modeling存在的问题流型假设上的问题低密度区域的问题Noise Conditional Score Network噪声条件分数网络(Noise Conditional Score Networks)annealed Langevin dy…

Kafka 架构、核心机制和场景解读

摘要 Kafka 是一款非常优秀的开源消息引擎&#xff0c;以消息吞吐量高、可动态扩容、可持久化存储、高可用的特性&#xff0c;以及完善的文档和社区支持成为目前最流行的消息队列中间件。 Kafka 的开发社区一直非常活跃&#xff0c;在消息引擎的领域取的不俗成绩之后&#xf…

组装式应用新基建——小程序容器技术

近年来&#xff0c;面对不断变化的业务环境和快速迭代的业务需求&#xff0c;“组装式应用”凭借其灵活性、复用性等优势&#xff0c;成为了重要战略技术趋势。 一直以来&#xff0c;传统应用程序开发面临着诸多挑战&#xff1a;一是没有足够的开发能力&#xff1b;二是选错技…

sql中的!=操作符的天坑(务必警觉)(=在处理null时也是同样有坑)

最近在测试数据&#xff0c;偶尔需要写sql进行数据比对&#xff0c;例如这样的语句&#xff1a; if( column_a ! column_b, 1, 0)&#xff0c;万万没想到就是这样的sql语句差点要了我的命。 其实对一般的数据&#xff0c;这条校验语句是没有问题的&#xff0c;最后再筛选一下1的…

Stm32旧版库函数10——A4988 单个步进电机 16拍

#include "stm32f10x_lib.h" #include "motor.h" u8 Step; void GPIO_Key(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_0|GPIO_Pin_1; // 选中管脚9 GPIO_InitStructure.GPIO_Mode …

使用java实现 分布式任务调度平台XXL-JOB 部署及使用

XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 详细的特性和优点参考官网地址&#xff1a;https://www.xuxueli.com/xxl-job/ 一、任务调度 0.下载官方源…

为什么微服务一定要有网关呢

一、什么是服务网关 服务网关 路由转发 过滤器1、路由转发&#xff1a;接收一切外界请求&#xff0c;转发到后端的微服务上去&#xff1b; 2、过滤器&#xff1a;在服务网关中可以完成一系列的横切功能&#xff0c;例如权限校验、限流以及监控等&#xff0c;这些都可以通过…

Anaconda环境GDAL库基于whl文件的配置方法

本文介绍在Anaconda环境下&#xff0c;基于.whl文件安装Python中高级地理数据处理库GDAL的方法。 在文章Anaconda下Python中GDAL模块的下载与安装方法&#xff08;https://blog.csdn.net/zhebushibiaoshifu/article/details/124307748&#xff09;中&#xff0c;我们介绍了基于…

[附源码]计算机毕业设计的实验填报管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis MavenVue等等组成&#xff0c;B/S模式…

我是如何使用docker安装nginx并配置https服务的

文章目录前言一、前期准备1、备案好的域名2、安装nginx2.1 下载nginx的docker镜像2.2 新建用于映射的目录2.3 从容器中拷贝nginx配置2.4 启动 nginx二、配置步骤1、申请免费的证书2、下载证书3、把证书上传至服务器4、配置 .conf 文件4.1 后端接口服务 api.conf 配置4.2 前端项…

数据智仓功能介绍(四)

字段设置 使用场景介绍 字段设置&#xff0c;即在数据智仓中&#xff0c;对输入上一数据处理节点的字段进行显示和隐藏、排序、重命名等操作。 操作配置 对数据类型的转换&#xff0c;主要用户复杂数据的处理的情况下 &#xff0c;例如某个字段是JSON &#xff0c;那么通过数…