Android App开发实战之实现微信记账本(附源码 超详细必看)

news2024/11/25 11:00:29

需要源码或图片集请点赞关注收藏后评论区留言~~~

一、需求描述

好用的记账本必须具备两项基本功能。一项时记录新帐单,另一项时查看账单列表,其中账单的记录操作要求用户输入账单的明细要素,包括账单的发生时间,账单的收支类型,账单的交易金额,账单的事由描述等等,账单通常分月展示,每页显示单个月份的账单数据,还要支持在不同月份之间切换,每月的账单数据按照时间从上往下排列,然后列表末尾展示当月的账单合计情况。

基本界面如下  用户可以自己输入类型,说明以及金额大小

 

二、界面设计 

除了文本视图,按钮,编辑框,单选按钮等简单控件之外,记账本还用到了下列控件以及相关的适配器  如果读者有疑问可以进我主页查看Android Studio专栏 里面有详细的讲解

Android App专栏

翻页视图

翻页标签栏

碎片适配器

碎片

列表视图

基本适配器

提醒对话框

日期选择对话框

下面列出了活动页面开始直到账单行的依赖嵌套关系(账单总体页面->每个月份的账单页->每月账单的明细列表->每行的账单信息) 

三、关键部分 

1:如何实现日期下拉框

填写账单时间的时候,输入界面默认展示当天日期,用户若想修改账单时间,就要点击日期文本,此时界面弹出日期选择对话框,等待用户选择完具体日期,再回到主界面展示选定日期的文本

2:如何编辑与删除账单项

因为账单明细位于列表视图当中,且列表视图允许同时设置列表项的点击监听器和长按监听器,所以可考虑将列表项的点击监听器映射到账单的编辑功能。

3:合并账单的添加与编辑功能

保存账单记录之时,也要先判断数据库中是否已经存在对应账单,如果有找到对应的账单记录,那么执行记录更新操作,否则执行记录添加操作。

 四、运行效果

选择时间页面框

 

查询账单页面框

翻页视图

 

 五、代码

java类代码

添加类代码

package com.example.chapter08;

import android.app.DatePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter08.bean.BillInfo;
import com.example.chapter08.database.BillDBHelper;
import com.example.chapter08.util.DateUtil;
import com.example.chapter08.util.ViewUtil;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class BillAddActivity extends AppCompatActivity implements
        RadioGroup.OnCheckedChangeListener, View.OnClickListener, DatePickerDialog.OnDateSetListener {
    private final static String TAG = "BillAddActivity";
    private TextView tv_date;
    private RadioButton rb_income;
    private RadioButton rb_expand;
    private EditText et_desc;
    private EditText et_amount;
    private int mBillType = 1; // 账单类型。0 收入;1 支出
    private int xuhao; // 如果序号有值,说明已存在该账单
    private Calendar calendar = Calendar.getInstance(); // 获取日历实例,里面包含了当前的年月日
    private BillDBHelper mBillHelper; // 声明一个账单数据库的帮助器对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bill_add);
        TextView tv_title = findViewById(R.id.tv_title);
        TextView tv_option = findViewById(R.id.tv_option);
        tv_date = findViewById(R.id.tv_date);
        RadioGroup rg_type = findViewById(R.id.rg_type);
        rb_income = findViewById(R.id.rb_income);
        rb_expand = findViewById(R.id.rb_expand);
        et_desc = findViewById(R.id.et_desc);
        et_amount = findViewById(R.id.et_amount);
        tv_title.setText("请填写账单");
        tv_option.setText("账单列表");
        findViewById(R.id.iv_back).setOnClickListener(this);
        tv_option.setOnClickListener(this);
        tv_date.setOnClickListener(this);
        findViewById(R.id.btn_save).setOnClickListener(this);
        rg_type.setOnCheckedChangeListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        xuhao = getIntent().getIntExtra("xuhao", -1);
        mBillHelper = BillDBHelper.getInstance(this); // 获取账单数据库的帮助器对象
        if (xuhao != -1) { // 序号有值,就展示数据库里的账单详情
            List<BillInfo> bill_list = (List<BillInfo>) mBillHelper.queryById(xuhao);
            if (bill_list.size() > 0) { // 已存在该账单
                BillInfo bill = bill_list.get(0); // 获取账单信息
                Date date = DateUtil.formatString(bill.date);
                Log.d(TAG, "bill.date="+bill.date);
                Log.d(TAG, "year="+date.getYear()+",month="+date.getMonth()+",day="+date.getDate());
                calendar.set(Calendar.YEAR, date.getYear()+1900);
                calendar.set(Calendar.MONTH, date.getMonth());
                calendar.set(Calendar.DAY_OF_MONTH, date.getDate());
                if (bill.type == 0) { // 收入
                    rb_income.setChecked(true);
                } else { // 支出
                    rb_expand.setChecked(true);
                }
                et_desc.setText(bill.desc); // 设置账单的描述文本
                et_amount.setText(""+bill.amount); // 设置账单的交易金额
            }
        }
        tv_date.setText(DateUtil.getDate(calendar)); // 设置账单的发生时间
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.iv_back) {
            finish(); // 关闭当前页面
        } else if (v.getId() == R.id.tv_option) {
            Intent intent = new Intent(this, BillPagerActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 设置启动标志
            startActivity(intent); // 跳到账单列表页面
        } else if (v.getId() == R.id.tv_date) {
            // 构建一个日期对话框,该对话框已经集成了日期选择器。
            // DatePickerDialog的第二个构造参数指定了日期监听器
            DatePickerDialog dialog = new DatePickerDialog(this, this,
                    calendar.get(Calendar.YEAR), // 年份
                    calendar.get(Calendar.MONTH), // 月份
                    calendar.get(Calendar.DAY_OF_MONTH)); // 日子
            dialog.show(); // 显示日期选择对话框
        } else if (v.getId() == R.id.btn_save) {
            saveBill(); // 保存账单
        }
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        mBillType = (checkedId==R.id.rb_expand) ? 1 : 0;
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
        tv_date.setText(DateUtil.getDate(calendar));
    }

    // 保存账单
    private void saveBill() {
        //ViewUtil.hideAllInputMethod(this); // 隐藏输入法软键盘
        ViewUtil.hideOneInputMethod(this, et_amount); // 隐藏输入法软键盘
        BillInfo bill = new BillInfo();
        bill.xuhao = xuhao;
        bill.date = tv_date.getText().toString();
        bill.month = 100*calendar.get(Calendar.YEAR) + (calendar.get(Calendar.MONTH)+1);
        bill.type = mBillType;
        bill.desc = et_desc.getText().toString();
        bill.amount = Double.parseDouble(et_amount.getText().toString());
        mBillHelper.save(bill); // 把账单信息保存到数据库
        Toast.makeText(this, "已添加账单", Toast.LENGTH_SHORT).show();
        resetPage(); // 重置页面
    }

    // 重置页面
    private void resetPage() {
        calendar = Calendar.getInstance();
        et_desc.setText("");
        et_amount.setText("");
        tv_date.setText(DateUtil.getDate(calendar));
    }
    
}

查看类代码

package com.example.chapter08;

import android.app.DatePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.widget.DatePicker;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerTabStrip;
import androidx.viewpager.widget.ViewPager;

import com.example.chapter08.adapter.BillPagerAdpater;
import com.example.chapter08.util.DateUtil;

import java.util.Calendar;

public class BillPagerActivity extends AppCompatActivity implements
        View.OnClickListener, DatePickerDialog.OnDateSetListener, ViewPager.OnPageChangeListener {
    private TextView tv_month;
    private ViewPager vp_bill; // 声明一个翻页视图对象
    private Calendar calendar = Calendar.getInstance(); // 获取日历实例,里面包含了当前的年月日

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bill_pager);
        TextView tv_title = findViewById(R.id.tv_title);
        TextView tv_option = findViewById(R.id.tv_option);
        tv_month = findViewById(R.id.tv_month);
        tv_title.setText("账单列表");
        tv_option.setText("添加账单");
        findViewById(R.id.iv_back).setOnClickListener(this);
        tv_option.setOnClickListener(this);
        tv_month.setOnClickListener(this);
        tv_month.setText(DateUtil.getMonth(calendar));
        // 从布局视图中获取名叫vp_bill的翻页视图
        vp_bill = findViewById(R.id.vp_bill);
        initViewPager(); // 初始化翻页视图
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.iv_back) {
            finish(); // 关闭当前页面
        } else if (v.getId() == R.id.tv_option) {
            Intent intent = new Intent(this, BillAddActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 设置启动标志
            startActivity(intent); // 跳到账单填写页面
        } else if (v.getId() == R.id.tv_month) {
            // 构建一个日期对话框,该对话框已经集成了日期选择器。
            // DatePickerDialog的第二个构造参数指定了日期监听器
            DatePickerDialog dialog = new DatePickerDialog(this, this,
                    calendar.get(Calendar.YEAR), // 年份
                    calendar.get(Calendar.MONTH), // 月份
                    calendar.get(Calendar.DAY_OF_MONTH)); // 日子
            dialog.show(); // 显示日期选择对话框
        }
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
        tv_month.setText(DateUtil.getMonth(calendar));
        vp_bill.setCurrentItem(month); // 设置翻页视图显示第几页
    }

    // 初始化翻页视图
    private void initViewPager() {
        // 从布局视图中获取名叫pts_bill的翻页标签栏
        PagerTabStrip pts_bill = findViewById(R.id.pts_bill);
        // 设置翻页标签栏的文本大小
        pts_bill.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);
        // 构建一个商品图片的翻页适配器
        BillPagerAdpater adapter = new BillPagerAdpater(getSupportFragmentManager(), calendar.get(Calendar.YEAR));
        vp_bill.setAdapter(adapter); // 设置翻页视图的适配器
        vp_bill.setCurrentItem(calendar.get(Calendar.MONTH)); // 设置翻页视图显示第几页
        vp_bill.addOnPageChangeListener(this); // 给翻页视图添加页面变更监听器
    }

    // 翻页状态改变时触发
    public void onPageScrollStateChanged(int state) {}

    // 在翻页过程中触发
    public void onPageScrolled(int position, float ratio, int offset) {}

    // 在翻页结束后触发
    public void onPageSelected(int position) {
        calendar.set(Calendar.MONTH, position);
        tv_month.setText(DateUtil.getMonth(calendar));
    }
}

适配器代码

package com.example.chapter08.adapter;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.example.chapter08.BillAddActivity;
import com.example.chapter08.R;
import com.example.chapter08.bean.BillInfo;
import com.example.chapter08.database.BillDBHelper;

import java.util.ArrayList;
import java.util.List;

public class BillListAdapter extends BaseAdapter implements AdapterView.OnItemClickListener,
        AdapterView.OnItemLongClickListener{
    private static final String TAG = "BillListAdapter";
    private Context mContext; // 声明一个上下文对象
    private List<BillInfo> mBillList = new ArrayList<BillInfo>(); // 账单信息列表

    public BillListAdapter(Context context, List<BillInfo> billList) {
        mContext = context;
        mBillList = billList;
    }

    @Override
    public int getCount() {
        return mBillList.size();
    }

    @Override
    public Object getItem(int position) {
        return mBillList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            // 根据布局文件item_bill.xml生成转换视图对象
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_bill, null);
            holder.tv_date = convertView.findViewById(R.id.tv_date);
            holder.tv_desc = convertView.findViewById(R.id.tv_desc);
            holder.tv_amount = convertView.findViewById(R.id.tv_amount);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        BillInfo bill = mBillList.get(position);
        holder.tv_date.setText(bill.date);
        holder.tv_desc.setText(bill.desc);
        if (bill.date.equals("合计")) {
            holder.tv_amount.setText(bill.remark);
        } else {
            holder.tv_amount.setText(String.format("%s%d元", bill.type==0?"收入":"支出", (int) bill.amount));
        }
        return convertView;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (position >= mBillList.size()-1) { // 合计行不响应点击事件
            return;
        }
        Log.d(TAG, "onItemClick position=" + position);
        BillInfo bill = mBillList.get(position);
        // 以下跳转到账单填写页面
        Intent intent = new Intent(mContext, BillAddActivity.class);
        intent.putExtra("xuhao", bill.xuhao); // 携带账单序号,表示已存在该账单
        mContext.startActivity(intent); // 因为已存在该账单,所以跳过去实际会编辑账单
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
        if (position >= mBillList.size()-1) { // 合计行不响应长按事件
            return true;
        }
        Log.d(TAG, "onItemLongClick position=" + position);
        BillInfo bill = mBillList.get(position); // 获得当前位置的账单信息
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        String desc = String.format("是否删除以下账单?\n%s %s%d %s", bill.date,
                bill.type==0?"收入":"支出", (int) bill.amount, bill.desc);
        builder.setMessage(desc); // 设置提醒对话框的消息文本
        builder.setPositiveButton("是", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                deleteBill(position); // 删除该账单
            }
        });
        builder.setNegativeButton("否", null);
        builder.create().show(); // 显示提醒对话框
        return true;
    }

    // 删除该账单
    private void deleteBill(int position) {
        BillInfo bill = mBillList.get(position);
        mBillList.remove(position);
        notifyDataSetChanged(); // 通知适配器发生了数据变化
        // 获得数据库帮助器的实例
        BillDBHelper helper = BillDBHelper.getInstance(mContext);
        helper.delete(bill.xuhao); // 从数据库删除指定序号的账单
    }

    public final class ViewHolder {
        public TextView tv_date;
        public TextView tv_desc;
        public TextView tv_amount;
    }

}

XML文件

添加

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/title_booking" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="5dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center|right"
            android:text="账单日期:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <TextView
            android:id="@+id/tv_date"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:drawableRight="@drawable/arrow_down"
            android:gravity="center"
            android:textColor="@color/black"
            android:textSize="17sp" />
    </LinearLayout>

    <RadioGroup
        android:id="@+id/rg_type"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_margin="5dp"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center|right"
            android:text="账单类型:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <RadioButton
            android:id="@+id/rb_income"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="left|center"
            android:checked="false"
            android:text="收入"
            android:textColor="#000000"
            android:textSize="17sp" />

        <RadioButton
            android:id="@+id/rb_expand"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="left|center"
            android:checked="true"
            android:text="支出"
            android:textColor="#000000"
            android:textSize="17sp" />
    </RadioGroup>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_margin="5dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center|right"
            android:text="事项说明:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <EditText
            android:id="@+id/et_desc"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:gravity="left|top"
            android:background="@drawable/editext_selector"
            android:textColor="@color/black"
            android:textSize="17sp"
            android:hint="请填写说明内容" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="5dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center|right"
            android:text="  金额:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <EditText
            android:id="@+id/et_amount"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:background="@drawable/editext_selector"
            android:inputType="number"
            android:textColor="@color/black"
            android:textSize="17sp"
            android:hint="单位(元)" />
    </LinearLayout>

    <Button
        android:id="@+id/btn_save"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="保  存"
        android:textColor="@color/black"
        android:textSize="20sp" />

</LinearLayout>

查看

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/title_booking" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:gravity="center|top"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:gravity="center|right"
                android:text="请选择月份:"
                android:textColor="@color/black"
                android:textSize="17sp" />

            <TextView
                android:id="@+id/tv_month"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="2"
                android:drawableRight="@drawable/arrow_down"
                android:gravity="center"
                android:textColor="@color/black"
                android:textSize="17sp" />
        </LinearLayout>

        <androidx.viewpager.widget.ViewPager
            android:id="@+id/vp_bill"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.viewpager.widget.PagerTabStrip
                android:id="@+id/pts_bill"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </androidx.viewpager.widget.ViewPager>
    </LinearLayout>

</LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

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

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

相关文章

C++ 输入输出及txt文件输入示例

std::istream typedef basic_istream<char> istream;输入流对象可以读取和解释来自字符序列的输入。 提供了特定的成员来执行这些输入操作&#xff08;参见下面的函数&#xff09;。 标准对象 cin 就是这种类型的对象。 std::istream::getline istream& getline (…

Web3 用例全解析:传统品牌加速进入 Web3 的原因?

Web3 有能力彻底改变品牌和客户相互联系的方式。许多品牌已经在尝试使用 NFT 和元宇宙来提高品牌知名度和消费者忠诚度&#xff0c;这是传统社交媒体和电子商务渠道根本无法做到的。 NIKE、Panini 和 Vodafone 是最早认识到 NFT 价值的公司&#xff0c;而 Gucci、Balmain、Prad…

C语言百日刷题第七天

C语言百日刷题第七天61. 写一个函数isPowerOfTwo判断是不是2的幂次方62. 写一个函数isPowerOfThree判断是不是3的幂次方63.n 的第 k 个因子64.有效的完全平方数65.搜索旋转排序数组66.桌上拿硬币67.计算生成元68.计算分子量69.最佳情侣身高差70.拯救外星人61. 写一个函数isPowe…

计算机毕业设计springboot+vue+elementUI校园疫情防控系统

项目介绍 基本实现了校园疫情防控系统应有的主要功能模块&#xff0c;本系统有管理员、学生。管理员&#xff1a;首页、个人中心、核酸检测管理、体温状态管理、学生管理、学生状态管理、休假申请管理、出入登记管理、疫情知识管理、论坛管理、系统管理。学生权限&#xff1b;…

矩阵分析与计算学习记录-广义逆矩阵

本章重点内容&#xff1a; Penrose方程 {1}-逆的计算及性质 Moore-Penrose逆的计算及性质 tips&#xff1a;广义逆矩阵是在系数矩阵不可逆的情况下进行求解 1. Penrose方程 1.1 广义逆的定义与计算 1.2 Penrose方程基本概念 2. {1}-逆的计算及性质 2.1 {1}-逆的计算 2.2 …

大白话之 Iptables

背景 今天在安装traefik的时候遇见了很神奇的问题&#xff0c;80端口没有任何程序在监听&#xff0c;但是访问的话会返回it works&#xff0c;想来想去可能是iptables的问题&#xff0c;由于Iptables每次都是现查&#xff0c;所以觉得还是理解不到位&#xff0c;总结一波。 表…

远距离WiFi无线传输方案,CV5200模组通信应用,无线自组网技术

无线自组网是一种特殊的无线通信技术&#xff0c;无需依赖任何预先架设的网络设施就可以快速自动组网&#xff0c;并具有很强的抗毁性和灵活性。 特别适用于远距离&#xff0c;高速率的场合&#xff0c;比如无人机&#xff0c;安防监控&#xff0c;智慧建筑&#xff0c;智慧农…

分布式事务Seata源码解析13:TCC事务模式实现原理

文章目录一、前言二、GlobalTransactionScanner1、判断某一个Bean是否需要做TCC动态代理1> 判断bean实现的接口中是否有接口标注了LocalTCC注解2> 当Bean的某一个接口实现了LocalTCC注解之后&#xff0c;解析相应接口中的TCC内容&#xff1a;TCCResource数据样例3> TC…

mysql是怎么运行的-笔记

文章目录启动**MySQL**服务器程序 **1.3.1 UNIX**里启动服务器程序**Windows**里启动服务器程序服务器处理客户端请求常用存储引擎一些重要的字符集**MySQL**中的**utf8**和**utf8mb4**比较规则的查看MySQL有四个级别的字符集和比较规则**InnoDB**记录结构compact 行格式变长字…

【黄啊码】PHP压缩图片(简洁易懂版,不懂我下次不写)

大家好&#xff0c;我是黄啊码&#xff0c;今天我们来解决一件头疼的事情。作为技术人员&#xff0c;我们一般传图片都知道尽量传清晰和大小适中的图片&#xff0c;部署的时候当然也希望客户能按说明办事&#xff0c;但有的客户偏偏不听&#xff0c;就传大的&#xff0c;就传大…

Python标准库glob模块详解

glob是python中的内置模块&#xff0c;该模块主要是用来查找文件与目录的。glob模块是按照 Unix shell 所使用的规则找出所有匹配特定模式的路径名称。我们只需要了解该模块的匹配规则与常用函数&#xff0c;就会使文件查找&#xff0c;路径匹配变得非常快捷简单。 1.匹配规则…

【springboot整合ES】springboot整合ES

springboot整合ES 在Springboot整合ES提供了启动依赖jar。 该jar包封了一个类: RestHighLevelClient 该类可以对象ES中各个接口进行相应的操作。 1. 新建项目 创建springboot工程并导入相关的依赖 2.3.12.RELEASE。最新版spring boot2.7.5中RestHighLevelClient已过时 2. 创建…

python_爬虫

定时、定量、制定目标的数据搜集程序。 技术库 网络请求 urllibrequests&#xff08;三方&#xff09;/ urllib3selenium&#xff08;UI自动测试、动态js渲染&#xff09;appium&#xff08;手机App的爬虫或UI测试&#xff09; urllib requests 基于urllib和urllib3封装的…

什么是“孤岛效应”? ----防孤岛保护装置

防孤岛保护是对分布式光伏电站有着重要保护作用的。即当电网出现电压高、电压低、频率高、频率低故障时&#xff0c;光伏并网开关及时跳闸。当电网恢复供电并且电压和频率达到允许值时&#xff0c;并网开关要自动合闸。这样的目的是在为了国家电网不受太大影响的情况下&#xf…

理解透C语言一维数组,二维数组这一篇就够啦!

前言 &#x1f496;作者&#xff1a;龟龟不断向前 ✨简介&#xff1a;宁愿做一只不停跑的慢乌龟&#xff0c;也不想当一只三分钟热度的兔子。 &#x1f47b;专栏&#xff1a;C初阶知识点 &#x1f47b;工具分享&#xff1a; 刷题&#xff1a; 牛客网 leetcode笔记软件&#xff…

网站部署:使用Nginx部署vue项目到阿里云服务器

最近租了个阿里云的服务器&#xff0c;想使用Nginx把刚做好的网站部署上去 下载Nginx 目前yum已经有了Nginx的源&#xff0c;因此可以直接用yum下载和安装 yum -y install nginx默认的安装位置为/etc/nginx 默认的项目位置为/usr/share/nginx 如果安装失败检查是否安装了zli…

渗透测试-CTF文件类型操作

识别文件类型 文件分离 文件合并 识别文件类型 当文件没有后缀名或者有后缀名无法正常打开时&#xff0c;根据识别的文件类型来修改后缀名即可正常打开文件。 使用场景&#xff1a;不知道后缀名&#xff0c;无法打开文件。 第一种方式&#xff1a;kali中使用 file 文件名 f…

173:vue+openlayers:解决国内openstreetmap地图加载不出来的问题(代码示例)

第173个 点击查看专栏目录 近来写程序,发现openlayers用OSM方式来加载OpenStreetMap地图,一片爆红,瓦片加载不出来。 本示例的目的是介绍演示如何在vue+openlayers中解决OpenStreetMap地图在国内被DNS污染,加载不出来瓦片的问题,通常我们是直接引用OSM,这里采用的是XYZ方…

2022年11月第十四届蓝桥杯校模拟赛详解+代码(一)

“须知少时凌云志&#xff0c;自许人间第一流” 鄙人11月八号有幸参加学校蓝桥杯校选拔赛&#xff0c;题型为5道填空题&#xff0c;5道编程题&#xff0c;总时间为小时。奈何能力有限&#xff0c;只完成了5道填空和3道编程大题&#xff0c;现进行自省自纠&#xff0c;分享学习&…

国产ETL工具 BeeDI 产品“实时同步“之 高阶 功能组件

BeeDI 提供“ 实时”企业数据集成。实时组件通过实时处理和传输业务数据的能力&#xff0c;增强了BeeDI的批处理功能。为满足当下复杂的业务需求&#xff0c;IT部门需要实时集成以加快核心业务流程和信息流。使用实时功能&#xff0c;IT部门可以使用统一界面&#xff0c;从BeeD…