学习进度
Dubbo
简单了解
Dubbo是Alibaba开源的分布式服务框架(一个业务分拆多个子业务,部署在不同的服务器上,既然各服务是部署在不同的服务器上,那服务间的调用就是要通过网络通信),它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费(Consumer)两个角色。 。 一般来说,对其的简单使用主要在以下节点角色, 可借鉴
http://dubbo.apache.org/zh-cn/docs/user/preface/usage.html 官方文档学习
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
具体调用步骤如下所示
1 服务容器负责启动,加载,运行服务提供者。
2 服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者在启动时,向注册中心订阅自己所需的服务。
3 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
dubbo与spring的结合
这里使用的是基于 Spring 的 Schema 和 XML 扩展机制实现的xml配置(一般推荐使用此方式)
- 加载spring配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 应用名 -->
<dubbo:application name="${application.name}"/>
<!-- 连接到哪个本地注册中心 -->
<dubbo:registry protocol="zookeeper" address="${dubbo.zk.servers}" group="${dubbo.zk.group}"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="${dubbo.port}"/>
<dubbo:monitor protocol="registry"/>
<dubbo:provider loadbalance="random" filter="LoggerFilter"/>
<dubbo:consumer check="false"/>
</beans>
- 服务提供者
<!-- provider -->
<dubbo:service interface="com.mine.goods.facade.GoodsFacade" ref="goodsFacade" timeout="2000" retries="0"/>
- 服务消费者
<!-- consumer -->
<dubbo:reference id="sequenceService" interface="com.mine.sequence.service.SequenceService" check="false"
timeout="2000"/>
- 加载Spring配置,并调用远程服务
import com.mine.sequence.domain.Sequence;
import com.mine.sequence.service.SequenceService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SequenceSafeClient extends AbstractSequnceClient {
private SequenceService sequenceService;
private Sequence seq = null;
private Lock lock = new ReentrantLock();
public SequenceSafeClient(String seqname) {
super(seqname);
}
public void setSequenceService(SequenceService sequenceService) {
this.sequenceService = sequenceService;
}
public synchronized void init() {
if (this.seq == null) {
this.seq = this.sequenceService.getSequence(this.getSeqname());
}
}
Mybats :resultMap
简单介绍
mybats的学习可参照 http://www.mybatis.org/mybatis-3/zh/index.html 文档
MyBatis 的真正强大在于它的映射语句,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 为聚焦于 SQL 而构建,以尽可能地为你减少麻烦。
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出): cache – 对给定命名空间的缓存配置。 cache-ref –
对其他命名空间缓存配置的引用。 resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。 sql –
可被其他语句引用的可重用语句块。 insert – 映射插入语句 update – 映射更新语句 delete – 映射删除语句
select – 映射查询语句
与Spring的整合
spring与mybats整合一般三种方法
具体可参考 https://www.cnblogs.com/wangmingshun/p/5674633.html 的文章。
我在实际中应用的是采用MapperScannerConfigurer,它将会查找类路径下的映射器并自动将它们创建成MapperFactoryBean。具体spring_mybats.xml如下所示,可以详细阅读注释了解基本使用。
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2017 ngmm365.com All rights reserved.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
default-autowire="byName">
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="connectProperties" value="config.decrypt=true"/>
<!-- 初始化连接数大小 -->
<property name="initialSize" value="20"/>
<!-- 最小空闲连接数 -->
<property name="minIdle" value="20"/>
<!-- 最大活跃连接 -->
<property name="maxActive" value="100"/>
<!-- 请求连接最大等待时间,单位:ms -->
<property name="maxWait" value="2000"/>
<!-- 请求连接使用非公平锁 -->
<property name="useUnfairLock" value="true"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:ms -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 配置一个空闲连接在池中最大生存的时间,单位:ms -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<!-- 测试sql语句 -->
<property name="validationQuery" value="SELECT 'x'"/>
<!-- 是否测试空闲连接的可用性 -->
<property name="testWhileIdle" value="true"/>
<!-- 请求连接的时候是否测试可用性 -->
<property name="testOnBorrow" value="false"/>
<!-- 返回连接的时候是否测试可用性 -->
<property name="testOnReturn" value="false"/>
<!-- 是否打开PSCache,mysql建议关闭 -->
<property name="poolPreparedStatements" value="false"/>
<property name="maxPoolPreparedStatementPerConnectionSize" value="-1"/>
<property name="proxyFilters">
<list>
<ref bean="stat-filter"/>
<ref bean="config-filter"/>
<ref bean="wall-filter"/>
</list>
</property>
</bean>
<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
<!--慢SQL统计,如果SQL执行时间超过一定时间则记录为慢SQL -->
<property name="slowSqlMillis" value="1000"/>
<!--慢SQL统计日志输出 -->
<property name="logSlowSql" value="true"/>
<!--合并SQL统计 例如select * from table t where t.id =1,会被变为select * from table t where t.id =?来统计 -->
<property name="mergeSql" value="true"/>
</bean>
<bean id="log-filter" class="com.alibaba.druid.filter.logging.Slf4jLogFilter">
<!--<property name="resultSetLogEnabled" value="false" />-->
<!--<property name="statementExecutableSqlLogEnable" value="true" />-->
</bean>
<bean id="config-filter" class="com.alibaba.druid.filter.config.ConfigFilter">
</bean>
<bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter">
</bean>
<bean id="goodsSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--<property name="configLocation" value="classpath:dal/mybatis-configuration.xml"/>-->
<property name="mapperLocations" value="classpath:dal/sqlmapper/*.xml"/>
<!--<property name="typeAliasesPackage" value="classpath:dal/domainobject"/>-->
</bean>
<bean id="goodsSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"
c:_0-ref="goodsSqlSessionFactory" lazy-init="true"></bean>
<!--<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">-->
<!--<!– 这里的basePackage 指定了dao层接口路径,这里的dao接口不用自己实现 –>-->
<!--<property name="basePackage" value="com.zhicong.goods.dal.dao"/>-->
<!--<!– 如果只有一个数据源的话可以不用指定,但是如果有多个数据源的话必须要指定 –>-->
<!--<!– <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> –>-->
<!--<!–直接制定了sqlsessionTemplate名称,这个和上面的其实是一样的 –>-->
<!--<!–<property name="sqlSessionTemplateBeanName" value="sqlSession" />–>-->
<!--</bean>-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<!--使用注释事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 幂等支持 -->
<bean id="idempotentExecutor" class="com.zhicong.distributed.IdempotentExecutor">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
ResultMap的使用
resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的长达数千行的代码。ResultMap 的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。
1 下面是一个实践中简单的mybats.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ActivityStock">
<!--非常重要: id 元素在嵌套结果映射中扮演着非常重要的角色。你应该总是指定一个或多个可以唯一标识结果的属性。 虽然,即使不指定这个属性,MyBatis 仍然可以工作,但是会产生严重的性能问题。 只需要指定可以唯一标识结果的最少属性。显然,你可以选择主键(复合主键也可以)。 -->
<resultMap id="ActivityStockDO" type="com.zhicong.goods.dal.domainobject.ActivityStockDO">
<id column="id" property="id"/>
<result column="goods_id" property="goodsId"/>
<result column="sku_id" property="skuId"/>
<result column="activity_id" property="activityId"/>
<result column="status" property="status"/>
<result column="stock" property="stock"/>
<result column="create_time" property="createTime"/>
<result column="modify_time" property="updateTime"/>
</resultMap>
<!--sql字段这个元素可以被用来定义可重用的 SQL 代码段,这些 SQL 代码可以被包含在其他语句中。它可以(在加载的时候)被静态地设置参数。 在不同的包含语句中可以设置不同的值到参数占位符上。-->
<sql id="ActivityStock_list_column">
id,goods_id,sku_id,activity_id,status,stock,create_time,modify_time
</sql>
<!--数据库插入操作 -->
<insert id="addActivityStock" parameterType="com.zhicong.goods.dal.domainobject.ActivityStockDO">
insert into activity_stock
(goods_id,sku_id,activity_id,status,stock,create_time,modify_time)
VALUE
(#{goodsId},#{skuId},#{activityId},#{status},#{stock},now(),now())
</insert>
2 然后可以在dao层持久化数据
public void addActivityStock(ActivityStockDO stock) {
goodsSqlSessionTemplate.insert("addActivityStock", stock);
}
3 另外,在上述查询只是介于一个表,其实还可以按如下操作关联两个表的查询还可以利用ResultMap进行嵌套查询如以下配置
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" column="blog_author_id" javaType="Author" resultMap="authorResult"/>
</resultMap>
<resultMap id="authorResult" type="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
</resultMap>
在上面的例子中,你可以看到,博客(Blog)作者(Writer)的关联元素委托名为 “WriterResult” 的结果映射来加载作者对象的实例。
现在,上面的示例使用了外部的结果映射元素来映射关联。这使得 Writer的结果映射可以被重用。 然而,如果你不打算重用它,或者你更喜欢将你所有的结果映射放在一个具有描述性的结果映射元素中。 你可以直接将结果映射作为子元素嵌套在内。
另外,对于mybats而言,使用的都是简单参数。实际上参数是 MyBatis 非常强大的元素。对于简单的使用场景,大约 90% 的情况下你都不需要使用复杂的参数,原始类型或简单数据类型(比如 Integer和 String)因为没有相关属性,它会完全用参数值来替代。
然而,如果传入一个复杂的对象,行为就会有一点不同了。 对向语句中传递参数来说,原始数据类型既简单又有效。不过参数映射的功能远不止于此。首先,像 MyBatis的其他部分一样,参数也可以指定一个特殊的数据类型。
#{property,javaType=int,jdbcType=NUMERIC}
默认情况下,使用 #{} 格式的语法会导致 MyBatis 创建 PreparedStatement 参数占位符并安全地设置参数(就像使用? 一样)。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中插入一个不转义的字符串。 比如,像 ORDER
BY,你可以这样来使用: ORDER BY ${columnName}
idea的熟练使用
参照 http://www.mybatis.org/mybatis-3/zh/index.html 文档学习
错误勘察
谷歌浏览器解除adobe flash player屏蔽
- 打开 chrome://settings/content
然后如下操作,把 Adobe Flash Player 插件设置更改为"允许网站运行Flash",就可以使用Adobe Flash Player 插件了。
2 如果上述方法无效,则打开chrome://flags/#run-all-flash-in-allow-mode,启用该选项。