webpack+react+redux+es6开发模式

一、预备知识

  node, npm, react, redux, es6, webpack

二、学习资源

  ECMAScript 6入门

  React和Redux的连接react-redux

  Redux 入门教程   redux middleware 详解   Redux研究

  React 入门实例教程

  webpack学习demo

  NPM 使用介绍

三、工程搭建

  之前有写过 webpack+react+es6开发模式 ,文章里介绍了一些简单的配置,欢迎访问。后续文章请参考 webpack+react+redux+es6开发模式---续

  1.可以npm init, 创建一个新的工程。创建package.json文件,定义需要的dependency,scripts,version等等。

  2.新增webpack.config.json文件,定义插件项配置,页面入口文件,文件输出,加载器的配置,其他解决方案配置等。下面提供了简单配置的demo,更详细的讲解,请参考  webpack 入门指南: w2bc.com/Article/50764。

var webpack = require('webpack');
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');module.exports = {//插件项
    plugins: [commonsPlugin],//页面入口文件配置
    entry: {bundle: './index.js'},//入口文件输出配置
    output: {path: './build/',filename: '[name].js'},module: {//加载器配置
        loaders: [{ test: /\.css$/, loader: 'style-loader!css-loader' },{ test: /\.js$/, loader: 'jsx-loader?harmony' },{ test: /\.scss$/, loader: 'style!css!sass?sourceMap'},{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}]},//其它解决方案配置
    resolve: {root: '******', //绝对路径extensions: ['', '.js', '.json', '.scss'],alias: {AppStore : 'js/stores/AppStores.js',ActionType : 'js/actions/ActionType.js',AppAction : 'js/actions/AppAction.js'}}
};
View Code

  3.编写如果文件 main.js。这里创建了provider,store,history,router。实现页面的路由以及react组件以及组件间的state交互。关于react-redux内容请参考 react-redux概念理解关于react-router内容请参考 React Router 使用教程 

var React = require('react');
var ReactDOM = require('react-dom');
var { Provider } = require('react-redux');
import { Router } from 'react-router';
import routes from 'routes';
import { createHashHistory, useBasename } from 'history';
import { syncReduxAndRouter } from 'redux-simple-router';
import { routeReducer } from 'redux-simple-router';
var configureStore = require('./stores/configureStore');// Run our app under the /base URL.
const history = useBasename(createHashHistory)({basename: '/',
});
const store = configureStore(window.__INITIAL_STATE__);syncReduxAndRouter(history, store);ReactDOM.render
(<Provider store={store}><Router history={history}>{routes}</Router></Provider>,document.getElementById('root')
);
View Code

  4.创建工程的各个模块

|--demo1|--src  //源码|--actions     // 存放当前触发Redux的动作行为|--components  // 存放工程内部的公共组件|--modules     // 存放工程各模块代码|--constants   // action动作常量|--reducers    // 存放reducer函数,用来修改store状态|--routes      // 放置页面路由 react router|--stores      // 放置stores配置文件|--main.js       // 入口js|--index.html  // 工程入口文件html|--node_modules  // 存放依赖的第三方模块库,使用命令 npm install|--build  //打包文件存放的目录|--webpack.config.js|--package.json    

四、功能开发

  1.做一个简单的Home页面

  (1).在modules文件夹新建Home.js, 使用antd 的Menu组件, 展示我们要演示的功能。

import React from 'react';
import 'less/home.less';
import { Scrollbars } from 'react-custom-scrollbars';
import {Menu} from 'antd';//首页
export class Home extends React.Component{constructor(props) {super(props);this.changeRoute = this.changeRoute.bind(this);}componentDidMount() {}changeRoute(e) {this.context.history.pushState({}, e.key);}render() {return (<div className='home'><Scrollbars style={{ height: 600 }}><Menu className='menu' onClick={this.changeRoute}><Menu.Item key='showSelfMsg'>页面渲染展示信息</Menu.Item><Menu.Item key='frontAndRearInteractive'>模拟前后台交互</Menu.Item><Menu.Item key='pageExchange'>页面切换</Menu.Item><Menu.Item key='extend'>子组件扩展</Menu.Item></Menu></Scrollbars></div>
    );}
}
Home.contextTypes = {history: React.PropTypes.object.isRequired,
};
module.exports = Home;
View Code

  (2).注册Home页面的路由,对应routes/index.js加入如下代码。

<Route path="/" component={ModuleRouters}><IndexRoute component={Home} />
</Route>

  (3).启动工程, npm run dev, 浏览器中输入 http://localhost:8000/demo1,即可预览我们的Home页面。

  

 

  2.单页面渲染,完成数据的展示和隐藏

  (1).在component目录下新建ShowSelfMsg.js, 通过改变state状态,重新渲染页面.

import React from 'react';
import {connect} from 'react-redux';
import {Button} from 'antd';
import 'less/common.less';
var mapStateToProps = function(state){};class ShowSelfMsg extends React.Component{constructor(props){super(props);this.state = {showContent: false};this.showContent = this.showContent.bind(this);}showContent() {this.setState({showContent: !this.state.showContent});}componentDidMount() {const { dispatch} = this.props;//加载该页面的数据
    }componentWillReceiveProps(nextProps) {}render() {let showContent = this.state.showContent;return (<div className='main'><div className='content'><Button type="ghost" onClick={this.showContent}>{!this.state.showContent ? '单击显示内容' : '单击隐藏内容'}</Button>
                    {showContent ? (<div><span>大家好,我是hjzgg</span></div>) : (null)}<div className='back'><Button type="ghost" onClick={()=>this.context.history.pushState({}, '/')}>返回</Button></div></div></div>
        );}
}ShowSelfMsg.contextTypes = {history: React.PropTypes.object.isRequired,
};
module.exports = connect(mapStateToProps)(ShowSelfMsg);
View Code

  (2).注册路由,在routes/index.js中加入如下代码。

<Route path="/showSelfMsg" component={ShowSelfMsg} />

  (3).在Home页面中点击 ‘页面渲染展示信息’,即可进入这个页面。

  

 

  3.模拟前后台交互

  (1).代码编写如下。

    (I).在constants新建ActoinTypesjs,定动作类型;

    (II).在actions目录中新建simulationRquest.js, 定义要分发的动作;

    (III)在reducers目录新建simulationRquest.js,存放reducer函数,用来修改store状态,然后将该函数放入到reducers/index.js中的combineReducers函数中,最终会合并成一个新的reducer;

    (IV)components目录中新建FrontAndRearInteractive.js, dispatch 自定义的动作,实现模拟前后台交互功能。

  ActionType.js

export const SIMULATION_REQUEST_SUCCESS = 'SIMULATION_REQUEST_SUCCESS';
export const SIMULATION_REQUEST_FAIL = 'SIMULATION_REQUEST_FAIL';
export const INIT_EXTEND_DATA_SUCCESS = 'INIT_EXTEND_DATA_SUCCESS';
export const INIT_EXTEND_DATA_FAIL = 'INIT_EXTEND_DATA_FAIL';
export const SAVE_EXTEND_DATA_SUCCESS = 'SAVE_EXTEND_DATA_SUCCESS';
View Code

  FrontAndRearInteractive.js

import React from 'react';
import {connect} from 'react-redux';
import {Button} from 'antd';
import {simulationRquestAction} from 'actions/simulationRequest';
var mapStateToProps = function(state){return {myRequest: state.myRequest,}
};class FrontAndRearInteractive extends React.Component{constructor(props){super(props);this.state = {showContent: false};this.simulationRequest = this.simulationRequest.bind(this);}simulationRequest() {const {dispatch} = this.props;console.log('props>>>dispath:' + dispatch);dispatch(simulationRquestAction());}componentDidMount() {const { dispatch} = this.props;//加载该页面的数据
    }componentWillReceiveProps(nextProps) {const { myRequest } = nextProps;if(myRequest.code && myRequest.msg)alert('请求结果:code=' + myRequest.code + ', msg=' + myRequest.msg);}render() {const { myRequest } = this.props;return (<div className='main'><div className='content'><Button type="ghost" onClick={this.simulationRequest}>模拟请求</Button>
                    {myRequest && myRequest.data ? (<div><span>{myRequest.data}</span></div>) : (null)}<div className='back'><Button type="ghost" onClick={()=>this.context.history.pushState({}, '/')}>返回</Button></div></div></div>
        );}
}
FrontAndRearInteractive.contextTypes = {history: React.PropTypes.object.isRequired,
};
module.exports = connect(mapStateToProps)(FrontAndRearInteractive);
View Code

  actions/simulationRquest.js

import {ajax} from 'utils/ajax';
import url from 'utils/Url';
import {SIMULATION_REQUEST_SUCCESS, SIMULATION_REQUEST_FAIL,} from 'constants/ActionTypes';function simulationRquestSuccess(data, msg){return {type: SIMULATION_REQUEST_SUCCESS,data,msg,}
}function simulationRquestFail(msg){return {type: SIMULATION_REQUEST_FAIL,msg,}
}export function simulationRquestAction(args){return function (dispatch) {console.log('actions>>>dispath:' + dispatch);/*//真是请求ajax({method : 'GET',url :  url.QUERY_ALL_USER,query : {'args': args},type : 'json',success : function(data) {return dispatch(simulationRquestSuccess(data));},error : function(data) {return dispatch(simulationRquestFail('request fail'));}    });*///假设请求成功return dispatch(simulationRquestSuccess('我是后台返回数据:hjzgg!!!', '获取数据成功'));};
}
View Code

  reducers/simulationRquest.js

import {SIMULATION_REQUEST_SUCCESS, SIMULATION_REQUEST_FAIL,}  from 'constants/ActionTypes';
import assign from 'lodash/assign';function myRequest(state = {data: null,msg: null,code: null,}, action) {console.log('reducer action属性>>>>>' + JSON.stringify(action));switch(action.type) {case SIMULATION_REQUEST_SUCCESS:return assign({}, state, {msg: action.msg,data: action.data,code: 'success',});case SIMULATION_REQUEST_FAIL:return assign({}, state, {msg: action.msg,data: null,code: 'fail',});default:return state;}}module.exports = myRequest;
View Code

  (2).路由注册,在routes/index.js增加如下代码。

<Route path="/frontAndRearInteractive" component={FrontAndRearInteractive} />

  (3).在Home页面中点击 ‘模拟前后台交互’,即可进入页面。

  

  4.页面切换

  (1).在components目录新建PageExchange.js 和 Childpage.js,分别为父页面和子页面。注意,这里父页面的变量信息 是通过路由的方式传递过去的,当然也可以通过state方式传递过去。

  PageExchange.js

import React from 'react';
import {connect} from 'react-redux';
import {Button} from 'antd';
import 'less/common.less';
var mapStateToProps = function(state){};class PageExchange extends React.Component{constructor(props){super(props);this.state = {showContent: false};this.gotoChildPage = this.gotoChildPage.bind(this);}gotoChildPage() {console.log('this.context.history>>>>>>' + JSON.stringify(this.context.history));this.context.history.pushState({}, 'childDemoPage/' + '我是父页面信息');}componentDidMount() {const { dispatch} = this.props;//加载该页面的数据
    }componentWillReceiveProps(nextProps) {}render() {let showContent = this.state.showContent;return (<div className='main'><div className='content'><Button type="ghost" onClick={this.gotoChildPage}>进入子页面</Button><div className='back'><Button type="ghost" onClick={()=>this.context.history.pushState({}, '/')}>返回</Button></div></div></div>
        );}
}PageExchange.contextTypes = {history: React.PropTypes.object.isRequired,
};
module.exports = connect(mapStateToProps)(PageExchange);
View Code

  Childpage.js

import React from 'react';
import {connect} from 'react-redux';
import {Button} from 'antd';
import 'less/common.less';
var mapStateToProps = function(state){return {}
};class ChildPage extends React.Component{constructor(props){super(props);this.returnParentPage = this.returnParentPage.bind(this);}componentDidMount() {const { dispatch} = this.props;//加载该页面的数据
    }componentWillReceiveProps(nextProps) {}returnParentPage() {this.context.history.pushState(null, 'pageExchange');}render() {const parentPageMsg = this.props.params.parentPageMsg;return (<div className='main'><div className='content'><Button type="ghost" onClick={this.returnParentPage}>返回父页面</Button>
                    {parentPageMsg ? (<div><span>{parentPageMsg}</span></div>) : (null)}</div></div>
        );}
}ChildPage.contextTypes = {history: React.PropTypes.object.isRequired,
};
module.exports = connect(mapStateToProps)(ChildPage);
View Code

  (2).注册路由,在routes/index.js中加入如下代码。

<Route path="/pageExchange" component={PageExchange} />
<Route path="/childDemoPage(/:parentPageMsg)" component={ChildPage}/>

  (3).在Home页面中点击‘页面切换’,即可进入页面。

  

  5.自定义扩展组件

   (1).先说一下应用场景:多个页面可能需要类似的扩展功能,通过自定义扩展组件,完成对信息的加载。主页面信息保存时,通知扩展组件要保存信息了,扩展组件将最新修改的信息告知主页面,主页面获取到全部信息后,一起将数据传给后台,完成主页面信息和扩展信息的保存。

  (2).在components目录下新建Page.js和ExtendPage.js,分别为主页面和自定义扩展组件。

  Page.js

import React from 'react';
import {connect} from 'react-redux';
import {Button, Input, Form} from 'antd';
import ExtendPage from 'components/ExtendPage';
import 'less/common.less';
const FormItem = Form.Item;
var mapStateToProps = function(state){return {extendStore: state.extendStore}
};class Page extends React.Component{constructor(props){super(props);this.state = {childState: false,}this.handleSubmit = this.handleSubmit.bind(this);this.onSaveExtendPage = this.onSaveExtendPage.bind(this);}componentDidMount() {const { dispatch} = this.props;//加载该页面的数据
    }componentWillReceiveProps(nextProps) {}//通知扩展组件,准备保存了
    onSaveExtendPage() {if(this.state.childState) {this.setState({childState: false,});}}save(values) {//打印父级和子级文本
        alert(JSON.stringify(values));}handleSubmit() {var self = this;this.props.form.validateFields((err, values) => {if (!err) {//表单符合标准//values 为当前父页面的数据,接下来获取子页面的数据this.setState({childState: true}, function() {const { extendStore } = self.props;values.extendData = extendStore && extendStore.data || extendStore;self.save(values);});}});}render() {const { getFieldProps } = this.props.form;const inputProps = getFieldProps('inputText', {initialValue: '',rules: [{required: true, message: 'the input is required' },],validateTrigger: "onBlur"});return (<div style={{marginTop: 50, width: 600, marginLeft: 'auto', marginRight: 'auto'}}><Form onSubmit={this.handleSubmit}><FormItem {...{labelCol: { span: 6 }, wrapperCol: { span: 14 }}} label="父级文本: "><Input {...inputProps} id='inputText' type='text'/></FormItem><FormItem wrapperCol={{ span: 12, offset: 6 }}><Button type="primary" htmlType="submit">提交</Button></FormItem></Form><ExtendPagechildState={this.state.childState}callBack={this.onSaveExtendPage}/><div style={{float: 'right'}}><Button type="ghost" onClick={()=>this.context.history.pushState({}, '/')}>返回</Button></div></div>
        );}
}
Page.contextTypes = {history: React.PropTypes.object.isRequired,
};
Page = Form.create()(Page);
module.exports = connect(mapStateToProps)(Page);
View Code

  ExtendPage.js

import React from 'react';
import {connect} from 'react-redux';
import {Button, Form, Input, message} from 'antd';
const FormItem = Form.Item;
import {initExtendData, saveExtendDataAction} from 'actions/extendPage';
var mapStateToProps = function(state){return {extendStore: state.extendStore}
};class ExtendPage extends React.Component{constructor(props){super(props);this.state = {}this.saveExtendData = this.saveExtendData.bind(this);this.checkText = this.checkText.bind(this);}checkText(rule, value, callBack) {if(/\s+/.test(value)) {callBack("不能有空白字符");} else {callBack();}}saveExtendData() {this.props.callBack();//保存成功后,更改父页面的childState的状态this.props.form.validateFields((err, values) => {if (!err) {//表单符合标准console.log('save ExtendPage values: ' + JSON.stringify(values));const {dispatch} = this.props;dispatch(saveExtendDataAction(values));}});}componentDidMount() {const { dispatch} = this.props;//初始化扩展页的数据
        dispatch(initExtendData());}componentWillReceiveProps(nextProps) {const { extendStore, childState } = nextProps;if(extendStore && extendStore.msg) {message.info(extendStore.msg, 5);extendStore.msg = null;}if(childState) {//父页面 改变 子页面的状态this.saveExtendData();}}render() {const { getFieldProps } = this.props.form;const { extendStore } = this.props;const inputValue = extendStore && extendStore.data && extendStore.data.extendInputText || null;const inputProps = getFieldProps('extendInputText', {initialValue: inputValue,rules: [{required: true, message: 'the input is required' },{validator: this.checkText}],validateTrigger: "onBlur"});return (<div><Form><FormItem {...{labelCol: { span: 6 }, wrapperCol: { span: 14 }}} label="扩展本文: "><Input {...inputProps} type="text" id="extendInputText"/></FormItem></Form></div>
        );}
}
ExtendPage = Form.create()(ExtendPage);
module.exports = connect(mapStateToProps)(ExtendPage);
View Code

  (3).说一下组件的扩展机制

  (I).扩展组件自身会维护更新自己state状态,在触发扩展组件保存时,扩展组件将自身数据通过dispatch进行分发,最后通过对应的reducer(这个reducer会通过combineReducers函数合并成一个新的reducer)进行处理,根据逻辑生成新的state。

  >>定义动作类型

  

   >>分发动作

  

  >>reducer处理动作,返回新的state

  

  >>自定义的reducer函数通过combineReducers函数进行合并

  

   (II).父级组件如何获取扩展组件的状态?

  

  也就是store中的状态树变化的时候,组件可以通过 mapStateToProps 函数从状态树中获取最新的state。

  (III).父级组件如何通知扩展组件 准备保存数据了?

  

  >>扩展组件接收父级组件两个参数:childState, 通知扩展组件状态发生变化; callBack, 修改childState状态,扩张组件通知父级组件更新完成。

 

  

  >>父级组件保存数据时,首先获取到自己的数据,然后通过setState()方法改变childState的值,通知扩展组件。最后通过setState方法传入的回调函数(该函数在组件更新完成之后调用)获取到扩展组件的最新state。

  

  

  >>扩展组件接收到父级组件的通知,刷新store中的state。这样父级组件和扩展组件自身都可以通过mapStateToProps方法获取到最新的state。

    (4).注册路由,在routes/index.js中加入如下代码。

  

  (5).在Home页面中点击‘页面切换’,即可进入页面。

    

 

 

 五、问题解惑

   1.module.filename、__filename、__dirname、process.cwd():  http://www.tuicool.com/articles/bQre2a
   2.node.js之path模块: http://www.jianshu.com/p/fe41ee02efc8
   3.react-router: http://www.ruanyifeng.com/blog/2016/05/react_router.html?utm_source=tool.lu
     4.出现如下错误:Cannot sync router: route state does not exist. Did you install the routing reducer,参考:

    http://stackoverflow.com/questions/34039619/redux-simple-router-react-router-error-route-state-does-not-exist

  5.module.exprots, export, export default区别:

export default variationimport variation from 'js file'export variationimport {variation} from 'js file'module.exports=variationimport variation from 'js file'

  参考:

  http://www.2cto.com/kf/201412/360211.html

  http://www.jb51.net/article/33269.htm

  http://blog.csdn.net/zhou_xiao_cheng/article/details/52759632

  http://blog.csdn.net/zhou_xiao_cheng/article/details/52759632

六、dispath疑问

  react-router相关API

  react-redux 之 connect 方法详解

  验证一下 redux store.dispatch  和 react组件 props中的dispath,的确是一样的。

  

dispath:function (action) {return typeof action === 'function' ? action(dispatch, getState) : next(action);
}

七、演示地址

  http://study.hujunzheng.cn:8000/DEMO_FRONT/

八、完整项目下载

  https://github.com/hjzgg/webpack-react-redux

转载于:https://www.cnblogs.com/hujunzheng/p/6133648.html

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

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

相关文章

fiddler发送post请求

1.指定为 post 请求&#xff0c;输入 url Content-Type: application/x-www-form-urlencoded;charsetutf-8 request body中的参数格式&#xff1a;userNameadminicxp&userPassword123qwe!# 这种方式可以用 request.getParameter的方式来获得。 2.指定为 post 请求&#xff…

Kettle之数据抽取、转换、装载

Kettle 官网 ETL利器Kettle实战应用解析系列 利用kettle组件导入excel文件到数据库 kettle中实现动态SQL查询 java中调用kettle转换文件 kettle 7.x版本下载&#xff1a;https://pan.baidu.com/s/1nvnzzCH  密码&#xff1a;6f5c mac 下运行spoon.sh,  windows下为spoon.bat…

webpack+react+redux+es6开发模式---续

一、前言 之前介绍了webpackreactreduxes6开发模式 &#xff0c;这个项目对于一个独立的功能节点来说是没有问题的。假如伴随着源源不断的需求&#xff0c;前段项目会涌现出更多的功能节点&#xff0c;需要独立部署运行。为了更好地管理这些独立的功能节点&#xff0c;我们需要…

RabbitMQ安装和使用(和Spring集成)

一、安装Rabbit MQ   Rabbit MQ 是建立在强大的Erlang OTP平台上&#xff0c;因此安装Rabbit MQ的前提是安装Erlang。通过下面两个连接下载安装3.2.3 版本&#xff1a; 下载并安装 Eralng OTP For Windows (vR16B03)运行安装 Rabbit MQ Server Windows Installer (v3.2.3)具体…

单点登录实现(spring session+redis完成session共享)

一、前言 项目中用到的SSO&#xff0c;使用开源框架cas做的。简单的了解了一下cas&#xff0c;并学习了一下 单点登录的原理&#xff0c;有兴趣的同学也可以学习一下&#xff0c;写个demo玩一玩。 二、工程结构 我模拟了 sso的客户端和sso的服务端&#xff0c; sso-core中主要是…

加密策略

一、前言 这两天研究了一下项目中的密码加密&#xff0c;可以说得上是学到了很多。下面来大致说一下。 二、常用加密 1.单向加密算法 单向加密算法主要用来验证数据传输的过程中&#xff0c;是否被篡改过。 BASE64 严格地说&#xff0c;属于编码格式&#xff0c;而非加密算法 …

Spring Data JPA: 实现自定义Repository

一、前言 由于项目中的 实体&#xff08;entity&#xff09;默认都是继承一个父类&#xff08;包含一些公共的属性&#xff0c;比如创建时间&#xff0c;修改时间&#xff0c;是否删除&#xff0c;主键id&#xff09;。为了实现逻辑删除&#xff0c;一般会自己实现RepositoryFa…

js冲刺一下

js中__proto__和prototype的区别和关系 1.对象有属性__proto__,指向该对象的构造函数的原型对象。  2.方法除了有属性__proto__,还有属性prototype&#xff0c;prototype指向该方法的原型对象。 深入浅出妙用 Javascript 中 apply、call、bind ***两道面试题*** 关于js中伪数…

Jackson序列化实例

参考文章 Jackson使用ContextualSerializer在序列化时获取字段注解的属性 使用BeanSerializerModifier定制jackson的自定义序列化(null值的处理) 关于使用ContextualSerializer的补充 BeanSerializerFactory中有如下代码&#xff0c; 关于设置SerializerModifier&#xff0c;如…

cas4.2.7实现单点登录

准备前参考&#xff1a;  cas server下载地址 cas client 下载地址 安全cookie setSecure详解 Spring通过构造方法注入的四种方式 cas 学习博文 自定义登录页和登录认证 cas server端的login-webflow详细流程 CAS服务端自定义数据库认证用户 准备工作 1. cas server下载之后解…

swagger restful api form映射实体对象和body映射实体对象配置

实体Model ModelAttribute一个具有如下三个作用&#xff1a; ①绑定请求参数到命令对象&#xff1a;放在功能处理方法的入参上时&#xff0c;用于将多个请求参数绑定到一个命令对象&#xff0c;从而简化绑定流程&#xff0c;而且自动暴露为模型数据用于视图页面展示时使用&…

ssh端口转发(之kettle ssh方式连接数据库)

ssh参数解释 格式  ssh [user]host [command] 选项&#xff1a; -1&#xff1a;强制使用ssh协议版本1&#xff1b; -2&#xff1a;强制使用ssh协议版本2&#xff1b; -4&#xff1a;强制使用IPv4地址&#xff1b; -6&#xff1a;强制使用IPv6地址&#xff1b; -A&#xff1a…

ThreadLocal和InheritableThreadLocal使用

InheritableThreadLocal代码 public class InheritableThreadLocal<T> extends ThreadLocal<T> {protected T childValue(T parentValue) {return parentValue;}ThreadLocalMap getMap(Thread t) {return t.inheritableThreadLocals;}void createMap(Thread t, T f…

mybatis generator修改默认生成的sql模板

相关连接&#xff1a; mybatis-generator扩展教程系列 -- 自定义sql xml文件 git项目地址 转载于:https://www.cnblogs.com/hujunzheng/p/7110510.html

oauth简单使用

一、oauth原理参考 理解OAuth 2.0 二、本例中采用授权码模式 大致流程 &#xff08;A&#xff09;用户访问客户端&#xff0c;后者将前者导向认证服务器。  &#xff08;B&#xff09;用户选择是否给予客户端授权。  &#xff08;C&#xff09;假设用户给予授权&#xff0c…

我眼中的服务提供和服务消费

服务提供和消费脑图 服务提供和消费脑图 参见: 服务提供者, 服务消费者, 服务注册中心 服务提供者 1.服务提供者启动&#xff0c;解析xml文件中配置的服务&#xff0c;这里使用Dom4j解析。 2.将服务的一些相关信息注册到 服务注册中心。 注&#xff1a;服务相关信息&#xff1a…

shiro整合oauth

前言 如果oauth原理还不清楚的地方&#xff0c;其参考这里。 一、基本思路脑图 二、客户端shiro配置 shiro配置文件 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:util&q…

springmvc+swagger2

一、swagger2依赖 <!--swagger--> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><exclusions><exclusion><artifactId>spring-aop</artifactId><groupId>org.s…

获取资源文件工具类

如果没有依赖spring&#xff0c;可以将分割线下的方法去掉 import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframe…

无状态shiro认证组件(禁用默认session)

准备内容 简单的shiro无状态认证 无状态认证拦截器 import com.hjzgg.stateless.shiroSimpleWeb.Constants; import com.hjzgg.stateless.shiroSimpleWeb.realm.StatelessToken; import org.apache.shiro.web.filter.AccessControlFilter;import javax.servlet.ServletRequest;…