LeanCloud 快速实现服务端

news2025/1/13 10:19:53

1. 实现与服务器交互平台

  1.1 Google 平台的 Firebase (需要科学网络)    

Firebasehttps://firebase.google.cn/

  1.2 LeanCloud 平台

LeanCloudhttps://www.leancloud.cn/

2. 配置信息

  2.1 在 LeanCloud 控制台创建应用, 根据 SDK下载 开发指南配置应用

  2.2 配置文件 build.gradle 添加库

   //视图绑定
   buildFeatures {
        viewBinding = true
    }

    //使用存储功能
    implementation 'cn.leancloud:storage-android:8.2.5'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    //使用即时通讯 / 推送服务
    implementation 'cn.leancloud:realtime-android:8.2.5'

  2.3 实现 Application, MyApplication.kt

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        LeanCloud.initialize(this, "bl8p52gwz7pVkOhMg3unRaT4-gzGzoHsz", "dL6QC52vonm41TegX4i5jB7S", "https://bl8p52gw.lc-cn-n1-shared.com")
    }
}

  2.4 配置文件 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <!-- 基本模块(必须)START -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.LeanDemo"
        tools:targetApi="31">
        <activity
            android:name=".SignUpActivity"
            android:exported="false">
            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
        <activity
            android:name=".LoginActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
        <activity android:name=".MainActivity" />
        <!-- 即时通讯和推送 START -->
        <!-- 即时通讯和推送都需要 PushService -->
        <service android:name="cn.leancloud.push.PushService" />
        <receiver
            android:name="cn.leancloud.push.LCBroadcastReceiver"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.USER_PRESENT" />
                <action
                    android:name="android.net.conn.CONNECTIVITY_CHANGE"
                    tools:ignore="BatteryLife" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

  2.5 退出菜单布局 menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menuLogout"
        android:title="退出" />
</menu>

3. 登录页面实现

  3.1 布局文件 activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".LoginActivity">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/textInputLayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/editTextUsername"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="用户名" />
    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/textInputLayout2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textInputLayout">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/editTextPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="密码" />
    </com.google.android.material.textfield.TextInputLayout>

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

    <Button
        android:id="@+id/buttonSignUp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="注册"
        app:layout_constraintEnd_toStartOf="@+id/guideline"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textInputLayout2" />

    <Button
        android:id="@+id/buttonLogin"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:enabled="false"
        android:text="登录"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline"
        app:layout_constraintTop_toBottomOf="@+id/textInputLayout2" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:visibility="invisible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonSignUp" />

</androidx.constraintlayout.widget.ConstraintLayout>

  3.2 实现事件, LoginActivity.kt

class LoginActivity : AppCompatActivity() {
    private lateinit var binding: ActivityLoginBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityLoginBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.editTextUsername.addTextChangedListener(watcher)
        binding.editTextPassword.addTextChangedListener(watcher)
        //注册
        binding.buttonSignUp.setOnClickListener {
            startActivity(Intent(this, SignUpActivity::class.java))
        }
        //登录
        binding.buttonLogin.setOnClickListener {
            login()
        }
    }

    //登录
    private fun login() {
        binding.progressBar.visibility = View.VISIBLE
        val name = binding.editTextUsername.text?.trim().toString()
        val pwd = binding.editTextPassword.text?.trim().toString()
        LCUser.logIn(name, pwd).subscribe(object : Observer<LCUser> {
            override fun onSubscribe(d: Disposable) {}
            //登录成功
            override fun onNext(t: LCUser) {
                binding.progressBar.visibility = View.INVISIBLE
                Toast.makeText(this@LoginActivity, "登录成功", Toast.LENGTH_SHORT).show()
                startActivity(Intent(this@LoginActivity, MainActivity::class.java))
                finish()
            }
            //登录失败
            override fun onError(e: Throwable) {
                Toast.makeText(this@LoginActivity, "${e.message}", Toast.LENGTH_SHORT).show()
                binding.progressBar.visibility = View.INVISIBLE
            }
            override fun onComplete() {}
        })
    }

    //监听 EditText
    private val watcher = object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            val t1 = binding.editTextUsername.text.toString().isNotEmpty()
            val t2 = binding.editTextPassword.text.toString().isNotEmpty()
            binding.buttonLogin.isEnabled = t1 and t2
        }
        override fun afterTextChanged(s: Editable?) {}
    }
}

4. 注册页面实现

  4.1 布局文件 activity_sign_up.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".SignUpActivity">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/textInputLayout3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/editTextUsername"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="用户名" />
    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/textInputLayout4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textInputLayout3">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/editTextPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="密码" />
    </com.google.android.material.textfield.TextInputLayout>

    <Button
        android:id="@+id/buttonSignUpConfirm"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:enabled="false"
        android:text="注册并登录"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textInputLayout4" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:visibility="invisible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonSignUpConfirm" />
</androidx.constraintlayout.widget.ConstraintLayout>

  4.2 实现事件 SignUpActivity.kt

class SignUpActivity : AppCompatActivity() {
    private lateinit var binding: ActivitySignUpBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivitySignUpBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.editTextUsername.addTextChangedListener(watcher)
        binding.editTextPassword.addTextChangedListener(watcher)
        //注册按钮
        binding.buttonSignUpConfirm.setOnClickListener {
            signUp()
        }
    }

    //注册
    private fun signUp() {
        binding.progressBar.visibility = View.VISIBLE
        val name = binding.editTextUsername.text?.trim().toString()
        val pwd = binding.editTextPassword.text?.trim().toString()
        LCUser().apply {
            username = name
            password = pwd
            signUpInBackground().subscribe(object : Observer<LCUser> {
                override fun onSubscribe(d: Disposable) {}
                //注册成功
                override fun onNext(t: LCUser) {
                    Toast.makeText(this@SignUpActivity, "注册成功", Toast.LENGTH_SHORT).show()
                    LCUser.logIn(name, pwd).subscribe(object : Observer<LCUser> {
                        override fun onSubscribe(d: Disposable) {}
                        override fun onNext(t: LCUser) {
                            binding.progressBar.visibility = View.INVISIBLE
                            startActivity(Intent(this@SignUpActivity, MainActivity::class.java).also {
                                it.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
                            })
                            //finish()
                        }
                        override fun onError(e: Throwable) {
                            binding.progressBar.visibility = View.INVISIBLE
                            Toast.makeText(this@SignUpActivity, "${e.message}", Toast.LENGTH_SHORT)
                                .show()
                        }
                        override fun onComplete() {}
                    })
                }
                //注册失败
                override fun onError(e: Throwable) {
                    binding.progressBar.visibility = View.INVISIBLE
                    Toast.makeText(this@SignUpActivity, "${e.message}", Toast.LENGTH_SHORT).show()
                }
                //注册完成
                override fun onComplete() {}
            })
        }
    }

    //监听 EditText
    private val watcher = object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            val t1 = binding.editTextUsername.text.toString().isNotEmpty()
            val t2 = binding.editTextPassword.text.toString().isNotEmpty()
            binding.buttonSignUpConfirm.isEnabled = t1 and t2
        }
        override fun afterTextChanged(s: Editable?) {}
    }
}

5. 主页实现

  5.1 添加词汇布局, new_word_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/editText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:ems="10"
        android:hint="输入单词"
        android:inputType="textPersonName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

  5.2 适配器布局 view_holder.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="60dp">

    <TextView
        android:id="@+id/textViewContent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="32dp"
        android:text="TextView"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textViewTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="32dp"
        android:text="TextView"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

  5.3 实现 Adapter 及 ViewHolder, MyAdapter.kt

class MyAdapter : Adapter<ViewHolder>() {
    private var _dataList = listOf<LCObject>()

    fun updateDataList(newList: List<LCObject>) {
        _dataList = newList
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.view_holder, parent, false)
        return object : ViewHolder(v) {}
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val obj = _dataList[position]
        holder.itemView.findViewById<TextView>(R.id.textViewContent).text =
            obj.get("word").toString()
        holder.itemView.findViewById<TextView>(R.id.textViewTime).text =
            obj.get("createdAt").toString()
    }
    
    override fun getItemCount(): Int = _dataList.size
}

  5.4 创建 ViewModel, MyViewModel.kt

class MyViewModel(application: Application) : AndroidViewModel(application) {
    private val _dataListLive = MutableLiveData<List<LCObject>>()
    val dataListLive: LiveData<List<LCObject>> = _dataListLive

    init {
        val query = LCQuery<LCObject>("Word")
        query.whereEqualTo("user", LCUser.getCurrentUser())
        query.findInBackground().subscribe(object : Observer<List<LCObject>> {
            override fun onSubscribe(d: Disposable) {}
            override fun onNext(t: List<LCObject>) {
                _dataListLive.value = t
            }
            override fun onError(e: Throwable) {
                Toast.makeText(application, "${e.message}", Toast.LENGTH_SHORT).show()
            }
            override fun onComplete() {}
        })

        //数据推送及同步
        val liveQuery = LCLiveQuery.initWithQuery(query)
        liveQuery.subscribeInBackground(object : LCLiveQuerySubscribeCallback() {
            //订阅成功
            override fun done(e: LCException?) {}
        })
        //推送回调
        liveQuery.setEventHandler(object : LCLiveQueryEventHandler() {
            //添加
            override fun onObjectCreated(LCObject: LCObject?) {
                super.onObjectCreated(LCObject)
                val t = _dataListLive.value?.toMutableList()
                t?.add(LCObject!!)
                _dataListLive.value = t
            }
            //删除
            override fun onObjectDeleted(objectId: String?) {
                super.onObjectDeleted(objectId)
                val t = _dataListLive.value?.toMutableList()
                val obj = t?.find {
                    it.get("objectId") == objectId
                }
                t?.remove(obj)
                _dataListLive.value = t
            }
            //更新
            override fun onObjectUpdated(LCObject: LCObject?, updateKeyList: MutableList<String>?) {
                super.onObjectUpdated(LCObject, updateKeyList)
                val obj = _dataListLive.value?.find {
                    it.get("objectId") == LCObject?.get("objectId")
                }
                updateKeyList!!.forEach {
                    obj?.put(it, LCObject?.get(it))
                }
                _dataListLive.value = _dataListLive.value
            }
        })
    }

    //添加表
    fun addWord(newWord: String) {
        LCObject("Word").apply {
            put("word", newWord)
            put("user", LCUser.getCurrentUser())
            saveInBackground().subscribe(object : Observer<LCObject> {
                override fun onSubscribe(d: Disposable) {}
                override fun onNext(t: LCObject) {
                    Toast.makeText(getApplication(), "添加成功", Toast.LENGTH_SHORT).show()
                }
                override fun onError(e: Throwable) {
                    Toast.makeText(getApplication(), "${e.message}", Toast.LENGTH_SHORT).show()
                }
                override fun onComplete() {}
            })
        }
    }
}

  5.5 主页布局 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="409dp"
        android:layout_height="729dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.915"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.976"
        app:srcCompat="@android:drawable/ic_input_add" />
</androidx.constraintlayout.widget.ConstraintLayout>

  5.6 实现事件,MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var viewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        viewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application))[MyViewModel::class.java]
        val myAdapter = MyAdapter()
        binding.recyclerView.apply {
            layoutManager = LinearLayoutManager(this@MainActivity)
            addItemDecoration(DividerItemDecoration(this@MainActivity, DividerItemDecoration.VERTICAL))
            adapter = myAdapter
        }
        viewModel.dataListLive.observe(this) {
            myAdapter.updateDataList(it)
            myAdapter.notifyDataSetChanged()
        }
        binding.floatingActionButton.setOnClickListener {
            addNewWord()
        }
    }

    //添加单词
    private fun addNewWord() {
        val view = LayoutInflater.from(this).inflate(R.layout.new_word_dialog, null)
        AlertDialog.Builder(this)
            .setTitle("添加")
            .setView(view)
            .setPositiveButton("确定") { _, _ ->
                val newWord = view.findViewById<EditText>(R.id.editText).text.trim().toString()
                viewModel.addWord(newWord)
            }
            .setNegativeButton("取消") { dialog, _ ->
                dialog.dismiss()
            }
            .show()
    }

    //退出
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        if (item.itemId == R.id.menuLogout) {
            LCUser.logOut()
            startActivity(Intent(this, LoginActivity::class.java))
            finish()
        }
        return super.onOptionsItemSelected(item)
    }

    //菜单项
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu, menu)
        return super.onCreateOptionsMenu(menu)
    }
}

6. 效果图

      

   

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

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

相关文章

拉伯杠杆平台|新冠药龙头跳水,万亿产业开启新阶段!

依照此前发表的时间表&#xff0c;新修订的《体育法》将于2023年1月1日起正式施行。 12月27日早盘&#xff0c;A股前期大热的抗疫体裁呈现显着回落。熊去氧胆酸、新冠药、肝炎概念、新冠检测、生物疫苗等体裁跌幅较大。熊去氧胆酸、新冠药两大板块跌幅超过4%&#xff0c;抢手龙…

外贸采购管理对业务的影响及解决方案

在外贸企业中&#xff0c;采购环节的把控对整个业务环节都有影响。像是采购供应商是否能够按时到货&#xff0c;会直接影响生产进度&#xff1b;采购质量的好坏直接影响产品的生产进度及质量&#xff1b;采购成本的高低&#xff0c;直接影响产品的成本及利润&#xff1b;采购供…

NSUM 问题

目录标题两数之和两数之和 2&#xff08;多个结果集去重&#xff09;15. 三数之和两数之和 问题描述 给定一个整数数组 nums 和一个目标值 target&#xff0c;请你在该数组中找出和为目标值的那 两个 整数&#xff0c;并返回他们的数组下标。 你可以假设每种输入只会对应一个答…

基于Java(JSP)+MySQL实现(Web)学生成绩综合管理系统【100010065】

Java 课程设计:师生交流系统 1.1 课设题目 信息商务学院学生成绩综合管理系统的综合与开发 2.1 课设目的 《Java 程序设计》课程是计算机专业的一门专业必修课程&#xff0c;针对课程进行为期两周的实践教学&#xff0c;旨在提升本专业学生对此课程中的理论知识的综合应用能…

[Python学习系列] 走进Django框架

文章目录1. 安装django2. 创建项目&#xff08;命令的方式&#xff09;在第一次创建django项目需要做的&#xff1a;每一次创建django项目需要做的&#xff1a;3. 创建app4. 启动运行django项目程序5. 模板&静态文件的存放地址6. django中的模板语法7. django中常见的请求和…

ArcGIS基础实验操作100例--实验4矢量要素的镜像复制,缩放

实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 基础编辑篇--实验4 矢量要素的镜像复制&#xff0c;缩放 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&#xff09;加载【Mirror Features】工具 &#x…

VMware之安装Windows10系统

系统下载 下载地址&#xff1a;原版软件 (itellyou.cn) 创建虚拟机系统框架 在菜单栏中选择文件下的新建虚拟机 选择自定义&#xff0c;然后点击下一步 直接下一步 选择稍后安装操作系统&#xff0c;然后点击下一步 因为安装的系统是Windows&#xff0c;这里注意选择Microsof…

使用eBPF追踪Linux内核

简介 BPF&#xff0c;及伯克利包过滤器Berkeley Packet Filter&#xff0c;最初构想提出于 1992 年&#xff0c;其目的是为了提供一种过滤包的方法&#xff0c;并且要避免从内核空间到用户空间的无用的数据包复制行为。它最初是由从用户空间注入到内核的一个简单的字节码构成&…

浏览器:理解HTTP无状态与Cookie的使用

一、理解HTTP无状态 1.1、理解http无状态 http无状态是指协议对于用户身份、用户状态、用户权限、交互场景等没有记忆能力。简单讲就是不能识别用户。 1.2、http无状态的优点&#xff1a; 可以更快地处理大量的事务&#xff0c;确保协议的可伸缩性&#xff0c;减少服务器的…

一文搞定十大排序算法(动画图解)

排序的定义 排序&#xff0c;就是重新排列表中的元素&#xff0c;使表中的元素满足按关键字递增或递减的过程。为了査找方便&#xff0c;通常要求计算机中的表是按关键字有序的。 排序的确切定义如下&#xff1a; 算法的稳定性&#xff1a; 若待排序表中有两个元素 Ri 和 Rj&am…

包装类和简单认识泛型

目录 1.包装类 1.1基本数据类型和对应的包装类 1.2装箱和拆箱 1.3自动装箱和自动拆箱 2.什么是泛型 3.引出泛型 3.1语法 4.泛型类的使用 4.1语法 4.2类型推导 5.裸类型 5.1说明 6.泛型如何编译的 6.1擦除机制 6.2为什么不能实例化泛型类型的数组 7.泛型的上界 …

MaxKey单点登录认证系统3.5.12发布,重要漏洞修复

业界领先的IAM/IDaas身份管理和认证产品 概述 MaxKey单点登录认证系统&#xff0c;谐音马克思的钥匙寓意是最大钥匙,是业界领先的IAM/IDaas身份管理和认证产品,支持OAuth 2.x/OpenID Connect、SAML 2.0、JWT、CAS、SCIM等标准协议&#xff0c;提供安全、标准和开放的用户身份…

STM32/51单片机实训day3——点亮LED灯、闪烁LED灯(二)实践

内 容&#xff1a;编写代码实现LED灯的点亮功能 学 时&#xff1a;2学时 知识点&#xff1a;分析原理图、LED灯控制原理 重点&#xff1a;GPIO参数配置、LED原理图分析 难点&#xff1a;编写 GPIO参数配置函数、LED点亮函数 时间&#xff1a;2022年12月21日 9:00&#xff5e;…

如何轻松做数据治理?开源技术栈告诉你答案

搭建一套数据治理体系耗时耗力&#xff0c;但或许我们没有必要从头开始搞自己的数据血缘项目。本文分享如何用开源、现代的 DataOps、ETL、Dashboard、元数据、数据血缘管理系统构建大数据治理基础设施。 元数据治理系统 元数据治理系统是一个提供了所有数据在哪、格式化方式…

vue2.0中集成并使用ueditor,解决第一次编辑器正常加载,第二次就不加载的问题,父组件调用子组件的方法

vue2.0中集成并使用ueditor 最近有项目需要使用编辑器&#xff0c;就找了一款百度的ueidtor编辑器&#xff0c;第一次用各种不会&#xff0c;所以记录一下 下面的链接就是ueditor的前后端的配置说明和API等 链接: ueidtor的API 下载ueidtor 下载最新版的1.5.0版本&#xf…

基于Flask+bootstrap+sqlite开发宝宝成长管理系统,宝宝成长记录系统源码

BabyLog 岁月如风&#xff0c;唯有此忆, 任凭时光匆匆&#xff0c;记录点点滴滴。 当爸爸了&#xff0c;就多陪陪孩子&#xff0c;有事没事的记些东西&#xff0c;不要总把心思放在程序编码上&#xff0c;也多陪陪孩子&#xff01; 记录了那么多条数据&#xff0c;是时候也为…

Linux之Shell脚本学习笔记(持续更新中......)

Shell是什么 命令解释器。为用户提供了一个向Linux内核发送请求一i按运行程序的界面系统级程序。 Shell编程快速入门 脚本格式要求 脚本以#!/bin/bash开头脚本需要有可执行权限 编写脚本&#xff0c;输出HelloWorld 编写 #!/bin/bash echo "hello world!"执行 …

Stm32开发1-蓝牙实现STM32的无线烧写程序 ISP模式 串口1不受影响 无线下载

最近研究如何实现Stm32的无线烧写程序。从CSDN上看到大部分的无线烧写方法&#xff0c;大都是采用ESP8266CMSIS-DAP的方式&#xff0c;其能下载也能调试程序&#xff0c;也能通过虚拟串口通信。但是其串口应该是用软件实现的&#xff0c;会占用系统资源&#xff0c;对于其能否实…

【unity3D】DoTween动画插件(上)

&#x1f497; 未来的游戏开发程序媛&#xff0c;现在的努力学习菜鸡 &#x1f4a6;本专栏是我关于游戏开发的学习笔记 &#x1f236;本篇是unity的DoTween动画插件 DoTween动画插件&#xff08;上&#xff09;基础知识一些常用方法DOMove和DoLocalMovefrom TerrnsDOText打字机…

JavaScript篇.day04-函数, 对象类型

目录 1.函数 2.对象类型 3.例题 (1)斐波拉契数列(递归) (2)猴子吃桃(递归) (3)求100内的数之和(递归) 1.函数 函数: 是完成某个功能的代码块 函数声明 function 函数名(){ }function 函数名(形参1, 形参2...){ }函数表达式: var 函数名 function(){ } 匿名函数 …