-
Notifications
You must be signed in to change notification settings - Fork 15
/
search_plus_index.json
1 lines (1 loc) · 165 KB
/
search_plus_index.json
1
{"./":{"url":"./","title":"Introduction","keywords":"","body":"个人学习笔记 学习/读书过程中的一点记录 在线阅读:https://note.ismy.wang 目录 算法与数据结构 数据库系统 MySQL Oracle Redis MongoDB 分布式事务 数据库优化 ORM 操作系统 FastDFS 虚拟化 软件工程 DevOps 前后端分离 设计模式 架构 架构模式 微服务 计算机系统 数字逻辑电路 网络安全 Web安全 计算机网络 HTTP RESTful 后端开发 语言 C JAVA JAVA并发编程 JAVA内存模型 JVM XML 中间件 ActiveMQ RabbitMQ RocketMQ Kafka Tomcat Nginx 全文检索 Lucene ElasticSearch 框架 Spring SpringBoot SpringCloud Mybatis-Plus Mybatis Netty Dubbo GraphQL ServiceComb 用户认证 Jakarta EE Servlet JSP Cookie&Session Filter&Listener JNDI JPA Freemarker 网络爬虫 前端开发 HTML CSS Less HTML5与CSS3 移动web开发 JavaScript Bootstrap Jquery AJAX NodeJs ES6 Vue ReactJS NPM Webpack 移动开发 安卓 小程序开发 开发工具 Docker K8s VIM GIT SVN idea Junit 构建工具 Gradle Maven 运维 持续集成 容器管理 项目开发 后端 travel 基于servlet与jsp的旅游网站 ssm 使用纯注解配置的ssm项目 pms 基于ssm的多模块权限管理系统 shop 基于Spring Cloud框架的微服务电商网站 edu 基于Spring Cloud框架的微服务在线视频教育网站 soc 基于Spring Cloud框架的微服务社交网站 sell 基于Spring Boot的点餐系统 前端 shop-web 纯HTML CSS实现的电商前端 travel-vue 基于VUE的旅游网站前端 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-02-10 14:21:04 "},"数据库系统/mysql/nav.html":{"url":"数据库系统/mysql/nav.html","title":"MySQL","keywords":"","body":"范式 设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。 目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。 备份还原 mysqldump 事务 说明 操作 开启事务 start transaction 回滚 rollback 提交 commit 问题 并发访问的问题 含义 脏读 一个事务读取到了另一个事务中尚未提交的数据 不可重复读 一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时数据是一致的,这 是事务 update 时引发的问题 幻读 一个事务中两次读取的数据的数量不一致,要求在一个事务多次读取的数据的数量是一致 的,这是 insert 或 delete 时引发的问题 隔离级别 级别 名字 隔离级别 脏读 不可重复读 幻读 数据库默认隔离级别 1 读未提交 read uncommitted 是 是 是 - 2 读已提交 read committed 否 是 是 Oracle 和 SQL Server 3 可重复读 repeatable read 否 否 是 MySQL 4 串行化 serializable 否 否 否 - 隔离级别越高越安全,但效率越来越低 用户及权限管理 创建一个能在主机登录的用户 create user 'user2'@'%' identified by '123'; 授予权限 grant all on *.* to 'user2'@'%'; 设计规范 命名规范 数据库 [a-z ][0-9] _ 不超过30字符 备份数据库可以加自然数 表 [a-z ][0-9] _ 相同关系的表可以加相同的前缀 字段 [a-z ][0-9] _ 多个单词使用下划线分割 每个表必须有自增主键(默认系统时间) 关联字段名尽可能相同 字段类型规范 使用较少的空间来存储 ip最好使用int 固定长度的类型使用char 最好给默认值 索引规范 加一个index后缀 为每个表创建主键索引 符合索引慎重 范式规范 必须满足第二范式 尽量满足第三范式 MYSQL设计原则 核心原则 不在数据库做运算 控制列数量(20以内) 平衡范式与冗余 禁止大SQL 禁止大事务 禁止大批量 字段原则 用好数据类型节约空间 字符转为数字 避免使用NULL 少用text 索引原则 不在索引列做运算 innodb主键使用自增 不用外键 SQL原则 尽可能简单 简单事务 避免使用触发器,函数 不使用select * OR改写成IN或UNION 避免前% 慎用count(*) limit高效分页 少用连接join group by 使用同类型比较 打散批量更新 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-29 23:02:26 "},"数据库系统/oracle/nav.html":{"url":"数据库系统/oracle/nav.html","title":"Oracle","keywords":"","body":"体系结构 基本操作 创建表空间 create tablespace test datafile 'd:\\test.dbf' size 100m autoextend on next 10m 删除表空间 drop tablespace test 创建用户 create user root identified by root default tablespace test 角色 CONNECT角色: --是授予最终用户的典型权利,最基本的 RESOURCE角色: --是授予开发人员的 DBA角色:拥有全部特权,是系统最高权限,只有DBA才可以创建数据库结构,并且系统权限也需要DBA授出,且DBA用户可以操作全体用户的任意基表,包括删除 授权 grant dba to root 数据类型 数据类型 描述 Varchar, varchar2 表示一个字符串 NUMBER NUMBER(n)表示一个整数,长度是n,NUMBER(m,n):表示一个小数,总长度是m,小数是n,整数是m-n DATA 表示日期类型 CLOB 大对象,表示大文本数据类型,可存4G BLOB 大对象,表示二进制数据,可存4G 序列 创建序列 create sequence s_person 使用 select s_person.nextval from dual; insert into person values(s_person.nextval,'123'); 查询 单行函数 upper lower ROUND:四舍五入 trunc MONTHS_BETWEEN TO_CHAR nvl 条件表达式 select t.empno, t.ename, case when t.job = 'CLERK' then '业务员' when t.job = 'MANAGER' then '经理' when t.job = 'ANALYST' then '分析员' when t.job = 'PRESIDENT' then '总裁' when t.job = 'SALESMAN' then '销售' else '无业' end from emp t 多行函数 聚合函数 分页查询 select * from (select rownum r ,emp.* from emp) b where b.r >5 and b.r 视图 索引 PLSQL MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-23 16:36:02 "},"数据库系统/Redis.html":{"url":"数据库系统/Redis.html","title":"Redis","keywords":"","body":" redis是一款高性能的NOSQL系列的非关系型数据库 应用场景 缓存(数据查询、短连接、新闻内容、商品内容等等) 聊天室的在线好友列表 任务队列。(秒杀、抢购、12306等等) 应用排行榜 网站访问统计 数据过期处理(可以精确到毫秒 分布式集群架构中的session分离 数据结构 字符串类型 string 哈希类型 hash 列表类型 list 集合类型 set 有序集合类型 sortedset 命令操作 字符串类型 存储:set key value 获取 get key 删除 del key 哈希类型 存储:hset key field value 获取:hget key field 删除: hdel key field 列表类型 将元素加入列表左边:lpush key value 将元素加入列表右边:rpush key value 范围获取:lrange key start end 删除列表最左边的元素,并将元素返回:lpop key 删除列表最右边的元素,并将元素返回:rpop key 集合类型 存储:sadd key value 获取:smembers key 删除:srem key value 有序集合类型 存储:zadd key score value 获取:zrange key start end 删除:zrem key value 通用 keys * : 查询所有的键(生产环境应禁用,原因:正则表达式可能会占用大量资源) type key : 获取键对应的value的类型 del key:删除指定的key value exists key:判断指定的key是否存在 expire key time:指定key的生存时间,单位:秒持久化 RDB 配置文件 after 60 sec if at least 10000 keys changed save 60 10000 AOF appendonly no(关闭aof) --> appendonly yes (开启aof) # appendfsync always : 每一次操作都进行持久化 appendfsync everysec : 每隔一秒进行一次持久化 # appendfsync no : 不进行持久化 Jedis 基本使用 Jedis jedis = new Jedis(\"127.0.0.1\"); jedis.set(\"name\",\"my\"); System.out.println(jedis.get(\"name\")); jedis.close(); 连接池 JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(15); config.setMaxTotal(30); JedisPool pool = new JedisPool(config); Jedis resource = pool.getResource(); System.out.println(resource.ping()); resource.close(); pool.close(); Spring Data Redis RedisTemplate基本操作 redisTemplate.opsForValue() :操作字符串 redisTemplate.opsForHash() :操作hash redisTemplate.opsForList():操作list redisTemplate.opsForSet():操作set redisTemplate.opsForZSet():操作zset StringRedisTemplate是K,V均为String的RedisTemplate 使用 template.opsForValue().set(\"name\",\"hello,bitch\"); MY all right reserved,powered by Gitbook该页面最后修改于: 2019-09-28 14:13:33 "},"数据库系统/MongoDB.html":{"url":"数据库系统/MongoDB.html","title":"MongoDB","keywords":"","body":" MongoDB 是一个跨平台的,面向文档的数据库,是当前 NoSQL 数据库产品中最热 门的一种。它介于关系数据库和非关系数据库之间,是非关系数据库当中功能最丰富,最 像关系数据库的产品。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以 存储比较复杂的数据类型。 基础概念 SQL术语/概念 MongoDB术语/概念 解释/说明 database database 数据库 table collection 数据库表/集合 row document 数据记录行/文档 column field 数据字段/域 index index 索引 table joins 表连接(MongoDB不支持) primary key primary key 主键,MongoDB自动在每个集合中添加_id的主键 数据类型 null:用于表示空值或者不存在的字段,{“x”:null} 布尔型:布尔类型有两个值true和false,{“x”:true} 数值:shell默认使用64为浮点型数值。{“x”:3.14}或{“x”:3} 对于整型值,可以使用 NumberInt(4字节符号整数)或NumberLong(8字节符号整数), {“x”:NumberInt(“3”)}{“x”:NumberLong(“3”)} 字符串:UTF-8字符串都可以表示为字符串类型的数据,{“x”:“呵呵”} 日期:日期被存储为自新纪元依赖经过的毫秒数,不存储时区,{“x”:new Date()} 正则表达式:查询时,使用正则表达式作为限定条件,语法与JavaScript的正则表达式相 同,{“x”:/[abc]/} 数组:数据列表或数据集可以表示为数组,{“x”: [“a“,“b”,”c”]} 内嵌文档:文档可以嵌套其他文档,被嵌套的文档作为值来处理,{“x”:{“y”:3 }} 对象Id:对象id是一个12字节的字符串,是文档的唯一标识,{“x”: objectId() } 二进制数据:二进制数据是一个任意字节的字符串。它不能直接在shell中使用。如果要 将非utf-字符保存到数据库中,二进制数据是唯一的方式。 代码:查询和文档中可以包括任何JavaScript代码,{“x”:function(){/…/}} 操作 show dbs #列出所有数据库 use test #使用数据库(不存在会自动创建,新创建的数据库不显示(至少包含一个集合)) db.dropDatabase() #删除当前数据库 db.createCollection(\"student\") # 创建集合 db.collection.drop() #删除集合 db.student.insert({\"name\":\"cxk\",\"age\":25}) # 插入文档 db.student.update({\"name\":\"cxk\"},{\"name\":\"xkc\"}) #更新文档(替换文档) db.student.find() # 查询全部 db.student.find({\"name\":\"cxk\"}) # 按条件查询 db.student.find({\"name\":\"cxk\"},{name:1,age:1,_id:0}) # 投影 # 创建用户 db.createUser( { user:\"root\", pwd:\"root\", roles:[ {role:\"root\",db:\"admin\"} ] } ) JAVA操作 依赖 org.mongodb mongo-java-driver 3.11.0 使用 MongoClient client = new MongoClient(\"my-pc\"); MongoDatabase db = client.getDatabase(\"db\"); MongoCollection spit = db.getCollection(\"spit\"); Document d = new Document(); d.append(\"name\",\"jntm\"); spit.insertOne(d); for (Document document : spit.find()) { System.out.println(document.getString(\"name\")); } client.close(); Spring data mongodb GridFS MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-12 00:28:45 "},"数据库系统/分布式事务.html":{"url":"数据库系统/分布式事务.html","title":"分布式事务","keywords":"","body":"分布式系统 部署在不同结点上的系统通过网络交互来完成协同工作的系统 分布式事务 在分布式系统中一次操作由多个系统协同完成,这种一次事务操作涉及多个系统通过网络协同完成的过程称为分布式事务。 CAP理论 一致性(Consistency):服务A、B、C三个结点都存储了用户数据, 三个结点的数据需要保持同一时刻数据一致性。 可用性(Availability):服务A、B、C三个结点,其中一个结点宕机不影响整个集群对外提供服务,如果只有服务A结 点,当服务A宕机整个系统将无法提供服务,增加服务B、C是为了保证系统的可用性。 分区容忍性(Partition Tolerance):分区容忍性就是允许系统通过网络协同工作,分区容忍性要解决由于网络分区 导致数据的不完整及无法访问等问题。 解决方案 两阶段提交(2PC) Coordinator Participant QUERY TO COMMIT --------------------------------> VOTE YES/NO prepare*/abort* ACKNOWLEDGMENT commit*/abort* 优点:实现强一致性 缺点:整个事务的执行需要由协调者在多个节点之间去协调 事务补偿(TCC) 优点:最终保证数据的一致性,在业务层实现事务控制,灵活性好。 缺点:开发成本高,每个事务操作每个参与者都需要实现try/confirm/cancel三个接口。 使用消息队列实现最终一致性 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-10-31 20:10:30 "},"数据库系统/数据库优化.html":{"url":"数据库系统/数据库优化.html","title":"数据库优化","keywords":"","body":"数据库优化 优化原因 避免网站出现访问错误 低效的查询导致数据库不稳定 优化用户体验 优化方面 硬件 系统配置 数据库表结构 SQL与索引 成本从下到上递增,效果从上到下递减 MYSQL优化 开启慢查询 set global slow_query_log=ON; #开启慢查询 set global long_query_time=1.0; #设置记录时长为1秒 set global log_queries_not_using_indexes = ON; #不适用索引 慢查询日志地址: 地址存储在slow_query_log_file变量中 慢查询日志存储格式 # Time: 2019-11-29T06:01:43.909217Z 执行时间 # User@Host: root[root] @ localhost [] Id: 9 主机信息 # Query_time: 0.104442 查询时间 Lock_time: 0.000153 锁定时间 Rows_sent: 1 发送行数 Rows_examined: 16249 锁扫描行数 SET timestamp=1575007303; 执行时间戳 select count(*) from actor,payment; SQL 慢查询分析工具 mysqldumpslow mysqldumpslow -t 10 日志地址 # 分析前10条记录 pt-query-digest wget percona.com/get/pt-query-digest # 下载 chmod u+x pt-query-digest # 添加执行权限 /pt-query-digest 慢查询日志地址 # 分析日志 问题定位 次数多、时间长 IO大 未命中索引 查询执行计划 explain sql id: 1 select_type: SIMPLE # table: staff partitions: NULL type: index possible_keys: NULL key: idx_fk_store_id key_len: 1 ref: NULL rows: 2 filtered: 100.00 Extra: Using index id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符. select_type: SELECT 查询的类型. SIMPLE, 表示此查询不包含 UNION 查询或子查询 PRIMARY, 表示此查询是最外层的查询 UNION, 表示此查询是 UNION 的第二或随后的查询 DEPENDENT UNION, UNION 中的第二个或后面的查询语句, 取决于外面的查询 UNION RESULT, UNION 的结果 SUBQUERY, 子查询中的第一个 SELECT DEPENDENT SUBQUERY: 子查询中的第一个 SELECT, 取决于外面的查询. 即子查询依赖于外层查询的结果. table: 查询的是哪个表 partitions: 匹配的分区 type: join 类型 通常来说, 不同的 type 类型的性能关系:ALL possible_keys: 此次查询中可能选用的索引 key: 此次查询中确切使用到的索引 key_len:表示查询优化器使用了索引的字节数. 这个字段可以评估组合索引是否完全被使用, 或只有最左部分字段被使用到 rows:估算 SQL 要查找到结果集需要扫描读取的数据行数,这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好 extra:EXplain 中的很多额外的信息会在 Extra 字段显示 Using filesort:表示 MySQL 需额外的排序操作, 不能通过索引顺序达到排序效果,一般有 Using filesort, 都建议优化去掉, 因为这样的查询 CPU 资源消耗大 Using index:\"覆盖索引扫描\", 表示查询在索引树中就可查找所需数据, 不用扫描表数据文件, 往往说明性能不错 Using temporary:查询有使用临时表, 一般出现于排序, 分组和多表 join 的情况, 查询效率不高, 建议优化 索引优化 索引 创建索引 ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引 ALTER TABLE table_name ADD INDEX index_name (column_list) ALTER TABLE table_name ADD UNIQUE (column_list) ALTER TABLE table_name ADD PRIMARY KEY (column_list) CREATE INDEX可对表增加普通索引或UNIQUE索引 CREATE INDEX index_name ON table_name (column_list) CREATE UNIQUE INDEX index_name ON table_name (column_list) 获取索引 show keys from table_name 何时使用索引 主键列中创建索引 多表连接时连接列创建索引 where子句查询的列 需要经常GROUP BY和ORDER BY的列 索引优化 找出重复冗余索引 索引不包含NULL 短索引 排序的索引问题 like语句前%不会使用索引 列上运算问题 NOT IN会进行全表扫描 数据库结构优化 选择合适的数据类型 范式化 反范式化 垂直拆分 水平拆分 配置优化 设置文件最大打开数 设置最大连接数 设置back_log 存放等待连接的堆栈大小 interactive_timeout 缓冲区 key_buffer_size query_cache_size record_buffer_size read_rnd_buffer_size sort_buffer_size join_buffer_size tmp_table_size table_cache max_heap_table_size thread_cache_size thread_concurrency wait_timeout 关于InnoDB 执行顺序 FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1 ON: 对虚表VT1进行ON筛选,只有那些符合的行才会被记录在虚表VT2中。 JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rug from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。 WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合的记录才会被插入到虚拟表VT4中。 GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5. CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6. HAVING: 对虚拟表VT6应用having过滤,只有符合的记录才会被 插入到虚拟表VT7中。 SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。 DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9. ORDER BY: 将虚拟表VT9中的记录按照进行排序操作,产生虚拟表VT10. LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。 执行引擎 MyISAM存储引擎 1、大文件(达到63位文件长度)在支持大文件的文件系统和操作系统上被支持。 2、当把删除和更新及插入操作混合使用的时候,动态尺寸的行产生更少碎片。这要通过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块自动完成。 3、每个MyISAM表最大索引数是64,这可以通过重新编译来改变。每个索引最大的列数是16 4、NULL被允许在索引的列中,这个值占每个键的0~1个字节 5、可以把数据文件和索引文件放在不同目录(InnoDB是放在一个目录里面的) InnoDB存储引擎 1、InnoDB给MySQL提供了具有提交、回滚和崩溃恢复能力的事物安全(ACID兼容)存储引擎。InnoDB锁定在行级并且也在SELECT语句中提供一个类似Oracle的非锁定读。这些功能增加了多用户部署和性能。在SQL查询中,可以自由地将InnoDB类型的表和其他MySQL的表类型混合起来,甚至在同一个查询中也可以混合 2、InnoDB是为处理巨大数据量的最大性能设计。它的CPU效率可能是任何其他基于磁盘的关系型数据库引擎锁不能匹敌的 3、InnoDB存储引擎完全与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB将它的表和索引在一个逻辑表空间中,表空间可以包含数个文件(或原始磁盘文件)。这与MyISAM表不同,比如在MyISAM表中每个表被存放在分离的文件中。InnoDB表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上 4、InnoDB支持外键完整性约束,存储表中的数据时,每张表的存储都按主键顺序存放,如果没有显示在表定义时指定主键,InnoDB会为每一行生成一个6字节的ROWID,并以此作为主键 MEMORY存储引擎 1、MEMORY表的每个表可以有多达32个索引,每个索引16列,以及500字节的最大键长度 2、MEMORY存储引擎执行HASH和BTREE缩影 3、可以在一个MEMORY表中有非唯一键值 4、MEMORY表使用一个固定的记录长度格式 5、MEMORY不支持BLOB或TEXT列 6、MEMORY支持AUTO_INCREMENT列和对可包含NULL值的列的索引 7、MEMORY表在所由客户端之间共享(就像其他任何非TEMPORARY表) 8、MEMORY表内存被存储在内存中,内存是MEMORY表和服务器在查询处理时的空闲中,创建的内部表共享 9、当不再需要MEMORY表的内容时,要释放被MEMORY表使用的内存,应该执行DELETE FROM或TRUNCATE TABLE,或者删除整个表(使用DROP TABLE) 对比 功能 MYISAM Memory InnoDB Archive 存储限制 256TB RAM 64TB None 支持事务 No No Yes No 支持全文索引 Yes No No No 支持数索引 Yes Yes Yes No 支持哈希索引 No Yes No No 支持数据缓存 No N/A Yes No 支持外键 No No Yes No MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-30 15:46:48 "},"数据库系统/ORM.html":{"url":"数据库系统/ORM.html","title":"ORM","keywords":"","body":" 对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中 JDBC操作的繁琐 Hibernate 依赖 org.hibernate hibernate-core 6.0.0.Alpha2 配置 jdbc:mysql:///hibernate com.mysql.cj.jdbc.Driver root 123 update org.hibernate.dialect.MySQL57Dialect true 实体类 @Entity @Table(name = \"tb_book\") public class Book { @Id @Column(name = \"bid\") @GeneratedValue(strategy = GenerationType.TABLE) private Integer id; @Column(name = \"bname\") private String name; @Column(name = \"bauthor\") private String author; } 使用 Configuration cfg = new Configuration().configure(); SessionFactory sessionFactory = cfg.buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); Book book = new Book(); book.setName(\"cxk 篮球入门指南\"); book.setAuthor(\"cxk\"); session.save(book); tx.commit(); session.close(); sessionFactory.close(); 查询 Session session = sessionFactory.openSession(); Book book = new Book(); book.setId(2); session.get(Book.class, 2); 删除 Book book = new Book(); book.setId(2); session.delete(book); 运行原理 Mybatis 运行原理 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-12-02 21:50:31 "},"操作系统/FastDFS.html":{"url":"操作系统/FastDFS.html","title":"FastDFS","keywords":"","body":"分布式文件系统 分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点(可简单的理解为一台计算机)相连 分类 NFS GFS HDFS 架构 Tracker:负责调度 Storage:负责存储 安装 docker pull delron/fastdfs 安装Tracker docker run -d --network=host --name tracker -v /docker/fastdfs/tracker:/var/fdfs delron/fastdfs tracker 安装Storage docker run -d --network=host --name storage -e TRACKER_SERVER=192.168.1.56:22122 -v /docker/fastdfs/storage:/var/fdfs -e GROUP_NAME=group1 delron/fastdfs storage 使用 依赖 com.github.tobato fastdfs-client ${fastDFS.client.version} 配置 fdfs: so-timeout: 1501 # 超时时间 connect-timeout: 601 # 连接超时时间 thumb-image: # 缩略图 width: 60 height: 60 tracker-list: # tracker地址 - my-pc:22122 image: adress: http://my-pc:8888/ 使用 StorePath storePath = storageClient.uploadImageAndCrtThumbImage(file.getInputStream(), file.getSize(),\"扩展名\", null); MY all right reserved,powered by Gitbook该页面最后修改于: 2019-10-14 22:43:50 "},"操作系统/虚拟化.html":{"url":"操作系统/虚拟化.html","title":"虚拟化","keywords":"","body":" 虚拟化技术是对软件基础设施、操作系统、软件等IT资源进行有效的管理,使用户不再受物理资源的限制, 提高计算机资源的利用率 服务器虚拟化技术 Hypervisor也叫VMM(virtual machine monitor) 在虚拟程序上运行操作系统 Containers容器化技术 虚拟程序上直接运行程序,无操作系统 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-01 16:32:10 "},"软件工程/DevOps.html":{"url":"软件工程/DevOps.html","title":"DevOps","keywords":"","body":" DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。 代码托管 虚拟化 持续集成 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-01 16:33:04 "},"软件工程/前后端分离.html":{"url":"软件工程/前后端分离.html","title":"前后端分离","keywords":"","body":"传统 需求-UI-前端-后端-集成-测试-交付 分离 需求-UI-前后端约定接口并行开发-集成-测试-交付 Mock.js mock js 数据 入门案例 let Mock = require('mockjs') let data = Mock.mock( { 'list|5':[{id:1,name:'kd'}] } ); 语法规则 文档 Easy-Mock 一个协同在线数据模拟服务 Easy-Mock MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-08 14:52:22 "},"软件工程/设计模式.html":{"url":"软件工程/设计模式.html","title":"设计模式","keywords":"","body":"设计模式 开闭原则 对扩展开放,对修改关闭 里氏代换原则 任何基类可以出现的地方,子类一定可以出现 依赖倒转原则 针对接口编程,依赖于抽象而不依赖于具体 迪米特法则 一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立 合成复用原则 原则是尽量使用合成/聚合的方式,而不是使用继承 NAV 创建型模式 封装了系统使用哪些类 隐藏了这些类类的实例是如何创建和放在一起的 结构型模式 如何组合类和对象以获得更大的结构 行为模式 主要涉及到算法和对象之间的职责分配 MVC MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-06 14:12:05 "},"软件工程/架构/架构.html":{"url":"软件工程/架构/架构.html","title":"架构","keywords":"","body":"架构 架构的目标 用最小的人力成本来满足构建和维护该系统的需求 乱麻系统 过度的自信导致软件维护成本持续上升 两个维度 行为价值 让系统正常运行 架构价值 让系统更容易修改 四种架构模式 按层封装 也就说传统的水平分层架构,在项目初期很合适 package controller{ Controller; } package service { Service; ServiceImpl; } package dao { Dao; } 按功能封装 即垂直切分 package Order { OrderController; OrderService; OrderDao; } 端口与适配器 package controller{...} package domain { Service; ServiceImpl; Domain; } package dao{...} 按组件封装 优点服务架构的味道 package controller {...} package order { Service; Dao; } NAV 编程范式 设计原则 组件构建原则 软件架构 实现细节 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-02-05 15:14:46 "},"软件工程/架构模式/架构模式.html":{"url":"软件工程/架构模式/架构模式.html","title":"架构模式","keywords":"","body":"架构模式 企业应用架构模式 架构 架构师最高层次的系统分解,且是组成系统的不易改变的组件 企业应用 一般来说,企业应用指的是大型系统 特点 持久化数据 大量数据 高并发 大量数据展示操作页面 多个系统集成 业务逻辑复杂 NAV 概览 领域逻辑模式 数据源架构模式 对象关系行为模式 对象关系结构模式 对象关系元数据映射模式 web表现模式 分布模式 离线并发模式 会话模式 基本模式 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-23 15:39:37 "},"软件工程/微服务/nav.html":{"url":"软件工程/微服务/nav.html","title":"微服务","keywords":"","body":"微服务 NAV 概览 服务建模 集成 分解单块系统 部署 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-02-12 14:46:54 "},"网络安全/Web安全/nav.html":{"url":"网络安全/Web安全/nav.html","title":"Web安全","keywords":"","body":"原则 黑名单与白名单思想 最小权限原则 纵深防御 数据与代码分离 不可预测原则 NAV 客户端脚本安全 浏览器安全 XSS攻击 CSRF 点击劫持 HTML5安全 服务端安全 注入攻击 文件上传漏洞 认证与会话管理 加密算法与随机数 Web框架安全 应用层拒绝服务攻击 web服务器配置安全 开放平台设计 运营安全 业务安全 安全开发与安全运营 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-29 16:25:34 "},"计算机网络/HTTP.html":{"url":"计算机网络/HTTP.html","title":"HTTP","keywords":"","body":"特点 基于TCP/IP的高级协议 默认端口号:80 基于请求/响应模型的:一次请求对应一次响应 无状态的:每次请求之间相互独立,不能交互数据 请求行 请求方式 请求url 请求协议/版本 请求头 请求头名称: 请求头值 请求空行 请求体 格式 POST /login.html HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko20100101 Firefox/60.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,enq=0.2 Accept-Encoding: gzip, deflate Referer: http://localhost/login.html Connection: keep-alive Upgrade-Insecure-Requests: 1 username=zhangsan 响应行 协议/版本 响应状态码 状态码描述 状态码 分类 分类描述 1** 信息,服务器收到请求,需要请求者继续执行操作 2** 成功,操作被成功接收并处理 3** 重定向,需要进一步的操作以完成请求 4** 客户端错误,请求包含语法错误或无法完成请求 5** 服务器错误,服务器在处理请求的过程中发生了错误 响应头 头名称: 值 HTTP/1.1 200 OK Content-Type: text/html;charset=UTF-8 Content-Length: 101 Date: Wed, 06 Jun 2018 07:08:42 GMT $Title$ hello , response CDN CDN加速意思就是在用户和我们的服务器之间加一个缓存机制,动态获取IP地址根据地理位置,让用户到最近的服务器访问 原理 1) 用户向浏览器提供要访问的域名; 2) 浏览器调用域名解析库对域名进行解析,由于CDN对域名解析过程进行了调整,所以解析函数库一般得到的是该域名对应的 CNAME记录,为了得到实际IP地址,浏览器需要再次对获得的CNAME域名进行解析以得到实际的IP地址;在此过程中,使用的全局负载均衡DNS解析,如根据地理位置信息解析对应的IP地址,使得用户能就近访问; 3) 此次解析得到CDN缓存服务器的IP地址,浏览器在得到实际的IP地址以后,向缓存服务器发出访问请求; 4) 缓存服务器根据浏览器提供的要访问的域名,通过Cache内部专用DNS解析得到此域名的实际IP地址,再由缓存服务器向此实际IP地址提交访问请求; 5) 缓存服务器从实际IP地址得得到内容以后,一方面在本地进行保存,以备以后使用,二方面把获取的数据返回给客户端,完成数据服务过程; 6) 客户端得到由缓存服务器返回的数据以后显示出来并完成整个浏览的数据请求过程。 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-28 10:26:50 "},"计算机网络/RESTful.html":{"url":"计算机网络/RESTful.html","title":"RESTful","keywords":"","body":" 资源 表现层 状态转化 URI代表一种资源、客户端与服务器,传递资源的某种表现层、客户端通过HTTP动词,对服务器资源进行操作 常见错误 URI包含动词 URI包含版本 Swagger 安装 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-07 16:44:51 "},"后端开发/语言/C/nav.html":{"url":"后端开发/语言/C/nav.html","title":"C","keywords":"","body":"NAV 概览 类型运算符与表达式 函数与程序结构 指针与数组 结构 输入与输出 UNIX系统接口 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-07-09 14:59:06 "},"后端开发/语言/JAVA/nav.html":{"url":"后端开发/语言/JAVA/nav.html","title":"JAVA","keywords":"","body":"NAV 语言基础 JAVA运行环境 关键字 常量与变量 数据类型转换 运算符 方法 流程控制 数组 面向对象和封装 高级 常用API 继承与多态 集合 异常 多线程 Lambda表达式 IO 网络编程 Stream流 JAVA模块化 反射 注解 嵌套类 JDBC 语法糖 泛型 编译器API 类加载器 JAVA运行管理 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-10 13:30:56 "},"后端开发/语言/JAVA/JAVA并发编程/JAVA并发编程.html":{"url":"后端开发/语言/JAVA/JAVA并发编程/JAVA并发编程.html","title":"JAVA并发编程","keywords":"","body":"线程安全性 当多个线程访问某个类时,这个类始终都能表现出正确的行为,则称这个类是线程安全的 无状态对象一定是线程安全的 原子性 if (condition){ a++; // 当此段代码运行在多线程的环境时,则会产生线程安全问题 } 观察结果的失效就是大多数竞态条件的本质 一种常见的竞态条件发生在单例构造模式中: public static Object get(){ if (instance == null){ instance = new Object(); } return instance; } 复合操作:由一系列原子操作构成 加锁机制 内置锁:synchronized关键字 重入:某个线程试图获得一个已经由它持有的锁 锁能使其保护的代码路径以串行形式访问 对持有锁的范围、时间进行良好设计 对象的共享 可见性 在没有同步的情况下,编译器或者处理器都会对一些上下文无关的指令进行重排序,这可能会导致一个线程修改了某一个数值,而另一个线程无法马上读取到修改后的数值 失效数据 非原子的64位操作 在java当中,一个64位大小的数值可以被分为2个32位的操作 加锁与可见性 之所以要在访问某个共享的可变变量时要求所有线程在锁上同步,就是为了确保读写可见性。 加锁的含义不局限与互斥行为,还包括内存可见性 volatile是比synchronized更为轻量级的同步机制,它无法进行互斥操作,但能保证内存可见性 典型用法 voatile boolean f; ... while (f){ // do something } 发布与逸出 发布: 使对象能在当前代码作用域之外使用 逸出: 某个不该发布的对象被发布了 线程封闭 某个对象只能在线程之内使用 Ad-hoc线程封闭 完全由程序承担,很脆弱 栈封闭 对象只能在局部(方法内)使用 ThreadLocal 使用ThreadLocal包装的对象只能在当前线程使用 不变性 不可变对象一定是线程安全的 对象创建后其状态就不能修改 对象的所有域都是final 在对象创建的过程中this引用没有逸出 安全发布 在静态初始化函数中初始化一个对象的引用 将对象的引用保存到volatile类型的域或者 Reference对象 将对象的引用保存到正确初始化的对象的final域 将对象的引用保存到由锁保护的域 对象的组合 依赖状态的操作:某个操作包含有基于状态的先验操作 if (a== 1){ a++; } 实例封闭 将线程不安全的对象封装在某个进行良好并发控制的对象内 客户端加锁 private Object obj = new Object(); ... synchronized(obj){ obj.xxx(); } 基础构建模块 JAVA5后自带了很多有关并发编程的类库 同步容器类 迭代器与ConcurrentModificationException 当在迭代的时候,容器元素发生了修改,则会抛出这个异常 并发容器 ConcurrentHashMap 分段锁 CopyOnWriteArrayList 在写的时候不对原集合进行修改,而是重新复制一份,修改完之后,再移动指针 阻塞队列 BlockingQueue 该类型的队列执行take时如果没有元素则会一直阻塞,put如果超过了界限也会一直阻塞,直至有可用空间 实现类:ArrayBlockingQueue与LinkedBlockingDeque等 同步工具类 CountDownLatch(闭锁) 确保某些活动直到其他活动都完成后才继续执行(并发编程中的屏障) CountDownLatch lock = new CountDownLatch(5); for (int i = 0; i { Random random = new Random(); try { Thread.sleep(random.nextInt(5000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(\"线程\"+ finalI +\"完成\"); lock.countDown(); }).start(); } lock.await(); System.out.println(\"all mission complete\"); FutureTask 用来执行一些较长时间的计算,通过get来获取结果(阻塞或者超时) Semaphore(信号量) 用来控制使用资源的主体数量 Semaphore semaphore = new Semaphore(5); for (int i = 0; i { Random rnd = new Random(); try { semaphore.acquire(); System.out.println(Thread.currentThread()+\"acquire lock\"); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }finally { semaphore.release(); } }).start(); CyclicBarrier(栅栏) 闭锁用于等待事件,而栅栏用于等待其他线程 CyclicBarrier barrier = new CyclicBarrier(5, () -> System.out.println(\"mission complete\")); for (int i = 0; i { Random rnd= new Random(); try { System.out.println(Thread.currentThread()+\"run\"); Thread.sleep(rnd.nextInt(3000)); barrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } }).start(); 任务执行 串行执行 显式创建线程执行 Executor框架 public interface Executor { void execute(Runnable command); } 执行策略 什么线程 什么顺序 多少任务执行 多少任务等待 如何放弃以及通知放弃 任务执行前操作 线程池 Executors.newFixedThreadPool(5); // 创建固定长度的线程池 Executors.newCachedThreadPool(); // 可缓存线程池,动态伸缩 Executors.newSingleThreadExecutor(); // 单线程线程池 Executors.newScheduledThreadPool(5); // 可以延迟或者定时执行 生命周期 ExecutorService继承了Executor,增加了一些方法 public interface ExecutorService extends Executor { // 平缓关闭 void shutdown(); // 粗暴关闭 List shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; Future submit(Callable task); Future submit(Runnable task, T result); Future submit(Runnable task); List> invokeAll(Collection> tasks) throws InterruptedException; T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException; } 取消与关闭 取消策略 通常,使用中断来取消是最合理的方式 class MyThread extends Thread{ @Override public void run() { while(!isInterrupted()){ System.out.println(\"running\"); try { Thread.sleep(1000); } catch (InterruptedException e) { break; } } System.out.println(\"my thread done\"); } } 使用Future取消 Future future = service.submit(() -> { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return Math.random(); }); try { Double ret = future.get(3, TimeUnit.SECONDS); System.out.println(\"result\"+ret); } catch (ExecutionException | TimeoutException e) { e.printStackTrace(); }finally { future.cancel(true); System.out.println(\"task cancel\"); } 处理不可中断的阻塞 由于如IO等的资源一旦阻塞就无法进行中断,所以可对其做关闭处理来模拟中断 停止基于线程的服务 使用生命周期管理ExecutorService 毒药对象 本质上就是一个flag,当队列读取到这个毒药时,就会停止相关操作 处理非正常的线程终止 Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(t + \"something happen\" + e); } }); new Thread(){ @Override public void run() { throw new RuntimeException(\"aaaa\"); } }.start(); JVM关闭钩子 Runtime.getRuntime().addShutdownHook(new Thread(){ @Override public void run() { System.out.println(\"jvm shutdown\"); } }); 线程池的大小 Ncpu = CPU数量 Ucpu = 预期CPU使用率 W/C = 等待时间/计算时间 最优大小等于 Ncpu Ucpu (1 + W/C) 活跃性危险 死锁 静态顺序死锁 动态顺序死锁 资源死锁 死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 诊断与避免 定时锁 获取-超时-退出 其他活跃性危险 饥饿 无法获取到需要的资源 响应性慢 活锁 线程不断重复某个操作 性能与伸缩性 引入线程的开销 上下文切换 内存同步 阻塞 如何减少锁的竞争 缩小锁的范围 缩小synchronized关键字包围的代码块 减小锁的粒度 不同的操作使用不同的锁 分段锁 替代独占锁 采取读写锁 并发程序测试 正确性测试 安全性测试 性能测试 性能测试陷阱 垃圾回收 动态编译(JIT) 编译优化 竞争程度 显式锁 Lock接口 public interface Lock { // 其中一个实现类:ReentrantLock void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition(); } 显式锁拥有比内置锁(synchronized关键字)更多的功能,但使用起来更加复杂,显式锁作为一种高级工具,只有在synchronized无法满足需求的情况下才使用 ReentrantLock是一种互斥锁,也就说在同一时间内只有一个线程能对资源读或者写,如果要对读写分别控制,考虑使用ReadWriteLock MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-01 15:45:00 "},"后端开发/语言/JAVA/JAVA并发编程/JAVA内存模型.html":{"url":"后端开发/语言/JAVA/JAVA并发编程/JAVA内存模型.html","title":"JAVA内存模型","keywords":"","body":"JAVA内存模型(JMM) 线程安全 当多个线程访问某个类时,这个类始终都能表现出正确的行为,则称这个类是线程安全的 解决方法 内置锁 同步方法 静态:当前类的同步代码块 非静态:当前对象的同步代码块 同步代码块 显式锁 死锁 两个线程互相等待对方持有的锁而陷入无限等待状态 ThreadLocal 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本 public class Main implements Runnable{ private ThreadLocal ts = new ThreadLocal<>(); @Override public void run() { ts.set(Thread.currentThread().getName()); System.out.println(ts.get()); } } 原理 public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { map.set(this, value); } else { createMap(t, value); } } JAVA内存模型JMM JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本 volatile 与可见性 可见性也就是说一旦某个线程修改了该被volatile修饰的变量,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,可以立即获取修改之后的值 重排序 数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性 as-if-serial语义 as-if-serial语义的意思指:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-12-30 21:24:59 "},"后端开发/语言/JAVA/JVM/JVM.html":{"url":"后端开发/语言/JAVA/JVM/JVM.html","title":"JVM","keywords":"","body":" 系统虚拟机 软件虚拟机 Hotspot构成 NAV 运行参数 内存结构 垃圾回收 字节码 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-04 14:14:38 "},"后端开发/语言/JAVA/JAVA编程规范.html":{"url":"后端开发/语言/JAVA/JAVA编程规范.html","title":"JAVA编程规范","keywords":"","body":"JAVA编程规范 编码 Integer缓存问题 【强制】所有整型包装类对象之间值的比较,全部使用 equals 方法比较。 说明:对于 Integer var = ? 在 - 128 至 127 范围内的赋值,Integer 对象是在 IntegerCache.cache 产 生,会复用已有对象,这个区间内的 Integer 值可以直接使用 == 进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断 Integer a = 100, b = 100, c = 150, d = 150; System.out.println(a == b); // true System.out.println(c == d); // false 直接创建包装类时,是通过valueOf方法来进行转换的,但是这个方法这里做了缓存,在某个区间内的同一个整数都会用同一个对象来表示 if (i >= IntegerCache.low && i 所以也就会造成上面那段代码的情况 同样,Long、Character、 Short 、Boolean都有这个问题 但是Boolean本来就取值范围就是true与false,所以这个包装类本身是使用了两个成员变量来缓存true与false MY all right reserved,powered by Gitbook该页面最后修改于: 2020-02-12 16:14:04 "},"后端开发/语言/xml.html":{"url":"后端开发/语言/xml.html","title":"XML","keywords":"","body":"xml 与 html xml标签都是自定义的,html标签是预定义。 xml的语法严格,html语法松散 xml是存储数据的,html是展示数据 基本语法 xml文档的后缀名 .xml xml第一行必须定义为文档声明 xml文档中有且仅有一个根标签 属性值必须使用引号(单双都可)引起来 标签必须正确关闭 xml标签名称区分大小写 组成部分 文档声明 格式: 属性列表: version:版本号,必须的属性 encoding:编码方式。告知解析引擎当前文档使用的字符集,默认值:ISO-8859-1 standalone:是否独立 取值: yes:不依赖其他文件 no:依赖其他文件 标签 规则: 名称可以包含字母、数字以及其他的字符 名称不能以数字或者标点符号开始 名称不能以字母 xml(或者 XML、Xml 等等)开始 名称不能包含空格 属性属性 id属性值唯一 文本: CDATA区:在该区域中的数据会被原样展示 格式: 约束 DTD 内部dtd:将约束规则定义在xml文档中 外部dtd:将约束的规则定义在外部的dtd文件中 本地: 网络: Schema 解析 DOM:将标记语言文档一次性加载进内存,在内存中形成一颗dom树 优点:操作方便,可以对文档进行CRUD的所有操作 缺点:占内存 SAX:逐行读取,基于事件驱动的。 优点:不占内存。 缺点:只能读取,不能增删改 jsuop Jsoup:工具类,可以解析html或xml文档,返回Document parse Document:文档对象。代表内存中的dom树 getElementByXX Element:元素对象 getElementByXX Node:节点对象 快捷查询 selector XPath MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-08 14:31:07 "},"后端开发/中间件/activeMQ.html":{"url":"后端开发/中间件/activeMQ.html","title":"ActiveMQ","keywords":"","body":"消息中间件带来的好处 解耦 异步 横向扩展 安全可靠 顺序保证 中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。 中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。 消息中间件是指一种在需要进行网络通信的系统进行通道的建立,数据或文件发送的中间件。消息中间件的一个重要作用是可以跨平台操作,为不同操作系统上的应用软件集成提供便利。 JMS Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。 Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。 队列模型 主题模型 JMS编码接口之间的关系 AMQP 高级消息队列协议即Advanced Message Queuing Protocol(AMQP)是一个用于统一面向消息中间件实现的一套标准协议,其设计目标是对于消息的排序、路由(包括点对点和订阅-发布)、保持可靠性、保证安全性。 对比 安装 windows linux 下载 解压 tar -xzf closer.cgi\\?filename=%2Factivemq%2 F5.15.9%2Fapache-activemq-5.15.9-bin.tar.gz\\&action=download 启动 ./activemq start 使用 初始化 // 创建连接 ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url); Connection connection = connectionFactory.createConnection(); connection.start(); // 创建会话 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // 创建目的 Destination destination = session.createQueue(queueName); 队列模式 生产消息 MessageProducer producer = session.createProducer(destination); for (int i = 0; i 消费消息 MessageConsumer consumer = session.createConsumer(destination); consumer.setMessageListener(new MessageListener() { public void onMessage(Message message) { System.out.println(message); } }); 在队列模式下,消费者会平均消费生产者生产的消息 主题模式 Destination destination = session.createTopic(topicName); 主题模式下,订阅之后才能收到消息 生产者生产消息会推送给所有消费者 集成Spring jms 配置 @Bean public ConnectionFactory connectionFactory(){ return new ActiveMQConnectionFactory(\"tcp://127.0.0.1:61616\"); } @Bean public Destination destination(){ return new ActiveMQQueue(\"queue\"); } @Bean public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory){ return new JmsTemplate(connectionFactory); } 使用 jmsTemplate.send(destination,new MessageCreator() { public Message createMessage(Session session) throws JMSException { TextMessage msg = session.createTextMessage(); msg.setText(message); return msg; } }); 配置消费者 @Bean public MessageListener messageListener(){ return new ConsumerMessageListener(); } @Bean public DefaultMessageListenerContainer defaultMessageListenerContainer(Destination destination, ConnectionFactory connectionFactory, MessageListener messageListener){ DefaultMessageListenerContainer container = new DefaultMessageListenerContainer(); container.setConnectionFactory(connectionFactory); container.setMessageListener(messageListener); container.setDestination(destination); return container; } 集群 高可用 负载均衡 集群方式 客户端集群 Broker集群 Master Slave 企业开发需要解决的问题 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-07-20 10:27:41 "},"后端开发/中间件/rabbitMQ.html":{"url":"后端开发/中间件/rabbitMQ.html","title":"RabbitMQ","keywords":"","body":"介绍 RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。 安装 安装erlang 安装rabbitmq-server 以上操作均可以使用包管理工具完成 使用docker docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management 消息模型 订阅模型-Fanout 可以有多个消费者 每个消费者有自己的queue(队列) 每个队列都要绑定到Exchange(交换机) 生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。 交换机把消息发送给绑定过的所有队列 队列的消费者都能拿到消息。实现一条消息被多个消费者消费 订阅模型-Direct 订阅模型-Topic Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符 # 可以匹配一个或多个词 *只能匹配一个词 消息确认机制(ACK) 自动ACK:消息一旦被接收,消费者自动发送ACK 手动ACK:消息接收后,不会发送ACK,需要手动调用 核心概念 Server Connection Channel (信道):它建立在上述的TCP连接中 Message Virtual host 权限控制的基本单位,一个VirtualHost里面有若干Exchange和 MessageQueue,以及指定被哪些user使用 Exchange 生产者将消息发送到Exchange(交换器),由Exchange将消息路由到一个 或多个Queue中(或者丢弃)。Exchange并不存储消息 Binding Routing key 生产者在将消息发送给Exchange的时候,一般会指定一个routing key, 来指定这个消息的路由规则,而这个routing key需要与Exchange Type及binding key联 合使用才能最终生效 Queue (队列)是RabbitMQ的内部对象,用于存储消息 使用 引入依赖 org.springframework.boot spring-boot-starter-amqp 添加队列 添加交换机 添加绑定 发送 @Autowired private RabbitTemplate rabbitTemplate; public void sendUser(User user) throws Exception{ CorrelationData correlationData = new CorrelationData(user.getUsername()); rabbitTemplate.convertAndSend(\"user-exchange\",\"user.abcd\",user,correlationData); } 接收 消费端配置 spring.rabbitmq.listener.simple.concurrency=5 spring.rabbitmq.listener.simple.acknowledge-mode=auto spring.rabbitmq.listener.simple.max-concurrency=10 spring.rabbitmq.listener.simple.prefetch=1 消费 @RabbitListener(bindings = @QueueBinding( value = @Queue(value = \"user-queue\"), exchange = @Exchange(name = \"user-exchange\",type = \"topic\"), key = \"user.#\" )) @RabbitHandler public void onMessage(@Payload User user){ log.info(\"on message:{}\",user); } 消息可靠投递方案 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-13 21:46:25 "},"后端开发/中间件/RocketMQ.html":{"url":"后端开发/中间件/RocketMQ.html","title":"RocketMQ","keywords":"","body":" Apache RocketMQ是一个采用Java语言开发的分布式的消息系统,由阿里巴巴团队开发,于2016年底贡献给Apache 核心概念 Producer 消息生产者,负责产生消息,一般由业务系统负责产生消息 Producer Group 一类 Producer 的集合名称,这类 Producer 通常发送一类消息,且发送逻辑一致 Consumer 消息费者,负责消费消息,一般是后台系统负责异步消费 Push Consumer 服务端向消费者端推送消息 Pull Consumer 消费者端向服务定时拉取消息 Consumer Group 一类 Consumer 的集合名称,这类 Consumer 通常消费一类消息,且消费逻辑一致 NameServer 集群架构中的组织协调员 收集broker的工作情况 不负责消息的处理 Broker 是RocketMQ的核心负责消息的发送、接收、高可用等(真正干活的) 需要定时发送自身情况到NameServer,默认10秒发送一次,超时2分钟会认为该broker失效。 Topic 不同类型的消息以不同的Topic名称进行区分,如User、Order等 是逻辑概念 Message Queue 消息队列,用于存储消息 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-12-23 13:20:17 "},"后端开发/中间件/Kafka.html":{"url":"后端开发/中间件/Kafka.html","title":"Kafka","keywords":"","body":"概念 生产者 消费者 消费者群组 节点 主题 Partition Replication Replication Leader ReplicaManager 应用场景 消息队列 行为跟踪 日志收集 流处理 事件源 持久性日志 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-07-31 10:23:59 "},"后端开发/中间件/Tomcat.html":{"url":"后端开发/中间件/Tomcat.html","title":"Tomcat","keywords":"","body":" Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以向浏览器等Web客户端提供文档,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。目前最主流的三个Web服务器是Apache、 Nginx 、IIS。 web服务器与web容器 目录结构 部署方式 直接将项目放到webapps目录下 配置conf/server.xml文件 在标签体中配置 docBase:项目存放的路径 path:虚拟目录 在conf\\Catalina\\localhost创建任意名称的xml文件。在文件中编写 虚拟目录:xml文件的名称 JAVA WEB项目目录结构 项目的根目录 WEB-INF目录: web.xml:web项目的核心配置文件 classes目录:放置字节码文件的目录 lib目录:放置依赖的jar包 优化 禁用AJP连接 AJP(Apache JServ Protocol)是定向包协议。因为性能原因,使用二进制格式来传输可读性文本。WEB服务器通过 TCP连接 和 SERVLET容器连接 设置线程池 设置运行模式 bio nio apr MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-24 21:38:16 "},"后端开发/中间件/Nginx.html":{"url":"后端开发/中间件/Nginx.html","title":"Nginx","keywords":"","body":"Nginx 主要功能 http服务器 反向代理 负载均衡 动态路由 请求过滤 虚拟主机 基于端口的虚拟主机 server { listen 80; ... } 基于域名的虚拟主机 server { listen 80; server_name www.itmayiedu.com; ... } location语法 =开头表示精确匹配 ^~ 开头表示uri以某个~字符串开头,不是正则匹配 ~ 开头表示区分大小写的正则匹配 ~* 开头表示不区分大小写的正则匹配 / 通用匹配, 如果没有其它匹配,任何请求都会匹配到 反向代理 正向代理:通过客户机的配置,实现让一台服务器代理客户机,客户的所有请求都交给代理服务器处理。正向代理隐藏真实客户端 反向代理:用一台服务器,代理真实服务器,用户访问时,不再是访问真实服务器,而是代理服务器。反向代理隐藏真实服务端 反向代理隐藏真实内部ip地址,请求先访问nginx代理服务器,nginx服务器再转发到真实服务器中 nginx反向代理配置 http{ ... server { listen 80; server_name hostname; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://127.0.0.1:8080; proxy_connect_timeout 600; proxy_read_timeout 600; } } } 负载均衡 所有请求先到负载均衡器,在由负载均衡器采用负载均衡算法(轮训、IP绑定、权重)分发到不同实际的服务器中 四层负载均衡:基于IP+端口的负载均衡(传输层),此种负载均衡不理解应用协议(如HTTP/FTP/MySQL等等)。例子:LVS(软负载),F5硬件负载 七层负载均衡:基于应用层的信息决定如何转发(应用层) 带来的问题 分布式Session一致性问题 分布式定时任务调度幂等性问题 分布式生成全局ID Upstream Server 上游服务器,就是被nginx代理最后真实访问的服务器 nginx配置负载均衡 upstream so { server www.baidu.com:80; server www.163.com:80; } server { listen 8080; location / { proxy_pass http://so/; } } 轮询算法 轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务,如果后端某台服务器死机,自动剔除故障系统,使用户访问不受影响。 weight(轮询权值) weight的值越大分配到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下。或者仅仅为在主从的情况下设置不同的权值,达到合理有效的地利用主机资源。 # 设置权重 server www.baidu.com:80 weight=2; ip_hash 每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题。俗称IP绑定。 server { ... ip_hash; } fair(第三方) 比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间 来分配请求,响应时间短的优先分配 url_hash(第三方) 按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步提高后端缓存服务器的效率 动态负载均衡 Consul Consul是一款开源的分布式服务注册与发现系统,通过HTTP API可以使得服务注册、发现实现起来非常简单 双机主从热备 LVS 可以实现传输层四层负载均衡。LVS是Linux Virtual Server的缩写,意思是Linux虚拟服务器。目前有三种IP负载均衡技术(VS/NAT、VS/TUN和VS/DR);八种调度算法(rr,wrr,lc,wlc,lblc,lblcr,dh,sh) Keepalived Keepalived是基于vrrp协议的一款高可用软件。Keepailived有一台主服务器和多台备份服务器,在主服务器和备份服务器上面部署相同的服务配置,使用一个虚拟IP地址对外提供服务,当主服务器出现故障时,虚拟IP地址会自动漂移到备份服务器 故障转移 当上游服务器,一旦出现故障或者是没有及时响应的话,应该直接轮训到下一台服务器,保证服务器的高可用 配置超时时间,超时进行故障转移 location / { proxy_pass http://so/; proxy_connect_timeout 1s; proxy_send_timeout 1s; proxy_read_timeout 1s; } 动静分离 动静分离将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态资源的速度,降低对后台应用访问的频次。这里我们将静态资源放到nginx中,动态资源转发到tomcat服务器中 nginx实现方式 通过对URL或者域名的判断,进行转发 浏览器缓存 对于静态文件,例如:CSS、图片,服务器会自动完成 Last Modified 和 If Modified Since 的比较,完成缓存或者更新 SSI 服务端嵌入 ssi包含类似于jsp页面中的incluce指令,ssi是在web服务端将include指定 的页面包含在网页中,渲染html网页响 应给客户端 。nginx、apache等多数web容器都支持SSI指令。 配置 server{ listen 80; server_name www.edu.com; ssi on; ssi_silent_errors on; ..... MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-25 20:57:45 "},"后端开发/全文检索/Lucene.html":{"url":"后端开发/全文检索/Lucene.html","title":"Lucene","keywords":"","body":"全文检索 数据分类 结构化数据 非结构化数据 数据查询 结构化查询 非结构化查询 顺序扫描法 全文检索 应用场景 数据量大 数据结构不固定 Lucene实现全文检索的流程 创建索引库 // 创建directory指定索引存放位置 Directory directory = FSDirectory.open(new File(\"./index\").toPath()); IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig()); File dir = new File(\"./res\"); File[] files = dir.listFiles(); assert files != null; // 遍历文件 for (File file : files) { String fileName = file.getName(); String filePath = file.getPath(); String content = FileUtils.readFileToString(file, \"utf8\"); long fileSize = FileUtils.sizeOf(file); // 根据文件内容生成成员 Field fieldName = new TextField(\"name\",fileName, Field.Store.YES); Field fieldPath = new TextField(\"path\",filePath,Field.Store.YES); Field fieldContent = new TextField(\"content\",content,Field.Store.YES); Field fieldSize = new TextField(\"size\", String.valueOf(fileSize),Field.Store.YES); // 将成员添加到文档中 Document document = new Document(); document.add(fieldName); document.add(fieldPath); document.add(fieldContent); document.add(fieldSize); // 将文档写入索引库 indexWriter.addDocument(document); } indexWriter.close(); 搜索 // 创建directory指定索引存放位置 Directory directory = FSDirectory.open(new File(\"./index\").toPath()); IndexReader indexReader = DirectoryReader.open(directory); IndexSearcher indexSearcher = new IndexSearcher(indexReader); Query query = new TermQuery(new Term(\"content\",\"spring\")); TopDocs docs = indexSearcher.search(query, 10); System.out.println(\"总记录数:\"+docs.totalHits); ScoreDoc[] scoreDocs = docs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) { int id = scoreDoc.doc; Document document = indexSearcher.doc(id); System.out.println(document.get(\"name\")); System.out.println(document.get(\"path\")); System.out.println(document.get(\"size\")); // System.out.println(document.get(\"content\")); System.out.println(\"--------------\"); } indexReader.close(); 分析 Analyzer analyzer = new StandardAnalyzer(); TokenStream tokenStream = analyzer.tokenStream(\"\", \"Learn how to create a web page with Spring MVC.\"); CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); tokenStream.reset(); while (tokenStream.incrementToken()){ System.out.println(charTermAttribute.toString()); } 使用别的分析器 Analyzer analyzer = new IKAnalyzer(); 维护 删除 Directory directory = FSDirectory.open(new File(\"./index\").toPath()); IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig()); //indexWriter.deleteAll(); indexWriter.deleteDocuments(new Term(\"content\",\"name\")); indexWriter.close(); 更新 indexWriter.updateDocument(new Term(\"content\",\"name\"),document); QueryParser MY all right reserved,powered by Gitbook该页面最后修改于: 2019-10-18 14:42:17 "},"后端开发/全文检索/ElasticSearch.html":{"url":"后端开发/全文检索/ElasticSearch.html","title":"ElasticSearch","keywords":"","body":" ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口 安装 使用 docker docker run elasticsearch:7.3.1 docker network create somenetwork; docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e \"discovery.type=single-node\" elasticsearch:7.3.1 图形化管理界面 head 概念 索引(indices)--------------------------------Databases 数据库 类型(type)-----------------------------Table 数据表 文档(Document)----------------Row 行 字段(Field)-------------------Columns 列 索引 index 类型 type 字段 field 映射 mapping 文档 document 集群 cluster 节点 node 分片与复制 索引结构 倒排索引:根据词找文章 正排索引:根据文章找词 创建索引 PUT /blog { \"settings\": { \"number_of_shards\": 3, \"number_of_replicas\": 2 } } 获取索引库信息 GET /blog 删除索引库 DELETE /blog 添加映射 PUT /索引库名/_mapping/类型名称 { \"properties\": { \"字段名\": { \"type\": \"类型\", \"index\": true, \"store\": true, \"analyzer\": \"分词器\" } } } 查看映射关系 GET /索引库名/_mapping 更新索引 POST http://my-pc:9200/blog/{indexName} 添加文档 POST /索引库名/类型名 { \"key\":\"value\" } 自定义id POST /索引库名/类型/id值 { ... } 删除文档 DELETE http://my-pc:9200/blog/hello/1 修改文档 UPDATE http://my-pc:9200/blog/hello/1 查询 基本查询 GET /索引库名/_search { \"query\":{ \"查询类型\":{ \"查询条件\":\"查询条件值\" } } } 根据ID查询 GET http://my-pc:9200/blog/hello/1 根据字段查询 Term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。 GET /shop/_search { \"_source\": [\"title\",\"price\"], \"query\": { \"term\": { \"price\": 2699 } } } queryString查询 { \"query\":{ \"query_string\":{ \"default_field\":\"content\", \"query\":\"内容\" } } } 过滤 includes:来指定想要显示的字段 excludes:来指定不想要显示的字段 GET /shop/_search { \"_source\": { \"includes\":[\"title\",\"price\"] }, \"query\": { \"term\": { \"price\": 2699 } } } 排序 GET /heima/_search { ... \"sort\": [ { \"price\": { \"order\": \"desc\" } } ] } 模糊查询 GET /heima/_search { \"query\": { \"fuzzy\": { \"title\": { \"value\":\"appla\", \"fuzziness\":1 } } } } 测试分词 GET http://my-pc:9200/_analyze { \"analyzer\": \"standard\", \"text\": \"中文测试分词\" } 中文分词器 下载 docker run --name elasticsearch --net somenetwork -v /root/plugin:/usr/share/elasticsearch/plugins -p 9200:9200 -p 9300:9300 -e \"discovery.type=single-node\" elasticsearch:7.3.1 GET http://my-pc:9200/_analyze { \"analyzer\": \"ik_max_word\", \"text\": \"中文测试分词\" } 聚合 桶 ES集群 集群 搭建 配置 # 集群名称,必须保持一致 cluster.name: elasticsearch # 节点的名称 node.name: node-1 # 监听网段 network.host: 0.0.0.0 # 本节点rest服务端口 http.port: 9201 # 本节点数据传输端口 transport.tcp.port: 9301 # 集群节点信息 discovery.seed_hosts: [\"127.0.0.1:9301\",\"127.0.0.1:9302\",\"127.0.0.1:9303\"] cluster.initial_master_nodes: [\"node-1\",\"node-2\",\"node-3\"] 另外两个节点配置省略... JAVA客户端 依赖 org.elasticsearch elasticsearch 7.3.1 org.elasticsearch.client transport 7.3.1 连接 Settings settings = Settings.builder() .put(\"cluster.name\",\"docker-cluster\") .build(); TransportClient client = new PreBuiltTransportClient(settings); client.addTransportAddress( new TransportAddress(InetAddress.getByName(\"my-pc\"),9300)); 创建索引 client.admin().indices().prepareCreate(\"index\").get(); 设置映射 XContentBuilder builder = XContentFactory.jsonBuilder() .startObject() .startObject(\"article\") .startObject(\"properties\") .startObject(\"id\") .field(\"type\", \"long\") .field(\"store\", true) .endObject() .startObject(\"title\") .field(\"type\", \"text\") .field(\"store\", true) .field(\"analyzer\", \"ik_smart\") .endObject() .startObject(\"content\") .field(\"type\", \"text\") .field(\"store\", true) .field(\"analyzer\", \"ik_smart\") .endObject() .endObject() .endObject() .endObject(); client.admin().indices().preparePutMapping(\"index\") .setType(\"article\") .setSource(builder) .get(); 添加文档 XContentBuilder builder = XContentFactory.jsonBuilder() .startObject() .field(\"id\",1L) .field(\"title\",\"央视快评:勇做敢于斗争善于斗争的战士\") .field(\"content\",\"9月3日,习近平总书记在中央党校(国家行政学院)中青年干部培训班开班式上发表重要讲话强调,广大干部特别是年轻干部要经受严格的思想淬炼、政治历练、实践锻炼,发扬斗争精神,增强斗争本领,为实现“两个一百年”奋斗目标、实现中华民族伟大复兴的中国梦而顽强奋斗。\") .endObject(); client.prepareIndex(\"index\",\"article\",\"1\") .setSource(builder) .get(); POJO添加文档 Article article = new Article(); article.setId(3L); article.setTitle(\"3央视快评:勇做敢于斗争善于斗争的战士\"); article.setContent(\"9月3日3333,(国家行政学院)中青年干部培训班开班式上发表重要讲话强调,广大干部特别是年\"); String json = new ObjectMapper().writeValueAsString(article); client.prepareIndex(\"index\",\"article\",\"3\") .setSource(json, XContentType.JSON) .get(); 查询 根据ID QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds(\"1\",\"2\"); SearchResponse response = client.prepareSearch(\"index\") .setTypes(\"article\") .setQuery(queryBuilder) .get(); SearchHits hits = response.getHits(); System.out.println(\"总记录:\"+hits); SearchHit[] ret = hits.getHits(); for (SearchHit documentFields : ret) { Map map = documentFields.getSourceAsMap(); System.out.println(\"id:\"+map.get(\"id\")); System.out.println(\"title:\"+map.get(\"title\")); System.out.println(\"content:\"+map.get(\"content\")); System.out.println(\"-------------------\"); } 根据term QueryBuilder queryBuilder = QueryBuilders.termQuery(\"title\",\"斗争\"); 根据queryString QueryBuilder queryBuilder = QueryBuilders.queryStringQuery(\"青年强调\") .defaultField(\"content\"); 分页查询 SearchResponse response = client.prepareSearch(\"index\") .setTypes(\"article\") .setQuery(queryBuilder) .setFrom(10) .setSize(5) .get(); 高亮显示结果 HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.field(highlight); highlightBuilder.preTags(\"\"); highlightBuilder.postTags(\"\"); SearchResponse response = client.prepareSearch(\"index\") .setTypes(\"article\") .setQuery(queryBuilder) .highlighter(highlightBuilder) .get(); SearchHits hits = response.getHits(); System.out.println(\"总记录:\"+hits.getTotalHits()); SearchHit[] ret = hits.getHits(); for (SearchHit documentFields : ret) { Map map = documentFields.getSourceAsMap(); System.out.println(\"id:\"+map.get(\"id\")); System.out.println(\"content:\"+map.get(\"content\")); Map highlightFields = documentFields.getHighlightFields(); System.out.println(highlightFields.get(highlight).getFragments()[0]); System.out.println(\"-------------------\"); } kibana Kibana是一个基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能,生成各种图表,如柱形图,线状图,饼图等。 而且还提供了操作Elasticsearch索引数据的控制台,并且提供了一定的API提示,非常有利于我们学习Elasticsearch的语法。 安装 docker docker pull kibana:5.6.8 # 拉取镜像 docker run -d --name kibana --net somenetwork -p 5601:5601 kibana:5.6.8 # 启动 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-12-20 19:14:06 "},"后端开发/框架/Spring/nav.html":{"url":"后端开发/框架/Spring/nav.html","title":"Spring","keywords":"","body":" 基本 spring概览 装配Bean 高级装配 AOP 事务 SpringMVC SpringMVC起步 渲染WEB视图 SpringMVC高级特性 Spring Data 概览 ORM 缓存数据 Elasticsearch Spring Security 概览 保护方法调用 Spring集成 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-11 19:12:17 "},"后端开发/框架/SpringBoot/nav.html":{"url":"后端开发/框架/SpringBoot/nav.html","title":"SpringBoot","keywords":"","body":"Spring Boot 内嵌式容器简化Web项目 没有冗余代码生成和XML配置的要求 与和SpringCloud SpringCloud依赖于SpringBoot组件,使用SpringMVC编写HTTP接口,同时SpringCloud是一套完整的微服务解决框架 环境搭建 org.springframework.boot spring-boot-starter-parent 2.1.8.RELEASE org.springframework.boot spring-boot-starter-web @SpringBootApplication public class Application{ public static void main(String[] args) { SpringApplication.run(Application.class); } } 热部署 org.springframework.boot spring-boot-devtools true IDEA需要开启自动编译 配置 YML语法 # 普通数据配置 name: hello # 对象配置 person: name: kb age: 3 # 配置数组、集合(字符串) city: - beijing - tianjing - chongqing # 配置数组、集合(对象) student: - name: tom age: 3 - name: ll age: 2 属性注入 @Value @Value(\"${name}\") private String name; @ConfigurationProperties @RestController @ConfigurationProperties(prefix = \"person\") public class Controller { private String name; private Integer age; @RequestMapping(\"/hi\") public String hello(){ return name+age; } // 省略setter } 全局异常捕获 @ControllerAdvice public class ErrorHandler { @ResponseBody @ExceptionHandler(Throwable.class) public String error(Exception e){ return e.getMessage(); } } 异步调用 添加@EnableAsync 在需要异步调用的方法上面添加@Async 多环境配置 spring.profiles.active=dev 添加开发环境配置文件application-dev.properties 事务管理 依赖 javax.transaction javax.transaction-api 1.3 添加@Transactional 多数据源 配置多个DataSource,一个DataSource配置一个事务管理器,声明事务时指定事务管理器, 不同的ORM框架有不同的指定数据源的方式 jta-atomikos 通过把多个DataSource交给jta事务管理器管理,使用jta事务管理器来解决分布式事务问题 打包 jar 添加插件 org.springframework.boot spring-boot-maven-plugin 执行mvn package war 添加打包插件 设置打包方式 war 执行打包命令 性能 组件自动扫描带来的问题 使用 @SpringBootApplication 注解后,会触发自动配置( auto-configuration )和 组件扫描 ( component scanning ) JVM参数调整 将tomcat改为undertow org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-tomcat org.springframework.boot spring-boot-starter-undertow 监控中心 Actuator是spring boot的一个附加功能,可在应用程序生产环境时监视和管理应用程序 添加依赖 org.springframework.boot spring-boot-starter-actuator 添加配置 # 暴露出所有监控接口 management: endpoints: web: exposure: include: \"*\" 路径 作用 /actuator/beans 显示应用程序中所有Spring bean的完整列表。 /actuator/configprops 显示所有配置信息。 /actuator/env 陈列所有的环境变量。 /actuator/mappings 显示所有@RequestMapping的url整理列表。 /actuator/health 显示应用程序运行状况信息 up表示成功 down失败 /actuator/info 返回配置中前缀为info的配置项 集成其他框架 集成freemarker 引入依赖 org.springframework.boot spring-boot-starter-freemarker 配置 spring.freemarker.allow-request-override=false spring.freemarker.cache=true spring.freemarker.check-template-location=true spring.freemarker.charset=UTF-8 spring.freemarker.content-type=text/html spring.freemarker.expose-request-attributes=false spring.freemarker.expose-session-attributes=false spring.freemarker.expose-spring-macro-helpers=false spring.freemarker.suffix=.ftl spring.freemarker.template-loader-path=classpath:/templates/ 创建Controller @Controller public class HelloController { @RequestMapping(\"hello\") public String index(ModelMap map){ map.put(\"hello\",\"java\"); return \"index\"; } } 在template目录下创建index.ftl ${hello} 集成Mybatis 引入依赖 org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.0 配置数据库信息和mybatis配置 # 数据库连接信息 spring.datasource.username=root spring.datasource.password=123 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql:///ssm # mybatis相关配置 mybatis.mapper-locations=mappers/*.xml mybatis.configuration.map-underscore-to-camel-case=true 配置mybatis包扫描路径 @MapperScan(basePackages = \"wang.ismy.springmybatis.mapper\") public class SpringMybatisApplication { public static void main(String[] args) { SpringApplication.run(SpringMybatisApplication.class, args); } } 整合PageHelper 引入依赖 com.github.pagehelper pagehelper-spring-boot-starter 1.2.13 配置 pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql pagehelper.page-size-zero=true 集成Junit 导入依赖 org.springframework.boot spring-boot-starter-test test 建立测试 @SpringBootTest @RunWith(SpringRunner.class) public class ControllerTest{ @Autowired UserMapper mapper; @Test public void test(){ assertNotNull(mapper); } } 集成Spring data jpa 依赖 org.springframework.boot spring-boot-starter-data-jpa 配置 # 数据库连接信息 spring.datasource.username=root spring.datasource.password=123 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql:///ssm # spring data jpa相关配置 spring.jpa.database=mysql spring.jpa.show-sql=true spring.jpa.generate-ddl=true spring.jpa.hibernate.ddl-auto=update 使用通用Mapper 依赖 tk.mybatis mapper-spring-boot-starter 2.1.5 继承 public interface UserMapper extends BaseMapper { } @MapperScan注解需要使用tk.mybatis包 集成Redis 依赖 org.springframework.boot spring-boot-starter-data-redis 2.1.8.RELEASE 配置 # redis相关配置 spring.redis.host=127.0.0.1 spring.redis.port=6379 使用 @RunWith(SpringRunner.class) @SpringBootTest public class RedisTest { @Autowired RedisTemplate redisTemplate; @Test public void test(){ String name = redisTemplate.boundValueOps(\"name\").get(); Assert.assertEquals(\"my\",name); } } MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-21 13:52:32 "},"后端开发/框架/SpringCloud/nav.html":{"url":"后端开发/框架/SpringCloud/nav.html","title":"SpringCloud","keywords":"","body":" NAV 注册中心 服务提供与调用 服务限流 熔断器与熔断监控 配置中心 消息总线 服务网关 链路追踪 demo demo MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-27 10:03:18 "},"后端开发/框架/mybatis-plus.html":{"url":"后端开发/框架/mybatis-plus.html","title":"Mybatis-Plus","keywords":"","body":"基本配置 spring boot 添加依赖 com.baomidou mybatis-plus-boot-starter 3.1.2 定义mapper接口 public interface UserMapper extends BaseMapper { } 使用 @Autowired UserMapper userMapper; @Test public void test(){ User user = new User(); user.setUsername(\"root\"); user.setPassword(\"123\"); user.setAge(15); user.setCreateTime(LocalDate.now()); assertEquals(1,userMapper.insert(user)); } 查询 普通查询 条件构造器查询 @Test public void test2(){ QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.like(\"username\",\"roo\") .lt(\"age\",50); var list = userMapper.selectList(queryWrapper); assertEquals(2,list.size()); assertEquals(\"root\",list.get(0).getUsername()); assertEquals(\"rood\",list.get(1).getUsername()); } 自定义SQL 注解 public interface UserMapper extends BaseMapper { @Select(\"SELECT * FROM user \") List selectAll(); } xml 同mybatis 分页查询 配置分页插件 @Bean public PaginationInterceptor paginationInterceptor(){ return new PaginationInterceptor(); } 查询 @Test public void test4(){ Page page = new Page<>(1,2); var list = userMapper.selectPage(page,null).getRecords(); assertEquals(2,list.size()); } 更新 @Test public void test5(){ UpdateWrapper wrapper = new UpdateWrapper().eq(\"username\",\"root\"); User user = new User(); user.setPassword(\"5678\"); userMapper.update(user, wrapper); } 删除 UpdateWrapper wrapper = new UpdateWrapper() .eq(\"username\",\"root\"); userMapper.delete(wrapper); AR模式 实体类继承Model @Data public class User extends Model { private String username; private String password; private Integer age; private LocalDate createTime; } @Test public void test6(){ User user = new User(); user.setUsername(\"20190716\"); user.setPassword(\"123\"); user.setCreateTime(LocalDate.now()); user.setAge(111); assertTrue(user.insert()); } 主键策略 设置策略 @TableId(type = IdType.UUID) private String username; User user = new User(); user.setPassword(\"1111\"); assertTrue(user.insert()); 通过Service MY all right reserved,powered by Gitbook该页面最后修改于: 2019-07-16 16:57:04 "},"后端开发/框架/mybatis/nav.html":{"url":"后端开发/框架/mybatis/nav.html","title":"Mybatis","keywords":"","body":"NAV 框架 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种 定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。 简而言之,框架其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别 人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。 Mybatis 持久层框架 动态sql ORM 搭建 创建mapper接口 public interface UserDao { List findAll(); } 创建总配置文件 创建映射配置文件 SELECT * FROM user 使用 @Test public void findAll() throws IOException { SqlSessionFactory factory = new SqlSessionFactoryBuilder().build( Resources.getResourceAsStream(\"config.xml\")); SqlSession sqlSession = factory.openSession(); List list = sqlSession.getMapper(UserDao.class).findAll(); assertEquals(6,list.size()); } 注解 public interface UserDao { @Select(\"SELECT * FROM user\") List findAll(); } 分析 目录 CURD操作 连接池与事务 多表操作 缓存 注解开发 分页插件 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-27 11:21:49 "},"后端开发/框架/netty.html":{"url":"后端开发/框架/netty.html","title":"Netty","keywords":"","body":" Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。 使用场景 高性能领域 多线程并发领域 异步通信领域 JAVA IO通信 BIO 同步阻塞IO 伪异步IO NIO 同步非阻塞IO AIO 异步非阻塞IO 阻塞与非阻塞 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程 同步与异步 同步和异步关注的是消息通信机制 所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。 而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用 Reactor模型 多线程模型 一个接收线程,多个处理线程 Reactor主从多线程模型 处理高并发 一组线程接收请求,一组线程处理IO 核心API ChannelHandler ChannelHandler 为 Netty 中最核心的组件,它充当了所有处理入站和出站数据的应用程序逻辑的容器。ChannelHandler 主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等 ChannelPipeline ChannelPipeline 为 ChannelHandler 链提供了一个容器并定义了用于沿着链传播入站和出站事件流的 API ChannelHandlerContext 使ChannelHandler与其ChannelPipeline和其他处理程序进行交互。处理程序可以通知ChannelPipeline中的下一个ChannelHandler,动态修改其所属的ChannelPipeline ChannelOption ChannelOption.SO_BACKLOG ChannelOption.SO_BACKLOG对应的是tcp/ip协议listen函数中的backlog参数,函数listen(int socketfd,int backlog)用来初始化服务端可连接队列,服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接,多个客户端来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理,backlog参数指定了队列的大小 ChannelOption.SO_KEEPALIVE Channeloption.SO_KEEPALIVE参数对应于套接字选项中的SO_KEEPALIVE,该参数用于设置TCP连接,当设置该选项以后,连接会测试链接的状态,这个选项用于可能长时间没有数据交流的连接。当设置该选项以后,如果在两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文 ChannelFuture ChannelFuture的作用是用来保存Channel异步操作的结果 EventLoop ServerBootStrap 使用服务器的ServerBootStrap,用于接受客户端的连接以及为已接受的连接创建子通道。 用于客户端的BootStrap,不接受新的连接,并且是在父通道类完成一些操作。 Unpooled类 操作缓冲区的工具类 WebSocket示例 依赖 io.netty netty-all 5.0.0.Alpha2 定义服务器 // 线程池 NioEventLoopGroup mainGroup = new NioEventLoopGroup(); NioEventLoopGroup subGroup = new NioEventLoopGroup(); try{ // 启动对象 ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap .group(mainGroup,subGroup) // 通道类型 .channel(NioServerSocketChannel.class) // 业务处理 .childHandler(new WebSocketChannelInitializer()); ChannelFuture sync = serverBootstrap.bind(9090).sync(); // 等待关闭 sync.channel().closeFuture().sync(); }catch (Exception e){ e.printStackTrace(); }finally { mainGroup.shutdownGracefully(); subGroup.shutdownGracefully(); } 定义handler public class WebSocketChannelInitializer extends ChannelInitializer { @Override protected void initChannel(SocketChannel channel) throws Exception { // 获取管道,添加ChannelHandler ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new ChunkedWriteHandler()); pipeline.addLast(new HttpObjectAggregator(1024*64)); pipeline.addLast(new WebSocketServerProtocolHandler(\"/ws\")); pipeline.addLast(new ChatHandler()); } } ChatHandler,处理请求建立以及消息到达 public class ChatHandler extends SimpleChannelInboundHandler { private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); @Override protected void messageReceived(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { String text = msg.text(); System.out.println(\"接收到消息:\" + text); for (Channel client : clients) { // 将消息发送给所有客户端 client.writeAndFlush(new TextWebSocketFrame(LocalDateTime.now() + \"---\" + text)); } } @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { clients.add(ctx.channel()); } } MY all right reserved,powered by Gitbook该页面最后修改于: 2019-12-06 15:15:24 "},"后端开发/框架/Dubbo.html":{"url":"后端开发/框架/Dubbo.html","title":"Dubbo","keywords":"","body":"架构演进 需求 当服务越来越多时,服务 URL 配置管理变得非常困难,F5 硬件负载均衡器的单点压力也越来越大 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器 架构 节点 角色说明 Provider 暴露服务的服务提供方 Consumer 调用远程服务的服务消费方 Registry 服务注册与发现的注册中心 Monitor 统计服务的调用次数和调用时间的监控中心 Container 服务运行容器 注册中心 ZooKeeper 服务提供者启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址 服务消费者启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址 监控中心启动时: 订阅 /dubbo/com.foo.BarService 目录下的所有提供者和消费者 URL 地址 服务方 依赖 org.springframework.boot spring-boot-starter org.apache.zookeeper zookeeper 3.5.6 com.101tec zkclient 0.11 com.alibaba.boot dubbo-spring-boot-starter 0.2.0 org.projectlombok lombok 1.18.10 com.alibaba dubbo 2.6.7 配置 server: port: 9090 spring: application: name: dubbo-service main: allow-bean-definition-overriding: true dubbo: application: version: 1.0.0 name: dubbo-service scan: base-packages: wang.ismy.dubbo.service protocol: name: dubbo port: 20880 registry: address: zookeeper://my-pc:2181 client: zkclient 编写服务实现类 // 声明这是一个dubbo服务 @Service(version = \"1.0.0\") public class UserServiceImpl implements UserService { @Override public List findAll() { // 省略 } } 编写启动类 @SpringBootApplication @EnableDubbo public class ServiceApplication { public static void main(String[] args) { new SpringApplicationBuilder(ServiceApplication.class) .web(WebApplicationType.NONE) .run(args); } } 消费方 依赖 org.springframework.boot spring-boot-starter-web org.apache.zookeeper zookeeper 3.5.6 com.101tec zkclient 0.11 com.alibaba.boot dubbo-spring-boot-starter 0.2.0 com.alibaba dubbo 2.6.7 配置 dubbo: application: name: dubbo-consumer registry: address: zookeeper://my-pc:2181 client: zkclient server: port: 9091 使用 @Reference(version = \"1.0.0\") private UserService userService; 负载均衡 设置负载均衡的方式 @Reference(version = \"1.0.0\",loadbalance = \"roudrobin\") private UserService userService; random 随机 roudrobin 轮询 协议 Dubbo 缺省协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。 反之,Dubbo 缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低 缺省协议,使用基于 mina 1.1.7 和 hessian 3.2.1 的 tbremoting 交互。 连接个数:单连接 连接方式:长连接 传输协议:TCP 传输方式:NIO 异步传输 序列化:Hessian 二进制序列化 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满 提供者,尽量不要用 dubbo 协议传输大文件或超大字符串。 适用场景:常规远程服务方法调用 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-12-08 21:54:21 "},"后端开发/GraphQL.html":{"url":"后端开发/GraphQL.html","title":"GraphQL","keywords":"","body":" GraphQL 是由 Facebook 创造的用于描述复杂数据模型的一种查询语言。这里查询语言所指的并不是常规意义上的类似 sql 语句的查询语言,而是一种用于前后端数据查询方式的规范 Restful的不足 扩展性,单个RESTful接口返回数据越来越臃肿 某个前端展现,实际需要调用多个独立的RESTful API才能获取到足够的数据 GraphQL的优势 按需索取数据 一次查询多个数据 API演进无需划分版本 查询规范 字段 在GraphQL的查询中,请求结构中包含了所预期结果的结构,这个就是字段。并且响应的结构和请求结构基本一致 { hero { name } } { \"data\": { \"hero\": { \"name\": \"R2-D2\" } } } 参数 语法:(参数名:参数值) { human(id: \"1000\") { name height } } { \"data\": { \"human\": { \"name\": \"Luke Skywalker\", \"height\": 1.72 } } } 别名 如果一次查询多个相同对象,但是值不同,这个时候就需要起别名了,否则json的语法就不能通过了 { empireHero: hero(episode: EMPIRE) { name } jediHero: hero(episode: JEDI) { name } } { \"data\": { \"empireHero\": { \"name\": \"Luke Skywalker\" }, \"jediHero\": { \"name\": \"R2-D2\" } } } 片段 查询对的属相如果相同,可以采用片段的方式进行简化定义 { leftComparison: hero(episode: EMPIRE) { ...comparisonFields } rightComparison: hero(episode: JEDI) { ...comparisonFields } } fragment comparisonFields on Character { name appearsIn friends { name } } { \"data\": { \"leftComparison\": { \"name\": \"Luke Skywalker\", \"appearsIn\": [ \"NEWHOPE\", \"EMPIRE\", \"JEDI\" ], \"friends\": [ { \"name\": \"Han Solo\" }, { \"name\": \"Leia Organa\" }, { \"name\": \"C-3PO\" }, { \"name\": \"R2-D2\" } ] }, \"rightComparison\": { \"name\": \"R2-D2\", \"appearsIn\": [ \"NEWHOPE\", \"EMPIRE\", \"JEDI\" ], \"friends\": [ { \"name\": \"Luke Skywalker\" }, { \"name\": \"Han Solo\" }, { \"name\": \"Leia Organa\" } ] } } } Schema Schema 是用于定义数据结构的,比如说,User对象中有哪些属性,对象与对象之间是什么关系等 schema { #定义查询 query: UserQuery } type UserQuery { #定义查询的类型 user(id:ID) : User #指定对象以及参数类型 } type User {#定义对象 id:ID! # !表示该属性是非空项 name:String age:Int } 类型规范 标量类型 Int :有符号 32 位整数。 Float :有符号双精度浮点值。 String :UTF‐8 字符序列。 Boolean : true 或者 false 。 ID : ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。 枚举类型 枚举类型是一种特殊的标量,它限制在一个特殊的可选值集合内 enum Episode { # 定义枚举 NEWHOPE EMPIRE JEDI } type Character { # 使用枚举 name: String! appearsIn: [Episode]! } 接口 跟许多类型系统一样,GraphQL 支持接口。一个接口是一个抽象类型,它包含某些字段,而对象类型必须包含这些字段,才能算实现了这个接口 interface Character { id: ID! name: String! friends: [Character] appearsIn: [Episode]! } type Human implements Character { id: ID! name: String! friends: [Character] appearsIn: [Episode]! starships: [Starship] totalCredits: Int } MY all right reserved,powered by Gitbook该页面最后修改于: 2019-12-09 22:10:10 "},"后端开发/ServiceComb.html":{"url":"后端开发/ServiceComb.html","title":"ServiceComb","keywords":"","body":" 致力于帮助企业、用户和开发者将企业应用轻松微服务化上云,并实现对微服务应用的高效运维管理。其提供一站式开源微服务解决方案,融合SDK框架级、0侵入ServiceMesh场景并支持多语言 设计思想 编程模型和通信模型分离,不同的编程模型可以灵活组合不同的通信模型。应用开发者在开发阶段只关注接口开发,部署阶段灵活切换通信方式;支持legacy系统的切换,legacy系统只需要修改服务发布的配置文件(或者annotation),而不需要修改代码。现阶段支持SpringMVC、JAX-RS和透明RPC三种开发方式。 内建API-first支持。通过契约规范化微服务开发,实现跨语言的通信,并支持配套的软件工具链(契约生成代码、代码生成契约等)开发,构建完整的开发生态。 定义了常用的微服务运行模型,将微服务从发现到交互过程中的各种容错手段都封装起来。该运行模型支持自定义和扩展。 注册中心 安装运行 docker pull servicecomb/service-center docker run -d -p 30100:30100 servicecomb/service-center:latest MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-04 22:11:56 "},"后端开发/用户认证.html":{"url":"后端开发/用户认证.html","title":"用户认证","keywords":"","body":" 认证与授权 单点登录 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统 Oauth2 OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时,任何第三方都可以使用OAUTH认 证服务,任何服务提供商都可以实现自身的OAUTH认证服务。 授权模式 授权码模式 密码模式 JWT JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简介的、自包含的协议格式,用于 在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公 钥/私钥对来签名,防止被篡改 缺点:令牌长度较长 组成 头部 {\"typ\":\"JWT\",\"alg\":\"HS256\"} // 经过base64加密后:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 载荷 标准中注册的声明 公共的声明 私有的声明 {\"sub\":\"1234567890\",\"name\":\"John Doe\",\"admin\":true} // eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9 签证 header (base64后的) payload (base64后的) secret secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用 来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流 露出去 JJWT 依赖 io.jsonwebtoken jjwt 0.9.1 构建 JwtBuilder jwtBuilder = Jwts.builder() .setId(\"jntm\") .setSubject(\"cxk\") .setIssuedAt(new Date()) .signWith(SignatureAlgorithm.HS256,\"1234\") .claim(\"role\",\"admin\") .setExpiration(new Date(System.currentTimeMillis()+300)); System.out.println(jwtBuilder.compact()); 解析 Claims body = Jwts.parser().setSigningKey(\"1234\") .parseClaimsJws(\"jwt\") .getBody(); System.out.println(body.getId()+\"|\"+body.getSubject()+\"|\"+body.getIssuedAt()); Bcrypt bcrypt是一个由Niels Provos以及David Mazières根据Blowfish加密算法所设计的密码散列函数,于1999年在USENIX中展示。实现中bcrypt会使用一个加盐的流程以防御彩虹表攻击,同时bcrypt还是适应性函数,它可以借由增加迭代之次数来抵御日益增进的电脑运算能力透过暴力法破解。 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-15 16:01:18 "},"后端开发/JakartaEE/Servlet.html":{"url":"后端开发/JakartaEE/Servlet.html","title":"Servlet","keywords":"","body":" server applet 运行在服务器端的小程序 使用 实现Servlet接口 public class MyServlet implements Servlet{ ... @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { servletResponse.getWriter().println(\"hello world\"); } ... } 在web.xml配置 MyServlet wang.ismy.web.MyServlet MyServlet /* 原理 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径 查找web.xml文件,是否有对应的标签体内容。 如果有,则在找到对应的全类名 tomcat会将字节码文件加载进内存,并且创建其对象 调用其方法 生命周期方法 被创建:执行init方法,只执行一次 * Servlet什么时候被创建? * 默认情况下,第一次被访问时,Servlet被创建 * 可以配置执行Servlet的创建时机。 * 在标签下配置 1\\. 第一次被访问时,创建 * 的值为负数 2\\. 在服务器启动时,创建 * 的值为0或正整数 * Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的 * 多个用户同时访问时,可能存在线程安全问题。 * 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值 提供服务:执行service方法,执行多次 * 每次访问Servlet时,Service方法都会被调用一次。 被销毁:执行destroy方法,只执行一次 * Servlet被销毁时执行。服务器关闭时,Servlet被销毁 * 只有服务器正常关闭时,才会执行destroy方法。 * destroy方法在Servlet被销毁之前执行,一般用于释放资源 Servlet3.0 加上注解后不用配置web.xml @WebServlet(\"/*\") 体系结构 配置 路径定义规则: /xxx:路径匹配 /xxx/xxx:多层路径,目录结构 *.do:扩展名匹配 Request 体系结构 request对象继承体系结构: ServletRequest -- 接口 | 继承 HttpServletRequest -- 接口 | 实现 org.apache.catalina.connector.RequestFacade 类(tomcat) 方法 获取请求行数据 String getMethod() String getContextPath() String getServletPath() String getQueryString() String getRequestURI() String getProtocol() String getRemoteAddr() 获取请求头数据 String getHeader(String name) Enumeration string getHeaderNames() 获取请求体数据 BufferedReader getReader() ServletInputStream getInputStream() 其他 String getParameter(String name) String[] getParameterValues(String name) Map getParameterMap() 请求转发 req.getRequestDispatcher(\"/404\") .forward(req,resp); 浏览器地址栏路径不发生变化 只能转发到当前服务器内部资源中。 转发是一次请求 共享数据 request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据 void setAttribute(String name,Object obj):存储数据 Object getAttitude(String name):通过键获取值 void removeAttribute(String name):通过键移除键值对 Response 方法 设置状态码:setStatus(int sc) 字符输出流:PrintWriter getWriter() 字节输出流:ServletOutputStream getOutputStream() * 重定向的特点:redirect 1\\. 地址栏发生变化 2\\. 重定向可以访问其他站点(服务器)的资源 3\\. 重定向是两次请求。不能使用request对象来共享数据 * 转发的特点:forward 1\\. 转发地址栏路径不变 2\\. 转发只能访问当前服务器下的资源 3\\. 转发是一次请求,可以使用request对象来共享数据 乱码问题 PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1 //设置编码,是在获取流之前设置 response.setContentType(\"text/html;charset=utf-8\"); ServletContext 获取: 通过request对象获取 request.getServletContext(); 通过HttpServlet获取 this.getServletContext(); 获取MIME类型 System.out.println(getServletContext().getMimeType(\"a.jpg\")); 域对象:共享数据 setAttribute(String name,Object value) getAttribute(String name) removeAttribute(String name) 获取文件真实路径 String getRealPath(String path) MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-11 09:02:27 "},"后端开发/JakartaEE/JSP.html":{"url":"后端开发/JakartaEE/JSP.html","title":"JSP","keywords":"","body":" Java Server Pages: java服务器端页面 JSP本质上就是一个Servlet 指令 page:配置JSP页面的 contentType:等同于response.setContentType() import:导包 errorPage:当前页面发生异常后,会自动跳转到指定的错误页面 isErrorPage:标识当前也是是否是错误页面。 include:页面包含的。导入页面的资源文件 taglib导入资源 注释 html注释: :只能注释html代码片段 jsp注释:推荐使用 :可以注释所有 JSP脚本 :定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么 :定义的java代码,在jsp转换后的java类的成员位置。 :定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。 内置对象 变量名 真实类型 作用 pageContext PageContext 当前页面共享数据,还可以获取其他八个内置对象 request HttpServletRequest 一次请求访问的多个资源(转发) session HttpSession 一次会话的多个请求间 application ServletContext 所有用户间共享数据 response HttpServletResponse 响应对象 page Object 当前页面(Servlet)的对象 this out JspWriter 输出对象,数据输出到页面上 config ServletConfig Servlet的配置对象 exception Throwable 异常对象 MVC 耦合性低,方便维护,可以利于分工协作 重用性高 使得项目架构变得复杂,对开发人员要求高 EL表达式 Expression Language 表达式语言 语法:${表达式} 忽略 设置jsp中page指令中:isELIgnored=\"true\" 忽略当前jsp页面中所有的el表达式 \\${表达式} :忽略当前这个el表达式 运算符 算术运算符 比较运算符 逻辑运算符 空运算符 ${empty list} 获取值 ${域名称.键名} pageScope requestScope sessionScope applicationScope ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。 获取对象、List集合、Map集合的值 对象:${域名称.键名.属性名} List集合:${域名称.键名[索引]} Map集合: ${域名称.键名.key名称} ${域名称.键名[\"key名称\"]} 逻辑视图 隐式对象 JSTL JavaServer Pages Tag Library JSP标准标签库 if choose forEach MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-11 16:00:56 "},"后端开发/JakartaEE/Cookie&Session.html":{"url":"后端开发/JakartaEE/Cookie&Session.html","title":"Cookie&Session","keywords":"","body":"Cookie 客户端会话技术,将数据保存到客户端 Cookie[] cookies = req.getCookies(); for (Cookie cookie : cookies) { if (\"time\".equals(cookie.getName())){ resp.getWriter().println(cookie.getValue()); } } resp.addCookie(new Cookie(\"time\", LocalDateTime.now().toString())); 实现原理 基于响应头set-cookie和请求头cookie实现 细节 持久化存储: setMaxAge(int seconds) 共享 设置共享虚拟目录范围:setPath(String path) 设置共享域:setDomain(String path) 特点 cookie存储数据在客户端浏览器 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个) 作用 cookie一般用于存出少量的不太敏感的数据 在不登录的情况下,完成服务器对客户端的身份识别 Session 服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession 使用 获取HttpSession对象: HttpSession session = request.getSession(); 使用HttpSession对象: Object getAttribute(String name) void setAttribute(String name, Object value) void removeAttribute(String name) 原理 Session的实现是依赖于Cookie的。 细节 持久化session Cookie c = new Cookie(\"JSESSIONID\",session.getId()); c.setMaxAge(60*60); response.addCookie(c); session序列化 tomcat自动完成 销毁时间 服务器关闭 session对象调用invalidate() session默认失效时间 30分钟 30 特点 session用于存储一次会话的多次请求的数据,存在服务器端 session可以存储任意类型,任意大小的数据 Session与Cookie区别 比较类别 Session Cookie 存储方式 服务端 客户端 大小限制 无 有 安全 较安全 较不安全 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-11 11:33:12 "},"后端开发/JakartaEE/Filter&Listener.html":{"url":"后端开发/JakartaEE/Filter&Listener.html","title":"Filter&Listener","keywords":"","body":"Filter 一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤 使用 实现Filter接口 配置 注解 web.xml demo1 cn.itcast.web.filter.FilterDemo1 demo1 /* 执行流程 执行过滤器 执行放行后的资源 回来执行过滤器放行代码下边的代码 生命周期方法 init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源 doFilter:每一次请求被拦截资源时,会执行。执行多次 destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源 拦截方式配置:资源被访问的方式 REQUEST:默认值。浏览器直接请求资源 FORWARD:转发访问资源 INCLUDE:包含访问资源 ERROR:错误跳转资源 ASYNC:异步访问资源 @WebFilter(value = \"/*\",dispatcherTypes = DispatcherType.ERROR) 过滤器链 注解配置 按照类名字符串排序 web.xml配置 按照filter-mapping排序 Listener ServletContextListener HttpSessionListener ServletRequestListener 使用 实现接口 配置 注解配置 @WebListener web.xml MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-12 10:07:42 "},"后端开发/JakartaEE/JNDI.html":{"url":"后端开发/JakartaEE/JNDI.html","title":"JNDI","keywords":"","body":" MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-19 13:51:23 "},"后端开发/JakartaEE/JPA.html":{"url":"后端开发/JakartaEE/JPA.html","title":"JPA","keywords":"","body":" JPA的全称是Java Persistence API, 即Java 持久化API,是SUN公司推出的一套基于ORM的规范,内部是由一系列的接口和抽象类构成 Persistence对象 Persistence对象主要作用是用于获取EntityManagerFactory对象的 EntityManagerFactory EntityManagerFactory 接口主要用来创建 EntityManager 实例 EntityManager 在 JPA 规范中, EntityManager是完成持久化操作的核心对象 getTransaction : 获取事务对象 persist : 保存操作 merge : 更新操作 remove : 删除操作 find/getReference : 根据id查询 EntityTransaction begin,commit,rollback 使用 创建classpath:META-INF/persistence.xml org.hibernate.jpa.HibernatePersistenceProvider 创建实体类 @Entity @Table(name = \"cst_customer\") @Data public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = \"cust_id\") /* * IDENTITY:底层数据库必须支持自动增长 * SEQUENCE: 底层数据库必须支持序列 * TABLE:jpa提供的机制 * AUTO:由程序自动选择策略 * */ private Long custId; @Column(name = \"cust_name\") private String custName; @Column(name = \"cust_source\") private String custSource; @Column(name = \"cust_level\") private String custLevel; @Column(name = \"cust_industry\") private String custIndustry; @Column(name = \"cust_phone\") private String custPhone; @Column(name = \"cust_address\") private String custAddress; } 操作 添加 EntityManager manager = Persistence .createEntityManagerFactory(\"jpa\").createEntityManager(); EntityTransaction tx = manager.getTransaction(); tx.begin(); Customer customer = new Customer(); customer.setCustName(\"老王\"); customer.setCustIndustry(\"隔壁\"); manager.persist(customer); tx.commit(); manager.close(); 根据ID查询 Customer customer = entityManager.find(Customer.class, 1L); // 立即加载 Customer customer = entityManager.getReference(Customer.class, 1L); // 延迟加载 删除 Customer customer = entityManager.find(Customer.class, 1L); entityManager.remove(customer); 更新 Customer customer = entityManager.find(Customer.class, 2L); customer.setCustName(\"老王八\"); entityManager.merge(customer); JPQL 基于首次在EJB2.0中引入的EJB查询语言(EJB QL),Java持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL 查询全部 String jpql = \"FROM Customer \"; List list = entityManager.createQuery(jpql).getResultList(); for (Object o : list) { System.out.println(o); } 倒序查询 FROM Customer ORDER BY custId DESC 统计查询 SELECT COUNT(custId) FROM Customer 分页查询 String jpql = \"FROM Customer\"; List list = entityManager.createQuery(jpql) .setFirstResult(0) .setMaxResults(2).getResultList(); 条件查询 String jpql = \"FROM Customer WHERE custName LIKE ?1\"; List list = entityManager.createQuery(jpql) .setParameter(1,\"%李%\") .getResultList(); MY all right reserved,powered by Gitbook该页面最后修改于: 2019-09-07 11:27:18 "},"后端开发/JakartaEE/Freemarker.html":{"url":"后端开发/JakartaEE/Freemarker.html","title":"Freemarker","keywords":"","body":"使用 org.springframework.boot spring-boot-starter-freemarker 配置 spring: freemarker: cache: false enabled: true suffix: .html content-type: text/html 指令 hello ${name} 类型 注释,即,介于其之间的内容会被freemarker忽略 插值(Interpolation):即${..}部分,freemarker会用真实的值代替${..} FTL指令:和HTML标记类似,名字前加#予以区分,Freemarker会解析标签中的表达式或逻辑。 文本,仅文本信息,这些不是freemarker的注释、插值、FTL指令的内容会被freemarker忽略解析,直接输出内 容。 list指令 ${name} map操作 ${map['name']} ${map.name} 遍历map ${map[key]} 条件渲染 jntm 空值处理 存在 ${map.class!\"default\"} 内建函数 内建函数语法格式: 变量+?+函数名称 ${time?time} ${time?date} ${time?datetime} MY all right reserved,powered by Gitbook该页面最后修改于: 2019-10-11 13:49:41 "},"前端开发/HTML.html":{"url":"前端开发/HTML.html","title":"HTML","keywords":"","body":" 静态资源 动态资源 超文本 标记语言 标签 围堵标签 自闭标签 基本标签 文件标签 html head title body 文本标签 h1 ~ h6 p br hr b i font 图片标签 src alt 列表标签 ul:无序 ol:有序 链接标签 块标签 div span 语义化标签 header footer nav 表格标签 编号 姓名 1 lisi 表单标签 input select option textarea label MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-06 15:05:08 "},"前端开发/CSS/nav.html":{"url":"前端开发/CSS/nav.html","title":"CSS","keywords":"","body":"CSS 层叠样式表(英语:Cascading Style Sheets,缩写:CSS;又称串样式列表、级联样式表、串接样式表、阶层式样式表)是一种用来为结构化文档(如HTML文档或XML应用)添加样式(字体、间距和颜色等)的计算机语言,由W3C定义和维护。当前最新版本是CSS2.1,为W3C的推荐标准。CSS3现在已被大部分现代浏览器支持,而下一版的CSS4仍在开发中。 书写规范 空格规范 /* 选择器 与 { 之间必须包含空格。 */ .selector { /* 属性名 与之后的 : 之间不允许包含空格, : 与 属性值 之间必须包含空格 */ font-size: 12px; } 选择器规范 /* 并集选择器,每个选择器声明必须独占一行 */ .post, .page, .comment { line-height: 1.5; } 一般情况情况下,选择器的嵌套层级应不大于 3 级,位置靠后的限定条件应尽可能精确 属性规范 /* 属性定义必须另起一行。 */ .selector { margin: 0; padding: 0; /* 属性定义后必须以分号结尾。 */ } 使用方式 内联 内容 内嵌 选择器(选择的标签) { 属性1: 属性值1; 属性2: 属性值2; 属性3: 属性值3; } 外联 属性 作用 rel 定义当前文档与被链接文档之间的关系,在这里需要指定为\"stylesheet\",表示被链接的文档是一个样式表文件。 type 定义所链接文档的类型,在这里需要指定为\"text/CSS\",表示链接的外部文件为CSS样式表。我们都可以省略 href 定义所链接外部样式表文件的URL,可以是相对路径,也可以是绝对路径。 比较 样式表 优点 缺点 使用情况 控制范围 行内样式表 书写方便,权重高 没有实现样式和结构相分离 较少 控制一个标签(少) 内部样式表 部分结构和样式相分离 没有彻底分离 较多 控制一个页面(中) 外部样式表 完全实现结构和样式相分离 需要引入 最多,强烈推荐 控制整个站点(多) 三大特性 层叠性 所谓层叠性是指多种CSS样式的叠加。 样式冲突,遵循的原则是就近原则。 那个样式离着结构近,就执行那个样式。 继承性 子元素可以继承父元素的样式(text-,font-,line-这些元素开头的可以继承,以及color属性) 优先级 标签选择器 计算权重公式 继承或者 * 0,0,0,0 每个元素(标签选择器) 0,0,0,1 每个类,伪类 0,0,1,0 每个ID 0,1,0,0 每个行内样式 style=\"\" 1,0,0,0 每个!important 重要的 ∞ 无穷大 权重叠加 div ul li ------> 0,0,0,3 .nav ul li ------> 0,0,1,2 a:hover -----—> 0,0,1,1 .nav a ------> 0,0,1,1 NAV 选择器 字体样式 复合选择器 标签显式模式 行高 背景 盒子模型 浮动 定位 高级技巧 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-11 09:53:42 "},"前端开发/Less/nav.html":{"url":"前端开发/Less/nav.html","title":"Less","keywords":"","body":"Less Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性,使 CSS 更易维护和扩展 CSS弊端 冗余度高 没有计算能力 不方便维护扩展,不利于复用 安装 npm install -g less 使用 变量定义与使用 // 必须有@为前缀 // 不能包含特殊字符 // 不能以数字开头 // 大小写敏感 @color: pink; div { background-color: @color; } 样式嵌套 .header { width: 200px; a { color: white; } } // 如果遇见 (交集|伪类|伪元素选择器) ,利用&进行连接 .header { width: 200px; &:hover { color: white; } } 运算 任何数字、颜色或者变量都可以参与运算。就是Less提供了加(+)、减(-)、乘(*)、除(/)算术运算 @width: 10px + 5; // 对颜色进行运算 div { border: @width solid red+2; } // 对宽度运算 div { width: (@width + 5) * 2; } 对于两个不同的单位的值之间的运算,运算结果的值取第一个值的单位 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-20 10:41:31 "},"前端开发/HTML5与CSS3/nav.html":{"url":"前端开发/HTML5与CSS3/nav.html","title":"HTML5与CSS3","keywords":"","body":"HTML5 HTML5 拓展了哪些内容 语义化标签 本地存储 兼容特性 2D、3D 动画、过渡 CSS3 特性 性能与集成 语义化标签 header --- 头部标签 nav --- 导航标签 article --- 内容标签 section --- 块级标签 aside --- 侧边栏标签 footer --- 尾部标签 语义化标签主要针对搜索引擎 新标签可以使用一次或者多次 在 IE9 浏览器中,需要把语义化标签都转换为块级元素 语义化标签,在移动端支持比较友好 多媒体标签 音频 -- audio 视频 -- video audio 音频格式 Chrome Firefox IE9 Opera Safari OGG 支持 支持 支持 支持 不支持 MP3 支持 不支持 支持 不支持 支持 WAV 不支持 支持 不支持 支持 不支持 属性 属性值 注释 src url 播放的音乐的url地址 preload preload 预加载(在页面被加载时进行加载或者说缓冲音频),如果使用了autoplay的话那么该属性失效。 loop loop 循环播放 controls controls 是否显示默认控制条(控制按钮) autoplay autoplay 自动播放 video 浏览器 MP4 WebM Ogg Internet Explorer YES NO NO Chrome YES YES YES Firefox YES YES YES Safari YES NO NO Opera YES (从 Opera 25 起) YES YES 音频标签与视频标签使用基本一致 多媒体标签在不同浏览器下情况不同,存在兼容性问题 谷歌浏览器把音频和视频标签的自动播放都禁止了 谷歌浏览器中视频添加 muted 标签可以自己播放 新增 input 标签 新增表单属性 CSS3 选择器 属性选择器 input[type=search] { color: skyblue; } 结构伪类选择器 nth-child 详解 n 可以是数字、关键字、公式 n 如果是数字,就是选中第几个 常见的关键字有 even 偶数、odd 奇数 常见的公式如下(如果 n 是公式,则从 0 开始计算) 但如果是第 0 个元素或者超出了元素的个数会被忽略 nth-child 和 nt-of-type 的区别 nth-child 选择父元素里面的第几个子元素,不管是第几个类型 nt-of-type 选择指定类型的元素 伪元素选择器 ::before 在元素内部的前面插入内容 ::after 在元素内部的后面插入内容 注意事项 before 和 after 必须有 content 属性 before 在内容前面,after 在内容后面 before 和 after 创建的是一个元素,但是属于行内元素 创建出来的元素在 Dom 中查找不到,所以称为伪元素 伪元素和标签选择器一样,权重为 1 2D转换 2D转换translate x 就是 x 轴上水平移动 y 就是 y 轴上水平移动 transform: translate(x, y) transform: translateX(n) transfrom: translateY(n) 2D 的移动主要是指 水平、垂直方向上的移动 translate 最大的优点就是不影响其他元素的位置 translate 中的100%单位,是相对于本身的宽度和高度来进行计算的 行内标签没有效果 2D旋转rotate 2D 旋转指的是让元素在二维平面内顺时针或者逆时针旋转 transform: rotate(度数) rotate里面跟度数,单位是deg` 角度为正时,顺时针,角度为负时,逆时针 默认旋转的中心点是元素的中心点 设置元素旋转中心点(transform-origin) transform-origin: x y; 注意后面的参数 x 和 y 用空格隔开 x y 默认旋转的中心点是元素的中心 (50% 50%),等价于 center center 还可以给 x y 设置像素或者方位名词(top、bottom、left、right、center) 2D 转换之 scale 用来控制元素的放大与缩小 transform: scale(x, y) 注意,x 与 y 之间使用逗号进行分隔 transform: scale(1, 1): 宽高都放大一倍,相当于没有放大 transform: scale(2, 2): 宽和高都放大了二倍 transform: scale(2): 如果只写了一个参数,第二个参数就和第一个参数一致 transform:scale(0.5, 0.5): 缩小 scale 最大的优势:可以设置转换中心点缩放,默认以中心点缩放,而且不影响其他盒子 综合写法 同时使用多个转换,其格式为 transform: translate() rotate() scale() 顺序会影响到转换的效果(先旋转会改变坐标轴方向) 但我们同时有位置或者其他属性的时候,要将位移放到最前面 动画 动画是 CSS3 中最具颠覆性的特征之一,可通过设置多个节点来精确的控制一个或者一组动画,从而实现复杂的动画效果 定义动画 @keyframes motion { 0% { transform: translateX(0); } 100% { transform: translateX(1000px); } } 使用动画 div { width: 200px; height: 200px; background-color: skyblue; animation: motion 5s; } 0% 是动画的开始,100 % 是动画的完成,这样的规则就是动画序列 在 @keyframs 中规定某项 CSS 样式,就由创建当前样式逐渐改为新样式的动画效果 动画是使元素从一个样式逐渐变化为另一个样式的效果,可以改变任意多的样式任意多的次数 用百分比来规定变化发生的时间,或用 from 和 to,等同于 0% 和 100% 场景属性 div { width: 100px; height: 100px; background-color: aquamarine; /* 动画名称 */ animation-name: move; /* 动画花费时长 */ animation-duration: 2s; /* 动画速度曲线 */ animation-timing-function: ease-in-out; /* 动画等待多长时间执行 */ animation-delay: 2s; /* 规定动画播放次数 infinite: 无限循环 */ animation-iteration-count: infinite; /* 是否逆行播放 */ animation-direction: alternate; /* 动画结束之后的状态 */ animation-fill-mode: forwards; } 简写 animation: name duration timing-function delay iteration-count direction fill-mode 简写属性里面不包含 animation-paly-state 暂停动画 animation-paly-state: paused; 经常和鼠标经过等其他配合使用 要想动画走回来,而不是直接调回来:animation-direction: alternate 盒子动画结束后,停在结束位置:animation-fill-mode: forwards 3D转换 三维坐标系 3D 移动 translate3d /* 注意:x, y, z 对应的值不能省略,不需要填写用 0 进行填充 */ transform: translate3d(x, y, z) 透视 perspective 透视需要写在被视察元素的父盒子上面 body { perspective: 1000px; } 3D 旋转rotate 3D 旋转指可以让元素在三维平面内沿着 x 轴、y 轴、z 轴 或者自定义轴进行旋转 transform: rotate3d(x, y, z, deg) rotateY rotateX rotateZ /* 沿着对角线旋转 */ transform: rotate3d(1, 1, 0, 180deg) 3D 呈现 transform-style 控制子元素是否开启三维立体环境 transform-style: flat 代表子元素不开启 3D 立体空间,默认的 transform-style: preserve-3d 子元素开启立体空间 浏览器私有前缀 火狐-moz- ie-ms- -webkit- -o- MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-17 11:42:50 "},"前端开发/移动web开发/nav.html":{"url":"前端开发/移动web开发/nav.html","title":"移动web开发","keywords":"","body":"移动web开发 流式布局 视口(viewport)就是浏览器显示页面内容的屏幕区域。 视口可以分为布局视口、视觉视口和理想视口 布局视口 layout viewport 一般移动设备的浏览器都默认设置了一个布局视口,用于解决早期的PC端页面在手机上显示的问题。 iOS, Android基本都将这个视口分辨率设置为 980px,所以PC上的网页大多都能在手机上呈现,只不过元素看上去很小,一般默认可以通过手动缩放网页 视觉视口 visual viewport 它是用户正在看到的网站的区域,我们可以通过缩放去操作视觉视口,但不会影响布局视口,布局视口仍保持原来的宽度 理想视口 ideal viewport 布局视口的宽度应该与理想视口的宽度一致,简单理解就是设备有多宽,我们布局的视口就多宽 meta标签 标准设置 视口宽度和设备保持一致 视口的默认缩放比例1.0 不允许用户自行缩放 最大允许的缩放比例1.0 最小允许的缩放比例1.0 二倍图 物理像素&物理像素比 物理像素点指的是屏幕显示的最小颗粒,是物理真实存在的。这是厂商在出厂时就设置好了,比如苹果6 是 750* 1334 我们开发时候的1px 不是一定等于1个物理像素的 一个px的能显示的物理像素点的个数,称为物理像素比或屏幕像素比 lRetina(视网膜屏幕)是一种显示技术,可以将把更多的物理像素点压缩至一块屏幕里,从而达到更高的分辨率,并提高屏幕显示的细腻程度 按照刚才的物理像素比会放大倍数,这样会造成图片模糊 在标准的viewport设置中,使用倍图来提高图片质量,解决在高清设备中的模糊问题 背景缩放background-size background-size: 背景图片宽度 背景图片高度; 单位: 长度|百分比|cover|contain; cover把背景图像扩展至足够大,以使背景图像完全覆盖背景区域。 contain把图像图像扩展至最大尺寸,以使其宽度或高度完全适应内容区域 移动开发选择和技术解决方案 单独制作移动端页面(主流) 响应式页面兼容移动端(其次) 解决方案 移动端浏览器基本以 webkit 内核为主,因此我们就考虑webkit兼容性问题 移动端公共样式Normalize.css 移动端大量使用 CSS3盒子模型box-sizing CSS3盒子模型:盒子的宽度= CSS中设置的宽度width 里面包含了 border 和 padding /*CSS3盒子模型*/ box-sizing: border-box; /*传统盒子模型*/ box-sizing: content-box; 移动端特殊样式 /*CSS3盒子模型*/ box-sizing: border-box; -webkit-box-sizing: border-box; /*点击高亮我们需要清除清除 设置为transparent 完成透明*/ -webkit-tap-highlight-color: transparent; /*在移动端浏览器默认的外观在iOS上加上这个属性才能给按钮和输入框自定义样式*/ -webkit-appearance: none; /*禁用长按页面时的弹出菜单*/ img,a { -webkit-touch-callout: none; } 移动端常见布局 移动端单独制作 流式布局(百分比布局) flex 弹性布局(强烈推荐) less+rem+媒体查询布局 混合布局 响应式 媒体查询 bootstarp 流式布局: 流式布局,就是百分比布局,也称非固定像素布局。 通过盒子的宽度设置成百分比来根据屏幕的宽度来进行伸缩,不受固定像素的限制,内容向两侧填充。 流式布局方式是移动web开发使用的比较常见的布局方式。 width:100%; max-width: 1200px; min-width: 320px; flex布局 pc端浏览器支持情况比较差 如果是移动端或者是不考虑兼容的pc则采用flex 原理 flex 是 flexible Box 的缩写,意为\"弹性布局\",用来为盒状模型提供最大的灵活性,任何一个容器都可以指定为 flex 布局 通过给父盒子添加flex属性,来控制子盒子的位置和排列方式 父项常见属性 flex-direction设置主轴的方向 flex-direction: value; justify-content 设置主轴上的子元素排列方式 flex-wrap设置是否换行 nowrap 不换行 wrap 换行 align-items 设置侧轴上的子元素排列方式(单行 ) flex-start 从头部开始 flex-end 从尾部开始 center 居中显示 stretch 拉伸 align-content 设置侧轴上的子元素的排列方式(多行) flex-flow 属性是 flex-direction 和 flex-wrap 属性的复合属性 flex-flow:row wrap; flex布局子项常见属性 flex 属性 定义子项目分配剩余空间,用flex来表示占多少份数 align-self控制子项自己在侧轴上的排列方式 align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性 order 属性定义项目的排列顺序 数值越小,排列越靠前,默认为0 rem布局 rem rem (root em)是一个相对单位,类似于em,em是父元素字体大小。 不同的是rem的基准是相对于html元素的字体大小 媒体查询 使用 @media查询,可以针对不同的媒体类型定义不同的样式 @media 可以针对不同的屏幕尺寸设置不同的样式 当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面 目前针对很多苹果手机、Android手机,平板等设备都用得到多媒体查询 @media mediatype and|not|only (media feature) { CSS-Code; } mediatype 查询类型 关键字 关键字将媒体类型或多个媒体特性连接到一起做为媒体查询的条件 媒体特性 为了防止混乱,媒体查询我们要按照从小到大或者从大到小的顺序来写,但是我们最喜欢的还是从小到大来写,这样代码更简洁 媒体特性也可以加在css引用中,来达到不同的屏幕加载不同的css文件 rem适配方案 1.less+rem+媒体查询 2.lflexible.js+rem MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-20 10:46:37 "},"前端开发/JavaScript/nav.html":{"url":"前端开发/JavaScript/nav.html","title":"JavaScript","keywords":"","body":"JavaScript 基础语法等 Web Api Web API 是浏览器提供的一套操作浏览器功能和页面元素的 API ( BOM 和 DOM )。 DOM 事件 BOM MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-29 11:10:57 "},"前端开发/Bootstrap.html":{"url":"前端开发/Bootstrap.html","title":"Bootstrap","keywords":"","body":"响应式布局 响应式需要一个父级做为布局容器,来配合子级元素来实现变化效果。 原理就是在不同屏幕下,通过媒体查询来改变这个布局容器的大小,再改变里面子元素的排列方式和大小,从而实现不同屏幕下,看到不同的页面布局和样式变化 Bootstrap 布局容器 container:两边留白 响应式布局的容器 固定宽度 大屏 ( >=1200px) 宽度定为 1170px 中屏 ( >=992px) 宽度定为 970px 小屏 ( >=768px) 宽度定为 750px 超小屏 (100%) container-fluid 百分百宽度 占据全部视口(viewport)的容器 栅格系统 按照不同屏幕划分为1~12 等份 行(row) 可以去除父容器作用15px的边距 xs-extra small:超小; sm-small:小; md-medium:中等; lg-large:大; 列(column)大于 12,多余的\"列(column)\"所在的元素将被作为一个整体另起一行排列 每一列默认有左右15像素的 padding 可以同时为一列指定多个设备的类名,以便划分不同份数 例如 class=\"col-md-4 col-sm-6\" 栅格嵌套 小列 小列 列偏移 1 2 列排序 左侧 右侧 响应式工具 使用这些工具类可以方便的针对不同设备展示或隐藏页面内容 visible-* 可达到相反的效果 文档 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-01-22 08:36:14 "},"前端开发/Jquery.html":{"url":"前端开发/Jquery.html","title":"Jquery","keywords":"","body":"转换 jq -- > js : jq对象[索引] 或者 jq对象.get(索引) js -- > jq : $(js对象) 基本操作 事件绑定 $(\"div\").click(function () { alert(\"click\"); }); 入口函数 $(function () { .... }); window.onload 和 $(function) 区别 window.onload 只能定义一次,如果定义多次,后边的会将前边的覆盖掉 $(function)可以定义多次的。 样式控制 $(\"div\").css(\"color\",\"red\"); 选择器 类型 语法 作用 标签选择器(元素选择器) $(\"html标签名\") 获得所有匹配标签名称的元素 ID选择器 $(\"#id的属性值\") 获得与指定id属性值匹配的元素 类选择器 $(\".class的属性值\") 获得与指定的class属性值匹配的元素 并集选择器 $(\"选择器1,选择器2....\") 获取多个选择器选中的所有元素 后代选择器 $(\"A B \") 选择A元素内部的所有B元素 子选择器 $(\"A > B\") 选择A元素内部的所有B子元素 属性名称选择器 $(\"A[属性名]\") 包含指定属性的选择器 属性选择器 $(\"A[属性名='值']\") 包含指定属性等于指定值的选择器 符合属性选择器 $(\"A[属性名='值'][]...\") 包含多个属性条件的选择器 过滤选择器 :first 获得选择的元素中的第一个元素 尾选择器 :last 获得选择的元素中的最后一个元素 非元素选择器 :not(selector) 不包括指定内容的元素 偶数选择器 :even 偶数,从 0 开始计数 奇数选择器 :odd 奇数,从 0 开始计数 等于索引选择器 :eq(index) 指定索引元素 大于索引选择器 :gt(index) 大于指定索引元素 小于索引选择器 :lt(index) 小于指定索引元素 标题选择器 :header 获得标题(h1~h6)元素,固定写法 可用元素选择器 :enabled 获得可用元素 不可用元素选择器 :disabled 获得不可用元素 选中选择器 :checked 获得单选/复选框选中的元素 选中选择器 :selected 获得下拉框选中的元素 DOM操作 内容操作 html(): 获取/设置元素的标签体内容 内容 --> 内容 text(): 获取/设置元素的标签体纯文本内容 内容 --> 内容 val(): 获取/设置元素的value属性值 属性操作 attr(): 获取/设置元素的属性 removeAttr():删除属性,如果操作的是元素自定义的属性,则建议使用attr prop():获取/设置元素的属性,如果操作的是元素的固有属性,则建议使用prop removeProp():删除属性 addClass():添加class属性值 removeClass():删除class属性值 toggleClass():切换class属性 css() 节点操作 append():父元素将子元素追加到末尾 对象1.append(对象2): 将对象2添加到对象1元素内部,并且在末尾 prepend():父元素将子元素追加到开头 对象1.prepend(对象2):将对象2添加到对象1元素内部,并且在开头 appendTo(): 对象1.appendTo(对象2):将对象1添加到对象2内部,并且在末尾 prependTo(): 对象1.prependTo(对象2):将对象1添加到对象2内部,并且在开头 after():添加元素到元素后边 对象1.after(对象2): 将对象2添加到对象1后边。对象1和对象2是兄弟关系 before():添加元素到元素前边 对象1.before(对象2): 将对象2添加到对象1前边。对象1和对象2是兄弟关系 insertAfter() 对象1.insertAfter(对象2):将对象2添加到对象1后边。对象1和对象2是兄弟关系 insertBefore() 对象1.insertBefore(对象2): 将对象2添加到对象1前边。对象1和对象2是兄弟关系 remove():移除元素 empty():清空元素的所有后代元素 动画 参数: speed:动画的速度。三个预定义的值(\"slow\",\"normal\", \"fast\")或表示动画时长的毫秒数值(如:1000) easing:用来指定切换效果,默认是\"swing\",可用参数\"linear\" swing:动画执行时效果是 先慢,中间快,最后又慢 linear:动画执行时速度是匀速的 fn:在动画完成时执行的函数,每个元素执行一次。 方法 默认 show([speed,[easing],[fn]]) hide([speed,[easing],[fn]]) toggle([speed],[easing],[fn]) 滑动 slideDown([speed],[easing],[fn]) slideUp([speed,[easing],[fn]]) slideToggle([speed],[easing],[fn]) 淡入淡出 fadeIn([speed],[easing],[fn]) fadeOut([speed],[easing],[fn]) fadeToggle([speed,[easing],[fn]]) 遍历 jq对象.each(callback) $(\"div\").each(function (i,e) { console.table(i,e); }); 如果当前function返回为false,则结束循环(break)。 如果当前function返回为true,则结束本次循环,继续下次循环(continue) $.each(object, [callback]) $.each($(\"div\"),function (i, e) { console.table(i,e); }) for..of ES6语法 for (let i of $(\"div\")){ console.log(i); } 事件绑定 标准绑定 jq对象.事件方法(回调函数),如果调用事件方法,不传递回调函数,则会触发浏览器默认行为。 on/off jq对象.on(\"事件名称\",回调函数) jq对象.off(\"事件名称\") 如果off方法不传递任何参数,则将组件上的所有事件全部解绑 插件 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-12 15:27:20 "},"前端开发/AJAX.html":{"url":"前端开发/AJAX.html","title":"AJAX","keywords":"","body":"异步和同步 原生方式 let xhr = new XMLHttpRequest(); xhr.open(\"get\",\"/web3_war_exploded\"); xhr.send(); xhr.onreadystatechange = function () { if (xhr.status === 200){ console.log(xhr.responseText); } } JQuery实现方式 ajax $.ajax({ url:\"./\" , // 请求路径 type:\"POST\" , //请求方式 //data: \"username=jack&age=23\",//请求参数 data:{\"username\":\"jack\",\"age\":23}, success:function (data) { alert(data); },//响应成功后的回调函数 error:function () { alert(\"出错啦...\") },//表示如果请求响应出现错误,会执行的回调函数 dataType:\"text\"//设置接受到的响应数据的格式 }); $.get $.post MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-12 16:39:34 "},"前端开发/NodeJs.html":{"url":"前端开发/NodeJs.html","title":"NodeJs","keywords":"","body":" 运行js文件 node xxx 模块导出与使用 exports.add=function(a,b){ return a+b; } var demo = require('./module'); demo.add(1,2); 创建web服务器 var http = require('http') http.createServer(function(request,response){ const body = \"hello world\"; response.writeHead(200,{ 'Content-Length':Buffer.byteLength(body), 'Content-Type':'text/plain' }); response.end(body); }).listen(8888); 获取请求参数 request.url MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-07 13:52:24 "},"前端开发/ES6.html":{"url":"前端开发/ES6.html","title":"ES6","keywords":"","body":"let 所声明的变量,只在let命令所在的代码块内有效 { let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1 const 声明一个只读的常量。一旦声明,常量的值就不能改变。 const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable. 模板字符串 let name = \"cxk\" console.log(`your name is ${name}`) let info =`123 456 789` 解构赋值 数组 let [a, b, c] = [1, 2, 3]; // a=1 b=2 c=3 const color = [1,2] const color2=[...color,3,4] // color2 = [1,2,3,4],同样能用于对象 对象 let {name,age} = {name:\"123\",age:15} // name = 123 age = 15 函数默认值 function a(a = 2){ console.log(a); } 箭头函数 let add = (a,b) => a+b; map和reduce let arr1 = ['1','2','3']; let arr2 = arr1.map(i => parseInt(i)); // arr2 = [1, 2, 3] let ret = arr2.reduce((i,j)=>i+j); // ret = 6 模块导入导出 import { stat, exists, readFile } from 'fs'; export { firstName, lastName, year }; export function multiply(x, y) { return x * y; }; Promise 解决异步编程问题 Promise 是一个对象,它代表了一个异步操作的最终完成或者失败 var promise1 = new Promise(function(resolve, reject) { setTimeout(function() { resolve('foo'); }, 300); }); promise1.then(function(value) { console.log(value); // expected output: \"foo\" }); MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-07 16:14:02 "},"前端开发/Vue/nav.html":{"url":"前端开发/Vue/nav.html","title":"Vue","keywords":"","body":"VUE 两种视图模式 MVP 与MVC不同的是,MVP中的M与V没有直接交互 MVVM vue实例 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的 var vm = new Vue({ // 选项 }) 根实例 └─ TodoList ├─ TodoItem │ ├─ DeleteTodoButton │ └─ EditTodoButton └─ TodoListFooter ├─ ClearTodosButton └─ TodoListStatistics 实例生命周期 nav 数据渲染 属性操作 系统指令 组件 动画 vue-cli 安装 npm install -g @vue/cli 创建项目 vue create project-name 工程结构 集成vue 单页面、多页面 vue.js 复杂单页面 vue-cli MY all right reserved,powered by Gitbook该页面最后修改于: 2020-02-06 09:44:07 "},"前端开发/ReactJS.html":{"url":"前端开发/ReactJS.html","title":"ReactJS","keywords":"","body":"前端开发的演变 静态页面-AJAX-前端MVC-SPA ReactJS ReactJS把复杂的页面,拆分成一个个的组件,将这些组件一个个的拼装起来,就会呈现多样的页面。ReactJS可以用于 MVC 架构,也可以用于 MVVM 架构,或者别的架构 JSX语法 JSX语法就是,可以在js文件中插入html片段,是React自创的一种语法 在JSX语法中,只能有一个根标签,不能有多个 const div1 = right; const div2 = errorerror; 函数调用 {f()} // f是函数名 组件 组件定义 import React from 'react'; class HelloWorld extends React.Component{ render() { // 重写渲染方法 return cxk:jntm } } export default HelloWorld; // 导出该类 使用自定义组件 import React from 'react'; import HelloWorld from \"./HelloWorld\"; class Show extends React.Component{ render() { return } } export default Show; 组件参数传递 // 属性传递 标签包裹传递 蔡徐坤 // 接收 {this.props.name}:{this.props.children} 组件状态 每一个组件都有一个状态,其保存在this.state中,当状态值发生变化时,React框架会自动调用render()方法,重新渲染页面 this.state值的设置要在构造参数中完成 要修改this.state的值,需要调用this.setState()完成,不能直接对其进行修改 class HelloWorld extends React.Component{ constructor(props, context) { super(props, context); this.state = { dataList : [1,2,3] }; } render() { // 重写渲染方法 return { this.state.dataList.map((value,index)=>{ return {value} }) } { let list = this.state.dataList; list.push(Math.random()); this.setState({dataList:list}) }}>click } } 生命周期 添加钩子方法 class HelloWorld extends React.Component{ // 组件挂载后调用 componentDidMount() { console.log(\"组件挂载后...\"); } // 省略其他 } 前端代码分层 Page 负责与用户直接打交道:渲染页面、接受用户的操作输入,侧重于展示型交互 性逻辑 Model 负责处理业务逻辑,为 Page 做数据、状态的读写、变换、暂存等 Service 负责与 HTTP 接口对接,进行纯粹的数据读写 使用DVA进行数据分层管理 添加models export default { namespace : 'list', state:{ data:[1,2,3] } } 使用数据 import React from 'react' import {connect} from 'dva' const namespace = 'list' const map = (state)=>{ const list = state[namespace].data; return { list } }; @connect(map) class List extends React.Component{ render() { return { this.props.list.map((v,i)=>{ return {v} }) } } } export default List; 修改数据 export default { namespace: 'list', state: { data: [1, 2, 3] } , reducers: { addNewData(state){ let list = [...state.data,Math.random()]; console.log(list); return { data:list } } } } // 省略导入 // 省略map1 const map1 = (dispatch)=>{ return { addNewData:()=>{ dispatch( { type:namespace+\"/addNewData\" } ) } } } @connect(map,map1) class List extends React.Component{ render() { return { this.props.list.map((v,i)=>{ return {v} }) } { this.props.addNewData() }}> 点击 } } export default List; MY all right reserved,powered by Gitbook该页面最后修改于: 2019-12-07 16:48:07 "},"前端开发/NPM.html":{"url":"前端开发/NPM.html","title":"NPM","keywords":"","body":" npm(全称 Node Package Manager,即“node包管理器”)是Node.js默认的、以JavaScript编写的软件包管理系统 初始化工程 npm init 安装模块 本地安装 npm install xxx 获取模块全局目录 npm root -g 全局安装 npm install xxx -g 批量安装 npm install # npm会根据package.json下载依赖 使用淘宝镜像 npm install -g cnpm --registry=http://registry.npm.taobao.org 运行 在package.json中定义 dev:开发阶段 build:构建编译 lint:运行js代码检测 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-07 14:39:14 "},"前端开发/Webpack.html":{"url":"前端开发/Webpack.html","title":"Webpack","keywords":"","body":" 全局安装 npm install webpack -g npm install webpack-cli -g 使用 模块导出 let tip = function () { alert(\"hello,world\"); }; module.exports.tip=tip; 模块引入 let {tip} = require(\"./model1\"); tip(); 打包 webpack main.js build.js 使用webpack-dev-server 安装 cnpm install webpack@3.6.0 webpack-dev-server@2.9.1 html-webpack-plugin@2.30.1 --save-dev 配置 { \"devDependencies\": { \"html-webpack-plugin\": \"^2.30.1\", \"webpack\": \"^3.6.0\", \"webpack-dev-server\": \"^2.9.1\" }, \"scripts\": { \"dev\":\"webpack-dev-server --inline --hot --open --port 5008\" } } 配置webpack.config.js //引用html-webpack-plugin插件,作用是根据html模板在内存生成html文件,它的工作原理是根据模板文件在内存中生成一个index.html文件。 var htmlwp = require('html-webpack-plugin'); module.exports={ entry:'./src/main.js', //指定打包的入口文件 output:{ path : __dirname+'/dist', // 注意:__dirname表示webpack.config.js所在目录的绝对路径 filename:'build.js' //输出文件 }, devtool: 'eval-source-map', plugins:[ new htmlwp({ title: '首页', //生成的页面标题首页 filename: 'index.html', //webpack-dev-server在内存中生成的文件名称,自动将build注入到这个页面底部,才能实现自动刷新功能 template: 'vue_02.html' //根据vue_02.html这个模板来生成(这个文件请程序员自己生成) }) ] } 运行 npm run dev 调试 var add = function (x, y) { debugger return x+y+1; } MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-07 14:46:35 "},"移动开发/安卓/nav.html":{"url":"移动开发/安卓/nav.html","title":"安卓","keywords":"","body":"NAV Activity Intent RecyclerView Handler IPC机制 通知栏 数据绑定 屏幕适配 Fragment MY all right reserved,powered by Gitbook该页面最后修改于: 2019-07-28 14:15:03 "},"移动开发/小程序开发/nav.html":{"url":"移动开发/小程序开发/nav.html","title":"小程序开发","keywords":"","body":"小程序开发 什么软件适合做小程序 业务逻辑简单 使用频率低 性能要求低 开发者工具界面 v1.02 目录结构 主文件 文件 必填 作用 app.js 是 小程序逻辑 app.json 是 小程序公共设置 app.wxss 否 小程序公共样式表 页面文件组成 文件类型 必填 作用 js 是 页面逻辑 ( 微信小程序没有window和document对象 ) wxml 是 页面结构 ( WeiXin Markup Language,不是HTML语法 ) wxss 否 页面样式表 (WeiXin Style Sheets 拓展了rpx尺寸单位,微信专属响应式像素 ) json 否 页面配置 分包 整个小程序所有分包大小不超过 8M 单个分包/主包大小不能超过 2M 移动设备的分辨率与rpx rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素 配置 全局配置app.json控制整个程序的行为 页面配置page.json控制单个页面 组件 swiper 页面注册 生命周期 生命周期回调 Page({ // 启动页面后弹出消息 onLoad: function () { wx.showToast({ title: '鸡你太美', }); } }) 视图 数据绑定 在小程序中,在js的data中定义变量 Page({ // .. data: { msg: 'msg' } //... 可以在WXML中进行绑定,跟VUE一样,但是需要注意的是,这种绑定是单向绑定 {{message}} 需要使用setData来设置或者更新数据 this.setData({msg:'abc'}); 更复杂的用法 Hidden 条件渲染 True WEBVIEW APP MINA 列表渲染 {{item}} 事件 在WXML中绑定事件 Page({ onTap(){ console.log('hello') } }) bind与catch bind是冒泡,事件会往上传递 catch会阻止事件向上冒泡 模块化 模块导出 function method1(){ console.log(\"123\"); } module.exports.method1 = method1; 模块使用 const common = require('common.js') 模板template 定义模板 FirstName: {{firstName}}, LastName: {{lastName}} 引入模板 使用模板 MY all right reserved,powered by Gitbook该页面最后修改于: 2020-02-12 14:33:17 "},"开发工具/Docker.html":{"url":"开发工具/Docker.html","title":"Docker","keywords":"","body":" Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口 容器与虚拟机 Docker架构 镜像与容器 容器是镜像的实例 安装 安装脚本 wget https://get.docker.com 使用 镜像相关 搜索镜像 docker search name 拉取镜像 docekr pull name 删除镜像 docker rmi 镜像ID 容器相关 查看容器 docker ps 运行一个容器 docker run -p 8080:80 -d daocloud.io/nginx 复制文件到容器中 docker cp index.html e07dc4e0236a://usr/share/nginx/html 从容器中复制出文件 docker cp name:容器文件路径 宿主路径 停止容器 docker stop name 启动容器 docker start name 进入容器内部 docker exec -it bash 目录挂载 在启动容器时,使用-v参数 查看容器信息 docker inspect name 常用软件部署 mysql # 将宿主机33306映射到容器3306,指定root密码为123 docker run -di --name=mysql1 -p 33306:3306 -e MYSQL_ROOT_PASSWORD=123 mysql tomcat docker run -di --name=mytomcat -p 9000:8080 -v /usr/local/webapps:/usr/local/tomcat/webapps tomcat nginx docker run -di --name=mynginx2 -p 8080:80 nginx-update 迁移与备份 保存镜像 docker commit -m 'update' e07dc4e0236a nginx-update 保存为压缩包 docker save -o nginx-update.tar nginx-update 把压缩包恢复成镜像 docker load -i nginx-update.tar Dockerfile 示例: FROM ubuntu MAINTAINER MY RUN apt-get update RUN apt-get install nginx -y COPY index.html /var/www/html ENTRYPOINT [\"/usr/sbin/nginx\",\"-g\",\"daemon off;\"] EXPOSE 80 根据文件构建镜像 docker build -t='name' . 镜像分层 私有仓库 搭建 docekr pull registry docker run -di --name=registry 5000:5000 registry 上传镜像到私服 docker tag nginx 127.0.0.1:5000/nginx docker push 127.0.0.1:5000/nginx Compose Docker 网络 网络类型 Bridge::Docker设计的NAT网络模型(默认类型) Host:与主机共享Network Namespace,--net=host None::不为容器配置任何网络功能,没有网络 --net=none Container:与另一个运行中的容器共享Network Namespace,--net=container:containerID 端口映射 # 将本机8080端口映射到容器80端口 docker run -p 8080:80 # 将本机端口随机与容器端口映射 docker run -P 镜像制作 DockerMaven插件 开启docker接受远程操作 添加maven插件 com.spotify docker-maven-plugin 0.4.12 my-pc:5000/${project.artifactId}:${project.version} java [\"java\", \"-jar\", \"/${project.build.finalName}.jar\"] / ${project.build.directory} ${project.build.finalName}.jar http://my-pc:2375 JDK8以上的版本需要添加如下依赖 javax.activation activation 1.1.1 构建并推送 mvn clean package docker:build -DpushImage MY all right reserved,powered by Gitbook该页面最后修改于: 2019-12-11 23:04:09 "},"开发工具/K8s.html":{"url":"开发工具/K8s.html","title":"K8s","keywords":"","body":" Kubernetes(常简称为K8s)是用于自动部署、扩展和管理容器化(containerized)应用程序的开源系统 架构 etcd保存了整个集群的状态; apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制; controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等; scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上; kubelet负责维护容器的生命周期,同时也负责Volume(CSI)和网络(CNI)的管理; Container runtime负责镜像管理以及Pod和容器的真正运行(CRI); kube-proxy负责为Service提供cluster内部的服务发现和负载均衡; MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-05 21:50:15 "},"开发工具/vim/vim.html":{"url":"开发工具/vim/vim.html","title":"VIM","keywords":"","body":"目录 [toc] VIM vim的四种模式 正常模式:启动vim后默认处于正常模式。不论位于什么模式,按下键(有时需要按两下)都会进入正常模式 w:跳到下一个单词 b:跳到上一个单词 0:跳到行首 $:跳到行尾 gg:跳到文档开头 G:跳到文档末尾 ctrl + u :上翻页 ctrl + f :下翻页 zz:将光标移到屏幕中间 dt{char} : delete to char (删除到char) ct{char} : delete to char and into insert(删除到char然后进入insert ctrl+u:向前滚动半页 模式) 插入模式:i:进入插入模式 o:新起一行进行添加 a:在光标后进行追加 在插入模式中,可以使用```ctrl + h``` 或者 ```ctrl + w```来删除上一个单词 ctrl + u :undo操作 命令模式:在正常模式中,按下:(英文冒号)键,会进入命令模式。在命令模式中可以执行一些输入并执行一些vim或插件提供的指令,就像在shell里一样。这些指令包括设置环境、文件操作、调用某个功能等等 %s s/{a}/{b}/g:全局把a替换成b vs:垂直分割屏幕 sp:水平分割屏幕 ctrl + w:移动到上一个屏幕 可视模式:在正常模式中按下v, V, +v,可以进入可视模式。可视模式中的操作有点像拿鼠标进行操作,选择文本的时候有一种鼠标选择的即视感,有时候会很方便 y:复制 p:粘贴宏的使用 录制宏: 回放宏:自动补全 单词自动补全 ctrl + n:下一个单词 ctrl + p: 上一个单词 文件自动补全 ctrl + f修改VIM的配色 : colorscheme xx 其中xx为配色名称持久化配置 在~/.vimrc中可以输入一些命令,以此来保存配置:set nu set autoindent set background=dark colorscheme hybrid syntax on 按键映射 map: 其中可以为i(insert),c(command),n(normal),v(visual) noremap: 的取值同上 nore的区别在于这种按键映射是非递归的。 举例:imap jj 这么样一条命令代表在insert模式下按下jj会自动切换到normal模式插件的安装 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-06-22 16:08:38 "},"开发工具/git.html":{"url":"开发工具/git.html","title":"GIT","keywords":"","body":" GIT 整体流程 初始化仓库 git init 配置信息 git config --global user.name my git config --global user.email 715711877@qq.com 配置默认编辑器 git config core.editor vim 查看状态 git status 添加所有文件到缓存区 git add . 提交所有更改 git commit -a -m \"first commit\" 查看提交日志 $ git log 回滚到某一次提交 git reset --hard 33ea7586bfe2d14e9ddbe9b07c5653159541338c 添加远程仓库 $ git remote add origin https://github.com/cjp715711877/test.git 推送到远程仓库 $ git push -u origin master 克隆仓库 $ git clone https://github.com/996icu/996.ICU.git 分支 开启一条新分支 $ git branch x 切换分支 git checkout x 分支合并 git merge x 推送到远程仓库 生成ssh密钥 ssh-keygen -t rsa 添加远程仓库地址 git remote add origin git@github.com:0xcaffebabe/repo1.git 推送 git push -u origin master 搭建Git私服 安装git 初始化服务器本地仓库 git --bare init /home/git/first 设置远程仓库地址 git remote add origin ssh://root@my-pc/home/git/first 推送 git push --set-upstream origin master 从远程仓库下载源码 git clone ssh://root@my-pc/home/git/first MY all right reserved,powered by Gitbook该页面最后修改于: 2019-09-10 17:25:40 "},"开发工具/SVN.html":{"url":"开发工具/SVN.html","title":"SVN","keywords":"","body":" 复制-修改-合并方案(Subversion默认的模式) 锁定-修改-解锁方案 服务端 visualsvn server 客户端 TortoiseSVN 操作 浏览 checkout commit update revert export edit conflict 整合IDEA share project 目录结构 Trunk 主干目录,此目录下的文件为基准文件 Branches 用于开发的分支目录 Tags 用于发布的版本目录 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-26 09:33:24 "},"开发工具/idea.html":{"url":"开发工具/idea.html","title":"idea","keywords":"","body":"安装 https://www.jetbrains.com/idea/download/#section=windows 项目目录 .idea 目录和 demo.iml 和我们开发无关,是IDEA工具自己使用的 out 目录是存储编译后的.class文件 src 目录是存储我们编写的.java源文件 常用快捷键 键位 说明 Alt+Enter 导入包,自动修正代码 Ctrl+Y 删除光标所在行 Ctrl+D 复制光标所在行的内容,插入光标位置下面 Ctrl+Alt+L 格式化代码 Ctrl+/ 单行注释 Ctrl+Shift+/ 选中代码注释,多行注释,再按取消注释 Alt+Ins 自动生成代码,toString,get,set等方法 Alt+Shift+上下箭头 移动当前代码行 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-01 14:02:10 "},"开发工具/Junit.html":{"url":"开发工具/Junit.html","title":"Junit","keywords":"","body":" 白盒测试 黑盒测试 @Test public void test(){ Assert.assertEquals(1,1); } @Before @After MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-04 13:36:45 "},"开发工具/构建工具/gradle.html":{"url":"开发工具/构建工具/gradle.html","title":"Gradle","keywords":"","body":"Gradle [toc] Gradle 的安装 安装过程跟Maven类似,Gradle基于JAVA,所以下载完之后将路径添加到环境变量即可 Groovy Groovy 是JVM 的一个替代语言—替代是指可以用Groovy 在Java 平台上进行Java 编程,使用方式基本与使用Java 代码的方式相同 程序示例: class Foo { doSomething() { data = [\"name\": \"James\", \"location\": \"London\"] for (e in data) { println(\"entry ${e.key} is ${e.value}\") } } closureExample(collection) { collection.each { println(\"value ${it}\") } } static void main(args) { values = [1, 2, 3, \"abc\"] foo = new Foo() foo.closureExample(values) foo.doSomething() } } 任务 在Gradle,可以自定义任务。 示例: task \"create-dirs\" 上面是创建一个自动创建目录的任务 生命周期 初始化->配置->执行 依赖管理 添加依赖 dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' compile group: 'com.google.guava', name: 'guava', version: '27.1-jre' } 依赖冲突 排序 强制多项目构建 自动化测试 发布 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-06-03 20:30:49 "},"开发工具/构建工具/maven.html":{"url":"开发工具/构建工具/maven.html","title":"Maven","keywords":"","body":"Maven 简介 项目管理工具。 基于项目对象模型(POM), 可以通过一小段描述信息管理项目的构建。 下载与安装 下载地址'https://maven.apache.org/' 配置环境变量 新增'M2_HOME' 将%M2_HOME%\\bin添加到Path环境变量下 目录结构 src main java package resources test java package resources 一些喜欢忘记的知识点 指定JDK版本: UTF-8 UTF-8 12 12 12 常用命令 mvn clean # 清理target目录下的类文件 mvn install # 将本项目安装到本地仓库 mvn compile # 编译 mvn test # 执行测试 mvn package #打包 添加依赖 junit junit 4.12 test 自动生成目录结构 mvn archetype:generate 坐标与构件 仓库 本地仓库 修改本地仓库地址 远程仓库 镜像仓库 配置镜像仓库 生命周期 clean 清理项目 pre-clean clean post-clean default 构件项目 compile test package install deploy site 生成项目站点 pre-site site post-site site-deploy 打包插件 org.apache.maven.plugins maven-source-plugin 3.0.0 true compile jar-no-fork POM元素 pom版本 反写的网址+项目名 项目名+模块名 1.0-SNAPSHOT 项目描述名 项目地址 项目描述 证书信息 组织信息 UTF-8 UTF-8 12 12 12 junit junit 4.12 test org.apache.maven.plugins maven-source-plugin 3.0.0 true compile jar-no-fork 依赖范围 依赖传递 A->B(compile) 第一关系: a依赖b compile B->C(compile) 第二关系: b依赖c compile 依赖冲突 短路优先 A->B->C->X(1.0) A->D->X(2.0) 由于只能引入一个版本的包,此时Maven按照最短路径选择导入x(2.0) A->B->X(1.0) A->D->X(2.0) 路径长度一致,则优先选择第一个,此时导入x(1.0) B B 0.1 C C 聚合与继承 聚合 study-common study-plugin study-blog study-web 继承 com.tiantian.mavenTest projectA 1.0-SNAPSHOT 创建web项目 高级应用 分模块构建 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-08-25 14:39:47 "},"运维/持续集成.html":{"url":"运维/持续集成.html","title":"持续集成","keywords":"","body":" 持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。 Jenkins https://jenkins-ci.org/ 好处 自动化集成部署,提高了集成效率。 更快的修复问题。 更快的进行交付。 提高了产品质量。 特点 它是一个自动化的周期性的集成测试过程,从检出代码、编译构建、运行测试、结果 记录、测试统计等都是自动完成的,无需人工干预 需要有专门的集成服务器来执行集成构建 需要有代码托管工具支持 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-22 13:40:16 "},"运维/容器管理.html":{"url":"运维/容器管理.html","title":"容器管理","keywords":"","body":"Rancher 可以对容器进行分类、分环境管理,以图形化界面操作docker Rancher是一个开源的企业级全栈化容器部署及管理平台。Rancher为容器提供一揽 子基础架构服务:CNI兼容的网络服务、存储服务、主机管理、负载均衡、防护墙…… Rancher让上述服务跨越公有云、私有云、虚拟机、物理机环境运行,真正实现一键式应 用部署和管理 主机 应用 容器 服务 扩容缩容 influxDB InfluxDB是一个由InfluxData开发的开源时序型数据库。它由Go写成,着力于高性能地查询与存储时序型数据。InfluxDB被广泛应用于存储系统的监控数据,IoT行业的实时数据等场景 cAdvisor CAdvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具。通过在主机上运行CAdvisor用户可以轻松的获取到当前主机上容器的运行统计信息,并以图表的形式向用户展示 Grafana grafana 是一款采用 go 语言编写的开源应用,主要用于大规模指标数据的可视化展现,是网络架构和应用分析中最流行的时序数据展示工具,目前已经支持绝大部分常用的时序数据库 MY all right reserved,powered by Gitbook该页面最后修改于: 2019-11-22 16:19:58 "},"通识/技术与世界.html":{"url":"通识/技术与世界.html","title":"技术与世界","keywords":"","body":"技术与世界 技术人员,很容易就陷入到“技术就是一切”的极端中,往往是只见树木,不见森林 仅仅是技术好,是不够的。必须有更大的视野,必须看更大的世界 编程语言的发展趋势 现代编程语言,可以说是抽象程度更高了,更符合人类的思维 领域特定语言(DSL) 做特定领域的事情,而不用纠结与太多的底层细节 GPPL(通用目标语言) MY all right reserved,powered by Gitbook该页面最后修改于: 2020-02-12 16:42:01 "}}