Spring 4.x (三)
1 Spring中加入DataSource并引入jdbc.properties
- 步骤:
- ①加入c3p0的jar包和mysql的驱动包
- ②在src下新建jdbc.propertes文件
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/spring jdbc.user=root jdbc.password=root
- ③在applicationContext.xml中配置加载jdbc.properties的类
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!--
配置加载jdbc.properties的类
-->
<context:property-placeholder location="classpath*:jdbc.properties"></context:property-placeholder>
<!--
配置c3p0连接池
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
2 Spring jdbcTemplate
- Spring的jdbc Template使用的是模板技术。
- 观察如下代码的结构:
- jdbcDaoSupport.java

- jdbcTemplate.java

- jdbcAccessor.java

- 我们可以得出如下的规律

- 看看Hibernate是不是也这样:
- HibernateDaoSupport.java


- 示例:使用Spring的jdbc Template来实现CRUD
- dao层
- PersonDao.java
- dao层
package com.xuweiwei.dao;
import java.sql.ResultSet;
public interface PersonDao {
public static final String DAO_NAME = "com.xuweiwei.dao.impl.PersonDaoImpl";
/**
* 增加
* @param sql
*/
public void save(String sql);
/**
* 删除
*/
public void delete(String sql);
public void update(String sql);
}
- PersonDaoImpl.java
package com.xuweiwei.dao.impl;
import com.xuweiwei.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.ResultSet;
@Repository(PersonDao.DAO_NAME)
public class PersonDaoImpl extends JdbcDaoSupport implements PersonDao {
@Resource(name = "dataSource")
public void setDataSourcePerson(DataSource dataSource){
super.setDataSource(dataSource);
}
@Override
public void save(String sql) {
this.getJdbcTemplate().execute(sql);
}
@Override
public void delete(String sql) {
this.getJdbcTemplate().execute(sql);
}
@Override
public void update(String sql) {
this.getJdbcTemplate().execute(sql);
}
}
- service层
- PersonService.java
- service层
package com.xuweiwei.service;
public interface PersonService {
public static final String SERVICE_NAME = "com.xuweiwei.service.impl.PersonServiceImpl";
/**
* 增加
* @param sql
*/
public void save(String sql);
/**
* 删除
*/
public void delete(String sql);
public void update(String sql);
}
- PersonServiceImpl.java
package com.xuweiwei.service.impl;
import com.xuweiwei.dao.PersonDao;
import com.xuweiwei.service.PersonService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service(PersonService.SERVICE_NAME)
public class PersonServiceImpl implements PersonService {
@Resource(name=PersonDao.DAO_NAME)
private PersonDao personDao;
@Override
public void save(String sql) {
personDao.save(sql);
}
@Override
public void delete(String sql) {
personDao.delete(sql);
}
@Override
public void update(String sql) {
personDao.update(sql);
}
}
- applicationContext.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!--
配置加载jdbc.properties的类
-->
<context:property-placeholder location="classpath*:jdbc.properties"></context:property-placeholder>
<!--
配置c3p0连接池
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:component-scan base-package="com.xuweiwei"/>
</beans>
- 测试
package com.xuweiwei.test;
import com.xuweiwei.service.PersonService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestJdbcTemplate {
@Test
public void add(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonService personService = (PersonService) context.getBean(PersonService.SERVICE_NAME);
String sql = " insert into student(name,description) values ('许威威','java开发') ";
personService.save(sql);
}
@Test
public void update(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonService personService = (PersonService) context.getBean(PersonService.SERVICE_NAME);
String sql = " update student set description ='Linux开发' where sid = 1 ";
personService.update(sql);
}
@Test
public void delete(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonService personService = (PersonService) context.getBean(PersonService.SERVICE_NAME);
String sql = " delete from student where sid = 1 ";
personService.delete(sql);
}
}
3 Spring的事务控制
3.1 引入Spring的事务控制
- 如果在上面的代码中,加入如下的代码
@Override
public void save(String sql) {
personDao.save(sql);
int a = 1 /0 ;
personDao.save(sql);
}
- 会发现当发生异常的时候,事务并没有回滚,我们可以通过查看数据库知道,已经插入了一条数据。但是,这显示是不符合实际的,所以,Spring给我们提供了对事务的控制,当前表现形式不同,其实原理是一样的。
3.2 声明式事务
3.2.1 事务管理器
- Spring对不同的技术实现提供了不同的事务管理器,当然,如果我们自己去写一个框架,那么要和Spring整合,也需要遵守Spring的规则。
- Spring提供了一个PlatformTransactionManager的接口,详细代码如下
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.transaction;
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}
- PlatformTransactionManager接口有一个抽象实现类是AbstractPlatformTransactionManager,其简化代码如下
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
Object transaction = this.doGetTransaction();
}
protected abstract Object doGetTransaction() throws TransactionException;
public final void rollback(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");
} else {
DefaultTransactionStatus defStatus = (DefaultTransactionStatus)status;
this.processRollback(defStatus);
}
}
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");
} else {
DefaultTransactionStatus defStatus = (DefaultTransactionStatus)status;
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
this.logger.debug("Transactional code has requested rollback");
}
this.processRollback(defStatus);
} else if (!this.shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
this.logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
this.processRollback(defStatus);
if (status.isNewTransaction() || this.isFailEarlyOnGlobalRollbackOnly()) {
throw new UnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");
}
} else {
this.processCommit(defStatus);
}
}
}
}
- DataSourceTransManager.java
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean {
protected Object doGetTransaction() {
DataSourceTransactionManager.DataSourceTransactionObject txObject = new DataSourceTransactionManager.DataSourceTransactionObject();
txObject.setSavepointAllowed(this.isNestedTransactionAllowed());
ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(this.dataSource);
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
}

- 示例:
- PersonDao.java
package com.xuweiwei.dao;
public interface PersonDao {
/**
* 增加
* @param sql
*/
public void save(String sql);
/**
* 删除
*/
public void delete(String sql);
public void update(String sql);
}
- PersonDaoImpl.java
package com.xuweiwei.dao.impl;
import com.xuweiwei.dao.PersonDao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class PersonDaoImpl extends JdbcDaoSupport implements PersonDao {
@Override
public void save(String sql) {
this.getJdbcTemplate().execute(sql);
}
@Override
public void delete(String sql) {
this.getJdbcTemplate().execute(sql);
}
@Override
public void update(String sql) {
this.getJdbcTemplate().execute(sql);
}
}
- PersonService.java
package com.xuweiwei.service;
public interface PersonService {
/**
* 增加
* @param sql
*/
public void save(String sql);
/**
* 删除
*/
public void delete(String sql);
public void update(String sql);
}
- PersonServiceImpl.java
package com.xuweiwei.service.impl;
import com.xuweiwei.dao.PersonDao;
import com.xuweiwei.service.PersonService;
public class PersonServiceImpl implements PersonService {
private PersonDao personDao;
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
@Override
public void save(String sql) {
personDao.save(sql);
int a = 1 /0 ;
personDao.save(sql);
}
@Override
public void delete(String sql) {
personDao.delete(sql);
}
@Override
public void update(String sql) {
personDao.update(sql);
}
}
- jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/spring jdbc.user=root jdbc.password=root
- applicationContext.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!--
配置加载jdbc.properties的类
-->
<context:property-placeholder location="classpath*:jdbc.properties"></context:property-placeholder>
<!--
配置c3p0连接池
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="personDao" class="com.xuweiwei.dao.impl.PersonDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="personService" class="com.xuweiwei.service.impl.PersonServiceImpl">
<property name="personDao" ref="personDao"/>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="tx" transaction-manager="transactionManager">
<!--
告诉spring容器什么样的目标方法采用什么样的事务策略
name 用来说明目标方法
save* 以save开头的目标方法
isolation 隔离属性
propagation 传播属性
是解决事务嵌套问题的
read-only
为true:只读事务 只能读
为false:读写事务
-->
<tx:attributes>
<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.xuweiwei.service.impl.PersonServiceImpl.*(..))"/>
<aop:advisor advice-ref="tx" pointcut-ref="pointcut"/>
</aop:config>
</beans>
- 测试
package com.xuweiwei.test;
import com.xuweiwei.service.PersonService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestJdbcTemplate {
@Test
public void add(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonService personService = (PersonService) context.getBean("personService");
String sql = " insert into student(name,description) values ('许威威','java开发') ";
personService.save(sql);
}
}
3.3 编程式事务
- PersonDao.java
package com.xuweiwei.dao;
public interface PersonDao {
public static final String DAO_NAME = "com.xuweiwei.dao.impl.PersonDaoImpl";
/**
* 增加
* @param sql
*/
public void save(String sql);
/**
* 删除
*/
public void delete(String sql);
public void update(String sql);
}
- PersonDaoImpl.java
package com.xuweiwei.dao.impl;
import com.xuweiwei.dao.PersonDao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Repository(PersonDao.DAO_NAME)
public class PersonDaoImpl extends JdbcDaoSupport implements PersonDao {
@Resource(name="dataSource")
public void setDataSourceDi(DataSource dataSource){
super.setDataSource(dataSource);
}
@Override
public void save(String sql) {
this.getJdbcTemplate().execute(sql);
}
@Override
public void delete(String sql) {
this.getJdbcTemplate().execute(sql);
}
@Override
public void update(String sql) {
this.getJdbcTemplate().execute(sql);
}
}
- PersonService.java
package com.xuweiwei.service;
public interface PersonService {
public static final String SERVICE_NAME = "com.xuweiwei.service.impl.PersonServiceImpl";
/**
* 增加
* @param sql
*/
public void save(String sql);
/**
* 删除
*/
public void delete(String sql);
public void update(String sql);
}
- PersonServiceImpl.java
package com.xuweiwei.service.impl;
import com.xuweiwei.dao.PersonDao;
import com.xuweiwei.service.PersonService;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Transactional
@Service(PersonService.SERVICE_NAME)
public class PersonServiceImpl implements PersonService {
@Resource(name=PersonDao.DAO_NAME)
private PersonDao personDao;
@Override
public void save(String sql) {
personDao.save(sql);
int a = 1 /0 ;
personDao.save(sql);
}
@Override
public void delete(String sql) {
personDao.delete(sql);
}
@Override
public void update(String sql) {
personDao.update(sql);
}
}
- jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/spring jdbc.user=root jdbc.password=root
- applicationContext.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!--
配置加载jdbc.properties的类
-->
<context:property-placeholder location="classpath*:jdbc.properties"></context:property-placeholder>
<!--
配置c3p0连接池
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="classpath*:jdbc.properties"/>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启编程式事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
- 测试
package com.xuweiwei.test;
import com.xuweiwei.service.PersonService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestJdbcTemplate {
@Test
public void add(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonService personService = (PersonService) context.getBean("personService");
String sql = " insert into student(name,description) values ('许威威','java开发') ";
personService.save(sql);
}
}
Spring 4.x (三)的更多相关文章
- spring与mybatis三种整合方法
spring与mybatis三种整合方法 本文主要介绍Spring与Mybatis三种常用整合方法,需要的整合架包是mybatis-spring.jar,可通过链接 http://code.googl ...
- MyEclipse Spring 学习总结三 SpringMVC
MyEclipse Spring 学习总结三 SpringMVC 一.SpringMVC原理 1.Springmvc 框架介绍 1)Spring 框架停工了构建Web应用程序的全功能MVC模块.Spr ...
- Spring学习总结三——SpringIOC容器三
一:spring容器自动装配注入 为了减少xml中配置内容,可以使用自动装配注入,代替setter注入,只需要在 bean对象配置中添加属性autoWire即可,那么在类中就会自动扫描setXXX() ...
- spring boot / cloud (三) 集成springfox-swagger2构建在线API文档
spring boot / cloud (三) 集成springfox-swagger2构建在线API文档 前言 不能同步更新API文档会有什么问题? 理想情况下,为所开发的服务编写接口文档,能提高与 ...
- spring配置datasource三种方式
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp34 spring配置datasource三种方式 1.使用org.spri ...
- Spring IOC(三)依赖注入
本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 1.AbstractBeanFactory ...
- Spring的第三天AOP之xml版
Spring的第三天AOP之xml版 ssm框架 spring AOP介绍 AOP(Aspect Oriented Programming),面向切面编程.它出来的目的并不是去取代oop,而是对它的 ...
- Spring Boot 2 (三):Spring Boot 2 相关开源软件
Spring Boot 2 (三):Spring Boot 2 相关开源软件 一.awesome-spring-boot Spring Boot 中文索引,这是一个专门收集 Spring Boot 相 ...
- Spring Environment(三)生命周期
Spring Environment(三)生命周期 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Envi ...
- Spring IOC(三)单例 bean 的注册管理
Spring IOC(三)单例 bean 的注册管理 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 在 Spring 中 ...
随机推荐
- 如何在一个项目中同时包含mvc建站、webapi接口
项目做得多了..就会发现有些小项目不想建太多的项目..现在思明在这里和大家分享一下如果再一个项目中同时包含mvc建站以及实现webapi接口 1.新建项目 aps.net web 应用程序 2 新建模 ...
- 利用 html2canvas 做个简单的诗词卡片生成器
html2canvas 简介 html2canvas 顾名思义,就是一个可以把 DOM 元素转换成图片的类库,常用于网页截图.网页截图常见的应用场景是,在意见反馈里对当前页面进行截图,方便反馈页面出现 ...
- 常见的VPS虚拟化架构:OpenVZ、Xen、Hyper-V、KVM、VMWare OpenVZ
OpenVZ OpenVZ特点是,它是直接调用母服务器的内核,所以会导致部分软件无法使用,以及部分内核文件是无法修改. OpenVZ适用人群:新手.低预算客户 OpenVZ注意事项:资源不是自己独有的 ...
- fiddler抓手机报文的配置指南
前言 1.fiddler大名鼎鼎的抓包工具,而且支持重发,自动解码报文之类. 2.做爬虫时经常遇到需要抓移动端(手机/pad等)报文的情况. 网上各种资料比较,下面这篇是最准确的,转载自csdn:ht ...
- vue 购物车练习
本人看了vue官网上的教程后,感觉对vue的依稀有点了解,决定动手练习个小功能项目,就找了购物车本项目.原文链接:http://blog.csdn.net/take_dream_as_horse/ar ...
- Java与算法之(3) - 斐波那契数列
斐波那契数列问题:如果一对兔子每月能生1对小兔子,而每对小兔在它出生后的第三个月里,又能开始生1对小兔子,假定在不发生死亡的情况下,由一对初生的兔子开始,1年后能繁殖出多少对兔子? 首先手工计算来总结 ...
- qsc oj 22 哗啦啦村的刁难(3)(随机数,神题)
哗啦啦村的刁难(3) 发布时间: 2017年2月28日 20:00 最后更新: 2017年2月28日 20:01 时间限制: 1000ms 内存限制: 128M 描述 哗啦啦村作为喵哈哈村 ...
- Treap(树堆)
treap是排序二叉树的一种改进,因为排序二叉树有可能会造成链状结构的时候复杂度变成O(n^2)所以通过随机一个优先级的方法来维持每次让优先级最大的作为树根,然后形成一个满足: A. 节点中的key满 ...
- angular2 表单验证
模版式表单 (1) angular遇到form自动接管,不想自动接管,添加ngNoForm,当标签为div时,但想被表单接管,添加ngForm; (2) ngForm可以被模版本地变量引用,以便在模版 ...
- ubuntu开启openssh-server,ssh[xshell]
在虚机中安装了ubuntu,但是从宿主机器上ping 22的端口始终不通,查询原因,虚机只安装了 openssh-client. 运行Terminal $-> sudo apt-get inst ...