一、java常用数据库连接池
1、JNDI
2、C3PO
3、Apache的Jakarta DBCP
4、BoneCP
其中spring框架依赖的第三方使用了c3p0和dbcp两种方式;而bonecp号称是速度最快的数据库连接池。jndi方式创建实现的datesource是真正实现javax.sql.datasource API,区别如下:
注意:c3p0、dbcp、boneccp是应用程序连接数据库,其配置的参数大同小异,可以通过配置文件的方式配置,也可以硬编码的方式实现。jndi方式是应用服务器连接数据库,不能通过main方法测试,因为junit是java jdk单元测试无法获取到web应用服务中的数据库连接(很多人忽略或者不知道)。
二、Spring整合Mybatis连接数据库与JDBC比较
JDBC连接数据库操作流程
1、在java程序中加载驱动程序
Class.forName(“com.mysql.jdbc.Driver”)
2、创建数据库连接对象
Connection connection = DriverManager.geiConnection(“”)。
3、创建Statement对象
Statement statament = connection.createStatement();
4、执行SQL语句
ResultSet resultSel = statement.executeQuery( "select * from st" );
5、关闭连接
connection .close()
Spring整合Mybatis连接数据库工作流程
1、加载数据库配置文件
2、配置dataSources数据源
3、生成SqlSessionFactory会话工厂
4、MapperScannerConfigurer扫描指定的包,创建动态代理对象
4、通过代理对象实现对数据库的操作
5、数据库连接池管理数据库连接状态
注意:Mybatis Mapper.xml中的select update 等标签前面的id或者称为statementID,一条完整的语句相当于JDBC中的Statement,Mybatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis是对JDBC的封装,相对JDBC,Mybatis有一下优点:
1、优化获取和释放
2、SQL统一管理。对数据库进行存取操作
3、生成动态SQL语句
4、能够对结果集进行映射
三、多数据源分布式事物
1、两段提交(太过复杂)
2、mq推送
3、atomikos+jta(推荐使用)
com.maday注入dataSource1, com.sunday注入dataSource2,
引入依赖
<!--分布式事务相关Atomikos+jta-->
<dependency>
<groupid>com.atomikos</groupid>
transactions-jdbc</artifactid>
<version>4.0.6</version>
</dependency>
<dependency>
<groupid>javax.transaction</groupid>
jta</artifactid>
<version>1.1</version>
</dependency>
配置mapper扫描器,生成dataSource1的数据库代理对象配置mapper扫描器,生成dataSource2的数据库代理对象
配置dataSource1
<bean class="com.atomikos.jdbc.AtomikosDataSourceBean"destroy-method="close" id="dataSource1 "init-method="init">
配置dataSource2
<bean class="com.atomikos.jdbc.AtomikosDataSourceBean"destroy-method="close" id="dataSource2 "init-method="init">
配置jta事物管理器
![](https://i-blog.csdnimg.cn/blog_migrate/f669c7c796f306d9c285c7edc2c499d5.png)
配置dataSource1的会话工厂
配置dataSource2的会话工厂
使用Spring AOP添加事物
![](https://i-blog.csdnimg.cn/blog_migrate/7d7a6dd81b10bfcffe6c1189722fbf9d.png)
四 OSI七层协议模型、TCP/IP四层模型和五层协议体系结构之间的关系
1、OSI七层模型 OSI七层协议模型主要是:应用层(Application)、表示层(Presentation)、会话层(Session)、传输层(Transport)、网络层(Network)、数据链路层(Data Link)、物理层(Physical)。
2、TCP/IP四层模型
TCP/IP是一个四层的体系结构,主要包括:应用层、运输层、网际层和网络接口层。从实质上讲,只有上边三层,网络接口层没有什么具体的内容。
3、五层体系结构
五层体系结构包括:应用层、运输层、网络层、数据链路层和物理层。
4、各层网络协议
5、各层的作用
1、物理层:
主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。
2、数据链路层:
定义了如何让格式化数据以进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正,以确保数据的可靠传输。
3、网络层:
在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择。Internet的发展使得从世界各站点访问信息的用户数大大增加,而网络层正是管理这种连接的层。
4、运输层:
定义了一些传输数据的协议和端口号(WWW端口80等),如:
TCP(transmission control protocol –传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据)
UDP(user datagram protocol–用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。
5、会话层:
通过运输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)
6、表示层:
可确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。例如,PC程序与另一台计算机进行通信,其中一台计算机使用扩展二一十进制交换码(EBCDIC),而另一台则使用美国信息交换标准码(ASCII)来表示相同的字符。如有必要,表示层会通过使用一种通格式来实现多种数据格式之间的转换。
7、应用层:
是最靠近用户的OSI层。这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务。
五、spring bean的5种作用域
spring中为bean定义了5种作用域,分别为
singleton(单例)
prototype(原型)
request
session
globalSession
1、singleton(单例) Spring IoC容器中只会存在一个共享的bean实例,无论多少个bean引用它,始终指向同一对象Singleton是spring默认的作用域,也可以显示的将bean定义为Singleton模式
· <beanid="userDao" class="com.ioc.UserDaoImpl"scope="singleton"/>
2、prototype:原型模式,每次通过spring容器获取prototype定义的bean时,容器都将创建一个新的bean实例,每个bean实例都有自己的的属性和状态,而singleton全局只有一个对象,一般来说,对有经验的bean使用prototype作用域,而对无状态的bean使用singleton模式
· <beanid="userDao" class="com.ioc.UserDaoImpl" scope="prototype"/>
3、request:在一次Http请求中,容器会返回该bean的同一实例,而对于不同的Http请求则会产生新的bean,而且该bean仅在当前Http Request有效,针对每一次Http请求,Spring容器根据该bean的定义创建一个全新的实例,且该实例仅在当前Http请求内有效,而其他请求无法看到当前请求中的变化,当前Http请求结束,该bean实例也将被销毁。
· <beanid="userDao" class="com.ioc.UserDaoImpl" scope=" request "/>
4、session:在一次Http Session中,容器会返回该bean的同一实例,而对不同的session请求将会创建新的实例,该bean实例仅在当前session内有效。
· <beanid="userDao" class="com.ioc.UserDaoImpl" scope=" session"/>
同Http请求相同,每一次session请求创建新的实例,而不同的实例之间不共享属性,且实例仅在自己的session请求内有效,请求结束,实例将被销毁。
5、global Session
每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效
六、Bean的生命周期
Spring容器可以管理singleton作用域下的Bean生命周期,在此作用域下,Spring能够精确的知道Bean何时被创建,何时初始化完成,以及何时被销毁。而对于prototype作用域的Bean,Spring只负责
创建,当容器创建了bean的实例后,bean的实例就交给客户端的代码管理,Spring容器将不再跟踪其生命周期,Spring Bean的生命周期是一个很复杂的过程,引用网上图片说明;
![](https://i-blog.csdnimg.cn/blog_migrate/ae013b8be2c0124cca561f20e6d4298f.png)
七、Spring 4种依赖注入/控制反转方式
程序员在某个类中需要依赖其他类的方法,通常是new一个依赖类在调用该类实例的方法,这种开发存在的问题的是new的实例不好统一管理,Spring提出了依赖注入的思想,通过Spring容器帮我们new指定的实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转”。
原始DAO方式
1、Set 注入 最简单的注入方式
![](https://i-blog.csdnimg.cn/blog_migrate/5f0f99eeadac0ff78c62a38273f5f956.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f4093cc03f6a636b61a09970a6503991.png)
2、构造器注入
3、静态工厂注入
![](https://i-blog.csdnimg.cn/blog_migrate/935e6c56a245fdb1b4ec1da52b51a35b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/eecc0ca3c063e29aea5a35ddce76b3cc.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5bb4ab576d26a1e3d559b9712654f534.png)
4、实例工厂注入
Mybatis与Spring整合 Mapper动态代理 注解开发
1、@Autowired Spring提供的注解,需要导入包
org.springframework.beans.factory.annotation.Autowired,装配Bean时只按照byType注入。
2、@Resource J2EE提供的注解,需要导入包
javax.annotation.Resource,装配Bean时默认按照ByName注入。
八、设计模式(个人感觉最为重要)
1、总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
还有两类:发型模式和线程池模式。用一个图片来整体描述一下:
举例如下:(只写会的,没写的还没有时间去学)
1、单例模式
1.1饿汉式单例
package com.sunday.menu;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import com.sunday.menu.service.MenuService;
import com.sunday.menu.vo.Menu;
/**
* @Description:菜单配置类/饿汉式单例
* @ClassName: MenuConfig
* @author Administrator
* @date 2017年11月25日 下午3:12:01
*
*/
public class MenuConfig {
private Map<String, String> menuMapConfig = new HashMap<String, String>();
/**
* 注入菜单menuService
*/
@Autowired
private MenuService menuService;
/**
*
*@Description:从缓存map中根据菜单ID获取菜单名字
* @Title: getMenuNameByID
* @param @param key
* @param @return 设定文件
* @return String 返回类型
*/
public String getMenuNameByID(String key) {
//如果缓存中没有,去数据库重新读取所有菜单信息,刷新缓存
if (menuMapConfig.get(key)==null) {
List<Menu> list = menuService.getMenuNameList();
if (list!=null) {
for (Menu menu : list) {
menuMapConfig.put(menu.getMenuID(), menu.getMenuName());
}
}
}
return menuMapConfig.get(key);
}
//构造方法私有化
private MenuConfig() {
}
}
1.2懒汉式单例
package com.sunday.menu;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import com.sunday.menu.service.MenuService;
import com.sunday.menu.vo.Menu;
/**
* @Description:菜单配置类/懒汉式单例
* @ClassName: MenuConfig
* @author Administrator
* @date 2017年11月25日 下午3:12:01
*
*/
public class MenuConfig {
private Map<String, String> menuMapConfig;
/**
* 注入菜单menuService
*/
@Autowired
private MenuService menuService;
/**
*
*@Description:从缓存map中根据菜单ID获取菜单名字
* @Title: getMenuNameByID
* @param @param key
* @param @return 设定文件
* @return String 返回类型
*/
public String getMenuNameByID(String key) {
if (menuMapConfig==null) {
menuMapConfig=new HashMap<String, String>();
}
//如果缓存中没有,去数据库重新读取所有菜单信息,刷新缓存
if (menuMapConfig.get(key)==null) {
List<Menu> list = menuService.getMenuNameList();
if (list!=null) {
for (Menu menu : list) {
menuMapConfig.put(menu.getMenuID(), menu.getMenuName());
}
}
}
return menuMapConfig.get(key);
}
//构造方法私有化
private MenuConfig() {
}
}
2、工厂模式
把菜单的增删改查操作交给工厂代理,利用spring去装配bean,初始化crudMenuMap,利用spring的工具类实现ApplicationContetAware接口,seter方式注入applicationContext。手动获取bean:SpringUtils.getBean(key);获取菜单操作工厂。
SpringUtils
package com.sunday.utils.common;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class SpringUtils implements ApplicationContextAware{
private static ApplicationContext apc;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
apc=applicationContext;
}
public static ApplicationContext getApplicationContext() {
checkApplicationContext();
return apc;
}
/**
*
* @Description: 根据beanName获取bean
* @param @param beanName
* @param @return 设定文件
* @return Object 返回类型
* @throws
*/
public static Object getBean(String beanName) {
checkApplicationContext();
return apc.getBean(beanName);
}
/**
*
* @Description: 根据bean名称判断bean是否存在
* @param @param beanName
* @param @return 设定文件
* @return boolean 返回类型
* @throws
*/
public static boolean IsContainsBean(String beanName) {
checkApplicationContext();
return apc.containsBean(beanName);
}
/**
*
* @Description: 检查ApplicationContext是否注入
* @param 设定文件
* @return void 返回类型
* @throws
*/
private static void checkApplicationContext(){
if (apc==null) {
throw new IllegalStateException("applicaitonContext未注入");
}
}
}
<!-- Spring工具类配置 -->
<bean class="com.sunday.utils.common.SpringUtils" />
<!-- 菜单工厂Bean配置 -->
<bean id="crudMenuFactory"
class="com.sunday.crudFactory.CrudMenuFactory">
<property name="crudMenuMap">
<map>
<entry key="update">
<bean
class="com.sunday.crudFactory.menubiz..UpdateMenu" />
</entry>
<entry key="delect">
<bean
class="com.sunday.crudFactory.menubiz..delectMenu" />
</entry>
<entry key="query">
<bean
class="com.sunday.crudFactory.menubiz.queryMenu" />
</entry>
<entry key="add">
<bean
class="com.sunday.crudFactory.menubiz.addMenu" />
</entry>
</map>
</property>
</bean>
2、设计模式的六大原则
1、开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。
2、里氏代换原则(Liskov Substitution Principle)
里氏代换原则(LiskovSubstitution Principle LSP)面向对象设计的基本原则之一。里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
3、依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
5、迪米特法则(最少知道原则)(Demeter Principle)
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
6、合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。
九、Nginx
nginx优缺点
占内存小,可以实现高并发连接、处理响应快。
可以实现http服务器、虚拟主机、反向代理、负载均衡。
nginx配置简单
可以不暴露真实服务器IP地址
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。负载均衡,英文名称为LoadBalance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
网关接口搭建:
故障转移:
负载均衡:
Session共享解决办法:
Nginx主配置文件:
十、Redis读写分离配置(主从模式)
引入pom.xml依赖
十一、ActiveMQ
JMS是java的消息服务,JMS的客户端之间可以通过JMS服务进行异步的消息传输。
○ Point-to-Point(P2P) --- 点对点
○ Publish/Subscribe(Pub/Sub)--- 发布订阅
发布订阅与点对点模式:
应用场景:
Spring整合MQ
编写生产者模板:
//注入JmsTemplate对象
@Autowired
private JmsTemplate jmsTemplate;
//编写方法生产消息队列(使用map集合存放消息队列)
jmsTemplate.send("activeCode",newMessageCreator() {
@Override
public Message createMessage(Session session) throwsJMSException {
MapMessage map =session.createMapMessage();
map.setString("telephone", model.getTelephone());//消息之一
map.setString("randomCode", randomCode);//消息之二
return map;
}
});
编写消费者类:
//实现MessageListener中的方法
publicvoidonMessage(Message message) {
MapMessage mapMessage = (TextMessage) message;
try {
System.out.println("消费者消费的信息为:手机号:"
+ mapMessage.getString("telephone")
+",验证码信息是:"+ mapMessage.getString("msg"));
} catch (JMSException e) {
e.printStackTrace();
}
}
十二、ZooKeeper
安装配置引用网上的,时间太长忘记怎么配置集群
客户端管理工具
监控查看
ZooInspector
运行脚本
@echo off
cd D:\software\zookeeper-3.4.6\ZooInspector\build
d:
Java -Dfile.encoding=UTF-8 -jar zookeeper-dev-ZooInspector.jar
、SOA 服务框架DUBBO
Dubbo能做什么
问题:
服务的URL管理非常困难(rmi://、http:*、)、F5负载均衡器的单点压力(硬件成本)
各个服务之间依赖管理非常复杂
各个服务之间如何进行监控
1.透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单
配置,没有任何API侵入。
2.软负载均衡及容错机制,可在内网替代F5等硬件负鞭均衡器,降低成本,
减少单点。
3.服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于楼口
名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
4.Dubbo采用全Spring 配置方式,功明化接入应用,对应用没有任何API侵
只需用Spring加载Dubbo的配置即可,Dubbo基FSpring的Schema扩
入,展进行加载。
DUBBO架构图:
节点角色说明:
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
生产者:生产者主要发布服务
pom.xml引入依赖
定义一个Service
实现service
发布服务:
消费者:
Dubbo支持哪些协议?
1.Dubbo协议
Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。Dubbo缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。
2.Hessian协议
Hessian协议用于集成Hessian的服务,Hessian底层采用Http通讯,采用Servlet暴露服务,Dubbo缺省内嵌Jetty作为服务器实现。Hessian是Caucho开源的一个RPC框架:http://hessian.caucho.com,其通讯效率高于WebService和Java自带的序列化。
基于Hessian的远程调用协议:
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。
适用场景:页面传输,文件传输,或与原生hessian服务互操作
3.HTTP协议
此协议采用spring 的HttpInvoker的功能实现,
连接个数:多个
连接方式:长连接
连接协议:http
传输方式:同步传输
序列化:表单序列化
适用范围:传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件。
适用场景:需同时给应用程序和浏览器JS使用的服务。
4.RMI协议
采用JDK标准的java.rmi.*实现,采用阻塞式短连接和JDK标准序列化方式
Java标准的远程调用协议:
连接个数:多连接
连接方式:短连接
传输协议:TCP
传输方式:同步传输
序列化:Java标准二进制序列化
适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
适用场景:常规远程服务方法调用,与原生RMI服务互操作
Dubbo整个架构流程
分为四大模块
生产者、消费者、注册中心、监控中心
生产者:提供服务
消费者: 调用服务
注册中心:注册信息(redis、zk)
监控中心:调用次数、关系依赖等。
首先生产者将服务注册到注册中心(zk),使用zk持久节点进行存储,消费订阅zk节点,一旦有节点变更,zk通过事件通知传递给消费者,消费可以调用生产者服务。
服务与服务之间进行调用,都会在监控中心中,存储一个记录。
Dubbox与Dubbo区别?
Dubox使用http协议+rest风格传入json或者xml格式进行远程调用。
Dubbo使用Dubbo协议。
RPC远程调用框架
SpringCloud、dubbo、Dubbox、thint、Hessian…
Rpc其实就是远程调用,服务与服务之间相互进行通讯。
目前主流 用http+json
SpringCloud与Dubbo区别?
相同点:
dubbo与springcloud都可以实现RPC远程调用。
dubbo与springcloud都可以使用分布式、微服务场景下。
区别:
dubbo有比较强的背景,在国内有一定影响力。
dubbo使用zk或redis作为作为注册中心
springcloud使用eureka作为注册中心
dubbo支持多种协议,默认使用dubbo协议。
Springcloud只能支持http协议。
Springcloud是一套完整的微服务解决方案。
Dubbo目前已经停止更新,SpringCloud更新速度快。