zhengsj 2020-07-29
Java EE 有相应的规范实现,包括但不限于:
所有这些规范和技术组成Java EE架构:
Java EE的缺点:
spring的提出,核心功能仅仅只是Aop和IoC,发展如火如荼之后也有缺点,spring boot应运而生。
JDK安装、maven配置、IoC与bean容器、注解、AOP示例。
Ant通配符:*: 匹配任意字符;**:匹配任意路径;?:匹配单个字符;如果一个请求,有多个@RequestMapping可以匹配,通常是更具体的匹配会去响应这个请求:有通配符的优先级低于没有通配符的;有‘**‘低于有‘*‘;
consumes & producesconsumes 意味着请求的HTTP头的content-type的媒体类型,带错content-typ的请求会报错:there was an unexpected error(type=unsupported content type, status=415), content type ‘’ not supported.produces 属性对应于 HTTP 请求 的 Accept 字段,通常浏览器都会将 Accept 设置为*.*
验证框架:sb支持JSR-303、bean框架
java里有两类数据库访问方式:
Spring JDBC Template,复杂的结果集通过实现 RowMapper 接口来映射到 Java 对象。JdbcTemplate 允许查询结果返回 一个 Map 而不是 POJO ,这样免去 RowMapper 的工作,数据库的字段名就是 Map 的 key:
String sql = "select * from user where id=?";Map map= jdbcTempalte.queryForMap(sql, userid);12
缺点:使用 Map 作为查询结果有非常多的弊端,很难通过 Map 了解查询结果集;鉴于泛型擦除,返回结果类型未知;以及数据库不一样,同样的词,有可能返回不同的数据类型,导致数据库平台不兼容。
数据库插入,对于 MySQL、SQL Server等数据库,含有自增序列 , 则需要提供一个 KeyHolder 来放置返回的序列。
NamedParameterJdbcTemplate 继承 JdbcTemplate,不同于 JdbcTemplate , 对 SQL 中的参数只支持传统的"?"占位符。 NamedParameterJdbcTemplate 允许 SQL 中使用参数的名字作为占位符:
String sql = "select count(1) from user where department_id=:deptId";MapSqlParameterSource namedParameters = new MapSqlParameterSource();namedParameters.addValue("dept Id", departmentId);123
BeetlSQL 介绍
Spring Data JPA, 基于hibernate,两个重要的特性:spring.jpa.hibernate.ddl-auto,自动建库。spring.jpa.show-sql,打印SQL。自动建表是个很酷的特性,但对于常规项目用处井不大,因为大多数项目都是在需求分析后建立物理模型 。 也就是先有数据库表设计,随后才是 Spring Boot 应用,因此数据库的 DDL 语句早已经具备 。 从另一方面讲,项目数据库管理人员、需求分析人员,甚至是项目经理并不喜欢 Hibernate 创建的表结构,比如,它的外键命名就很随机,不符合命名规范 。 自动建表对于小型项目或者工具类项目(如工作流引擎)还是很方便的 。一个部门拥有多个用户 ,使用 Set 而不是 List,是因为 Set 结构是存放不同元素的集合,这也是 JPA 要求的。
Repository:CrudRepositoryPagingAndSortingRepositoryJpaRepository自定义Repository
Repository 提供 save 方法来保存或者更新一个实体,默认情况下,如果 Entity 主键属性为空,则认为是新的实体,保存实体;反之,如果 Entity 主键属性不为空,则更新实体 。Spring Data 提供另外一个判断实体是否是“新的实体”的方法一Entity 实现Persistable 接口的 isNew 方法。
Hibernate 的 showSql 配置只打印 SOL,并未像 BeetlSQL 那样同时打印 SOL参数、执行时间等信息,如果需要这些信息,可以使用第三方工具 log4jdbc 来完成 。
无论是 JPQL , 还是 SQL 语句,都支持 “命名参数” :
@Query(value="select * from user where name=:name and department_id=:departmentId", nativeQuery=true)public User nativeQuery2 (String name, Integer departmentId);12
查询时可以使用 Pageable 和 Sort 来对协助“ JPQL ” 完成翻页和排序:
@Query(value="select u from User u where u.department.id=?1")public Page<User> queryUsers(Integer departmentid, Pageable page );12
@Query 还允许 SQL 更新、删除语句,此时必须搭配@Modifying 使用,比如:
@Modifying@Query("update User u set u.name= ?1 where u.id=?2")int updateName(String name, Integer id) ;123
小技巧:
模式自由,不需要事先定义文档格式,可以任意改变文档格式。MongoDB 以下面线开头的字段都有特殊意义,表示文档主键,如果文档没有提供此主键,则系统自动生成一个 ObjectID 类型的主键。推荐在SB应用中,由应用来定义一个主键而不是由 MongoDB 生成。用12字节存储,分别是4字节时间戳,3字节机器唯一标识,2 字节的进程标识,以及最后 3 字节的自增, ObjectID 转成可读的 16 进制看起来是这个样子:4e7020cb7cac8laf7136236b。replaceOne 与 updateOne,前者是替换整个文档,而后者是更新部分文档 。这两个方法都只替换匹配的第一条记录,如果有多条记录匹配,可以使用 updateMany。options 有如下属性可 以控制更新特性:upsert,默认为 false , 如果设置成 true ,未匹配的文档会 insert 到数据库中 。writeConcern ,对写入进行配置 ,包含以下属性 。
Redis 在内存中存储数据,因此原则上,存放在 Redis 中的数据不应该大于内存容量,否则会因为操作系统虚拟内存导致性能降低 。Redis 一共有 14 个命令组、两百多个命令。DECRBY/INCRBY , 数字类型数据减去某个指定的整数或者增加某个指定整数。INCRBYFLOAT , 数字增加一个浮点数,负数表示减去。Redis List 类型类似 Java 的 LinkedList,通过链表来完成,向其添加元素速度非常快,按照索引方式获取元素比较慢。rpush,将多个值放入 list 尾部;Ipush,将多个值放入 list 头部;
zk,分布式应用可以基于它实现协调服务,比如同步、集群、领导选取,以及分布式系统的配置管理、命名服务。使用文件系统目录树作为数据模型。能够保证操作的时序性:zk 对每次更新都有时间戳记录,从而保证操作的时序性,保证可以完成更高层次的协调服务,如分布式锁。zk 提供的命名空间 ( name space )类似文件系统,每一个节点都是通过路径来表示的,不同的是,节点可以包含一定的数据(2MB 字节),这些节点可以用来存放业务信息,节点还包含更新的版本、时间戳。节点类型:临时节点,创建节点的会话存在,节点就存在, 一旦会话结束,如客户端创建的连接断掉,或者客户端主动关 彼此会话,则节点会被删除 。 还可以指定节点为顺序节点,创建节点的时候,自动为节点增加一个序列号,并且序列号递增 。节点可以被监控, 一旦节点变化,如删除节点,或者节点数据变化,客户端就会收到此事件,此监控失效 。 客户端可以调用 API 继续监控这个节点 。心跳包通常用于长连接 , 如果长连接没有心跳包,会导致服务器或者防火墙主动断开 。 心跳包通常就是内容为空的包 。命令:create -e,创建临时节点;create -s,创建带有序列号的节点;get 操作返回节点内部使用的数据:
watch 操作 , ls 命令和 get 命令都可以增加一个 watch 操作, 节点变化的时候会通知客户端。通知完毕后,还需要再次调用 ls 或者 get 才能监信此节点变化。选举领导者以及候选过程每个候选者使用 zk 创建一个节点的时候,都会知道自己创建的节点名,在选举过程中,用自己的节点名同/election 目录下所有节点进行比较,如果自己的序列号就是最小的序列号,那自己就是当仁不让的领导者节点 。其他节点同时还需要 watch 领导节点,即序列号最小的节点,如果领导节点被删除/退出或者意外危机,则所有候选者都会收到消息,再次进行如上所述的选举过程 。这种选举过程比较简单,唯一的问题是如果有大量候选者,节点变化同时通知其他大量的候选者再次进行选举会对 zk 有一定的性能影响,因此,一般改进的方式是每个候选者仅监听比自己序列号小的那个候选者。这样,如果领导节点被删除,则序列号较大的候选者能收到领导节点变化事件,只有这一个节点完成选举过程,确认自己是领导节点。
分布式锁实现分布式锁可以利用节点唯一性,比如创建一个locks/xxx的节点,xxx可以对应到业务数据。如果创建节点成功,则认为自己获得锁,可以进行业务操作,如果创建失败,则监听此节点,等待节点被删除。业务操作完毕后,可以删除此节点 。 这时候其他客户端将得到 watch 事件,再次创建/locks/xxx,成功则意味着再次获得这个锁。缺点:
类似领导选举那样的算法来实现分布式锁,谁是领导节点,谁就相当于获得锁。 释放锁,将自己创建的节点删除就可以;需要查看有多少客户端在等待锁,只需要查看有多少节点就可以 。
服务注册和服务发现通过 zk 可以实现服务注册和服务发现。
CuratorCurator 实现 ZooKeeper 提供的所有应用场景(除了两阶段提交〉,有以下实现:
RetryPolicy接口用于重连策略,实现类有以下:
Curator API 是链式调用风格,遇到 forPath 接口就触发 ZooKeeper 调用,delete删除节点,以 forPath 结尾,如果节点不存在,将抛出 NoNodeException,如果节点是非空节点,则抛出 NotEmptyException。Curator 提供 InterProcessMutex 来实现分布式锁,用 acquire 方法获取锁,以及用 release释放锁。Curator 提供一个服务注册与发现的封装库curator-x-discovery。通过 ServicelnstanceBuilder 构造一个服务描述,以及通过 ServiceDiscovery 注册服务,还允许设置 payload,可以是任何类,用来放置额外的信息,也可以采用自定义类。
能查看和监控以下信息 :
trace 是通过 InMemoryTraceRepository 类来实现的,默认保留最后 100 条访问数据,可以自己配置InMemoryTraceRepository 或者实现 TraceRepository 接口,可以修改保留数据的条数。
Actuator 允许查看日志配置 ,还允许修改日志等级配置, Actuator 也可以在线查看日志内容 。http://localhost:8081/application/loggers可以通过提交以下 POST 片段来动态改变日志等级。
http://127.0.0.1:8081/application/dump 获得线程的堆栈信息http://127.0.0.1:8081/application/dump 获得内存镜像信息,内存镜像通常是查看内存溢出最好的办法,获得内存镜像更通用的方法是使用 JDK 提供的 jmap 命令,还可以在 Spring Boot 应用启动的时候增加如下参数:XX:+HeapDumpOnOutOfMemoryError XX:HeapDumpPath=/xxx/file.hprofjhat 来读取内存镜像文件 , 经通过 OQL 对象查询语言来分析内存。参数-port 指示 jhat 的访问地址,可以通过浏览器访 问 该地址, 进入内存分析界面。OQL语句示例:select s from java.util.ArrayList s where s.size >= 400
其他endpoint:configprops : 所有@ConfigurationProperties 注解的配置信息,如文件上传的最大允许配置等。
Healthlndicator 接口实现监控信息显示,默认有如下类实现 Healthlndicator 接口:DiskSpaceHealthlndicatorDataSourceHealthlndicatorXXXHealthlndicator: Elasticsearch 、几恒、 Mail 、 MongoDB 、 Rabbit 、 Redis 、Solr。自定义监控指标,实现接口Healthlndicator,重写方法health,返回一个 Health 对象。
由于篇幅限制,小编这里只将此实战文档的所含的部分内容展现出来了,需要获取完整文档用以学习的朋友们可以添加小助理微信【msbjy2019】获取