SpringBoot集成FastDFS+Nginx整合基于Token的防盗链

  为什么要用SpringBoot?

  SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

  创建独立的Spring应用程序

  嵌入的Tomcat,无需部署WAR文件

  简化Maven配置

  自动配置Spring

  提供生产就绪型功能,如指标,健康检查和外部配置

  绝对没有代码生成并且对XML也没有配置要求

  为什么要用Nginx?

  概述

  Nginx(engine x)是一个开源的,支持高并发的www服务和代理服务软件。Nginx是俄罗斯人Igor Sysoev开发的,最初被应用到俄罗斯的大型网站(www.rambler.ru)上。后来作者将源代码以类BSD许可证的形式开源出来供全球使用。在功能应用方面,Nginx不仅是一个优秀的Web服务软件,还具有反向代理负载均衡和缓存的功能。在反向代理负载均衡方面类似于LVS负载均衡及HAProxy等你专业代理软件。Nginx部署起来更加方便简单,在缓存服务功能方面,有类似于Squid等专业的缓存服务软件。Nginx可以运行在UNIX、Linux、MS Windows Server、Mac OS X Server、Solaris等操作系统中。

  Nginx的重要特性

  可以针对静态资源高速节点并发访问及缓存。

  可以使用反向代理加速,并且可以进行数据缓存。

  具有简单负载均衡,节点健康检查和容错功能。

  支持远程Fast CGI服务的缓存加速。

  支持Fast CGI、Uwsgi、SCGI、Memcached Server的加速和缓存。

  支持SSL、TLS、SNI。

  具有模块化的架构。

  过滤器包括gzip压缩、ranges支持、chunked响应、XSLT、SSL和图像缩放等功能。

  在SSL过滤器中,包含多个SSL页面,如果经由Fast CGI或反向代理处理,可以并行处理。

  Nginx所具备的WWW服务特性

  支持基于域名、端口和IP的虚拟主机配置。

  支持KeepAlived和piplined连接。

  可进行简单、方便、灵活的配置和管理。

  支持修改Nginx配置,并且在代码上线时,可平滑重启,不中断业务访问。

  可自定义访问日志格式,临时缓冲写日志操作,快速日志轮询及通过rsyslog处理日志。

  可利用信号控制Nginx进程。

  支持3xx-5xxHTTP状态码重定向。

  支持rewrite模块,支持URI重写及正则表达式匹配。

  支持基于客户端IP地址和HTTP基本认证的访问控制。

  支持PUT、DELETE、MKCOL、COPY、MOVE等特殊的HTTP请求方法。

  支持FLV流和MP4流技术产品应用。

  支持HTTP响应速率限制。

  支持同一IP地址的并发连接或请求限制。

  支持邮件服务代理。

  支持高并发,可以支持几百万并发连接。

  资源消耗少,在3万并发连接下,可以开启10个nginx的线程消耗的内存不到200MB。

  可以做HTTP反向代理及加速缓存,及负载均衡功能,内置对RS节点服务器健康检查功能,折现但能够与专业的HAProxy或LVS的功能。

  具备Squid等专业缓存软件等的缓存功能。

  支持异步网络I/O事件模型epoll(Linux2.6+)。

  Nginx软件主要企业应用

  作为Web服务软件。

  使用Nginx运行HTML、JS、CSS、小图片等静态数据(类似于Lighttpd)。

  结合Fast CGI运行PHP等动态程序(例如使用fastcgi_pass方式)。

  Nginx结合Tomcat/Resin等支持Java动态程序(常用proxy_pass)。

  反向代理或负载均衡服务(Nginx从1.9.0开始就开始支持TCP的代理了)。

  前端业务数据缓存服务。

  Web服务应用产品性能对比

  静态数据的访问上:处理小文件(小于1MB)时,Nginx和Lighttpd比Apache更有优势,Nginx处理小文件的优势明显,Lighttpd综合最强。

  动态数据的访问上:三者差距不大,Apache更有优势,因为处理动态数据的能力在于PHP(Java)和后端数据库的服务能力,也就是说瓶颈不在Web服务器上。

  一般情况下普通PHP引擎支持的并发连接参考值300~1000。Java引擎和数据库的并发连接参考值300~1500。

  为什么Nginx比Apache的性能高?

  Nginx使用最新版的eepoll(Linux 2.6内核)和kqueue(FreeBSD)异步网络I/O模型,而Apache使用的是传统的select模型。

  目前Linux下能够承受高并发访问的Squid、Memcached软件采用都是epoll模型。

  处理大量的连接的读写时,Apache所采用的select网络I/O模型比较低。

  如何正确采用Web服务器?

  静态业务:如果是高并发场景,尽量采用Nginx或Lighttpd,二者首选Nginx。

  动态业务:理论上采用Nginx和Apache均可,建议使用Nginx,为了避免相同业务服务的软件多样化,增加维护成本,动态业务可以使用Nginx兼做前端代理,再根据页面的元素或目录转发到其他的服务器进行处理。

  既有动态业务又有静态业务,就用Nginx。

  关于部署,就不在重复了。

  使用IDEA场景启动器创建工程。郑州 不  孕 不  育 医院:http://jbk.39.net/yiyuanzaixian/zztjyy/

  创建Maven工程,修改POM.xml文件添加如下依赖:

  org.springframework.boot

  spring-boot-autoconfigure

  1.5.20.RELEASE

  org.springframework.boot

  spring-boot-configuration-processor

  1.5.20.RELEASE

  org.springframework.boot

  spring-boot-starter-logging

  1.5.20.RELEASE

  org.apache.commons

  commons-pool2

  2.6.0

  创建必要的包

  annotation:存放相关的注解

  autoconfiguation: 存储自动配置类

  factory: 存放工厂类

  properties: 存放配置参数类

  service: 存放服务类

  一般情况下,SpringBoot都会提供相应的@EnableXxx注解标注在应用的主启动类上开启某个功能:

  // EnableFastdfsClient.java

  @Target(ElementType.TYPE)

  @Retention(RetentionPolicy.RUNTIME)

  @Import(FastdfsAutoConfiguration.class)

  @Documented

  public @interface EnableFastdfsClient {

  }

  下面是相关的自动配置类:

  // FastdfsAutoConfiguration.java

  @Configuration

  @EnableConfigurationProperties(FastdfsProperties.class)

  public class FastdfsAutoConfiguration {

  @Autowired

  private FastdfsProperties fastdfsProperties;

  @Bean

  @ConditionalOnMissingBean(FastdfsClientService.class)

  public FastdfsClientService fastdfsClientService() throws Exception {

  return new FastdfsClientService(fastdfsProperties);

  }

  }

  创建相关的工厂类:

  // StorageClientFactory.java

  // 用于创建连接对象的工厂类

  public class StorageClientFactory implements PooledObjectFactory {

  @Override

  public PooledObject makeObject() throws Exception {

  TrackerClient client = new TrackerClient();

  TrackerServer server = client.getConnection();

  return new DefaultPooledObject<>(new StorageClient(server, null));

  }

  @Override

  public void destroyObject(PooledObject p) throws Exception {

  p.getObject().getTrackerServer().close();

  }

  @Override

  public boolean validateObject(PooledObject p) {

  return false;

  }

  @Override

  public void activateObject(PooledObject p) throws Exception {

  }

  @Override

  public void passivateObject(PooledObject p) throws Exception {

  }

  }

  Properties类用来映射application.properties或者application.yml配置文件:

  // FastdfsProperties.java

  @ConfigurationProperties(prefix = "fastdfs")

  public class FastdfsProperties {

  // 连接超时时间

  // 网络超时时间

  // 字符集编码

  // 是否使用Token

  // Token加密密钥

  // 跟踪器IP地址,多个使用分号隔开

  // 连接池的连接对象最大个数

  // 连接池的最大空闲对象个数

  // 连接池的最小空闲对象个数

  // Nginx服务器IP,多个使用分号分割

  // 获取连接对象时可忍受的等待时长(毫秒)

  private String connectTimeout = "5";

  private String networkTimeout = "30";

  private String charset = "UTF-8";

  private String httpAntiStealToken = "false";

  private String httpSecretKey = "";

  private String httpTrackerHttpPort = "";

  private String trackerServers = "";

  private String connectionPoolMaxTotal = "18";

  private String connectionPoolMaxIdle = "18";

  private String connectionPoolMinIdle = "2";

  private String nginxServers = "";

  // 需要创建相关的Setter和Getter方法

  }

  在Service类中封装方法, 下面仅展示3个常用的方法:

  // FastdfsClientSerivce.java

  public class FastdfsClientService {

  // SpringBoot加载的配置文件

  // 连接池配置项

  // 转换后的配置条目

  // 连接池

  // Nginx服务器地址

  private FastdfsProperties fdfsProp;

  private GenericObjectPoolConfig config;

  private Properties prop;

  private GenericObjectPool pool;

  private String[] nginxServers;

  private Logger logger;

  public FastdfsClientService(FastdfsProperties fdfsProp) throws Exception {

  this.fdfsProp = fdfsProp;

  this.logger = LoggerFactory.getLogger(getClass());

  init();

  create();

  info();

  }

  /**

  * 初始化全局客户端

  */

  private void init() throws Exception {

  this.prop = new Properties();

  this.logger.info("FastDFS: reading config file...");

  this.logger.info("FastDFS: fastdfs.connect_timeout_in_seconds=" + this.fdfsProp.getConnectTimeout());

  this.logger.info("FastDFS: fastdfs.network_timeout_in_seconds=" + this.fdfsProp.getNetworkTimeout());

  this.logger.info("FastDFS: fastdfs.charset=" + this.fdfsProp.getCharset());

  this.logger.info("FastDFS: fastdfs.http_anti_steal_token=" + this.fdfsProp.getHttpAntiStealToken());

  this.logger.info("FastDFS: fastdfs.http_secret_key=" + this.fdfsProp.getHttpSecretKey());

  this.logger.info("FastDFS: fastdfs.http_tracker_http_port=" + this.fdfsProp.getHttpTrackerHttpPort());

  this.logger.info("FastDFS: fastdfs.tracker_servers=" + this.fdfsProp.getTrackerServers());

  this.logger.info("FastDFS: fastdfs.connection_pool_max_total=" + this.fdfsProp.getConnectionPoolMaxTotal());

  this.logger.info("FastDFS: fastdfs.connection_pool_max_idle=" + this.fdfsProp.getConnectionPoolMaxIdle());

  this.logger.info("FastDFS: fastdfs.connection_pool_min_idle=" + this.fdfsProp.getConnectionPoolMinIdle());

  this.logger.info("FastDFS: fastdfs.nginx_servers=" + this.fdfsProp.getNginxServers());

  this.prop.put("fastdfs.connect_timeout_in_seconds", this.fdfsProp.getConnectTimeout());

  this.prop.put("fastdfs.network_timeout_in_seconds", this.fdfsProp.getNetworkTimeout());

  this.prop.put("fastdfs.charset", this.fdfsProp.getCharset());

  this.prop.put("fastdfs.http_anti_steal_token", this.fdfsProp.getHttpAntiStealToken());

  this.prop.put("fastdfs.http_secret_key", this.fdfsProp.getHttpSecretKey());

  this.prop.put("fastdfs.http_tracker_http_port", this.fdfsProp.getHttpTrackerHttpPort());

  this.prop.put("fastdfs.tracker_servers", this.fdfsProp.getTrackerServers());

  ClientGlobal.initByProperties(this.prop);

  }

  /**

  * 显示初始化信息

  */

  private void info() {

  this.logger.info("FastDFS parameter: ConnectionPoolMaxTotal ==> " + this.pool.getMaxTotal());

  this.logger.info("FastDFS parameter: ConnectionPoolMaxIdle ==> " + this.pool.getMaxIdle());

  this.logger.info("FastDFS parameter: ConnectionPoolMinIdle ==> " + this.pool.getMinIdle());

  this.logger.info("FastDFS parameter: NginxServer ==> " + Arrays.toString(this.nginxServers));

  this.logger.info(ClientGlobal.configInfo());

  }

  /**

  * 创建连接池

  */

  private void create() {

  this.config = new GenericObjectPoolConfig();

  this.logger.info("FastDFS Client: Creating connection pool...");

  this.config.setMaxTotal(Integer.parseInt(this.fdfsProp.getConnectionPoolMaxTotal()));

  this.config.setMaxIdle(Integer.parseInt(this.fdfsProp.getConnectionPoolMaxIdle()));

  this.config.setMinIdle(Integer.parseInt(this.fdfsProp.getConnectionPoolMinIdle()));

  StorageClientFactory factory = new StorageClientFactory();

  this.pool = new GenericObjectPool(factory, this.config);

  this.nginxServers = this.fdfsProp.getNginxServers().split(",");

  }

  /**

  * Nginx服务器负载均衡算法

  *

  * @param servers 服务器地址

  * @param address 客户端IP地址

  * @return 可用的服务器地址

  */

  private String getNginxServer(String[] servers, String address) {

  int size = servers.length;

  int i = address.hashCode();

  int index = abs(i % size);

  return servers[index];

  }

  /**

  * 带有防盗链的下载

  *

  * @param fileGroup 文件组名

  * @param remoteFileName 远程文件名称

  * @param clientIpAddress 客户端IP地址

  * @return 完整的URL地址

  */

  public String autoDownloadWithToken(String fileGroup, String remoteFileName, String clientIpAddress) throws Exception {

  int ts = (int) (System.currentTimeMillis() / 1000);

  String token = ProtoCommon.getToken(remoteFileName, ts, ClientGlobal.getG_secret_key());

  String nginx = this.getNginxServer(this.nginxServers, clientIpAddress);

  return "http://" + nginx + "/" + fileGroup + "/" + remoteFileName + "?token=" + token + "&ts=" + ts;

  }

  /**

  * 上传文件,适合上传图片

  *

  * @param buffer 字节数组

  * @param ext 扩展名

  * @return 文件组名和ID

  */

  public String[] autoUpload(byte[] buffer, String ext) throws Exception {

  String[] upload = this.upload(buffer, ext, null);

  return upload;

  }

  /**

  * 不带防盗链的下载,如果开启防盗链会导致该方法抛出异常

  *

  * @param fileGroup 文件组名

  * @param remoteFileName 远程文件ID

  * @param clientIpAddress 客户端IP地址,根据客户端IP来分配Nginx服务器

  * @return 完整的URL地址

  */

  public String autoDownloadWithoutToken(String fileGroup, String remoteFileName, String clientIpAddress) throws Exception {

  if (ClientGlobal.getG_anti_steal_token()) {

  this.logger.error("FastDFS Client: You‘ve turned on Token authentication.");

  throw new Exception("You‘ve turned on Token authentication.");

  }

  String nginx = this.getNginxServer(this.nginxServers, clientIpAddress);

  return "http://" + nginx + fileGroup + "/" + remoteFileName;

  }

  // 后面还有好多方法,就不一一展示了

  }

  为了在IDEA中使用便捷的配置提示功能,我们需要创建元数据文件(resources/spring-configuration-metadata.json):

  {

  "groups": [

  {

  "name": "fastdfs",

  "type": "com.bluemiaomiao.properties.FastdfsProperties",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties"

  }

  ],

  "properties": [

  {

  "name": "connectTimeout",

  "type": "java.lang.String",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties",

  "defaultValue": "5"

  },

  {

  "name": "networkTimeout",

  "type": "java.lang.String",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties",

  "defaultValue": "30"

  },

  {

  "name": "charset",

  "type": "java.lang.String",

  "defaultValue": "UTF-8"

  },

  {

  "name": "httpAntiStealToken",

  "type": "java.lang.String",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties",

  "defaultValue": "false"

  },

  {

  "name": "httpSecretKey",

  "type": "java.lang.String",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties"

  },

  {

  "name": "httpTrackerHttpPort",

  "type": "java.lang.Integer",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties"

  },

  {

  "name": "trackerServers",

  "type": "java.lang.String",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties"

  },

  {

  "name": "connectionPoolMaxTotal",

  "type": "java.lang.Integer",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties",

  "defaultValue": "18"

  },

  {

  "name": "connectionPoolMaxIdle",

  "type": "java.lang.Integer",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties",

  "defaultValue": "18"

  },

  {

  "name": "connectionPoolMinIdle",

  "type": "java.lang.Integer",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties",

  "defaultValue": "2"

  },

  {

  "name": "nginxServers",

  "type": "java.lang.String",

  "sourceType": "com.bluemiaomiao.properties.FastdfsProperties"

  }

  ],

  "hints": [

  {

  "name": "http_anti_steal_token",

  "values": [

  {

  "value": "false"

  },

  {

  "value": "true"

  }

  ]

  }

  ]

  }

  将自定义starter添加到项目

  创建SpringBoot项目,勾选Web选项,版本选择1.5.20

  进入场景启动器的项目目录执行mvn clean install 将其安装到本地

  在POM.xml文件中添加依赖:

  com.bluemiaomiao

  fastdfs-spring-boot-starter

  1.0-SNAPSHOT

  记得开启IDEA的自动导入功能

  创建配置文件application.properties

  fastdfs.nginx-servers=192.168.80.2:8000,192.168.80.3:8000,192.168.80.4:8000

  fastdfs.tracker-servers=192.168.80.2:22122,192.168.80.3:22122,192.168.80.4:22122

  fastdfs.http-secret-key=2scPwMPctXhbLVOYB0jyuyQzytOofmFCBIYe65n56PPYVWrntxzLIDbPdvDDLJM8QHhKxSGWTcr+9VdG3yptkw

  fastdfs.http-anti-steal-token=true

  fastdfs.http-tracker-http-port=8080

  fastdfs.network-timeout=30

  fastdfs.connect-timeout=5

  fastdfs.connection-pool-max-idle=18

  fastdfs.connection-pool-min-idle=2

  fastdfs.connection-pool-max-total=18

  fastdfs.charset=UTF-8

  或者使用application.yml

  fastdfs:

  charset: UTF-8

  connect-timeout: 5

  http-secret-key: 2scPwMPctXhbLVOYB0jyuyQzytOofmFCBIYe65n56PPYVWrntxzLIDbPdvDDLJM8QHhKxSGWTcr+9VdG3yptkw

  network-timeout: 30

  http-anti-steal-token: true

  http-tracker-http-port: 8080

  connection-pool-max-idle: 20

  connection-pool-max-total: 20

  connection-pool-min-idle: 2

  nginx-servers: 192.168.80.2:8000,192.168.80.3:8000,192.168.80.4:8000

  tracker-servers: 192.168.80.2:22122,192.168.80.3:22122,192.168.80.4:22122

  创建控制器类测试方法

  // controllers.DownloadController.java

  @Controller

  @RequestMapping(value = "/download")

  public class DownloadController {

  @Autowired

  private FastdfsClientService service;

  @ResponseBody

  @RequestMapping(value = "/image")

  public String image() throws Exception {

  // 之前上传过的数据,实际应用场景应该使用SQL数据库来存储

  return service.autoDownloadWithToken("group1", "M00/00/00/wKhQA1ysjSGAPjXbAAVFOL7FJU4.tar.gz", "192.168.80.1");

  }

  }

原文地址:https://www.cnblogs.com/dream8023/p/10819146.html

时间: 2024-11-06 07:17:32

SpringBoot集成FastDFS+Nginx整合基于Token的防盗链的相关文章

Nginx修改配置实现图片防盗链

一般情况下,防盗链是针对软件下载和图片的,由于一般的站点不提供资源下载,所以本文主要是针对图片的防盗链 1.如果对全站图片做防盗链,至少需要一个另外的域名存放指向图片.因为如果对全站图片做了防盗链,包括盗链提示图片在内的所有图片都不可能显示. 此类情况修改 /usr/local/nginx/conf/nginx.conf 文件 2.对单独域名配置图片防盗链,个人比较推荐,一是便于控制,二是可以重新创建一个域名在同服务器上用来存放盗链提示图片. 此类情况修改 /usr/local/nginx/co

FastDFS + nginx 整合

1.首先安装解压各个压缩包(略过) 2.然后安装完统一编译安装各个依赖(略过) 3.开始安装nginx ./configure --add-module=/opt/fastdfs-nginx-module/src/ #整合了fatdfs的模块 make make install ps:根据自己的情况修改模块的地址. 安装完nginx后,会出现几行字,这是nginx的安装后所在的目录 4.修改nginx.conf nginx.conf 的更改 user root 避免权限的问题 location

FastDFS + Nginx实现基于CentOS7平台的分布式文件存储与访问

相比较于MogileFS,FastDFS同样有tracker和storage这样的功能分类.但是FastDFS的tracker节点的元数据信息是由各个storage节点通过tcp协议上报得到的,因此在一定程度上减轻了tracker的负载压力.storage节点以group为单位进行组织.任何一个storage server都应该属于某个group,一个group应该包含多个storage server:在同一个group内部,各storage server的数据互相冗余. 本文通过构建FastD

教你突破基于HTTP_REFERER的防盗链的方法

其实防盗链这个技术并不复杂,目前基本就是在服务器端判断HTTP_REFERER的位置,如果不是来自本站自身,则拒绝输出详细. 那么如果考虑突破防盗链的措施,就需要考虑在HTTPREFERER上面做手脚了.PHP 脚本中对应的变量是$SERVER['HTTPREFERER'] ,它存储了 HTTPREFERER 的值. 由于直接访问目标URL资源已经被上述防盗链的措施给屏蔽,所以我们需要个类似网关的玩意去获取.说白了就是编写已经包装过的HTTP头的 PHP 脚本. 下面是简单的函数实现: func

nginx防盗链

一.防盗链的一般方法是在server或者location段中加入如下格式代码: 1 valid_referers none blocked server_names 其中 none表示空的来路,也就是直接访问,比如直接在浏览器打开一个图片.blocked表示被防火墙标记过的来路,server_names是域名,可以用*.demo.com来表示所有的二级域名 1 2 3 4 5 6 7 location ~ \.(wma|wmv|asf|mp3|mmf|zip|rar|jpg|gif|png|sw

防盗链Nginx设置图片防盗链,设置无效的请仔细看红字

*******************************************************************切记,替换的图片地址要使用没有防盗链的网站图片,否则由于替换的图片其实也处于防盗链情况下,会造成仍旧无法显示设置的图片.******************************************************************* 一.全站图片防盗链 在/usr/local/nginx/conf/nginx.conf文件要添加防盗链的ser

Apache和Nginx防盗链的几种配置方法

要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫 referer,采用URL的格式来表示从哪儿链接到当前的网页或文件.换句话说,通过referer,网站可以检测目标网页访问的来源网页,如果是资源 文件,则可以跟踪到显示它的网页地址.有了referer跟踪来源就好办了,这时就可以通过技术手段来进行处理,一旦检测到来源不是本站即进行阻止或者返 回指定的页面. Nginx防盗链的配置 1.nginx针对文件类型的防盗链配置

Nginx服务优化(七)网页压缩与防盗链

配置Nginx实现网页压缩功能 Nginx的ngx_http_gzip_module压缩模块提供对文件内容压缩的功能,允许Nginx服务器将输出内容在发送客户端之前进行压缩,以节约网站带宽,提升用户的访问体验,默认已经安装.可在配置文件中加入相应的压缩功能参数对压缩性能进行优化. 压缩功能参数讲解 gzip on:开启gzip压缩输出 gzip_min_length 1k:用于设置允许压缩的页面最小字节数 gzip_buffers 4 16k:表示申请4个单位为16k的内存作为压缩结果流缓存,默

FastDFS 和nginx整合

失败的经历:     从昨晚到今晚,一直在配置这FastDFS 和nginx整合这两个东西.听了黑马的讲师说一个人第一次做这个,光是搭建一个最简单的分布式文件系统至少需要1天时间.其实看来,果然没错.不过大部分时间都花在了执行错误的方法上面. 可能有人是看过了传智播客的讲师错误配置方法之后才来网上寻找答案的,没错.拜托那个错误的配置文档之后,重新开启一台虚拟机,铛!!!!!花了4个小时左右,配置成功了. 下面是效果图: 总有一个体会,每次对一件事物感到深刻是对它想吐之后才会有.这次是真的恶心到我