当前位置: 首页 > news >正文

React(六):Redux的使用、react-redux简化代码、redux模块化、RTK的使用

React(六)

  • 一、Redux测试项目搭建
    • 1.创建store仓库
    • 2.创建reducer函数(纯函数)
    • 3.constants.js保存action名字
    • 4.修改store中的数据
    • 5.动态生成action
  • 二、React中如何使用redux
    • 1.安装redux
    • 2.创建store
    • 3.组件中订阅store
    • 4.派发action修改store数据
  • 三、第三方库react-redux简化代码
    • 1.省掉手动订阅的步骤
    • 2.同步派发action
    • 3.redux如何进行异步操作
      • (1)在组件中派发异步action
      • (2)在actionCreators中派发异步action
    • 4.redux的devtools怎么打开
  • 四、redux模块化
  • 五、Redux ToolKit的使用
    • 1.三个核心的API
    • 2.用更简洁的代码创建store
      • (1)configureStore创建大仓库store
      • (2)createSlice创建小仓库
      • (3)将小仓库添加到大仓库中
    • 3.组件中使用和修改仓库的数据
    • 4.RTK的异步请求写在哪里

一、Redux测试项目搭建

新建一个文件夹Redux,里面建个src文件夹。先看一下最终的项目结构:

在这里插入图片描述

src目录下开启终端执行:

npm init
npm add redux 

src目录下启动:

node 文件名

我们一点一点来看这个redux的使用过程:

1.创建store仓库

由于我们是node,所以导包用的不是import(这里没学过node,先不管,反正是import那个意思)

index.js中:

const { createStore } = require('redux');
const {reducer} = require('./reducer');// 创建的store
const store = createStore(reducer);module.exports = store;

其中第一行是导入这个创建store的函数,然后reducer我们在另一个文件中引入:

2.创建reducer函数(纯函数)

纯函数就是在这个函数中不能对传进来的参数内部的东西(属性)进行修改。

第一行是引入的action名字,先不管。

1、第一步是定义一个初始化数据。
2、第二步是创建reducer函数,该函数有两个参数,第一个state是目前保存的旧state数据,第二个参数action是别的地方dispatch传过来的需要更新的数据
3、render函数里面主要是找到对应的action,然后修改数据并返回一个新的浅拷贝的state对象。
4、如果没有对应的aciton的话,就返回默认的初始state

const {CHANGENAME, CHANGEAGE} = require('./constants');//初始化数据
const initialState = {name: 'zzy',age: 18
}//定义reducer函数:纯函数
//参数1:store目前保存state
//参数2:本次需要更新的action(dispatch传过来的)
//返回值:作为store之后存储的state
function reducer(state = initialState, action) {// console.log('reducer', state, action)// reducer { name: 'zzy', age: 18 } { type: 'changeName', name: 'ht' }//1.第一种,if-else// if (action.type === 'changeName') {//     return { ...state, name: action.name };// }// if(action.type === 'changeAge') {//     let newState = {...state};//     newState.age = action.age;//     return newState;// }// return state;//2.第二种,switch-caseswitch(action.type) {case CHANGENAME:return { ...state, name: action.name };case CHANGEAGE:let newState = {...state};newState.age = action.age;return newState;default: return state}
}module.exports = {reducer};

这里呢有个没见过的写法,先学习一下:

const obj = {name: 'zzy', age: 18};
const copy = {...obj, name:'ht'};
console.log(copy);//{name: 'ht', age: 18}

上面的代码中,是浅拷贝一个obj,并把里面的name替换成ht
其实本质上是:

const obj = {name: 'zzy', age: 18};
const copy = {...obj};
copy.name = 'ht'
console.log(copy);//{name: 'ht', age: 18}

最后我们再来看第一行是什么,其实这里的action的名字,只不过我们把名字单独写到另一个js文件引入进来,避免一些名字写错的问题。

3.constants.js保存action名字

这里的名字是为了action自己写名字的时候不小心写错,需要在两个地方引用这个变量:
1、reducer函数中
2、dipatch的地方()

const CHANGENAME = 'changeName';
const CHANGEAGE = 'changeAge';
module.exports = {CHANGENAME,CHANGEAGE
}

4.修改store中的数据

上面这些搞定了,接下来我们来看看如何修改store中的数据:

某个js文件:
const store = require('./store');
console.log(store.getState());
//修改store中的数据
store.dispatch({type: 'changeName', name: 'ht'});
console.log(store.getState());
store.dispatch({type: 'changeAge', age: 30});
console.log(store.getState());

把store引入进来,然后dispatch,传入一个对象,该对象有两个属性,type是固定的,值是action的名字;name是要修改的属性值。通过store.getState()可以读取当前仓库state的值。

但是这样的话你会发现每次改都要手动输出修改的值,这样很麻烦,所以我们可以通过store.subscribe订阅数据的改变,这样的话store中数据一旦改变,就会执行回调,该回调中通过store.getState()读取的是改变后的新值。

const store = require('./store');//订阅数据的改变
const unsubscribe = store.subscribe(() => {console.log('数据变化了,变成了:', store.getState());
})//修改store中的数据:必须action
store.dispatch({ type: 'changeName', name: 'ht' });
//一般在销毁钩子中取消订阅
unsubscribe();
store.dispatch({ type: 'changeAge', age: 30 });

当然啊,如果在框架中用的话,最好在销毁钩子中取消订阅,方法就是调用这个玩意儿。

5.动态生成action

如果有多个dispatch:

store.dispatch({ type: CHANGENAME, name: 'ht' });
store.dispatch({ type: CHANGEAGE, age: 30 });
store.dispatch({ type: CHANGEAGE, age: 40 });
store.dispatch({ type: CHANGEAGE, age: 50 });
store.dispatch({ type: CHANGEAGE, age: 60 });
store.dispatch({ type: CHANGEAGE, age: 70 });

那么每次dispatch都要传一个对象,然后写触发哪个action,要改什么,这真的是非常麻烦,所以最后一个关键文件就是:actionCreators.js用来封装每个dispatch的值:

在这里插入图片描述

二、React中如何使用redux

在这里插入图片描述

1.安装redux

在目录下创建一个脚手架

create-react-app 项目名

安装redux,在脚手架目录下:

npm install redux  或  npm add redux

2.创建store

创建store文件夹,里面先来两个文件:index.jsreducer.js

index.js
import {createStore} from 'redux';
import reducer from './reducer';let store = createStore(reducer);export default store;
reducer.js
let initialState = {counter: 1
}
function reducer(state = initialState, action) {switch(action.type) {default:return state;}
}export default reducer;

再创建两个空文件constants.jsactionCreators.js备用

3.组件中订阅store

1、组件中我们如果想要去用store中的数据,可以在state中直接通过store.getState().属性名去读取一个初始值。但是如果store数据改变,这里不会跟着变。

2、如果想要store数据改变时组件能跟着变,那么我们需要在componentDidMount钩子中去订阅store,每次数据改变,就会执行回调,回调中我们调用setState重新读取store,组件就能够实现和store数据的同步。

import React, { PureComponent } from 'react';
import store from './store';
export class App extends PureComponent {constructor() {super();this.state = {counter: store.getState().counter}}componentDidMount() {//订阅storestore.subscribe(() => {// console.log(store.getState());this.setState({counter: store.getState().counter})})}render() {let { counter } = this.state;return (<div><h2>{counter}</h2></div>)}
}export default App;

4.派发action修改store数据

比如我们定义一个按钮用来控制store中的counter+1,那么:
1、回到第一步的空文件constants.js中,我们来用变量存储action的名字

export const CHANGECOUNTER = 'changeCounter';

2、回到空文件actionCreators.js中,我们定义函数来格式化action对象

import {CHANGECOUNTER} from './constants'
export const change = (num) => {return {type: CHANGECOUNTER,num: num}
}

3、再回到组件中:
当我们点击的时候就派发action,action对象由上面定义好的函数来生成。

import React, { PureComponent } from 'react';
import store from './store';
import {change} from './store/actionCreators'
export class App extends PureComponent {constructor() {super();this.state = {counter: store.getState().counter}}componentDidMount() {//订阅storestore.subscribe(() => {// console.log(store.getState());this.setState({counter: store.getState().counter})})}change(num) {store.dispatch(change(num));}render() {let { counter } = this.state;return (<div><h1>App</h1><h2>{counter}</h2><button onClick={() => this.change(1)}>点击+1</button><Son /></div>)}
}export default App;

使用流程大概就是这样。

三、第三方库react-redux简化代码

这个库是专门用于简化在react中使用redux的。
安装:

npm install react-redux

1.省掉手动订阅的步骤

这里是react-redux的使用步骤

在src的index.js中引入Provider,包裹App组件并传入我们定义好的store,这样的话后代组件就可以访问store

在这里插入图片描述
定义一个子组件Son,引入connect函数,该函数返回一个高阶组件,高阶组件本身是一个函数,调用该函数可以给Son注入东西。connect的参数是一个回调mapStateToProps ,顾名思义就是把store中的state通过高阶组件注入到Son的props中,具体代码如下:

import React, { PureComponent } from 'react';
import store from '../store';
import {connect} from 'react-redux';export class Son extends PureComponent {render() {let { Soncounter } = this.props;return (<div><h1>Son</h1><h2>{Soncounter}</h2></div>)}
}//调用connect返回一个高阶组件(函数)
//高阶组件中传入我们要注入store的组件
const mapStateToProps = (state) => {//返回一个对象,这样可以读到store中state的数据,并把这个数据// 通过connect()返回的高阶组件注入到Son的props中return {//注入给Son的props.SoncounterSoncounter: state.counter  }
}
export default connect(mapStateToProps)(Son);

2.同步派发action

connect的第二个参数也是一个函数mapDispatchToProps,参数是一个dispatch函数。

mapDispatchToProps可以向组件中注入一些函数,这些函数是用来派发action的。

组件可以通过props接收函数并调用传参,把要修改的值传过去,然后通知仓库修改数据。

在这里插入图片描述

3.redux如何进行异步操作

先安装axios

npm install axios

(1)在组件中派发异步action

如果我们要在组件中异步请求数据,然后把数据保存到store中,按照react-redux库的步骤来说是这样的:

1、constants.js中定义action的名字:

在这里插入图片描述
2、actionCreators.js中定义创建action对象的函数:
在这里插入图片描述
3、reducer.js中定义接收数据后对应的更改操作

在这里插入图片描述
4、去组件中的componentDidMount中发送网络请求并通知store更新数据。

在这里插入图片描述

(2)在actionCreators中派发异步action

如果发送请求的组件根本不用这个数据呢?发请求只是为了把数据存到store中,那这样写在挂载钩子里就不太好。所以我们可以把异步的过程放到redux中去处理。

这里我们用到一个中间件redux-thunk:

npm install redux-thunk

这个中间件可以让dispatch的参数是一个函数的调用,那么我们可以在这个函数里进行异步操作,得到结果后就再执行dispatch传入action对象

使用步骤:
1、在store/index.js中传入createStore的第二个参数,意思是使用中间件,参数传我们刚才安装的thunk。这样的话dispatch就可以派发一个函数了。

在这里插入图片描述
2、在actionCreators.js中把之前的函数返回值从一个action对象换成一个函数,在函数中请求到数据后再次dispatch一个action对象:{type: xxx, newsList: red.data}

在这里插入图片描述
3、回到组件中,直接把dispatch改成一个函数的调用

在这里插入图片描述
ok,异步请求数据就是这么搞的。

4.redux的devtools怎么打开

安装直接去浏览器插件库里一搜就有。

在开发环境下如果想要打开,需要在store/index.js中:

在这里插入图片描述

import {createStore, applyMiddleware, compose} from 'redux';
import reducer from './reducer';
import thunk from 'redux-thunk';const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;let store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)));export default store;

当然这是由中间件thunk的情况下,其他情况请见github:
https://github.com/zalmoxisus/redux-devtools-extension

四、redux模块化

类似vuex中的namespace,不过比那个麻烦一些。

在这里插入图片描述

👇👇👇👇👇👇

在这里插入图片描述

除了把每部分的数据拆开,每个小仓库的index.js只需要把reducer函数导出

import reducer from './reducer';
export default reducer;

然后在大仓库中,通过combineReducers把小仓库的reducer合并成一个大reducer并给每个小仓库起个名字。

在这里插入图片描述

其他需要注意的就是路径的问题了。还有就是读取仓库数据的时候,需要加上小仓库的名字:

在这里插入图片描述

五、Redux ToolKit的使用

Redux ToolKit 中文官方文档

安装:npm install @reduxjs/toolkit

如果没安react-redux也要带着一起安装:npm install react-redux @reduxjs/toolkit

1.三个核心的API

configureStore: 包装旧的createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供的任何 Redux 中间件,redux-thunk默认包含(这个东西就是让dispatch可以是一个函数的调用的中间件),并启用 Redux DevTools Extension(通过某个地方写api可以直接设置devtool是否启用,不用我们再window.xxxxx了)。

createSlice: 接受reducer函数的对象、切片名称初始状态值,并自动生成切片reducer,并带有相应的actions

createAsyncThunk: 接受一个动作类型字符串和一个可以写异步的函数,并生成一个包含pending/fulfilled/rejected的对象,我们可以通过某种方式监听状态的改变。

2.用更简洁的代码创建store

(1)configureStore创建大仓库store

store/index.js中,我们先创建一个store

import {configureStore} from '@reduxjs/toolkit';const store = configureStore({reducer: {待填写......},devTools: true, //默认就是true
})export default store;

传入的配置对象中,有如下三个常见的参数:

  • reducer:将slice中的reducer可以组成一个对象传入此处;

  • middleware:可以使用参数,传入其他的中间件(自行了解);

  • devTools:是否配置devTools工具,默认为true;

(2)createSlice创建小仓库

一般我们会在store/modules里创建小仓库:

在这里插入图片描述

比如login.js

import {createSlice} from '@reduxjs/toolkit';const loginSlice = createSlice({name:'login',initialState: {counter: 99},//相当于reducer函数reducers: {//相当于每个caseaddNumber(state, action) {//这里可以直接改不用浅拷贝,默认给你拷贝好了state.counter = action.payload;}}
})
//reducers里的方法会自动放在counterSlice的actions属性中,用于派发action
export const { addNumber } = loginSlice.actions;
//注意导出的是reducer,用于在index.js中对reducer进行组合
export default loginSlice.reducer

createSlice的配置对象中,一般有如下几个配置项:

  • name:用户标记slice的名词,在之后的redux-devtool中会显示对应的名词;

  • initialState:初始化值,第一次初始化数据时的值;

  • reducers:相当于之前的reducer函数,是对象类型,对象中可以添加很多的函数;
    函数类似于redux原来reducer中的一个case语句,该函数的参数如下:

参数一: state, 当前的state状态
参数二: 传递的actions参数, actions有两个属性,一个是自动生成的type, 另一个是传递的参数放在payload中;

createSlice返回值是一个对象,包含所有的actions,通常我们会把每个action暴露出去;

(3)将小仓库添加到大仓库中

回到index.js,把创建的loginreducer函数导出来,添加到大仓库中

import {configureStore} from '@reduxjs/toolkit';
//导入reducer
import loginReducer from './modules/login';const store = configureStore({reducer: {login: loginReducer,},devTools: true, //默认就是true
})export default store;

这样的话, redux就搭建完成了,接下来我们去组件里使用

3.组件中使用和修改仓库的数据

这里要用到react-redux这个库,前边已经安装过了,需要配置的地方和之前差不多:
点击查看如何建立redux和react的连接

这样我们来到logIn.jsx组件中,就可以去使用仓库中的counter

在这里插入图片描述
使用方式还是没什么太大区别的嗷。修改的话也是一样,看上面那个图,其实也是通过connectdispatch的方法注入props,然后调用派发action

这个React ToolKit在这里简化了哪些东西呢?我感觉是简化了我们自己生成action对象的操作,还有用变量存储type名字的操作,以前我们需要很繁琐的操作(先生成action对象再派发)。

但是现在!我们派发可以直达小仓库的这个函数(可以直接导入进来)

import {createSlice} from '@reduxjs/toolkit';const loginSlice = createSlice({name:'login',initialState: {counter: 99},//相当于reducer函数reducers: {//相当于每个caseaddNumber(state, action) {console.log(action);//{type: 'login/addNumber', payload: 1}//这里可以直接改不用浅拷贝,默认给你拷贝好了state.counter = action.payload;}}
})
//reducers里的方法会自动放在counterSlice的actions属性中,用于派发action
export const { addNumber } = loginSlice.actions;
//注意导出的是reducer,用于在index.js中对reducer进行组合
export default loginSlice.reducer
import { addNumber } from '../store/modules/login';

而且输出aciton会发现type是自动生成了个东西login/addNumber,不用再担心自己会写错名字了。传过来的数值1存到payload中。

最关键的!我们可以直接通过state参数去修改仓库数据,不用再向之前一样先浅拷贝再修改了(底层做了处理),确实方便了许多。

4.RTK的异步请求写在哪里

可以像以前一样,写在挂载钩子中,写法一样,但是还是那个意思,组件里发请求不太好。所以RTK给我们封装的话我们异步在redux中如何写?

像上面一样,创建另一个小仓库home

这里就要用到第三个API:createAsyncThunk,调用它返回一个函数,我们把函数暴露出去,在组件中引入并在dispatch中传入该函数的调用,即可回来执行函数的第二个参数(发请求的回调)

import {createSlice, createAsyncThunk} from '@reduxjs/toolkit';
import axios from 'axios';//异步操作的处理
export const reqNewsList = createAsyncThunk('reqData', async () => {const result = await axios.get('https://ku.qingnian8.com/dataApi/news/newslist.php')return result.data;
})const homeSlice = createSlice({name: 'home',initialState: {newsList: ['无数据'],},reducers: {getNewsList(state, {payload}) {console.log(payload);state.newsList = payload;}},//监听异步的状态变化extraReducers: {[reqNewsList.pending](state, {payload}) {console.log('异步处于pending状态');},[reqNewsList.fulfilled](state, {payload}) {console.log(payload);state.newsList = payload;},[reqNewsList.rejected](state, {payload}) {console.log('异步处于rejected状态,有错误!');},}
})export const {getNewsList} = homeSlice.actions;
export default homeSlice.reducer;

异步请求到数据后,把数据返回出来,我们通过createSlice配置对象中另一个配置项extraReducers可以监听异步请求的变化:

  • 如果请求中就调用pending
  • 请求到了就调用fulfilled并把返回值用payload接收,我们就可以拿到异步请求的数据了;
  • 如果有错误,就会执行rejected的回调。

组件:

在这里插入图片描述

搞定

相关文章:

React(六):Redux的使用、react-redux简化代码、redux模块化、RTK的使用

React&#xff08;六&#xff09;一、Redux测试项目搭建1.创建store仓库2.创建reducer函数&#xff08;纯函数&#xff09;3.constants.js保存action名字4.修改store中的数据5.动态生成action二、React中如何使用redux1.安装redux2.创建store3.组件中订阅store4.派发action修改…...

静态库和动态库的打包与使用

静态库和动态库 静态库和动态库的打包 生成可执行程序时链接使用 运行可执行程序时加载使用 提前声明&#xff0c;笔者示例的文件有mian.c/child.c/child.h。OK&#xff0c;我们先了解一下&#xff0c;库文件是什么&#xff1f;它其实就是打包了一堆实现常用功能的代码文件. ⭐…...

h264编码之SPS解析

一、概念 SPS即Sequence Paramater Set&#xff0c;又称作序列参数集。SPS中保存了一组编码视频序列(Coded video sequence)的全局参数。 二、定义 H.264标准协议中规定的SPS格式位于文档的7.3.2.1.1&#xff0c;如下图所示&#xff1a; 1、profile_idc 根据《T-REC-H.264-2…...

使用R语言包clusterProfiler做KEGG富集分析时出现的错误及解决方法

使用enrichKEGG做通路富集分析时&#xff0c;一直报错&#xff1a;显示No gene can be mapped....k <- enrichKEGG(gene gene, organism "hsa", pvalueCutoff 1, qvalueCutoff 1)但是之前用同样的基因做分析是能够成功地富集到通路&#xff0c;即便是网上的数据…...

框架——MyBatis的入门案例

框架概述1.1什么是框架框架&#xff08;Framework&#xff09;是整个或部分系统的可重用设计&#xff0c;表现为一组抽象构件及构件实例间交与的方法&#xff1b;另一种定义认为&#xff0c;框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义…...

hadoop兼容性验证

前言 Hadoop是一个由Apache基金会所开发的分布式系统基础架构&#xff0c;主要解决海量数据的存储和海量数据的分析计算问题&#xff0c;广义上来说&#xff0c;Hadoop通常是指一个更广泛的概念–hadoop生态圈 Hadoop优缺点&#xff1a; 优点&#xff1a; 1、高可靠性&#x…...

运维提质增效,有哪些办法可以做

凡是代码&#xff0c;难免有 bug。 开发者们的日常&#xff0c;除了用一行行代码搭产品外&#xff0c;便是找出代码里的虫&#xff0c;俗称 debug。 随着移动互联网的快速发展&#xff0c;App 已经成为日常生活中不可或缺的一部分。但是在开发者/运维人员的眼里简直就是痛苦的…...

c++基础——结构体

结构体结构体&#xff08;struct&#xff09;&#xff0c;可以看做是一系列称为成员元素的组合体。可以看做是自定义的数据类型。定义结构体struct abc {int x;int y; } e[array_length];const abc a; abc b, B[array_length], tmp; abc *c;上例中定义了一个名为 abc 的结构体&…...

applicationContext相关加载

spring refresh 概述 refresh是一个方法&#xff0c;spring中所有的ApplicationContext容器都需要通过refresh方法初始化&#xff1b; 处理步骤 其中refresh方法包含12个主要的处理步骤&#xff1a; 1、第1个步骤做前置准备 2、第2~6步骤创建BeanFactory&#xff08;Appl…...

数据同步工具Sqoop

大数据Hadoop之——数据同步工具SqoopSqoop基本原理及常用方法 1 概述 Apache Sqoop&#xff08;SQL-to-Hadoop&#xff09;项目旨在协助RDBMS&#xff08;Relational Database Management System&#xff1a;关系型数据库管理系统&#xff09;与Hadoop之间进行高效的大数据交…...

Kafka 版本

kafka-2.11-2.1.1 : Kafka 1.0.0 后&#xff0c;Kafka 版本命名规则从 4 位到 3 位Kafka版本号是 2.1.1前 2 : 大版本号 (MajorVersion)中 1 : 小版本号或次版本号 (Minor Version)后 1 : 修订版本号 (Patch) Kafka 0.7 最早开源版本 &#xff1a; 只提供最基础的消息队列功…...

ElasticSearch 在Java中的各种实现

ES JavaAPI的相关体系&#xff1a; 词条查询 所谓词条查询&#xff0c;也就是ES不会对查询条件进行分词处理&#xff0c;只有当词条和查询字符串完全匹配时&#xff0c;才会被查询到。 等值查询-term 等值查询&#xff0c;即筛选出一个字段等于特定值的所有记录。 【SQL】 s…...

SpringBoot整合Knife4j

文章目录前言一、Knife4j是什么&#xff1f;二、使用步骤1.导入依赖2.编写配置文件3.编写controller和实体类4.测试总结前言 接上篇整合Swagger链接奉上http://t.csdn.cn/9mXSu 一、Knife4j是什么&#xff1f; 官方文档&#xff1a;https://doc.xiaominfo.com/ knife4j可以理解…...

MyISAM和InnoDB存储引擎的区别

目录前言存储引擎区别事务外键表单的存储数据查询效率数据更新效率如何选择前言 MyISAM和InnoDB是使用MySQL最常用的两种存储引擎&#xff0c;在5.5版本之前默认采用MyISAM存储引擎&#xff0c;从5.5开始采用InnoDB存储引擎。 存储引擎 存储引擎是&#xff1a;数据库管理系统…...

SpringMVC自定义处理多种日期格式的格式转换器

package cn.itcast.utils;import org.springframework.core.convert.converter.Converter;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;/*** 把字符串转换日期*/public class StringToDateConverter implements Converter<String…...

NYUv2生成边界GT(1)

看了cityscape和NYUv2生成边界GT的代码后&#xff0c;因为自己使用的是NYUv2数据集&#xff0c;所以需要对自己的数据集进行处理。CASENet生成边界GT所使用的代码是MATLAB&#xff0c;所以又重新看了一下MATLAB的代码&#xff0c;并进行修改&#xff0c;生成了自己的边界代码。…...

Spring基本概念与使用

文章目录一、Spring概念1.容器2.IoC3.DI4.Ioc与DI的关系二、Spring创建与使用1.Maven2.添加Spring框架支持注&#xff1a;国内的Maven源配置3.简单实例&#xff08;1&#xff09;创建一个Bean对象。&#xff08;2&#xff09;将Bean对象存储到Spring当中&#xff08;3&#xff…...

安恒信息java实习面经

目录1.Java ME、EE、SE的区别&#xff0c;Java EE相对于SE多了哪些东西&#xff1f;2.jdk与jre的区别3.说一下java的一些命令&#xff0c;怎么运行一个jar包4.简单说一下java数据类型及使用场景5.Map跟Collection有几种实现&#xff1f;6.面向对象的特性7.重载和重写的区别8.重…...

第八章:枚举类与注解

第八章&#xff1a;枚举类与注解 8.1&#xff1a;枚举类的使用 ​ 类的对象只有有限个&#xff0c;确定的。我们称此类为枚举类。当需要定义一组常量是&#xff0c;强烈建议使用枚举类。如果枚举类中只有一个对象&#xff0c;则可以作为单例模式的实现方式。 如何定义枚举类 …...

Ceph介绍

分布式存储概述 常用的存储可以分为DAS、NAS和SAN三类 DAS&#xff1a;直接连接存储&#xff0c;是指通过SCSI接口或FC接口直接连接到一台计算机上&#xff0c;常见的就是服务器的硬盘NAS&#xff1a;网络附加存储&#xff0c;是指将存储设备通过标准的网络拓扑结构&#xff…...

remove 和 erase 的区别

remove 和 erase 的区别 以容器vector来说明remove和erase的区别 在STL中&#xff0c;vector容器也提供了remove()和erase()函数&#xff0c;用于从vector中删除元素。虽然这两个函数都可以实现删除元素的功能&#xff0c;但是它们之间还是有一些区别的。 remove() remove(…...

NFTScan:怎么使用 NFT API 开发一个 NFT 数据分析平台?

对很多开发者来说&#xff0c;在 NFT 数据海洋中需要对每个 NFT 进行索引和筛选是十分困难且繁琐的&#xff0c;NFT 数据获取仍是一大问题。而数据平台提供的 API 使得开发者可以通过接口获取区块链上 NFT 的详细信息&#xff0c;并对其进行分析、处理、统计和可视化。在本篇文…...

ECOLOY直接更换流程表单后导致历史流程中数据为空白的解决方案

用户反馈流历史流程打开是空白了没有内容。 一、问题调查分析&#xff1a; 工作流“XX0204 员工培训协议审批流程”workflowId37166产生的7个具体流程中&#xff0c;创建日期为2021年的4个具体流程原先引用的数据库表单应该是“劳动合同签订审批表”(formtable_main_190)&…...

mysql中的共享锁,排他锁,间隙锁,意向锁及死锁机制

一、前言&#xff08;以下均为读完 高性能Mysql第四版 后的个人理解&#xff0c;建议阅读&#xff0c;挺不错的&#xff09;在写锁机制前先简单贴出mysql InnoDB引擎中的事务特性与隔离级别&#xff1a;事务的ACID标准(1)原子性-atomicity&#xff1a;一个事务作为一个不可分割…...

SpringBoot整合MybatisPlus

文章目录前言一、MybatisPlus是什么&#xff1f;二、使用步骤1.导入依赖2.编写配置文件3.编写Controller和实体类4.编写持久层接口mapper5.启动类加包扫描注解6.测试总结前言 本篇记录一下SpringBoot整合MybatisPlus 一、MybatisPlus是什么&#xff1f; MyBatis-Plus&#xff…...

中电金信Gien享汇・大数据专题|金融行业数据架构及模型演进

本期嘉宾 陈子刚 中电金信商业分析事业部华南区总经理 毕业于复旦大学&#xff0c;硕士研究生&#xff1b;拥有16年以上金融行业商业智能领域从业经验&#xff1b;曾就职于中国工商银行、Teradata、东亚银行&#xff0c;服务于平安银行、广发银行、招商银行、广东农信、招商…...

Cadence Allegro 导出Design Cross Section报告详解

⏪《上一篇》   🏡《上级目录》   ⏩《下一篇》 目录 1,概述2,Design Cross Section作用3,Design Cross Section示例4,Component Report导出方法4.1,方法14.2,方法2B站关注“硬小二”浏览更多演示视频 1,概述 <...

【LeetCode】剑指 Offer 23. 链表中环的入口节点 p139 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/c32eOV/ 1. 题目介绍&#xff08;23. 链表中环的入口节点&#xff09; 给定一个链表&#xff0c;返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环&#x…...

LeetCode-96. 不同的二叉搜索树

题目来源 96. 不同的二叉搜索树 递归 1.我们要知道二叉搜索树的性质&#xff0c;对于一个二叉搜索树&#xff0c;其 【左边的节点值 < 中间的节点值 < 右边的节点值】&#xff0c;也就是说&#xff0c;对于一个二叉搜索树&#xff0c;其中序遍历之后形成的数组应该是一…...

JavaWeb基础

Servlet 是在服务器上运行的小程序。这个词是在 Java applet的环境中创造的&#xff0c;Java applet 是一种当作单独文件跟网页一起发送的小程序&#xff0c;它通常用于在客户端运行&#xff0c;结果得到为用户进行运算或者根据用户互作用定位图形等服务。服务器上需要一些程序…...